1use super::*;
10use crate::isa::riscv64::lower::isle::generated_code::{
11 COpcodeSpace, CaOp, CbOp, CiOp, CiwOp, ClOp, CrOp, CsOp, CssOp, CsznOp, FpuOPWidth,
12 VecAluOpRImm5, VecAluOpRR, VecAluOpRRRImm5, VecAluOpRRRR, VecOpCategory, ZcbMemOp,
13};
14use crate::machinst::isle::WritableReg;
15
16fn unsigned_field_width(value: u32, width: u8) -> u32 {
17 debug_assert_eq!(value & (!0 << width), 0);
18 value
19}
20
21fn encode_r_type_bits(opcode: u32, rd: u32, funct3: u32, rs1: u32, rs2: u32, funct7: u32) -> u32 {
25 let mut bits = 0;
26 bits |= unsigned_field_width(opcode, 7);
27 bits |= unsigned_field_width(rd, 5) << 7;
28 bits |= unsigned_field_width(funct3, 3) << 12;
29 bits |= unsigned_field_width(rs1, 5) << 15;
30 bits |= unsigned_field_width(rs2, 5) << 20;
31 bits |= unsigned_field_width(funct7, 7) << 25;
32 bits
33}
34
35pub fn encode_r_type(
37 opcode: u32,
38 rd: WritableReg,
39 funct3: u32,
40 rs1: Reg,
41 rs2: Reg,
42 funct7: u32,
43) -> u32 {
44 encode_r_type_bits(
45 opcode,
46 reg_to_gpr_num(rd.to_reg()),
47 funct3,
48 reg_to_gpr_num(rs1),
49 reg_to_gpr_num(rs2),
50 funct7,
51 )
52}
53
54fn encode_i_type_bits(opcode: u32, rd: u32, funct3: u32, rs1: u32, offset: u32) -> u32 {
58 let mut bits = 0;
59 bits |= unsigned_field_width(opcode, 7);
60 bits |= unsigned_field_width(rd, 5) << 7;
61 bits |= unsigned_field_width(funct3, 3) << 12;
62 bits |= unsigned_field_width(rs1, 5) << 15;
63 bits |= unsigned_field_width(offset, 12) << 20;
64 bits
65}
66
67pub fn encode_i_type(opcode: u32, rd: WritableReg, width: u32, rs1: Reg, offset: Imm12) -> u32 {
69 encode_i_type_bits(
70 opcode,
71 reg_to_gpr_num(rd.to_reg()),
72 width,
73 reg_to_gpr_num(rs1),
74 offset.bits(),
75 )
76}
77
78pub fn encode_s_type(opcode: u32, width: u32, base: Reg, src: Reg, offset: Imm12) -> u32 {
84 let mut bits = 0;
85 bits |= unsigned_field_width(opcode, 7);
86 bits |= (offset.bits() & 0b11111) << 7;
87 bits |= unsigned_field_width(width, 3) << 12;
88 bits |= reg_to_gpr_num(base) << 15;
89 bits |= reg_to_gpr_num(src) << 20;
90 bits |= unsigned_field_width(offset.bits() >> 5, 7) << 25;
91 bits
92}
93
94pub fn encode_valu(
107 op: VecAluOpRRR,
108 vd: WritableReg,
109 vs1: Reg,
110 vs2: Reg,
111 masking: VecOpMasking,
112) -> u32 {
113 let funct7 = (op.funct6() << 1) | masking.encode();
114 encode_r_type_bits(
115 op.opcode(),
116 reg_to_gpr_num(vd.to_reg()),
117 op.funct3(),
118 reg_to_gpr_num(vs1),
119 reg_to_gpr_num(vs2),
120 funct7,
121 )
122}
123
124pub fn encode_valu_rr_imm(
138 op: VecAluOpRRImm5,
139 vd: WritableReg,
140 imm: Imm5,
141 vs2: Reg,
142 masking: VecOpMasking,
143) -> u32 {
144 let funct7 = (op.funct6() << 1) | masking.encode();
145 let imm = imm.bits() as u32;
146 encode_r_type_bits(
147 op.opcode(),
148 reg_to_gpr_num(vd.to_reg()),
149 op.funct3(),
150 imm,
151 reg_to_gpr_num(vs2),
152 funct7,
153 )
154}
155
156pub fn encode_valu_rrrr(
157 op: VecAluOpRRRR,
158 vd: WritableReg,
159 vs2: Reg,
160 vs1: Reg,
161 masking: VecOpMasking,
162) -> u32 {
163 let funct7 = (op.funct6() << 1) | masking.encode();
164 encode_r_type_bits(
165 op.opcode(),
166 reg_to_gpr_num(vd.to_reg()),
167 op.funct3(),
168 reg_to_gpr_num(vs1),
169 reg_to_gpr_num(vs2),
170 funct7,
171 )
172}
173
174pub fn encode_valu_rrr_imm(
175 op: VecAluOpRRRImm5,
176 vd: WritableReg,
177 imm: Imm5,
178 vs2: Reg,
179 masking: VecOpMasking,
180) -> u32 {
181 let funct7 = (op.funct6() << 1) | masking.encode();
182 let imm = imm.bits() as u32;
183 encode_r_type_bits(
184 op.opcode(),
185 reg_to_gpr_num(vd.to_reg()),
186 op.funct3(),
187 imm,
188 reg_to_gpr_num(vs2),
189 funct7,
190 )
191}
192
193pub fn encode_valu_rr(op: VecAluOpRR, vd: WritableReg, vs: Reg, masking: VecOpMasking) -> u32 {
194 let funct7 = (op.funct6() << 1) | masking.encode();
195
196 let (vs1, vs2) = if op.vs_is_vs2_encoded() {
197 (op.aux_encoding(), reg_to_gpr_num(vs))
198 } else {
199 (reg_to_gpr_num(vs), op.aux_encoding())
200 };
201
202 encode_r_type_bits(
203 op.opcode(),
204 reg_to_gpr_num(vd.to_reg()),
205 op.funct3(),
206 vs1,
207 vs2,
208 funct7,
209 )
210}
211
212pub fn encode_valu_r_imm(
213 op: VecAluOpRImm5,
214 vd: WritableReg,
215 imm: Imm5,
216 masking: VecOpMasking,
217) -> u32 {
218 let funct7 = (op.funct6() << 1) | masking.encode();
219
220 debug_assert_eq!(op, VecAluOpRImm5::VmvVI);
222 let vs1 = imm.bits() as u32;
223 let vs2 = op.aux_encoding();
224
225 encode_r_type_bits(
226 op.opcode(),
227 reg_to_gpr_num(vd.to_reg()),
228 op.funct3(),
229 vs1,
230 vs2,
231 funct7,
232 )
233}
234
235pub fn encode_vcfg_imm(opcode: u32, rd: Reg, imm: UImm5, vtype: &VType) -> u32 {
240 let mut bits = 0;
241 bits |= unsigned_field_width(opcode, 7);
242 bits |= reg_to_gpr_num(rd) << 7;
243 bits |= VecOpCategory::OPCFG.encode() << 12;
244 bits |= unsigned_field_width(imm.bits(), 5) << 15;
245 bits |= unsigned_field_width(vtype.encode(), 10) << 20;
246 bits |= 0b11 << 30;
247 bits
248}
249
250pub fn encode_vmem_load(
255 opcode: u32,
256 vd: Reg,
257 width: VecElementWidth,
258 rs1: Reg,
259 lumop: u32,
260 masking: VecOpMasking,
261 mop: u32,
262 nf: u32,
263) -> u32 {
264 let width = match width {
266 VecElementWidth::E8 => 0b000,
267 VecElementWidth::E16 => 0b101,
268 VecElementWidth::E32 => 0b110,
269 VecElementWidth::E64 => 0b111,
270 };
271
272 let mut bits = 0;
273 bits |= unsigned_field_width(opcode, 7);
274 bits |= reg_to_gpr_num(vd) << 7;
275 bits |= width << 12;
276 bits |= reg_to_gpr_num(rs1) << 15;
277 bits |= unsigned_field_width(lumop, 5) << 20;
278 bits |= masking.encode() << 25;
279 bits |= unsigned_field_width(mop, 2) << 26;
280
281 bits |= 0b0 << 28;
284
285 bits |= unsigned_field_width(nf, 3) << 29;
286 bits
287}
288
289pub fn encode_vmem_store(
294 opcode: u32,
295 vs3: Reg,
296 width: VecElementWidth,
297 rs1: Reg,
298 sumop: u32,
299 masking: VecOpMasking,
300 mop: u32,
301 nf: u32,
302) -> u32 {
303 encode_vmem_load(opcode, vs3, width, rs1, sumop, masking, mop, nf)
306}
307
308pub fn encode_csr_reg(op: CsrRegOP, rd: WritableReg, rs: Reg, csr: CSR) -> u32 {
311 encode_i_type(op.opcode(), rd, op.funct3(), rs, csr.bits())
312}
313
314pub fn encode_csr_imm(op: CsrImmOP, rd: WritableReg, csr: CSR, imm: UImm5) -> u32 {
317 encode_i_type_bits(
318 op.opcode(),
319 reg_to_gpr_num(rd.to_reg()),
320 op.funct3(),
321 imm.bits(),
322 csr.bits().bits(),
323 )
324}
325
326pub fn encode_cr_type(op: CrOp, rd: WritableReg, rs2: Reg) -> u16 {
331 let mut bits = 0;
332 bits |= unsigned_field_width(op.op().bits(), 2);
333 bits |= reg_to_gpr_num(rs2) << 2;
334 bits |= reg_to_gpr_num(rd.to_reg()) << 7;
335 bits |= unsigned_field_width(op.funct4(), 4) << 12;
336 bits.try_into().unwrap()
337}
338
339pub fn encode_cr2_type(op: CrOp, rs1: Reg) -> u16 {
344 encode_cr_type(op, WritableReg::from_reg(rs1), zero_reg())
345}
346
347pub fn encode_ca_type(op: CaOp, rd: WritableReg, rs2: Reg) -> u16 {
352 let mut bits = 0;
353 bits |= unsigned_field_width(op.op().bits(), 2);
354 bits |= reg_to_compressed_gpr_num(rs2) << 2;
355 bits |= unsigned_field_width(op.funct2(), 2) << 5;
356 bits |= reg_to_compressed_gpr_num(rd.to_reg()) << 7;
357 bits |= unsigned_field_width(op.funct6(), 6) << 10;
358 bits.try_into().unwrap()
359}
360
361pub fn encode_cj_type(op: CjOp, imm: Imm12) -> u16 {
368 let imm = imm.bits();
369 debug_assert!(imm & 1 == 0);
370
371 let mut imm_field = 0;
374 imm_field |= ((imm >> 11) & 1) << 10;
375 imm_field |= ((imm >> 4) & 1) << 9;
376 imm_field |= ((imm >> 8) & 3) << 7;
377 imm_field |= ((imm >> 10) & 1) << 6;
378 imm_field |= ((imm >> 6) & 1) << 5;
379 imm_field |= ((imm >> 7) & 1) << 4;
380 imm_field |= ((imm >> 1) & 7) << 1;
381 imm_field |= ((imm >> 5) & 1) << 0;
382
383 let mut bits = 0;
384 bits |= unsigned_field_width(op.op().bits(), 2);
385 bits |= unsigned_field_width(imm_field, 11) << 2;
386 bits |= unsigned_field_width(op.funct3(), 3) << 13;
387 bits.try_into().unwrap()
388}
389
390pub fn encode_ci_type(op: CiOp, rd: WritableReg, imm: Imm6) -> u16 {
397 let imm = imm.bits();
398
399 let mut bits = 0;
400 bits |= unsigned_field_width(op.op().bits(), 2);
401 bits |= unsigned_field_width((imm & 0x1f) as u32, 5) << 2;
402 bits |= reg_to_gpr_num(rd.to_reg()) << 7;
403 bits |= unsigned_field_width(((imm >> 5) & 1) as u32, 1) << 12;
404 bits |= unsigned_field_width(op.funct3(), 3) << 13;
405 bits.try_into().unwrap()
406}
407
408pub fn encode_ci_sp_load(op: CiOp, rd: WritableReg, imm: Uimm6) -> u16 {
411 let imm = imm.bits();
412
413 let low_bits = match op {
422 CiOp::CLwsp => 3, CiOp::CLdsp | CiOp::CFldsp => 2, _ => unreachable!(),
425 };
426 let high_bits = 6 - 1 - low_bits;
427 let mut enc_imm = 0;
428
429 enc_imm |= imm >> (6 - high_bits);
431
432 enc_imm |= (imm & ((1 << low_bits) - 1)) << high_bits;
434
435 enc_imm |= ((imm >> low_bits) & 1) << 5;
437
438 let enc_imm = Imm6::maybe_from_i16((enc_imm as i16) << 10 >> 10).unwrap();
439
440 encode_ci_type(op, rd, enc_imm)
441}
442
443pub fn encode_c_addi16sp(imm: Imm6) -> u16 {
445 let imm = imm.bits();
446
447 let mut enc_imm = 0;
449 enc_imm |= ((imm >> 5) & 1) << 5;
450 enc_imm |= ((imm >> 0) & 1) << 4;
451 enc_imm |= ((imm >> 2) & 1) << 3;
452 enc_imm |= ((imm >> 3) & 3) << 1;
453 enc_imm |= ((imm >> 1) & 1) << 0;
454 let enc_imm = Imm6::maybe_from_i16((enc_imm as i16) << 10 >> 10).unwrap();
455
456 encode_ci_type(CiOp::CAddi16sp, writable_stack_reg(), enc_imm)
457}
458
459pub fn encode_ciw_type(op: CiwOp, rd: WritableReg, imm: u8) -> u16 {
464 let mut imm_field = 0;
466 imm_field |= ((imm >> 1) & 1) << 0;
467 imm_field |= ((imm >> 0) & 1) << 1;
468 imm_field |= ((imm >> 4) & 15) << 2;
469 imm_field |= ((imm >> 2) & 3) << 6;
470
471 let mut bits = 0;
472 bits |= unsigned_field_width(op.op().bits(), 2);
473 bits |= reg_to_compressed_gpr_num(rd.to_reg()) << 2;
474 bits |= unsigned_field_width(imm_field as u32, 8) << 5;
475 bits |= unsigned_field_width(op.funct3(), 3) << 13;
476 bits.try_into().unwrap()
477}
478
479pub fn encode_cb_type(op: CbOp, rd: WritableReg, imm: Imm6) -> u16 {
486 let imm = imm.bits();
487
488 let mut bits = 0;
489 bits |= unsigned_field_width(op.op().bits(), 2);
490 bits |= unsigned_field_width((imm & 0x1f) as u32, 5) << 2;
491 bits |= reg_to_compressed_gpr_num(rd.to_reg()) << 7;
492 bits |= unsigned_field_width(op.funct2(), 2) << 10;
493 bits |= unsigned_field_width(((imm >> 5) & 1) as u32, 1) << 12;
494 bits |= unsigned_field_width(op.funct3(), 3) << 13;
495 bits.try_into().unwrap()
496}
497
498pub fn encode_css_type(op: CssOp, src: Reg, imm: Uimm6) -> u16 {
505 let imm = imm.bits();
506
507 let low_bits = match op {
516 CssOp::CSwsp => 4, CssOp::CSdsp | CssOp::CFsdsp => 3, };
519 let high_bits = 6 - low_bits;
520
521 let mut enc_imm = 0;
522 enc_imm |= (imm & ((1 << low_bits) - 1)) << high_bits;
523 enc_imm |= imm >> low_bits;
524
525 let mut bits = 0;
526 bits |= unsigned_field_width(op.op().bits(), 2);
527 bits |= reg_to_gpr_num(src) << 2;
528 bits |= unsigned_field_width(enc_imm as u32, 6) << 7;
529 bits |= unsigned_field_width(op.funct3(), 3) << 13;
530 bits.try_into().unwrap()
531}
532
533pub fn encode_cs_type(op: CsOp, src: Reg, base: Reg, imm: Uimm5) -> u16 {
540 let size = match op {
541 CsOp::CFsd | CsOp::CSd => 8,
542 CsOp::CSw => 4,
543 };
544
545 encode_cs_cl_type_bits(op.op(), op.funct3(), size, src, base, imm)
546}
547
548pub fn encode_cl_type(op: ClOp, dest: WritableReg, base: Reg, imm: Uimm5) -> u16 {
555 let size = match op {
556 ClOp::CFld | ClOp::CLd => 8,
557 ClOp::CLw => 4,
558 };
559
560 encode_cs_cl_type_bits(op.op(), op.funct3(), size, dest.to_reg(), base, imm)
561}
562
563fn encode_cs_cl_type_bits(
568 op: COpcodeSpace,
569 funct3: u32,
570 size: u32,
571 dest_src: Reg,
572 base: Reg,
573 imm: Uimm5,
574) -> u16 {
575 let imm = imm.bits();
576
577 let imm2 = match size {
583 4 => ((imm >> 4) & 1) | ((imm & 1) << 1),
584 8 => (imm >> 3) & 0b11,
585 _ => unreachable!(),
586 };
587
588 let imm3 = match size {
590 4 => (imm >> 1) & 0b111,
591 8 => (imm >> 0) & 0b111,
592 _ => unreachable!(),
593 };
594
595 let mut bits = 0;
596 bits |= unsigned_field_width(op.bits(), 2);
597 bits |= reg_to_compressed_gpr_num(dest_src) << 2;
598 bits |= unsigned_field_width(imm2 as u32, 2) << 5;
599 bits |= reg_to_compressed_gpr_num(base) << 7;
600 bits |= unsigned_field_width(imm3 as u32, 3) << 10;
601 bits |= unsigned_field_width(funct3, 3) << 13;
602 bits.try_into().unwrap()
603}
604
605pub fn encode_cszn_type(op: CsznOp, rd: WritableReg) -> u16 {
612 let mut bits = 0;
613 bits |= unsigned_field_width(op.op().bits(), 2);
614 bits |= unsigned_field_width(op.funct5(), 5) << 2;
615 bits |= reg_to_compressed_gpr_num(rd.to_reg()) << 7;
616 bits |= unsigned_field_width(op.funct6(), 6) << 10;
617 bits.try_into().unwrap()
618}
619
620fn encode_zcbmem_bits(op: ZcbMemOp, dest_src: Reg, base: Reg, imm: Uimm2) -> u16 {
625 let imm = imm.bits();
626
627 let imm = match op {
629 ZcbMemOp::CLh | ZcbMemOp::CLhu | ZcbMemOp::CSh => {
630 debug_assert_eq!(imm & !1, 0);
631 let opcode_bit = (op == ZcbMemOp::CLh) as u8;
633 imm | (opcode_bit << 1)
634 }
635 _ => ((imm & 1) << 1) | ((imm >> 1) & 1),
637 };
638
639 let mut bits = 0;
640 bits |= unsigned_field_width(op.op().bits(), 2);
641 bits |= reg_to_compressed_gpr_num(dest_src) << 2;
642 bits |= unsigned_field_width(imm as u32, 2) << 5;
643 bits |= reg_to_compressed_gpr_num(base) << 7;
644 bits |= unsigned_field_width(op.funct6(), 6) << 10;
645 bits.try_into().unwrap()
646}
647
648pub fn encode_zcbmem_load(op: ZcbMemOp, rd: WritableReg, base: Reg, imm: Uimm2) -> u16 {
649 encode_zcbmem_bits(op, rd.to_reg(), base, imm)
650}
651
652pub fn encode_zcbmem_store(op: ZcbMemOp, src: Reg, base: Reg, imm: Uimm2) -> u16 {
653 encode_zcbmem_bits(op, src, base, imm)
654}
655
656pub fn encode_fli(ty: Type, imm: FliConstant, rd: WritableReg) -> u32 {
657 let op = FpuOPRR::FmvFmtX;
660 let width = FpuOPWidth::try_from(ty).unwrap();
661 let frm = 0; let rs2 = 1; let mut bits = 0;
665 bits |= unsigned_field_width(op.opcode(), 7);
666 bits |= reg_to_gpr_num(rd.to_reg()) << 7;
667 bits |= unsigned_field_width(frm, 3) << 12;
668 bits |= unsigned_field_width(imm.bits() as u32, 5) << 15;
669 bits |= unsigned_field_width(rs2, 6) << 20;
670 bits |= unsigned_field_width(op.funct7(width), 7) << 25;
671 bits
672}
673
674pub fn encode_fp_rr(op: FpuOPRR, width: FpuOPWidth, frm: FRM, rd: WritableReg, rs: Reg) -> u32 {
675 encode_r_type_bits(
676 op.opcode(),
677 reg_to_gpr_num(rd.to_reg()),
678 frm.as_u32(),
679 reg_to_gpr_num(rs),
680 op.rs2(),
681 op.funct7(width),
682 )
683}
684
685pub fn encode_fp_rrr(
686 op: FpuOPRRR,
687 width: FpuOPWidth,
688 frm: FRM,
689 rd: WritableReg,
690 rs1: Reg,
691 rs2: Reg,
692) -> u32 {
693 encode_r_type_bits(
694 op.opcode(),
695 reg_to_gpr_num(rd.to_reg()),
696 frm.as_u32(),
697 reg_to_gpr_num(rs1),
698 reg_to_gpr_num(rs2),
699 op.funct7(width),
700 )
701}
702
703pub fn encode_fp_rrrr(
704 op: FpuOPRRRR,
705 width: FpuOPWidth,
706 frm: FRM,
707 rd: WritableReg,
708 rs1: Reg,
709 rs2: Reg,
710 rs3: Reg,
711) -> u32 {
712 let funct7 = (reg_to_gpr_num(rs3) << 2) | width.as_u32();
713 encode_r_type_bits(
714 op.opcode(),
715 reg_to_gpr_num(rd.to_reg()),
716 frm.as_u32(),
717 reg_to_gpr_num(rs1),
718 reg_to_gpr_num(rs2),
719 funct7,
720 )
721}