Skip to main content

asmkit/riscv/
assembler.rs

1use super::opcodes::Opcode;
2use crate::AsmError;
3use crate::core::buffer::{CodeBuffer, CodeOffset, ConstantData, LabelUse, Reloc, RelocTarget};
4use crate::core::operand::*;
5use crate::core::operand::{Imm, Sym};
6use crate::core::patch::PatchSiteId;
7use crate::riscv::opcodes::Encoding;
8use crate::riscv::{EmitterExplicit, RA};
9use crate::{core::emitter::Emitter, riscv::opcodes::Inst};
10pub struct Assembler<'a> {
11    pub buffer: &'a mut CodeBuffer,
12    last_error: Option<AsmError>,
13}
14
15impl<'a> Assembler<'a> {
16    pub fn new(buffer: &'a mut CodeBuffer) -> Self {
17        Assembler {
18            buffer,
19            last_error: None,
20        }
21    }
22
23    pub fn get_label(&mut self) -> Label {
24        self.buffer.get_label()
25    }
26
27    pub fn bind_label(&mut self, label: Label) {
28        self.buffer.bind_label(label);
29    }
30
31    pub fn add_constant(&mut self, c: impl Into<ConstantData>) -> Label {
32        let c = self.buffer.add_constant(c);
33        self.buffer.get_label_for_constant(c)
34    }
35
36    pub fn label_offset(&self, label: Label) -> CodeOffset {
37        self.buffer.label_offset(label)
38    }
39
40    pub fn patchable_j(&mut self, label: Label) -> PatchSiteId {
41        let offset = self.buffer.cur_offset();
42        self.j(label);
43        self.buffer
44            .record_label_patch_site(offset, label, LabelUse::RVJal20)
45    }
46
47    pub fn patchable_call(&mut self, label: Label) -> PatchSiteId {
48        let offset = self.buffer.cur_offset();
49        self.jal(RA, label);
50        self.buffer
51            .record_label_patch_site(offset, label, LabelUse::RVJal20)
52    }
53
54    pub fn la(&mut self, rd: impl OperandCast, target: impl OperandCast) {
55        let rd = *rd.as_operand();
56        let target = target.as_operand();
57
58        if target.is_label() {
59            let off = self.buffer.cur_offset();
60            self.buffer
61                .use_label_at_offset(off, target.as_::<Label>(), LabelUse::RVPCRelHi20);
62            self.auipc(rd, imm(0));
63            let off = self.buffer.cur_offset();
64            self.buffer
65                .use_label_at_offset(off, target.as_::<Label>(), LabelUse::RVPCRelLo12I);
66            self.addi(rd, rd, imm(0));
67        } else if target.is_sym() {
68            if self.buffer.env().pic() {
69                // Load a PC-relative address into a register.
70                // RISC-V does this slightly differently from other arches. We emit a relocation
71                // with a label, instead of the symbol itself.
72                //
73                // See: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses
74                //
75                // Emit the following code:
76                // label:
77                //   auipc rd, 0              # R_RISCV_GOT_HI20 (symbol_name)
78                //   ld    rd, rd, 0          # R_RISCV_PCREL_LO12_I (label)
79
80                let sym = target.as_::<Sym>();
81
82                // Create the label that is going to be published to the final binary object.
83                let auipc_label = self.get_label();
84                self.bind_label(auipc_label);
85                self.buffer
86                    .add_reloc(Reloc::RiscvGotHi20, RelocTarget::Sym(sym), 0);
87
88                // Get the current PC.
89                self.auipc(rd, imm(0));
90                // The `ld` here, points to the `auipc` label instead of directly to the symbol.
91                self.buffer
92                    .add_reloc(Reloc::RiscvPCRelLo12I, RelocTarget::Label(auipc_label), 0);
93                self.ld(rd, rd, imm(0));
94            } else {
95                // In the non PIC sequence we relocate the absolute address into
96                // a prealocatted space, load it into a register and jump over it.
97                //
98                // Emit the following code:
99                //   ld rd, label_data
100                //   j label_end
101                // label_data:
102                //   <8 byte space>           # ABS8
103                // label_end:
104                let label_data = self.get_label();
105                let label_end = self.get_label();
106
107                self.ld(rd, rd, label_data);
108                self.j(label_end);
109                self.bind_label(label_data);
110                self.buffer
111                    .add_reloc(Reloc::Abs8, RelocTarget::Sym(target.as_::<Sym>()), 0);
112                self.buffer.put8(0);
113                self.bind_label(label_end);
114            }
115        } else {
116            unreachable!("LA expects label or symbol");
117        }
118    }
119
120    pub fn call(&mut self, target: impl OperandCast) {
121        let target = target.as_operand();
122
123        if target.is_label() {
124            let off = self.buffer.cur_offset();
125            self.buffer
126                .use_label_at_offset(off, target.as_::<Label>(), LabelUse::RVPCRelHi20);
127            self.auipc(RA, imm(0));
128            assert!(self.last_error.is_none());
129            let off = self.buffer.cur_offset();
130            self.buffer
131                .use_label_at_offset(off, target.as_::<Label>(), LabelUse::RVPCRelLo12I);
132            self.jalr(RA, RA, imm(0));
133            assert!(self.last_error.is_none());
134        } else if target.is_sym() {
135            let sym = target.as_::<Sym>();
136
137            let reloc = Reloc::RiscvCallPlt;
138
139            self.buffer.add_reloc(reloc, RelocTarget::Sym(sym), 0);
140            self.auipc(RA, imm(0));
141            self.jalr(RA, RA, imm(0));
142        } else if target.is_imm() {
143            self.jalr(RA, RA, *target);
144        } else if target.is_reg() {
145            self.jalr(RA, *target, imm(0));
146        } else {
147            unreachable!();
148        }
149    }
150}
151macro_rules! enc_ops1 {
152    ($op0:ident) => {
153        OperandType::$op0 as u32
154    };
155}
156
157macro_rules! enc_ops2 {
158    ($op0:ident, $op1:ident) => {
159        (OperandType::$op0 as u32) | ((OperandType::$op1 as u32) << 3)
160    };
161}
162
163macro_rules! enc_ops3 {
164    ($op0:ident, $op1:ident, $op2:ident) => {
165        (OperandType::$op0 as u32)
166            | ((OperandType::$op1 as u32) << 3)
167            | ((OperandType::$op2 as u32) << 6)
168    };
169}
170
171macro_rules! enc_ops4 {
172    ($op0:ident, $op1:ident, $op2:ident, $op3:ident) => {
173        (OperandType::$op0 as u32)
174            | ((OperandType::$op1 as u32) << 3)
175            | ((OperandType::$op2 as u32) << 6)
176            | ((OperandType::$op3 as u32) << 9)
177    };
178}
179
180impl<'a> Emitter for Assembler<'a> {
181    fn emit(
182        &mut self,
183        opcode: i64,
184        op0: &crate::core::operand::Operand,
185        op1: &crate::core::operand::Operand,
186        op2: &crate::core::operand::Operand,
187        op3: &crate::core::operand::Operand,
188    ) {
189        self.emit_n(opcode, &[op0, op1, op2, op3])
190    }
191
192    #[allow(unused_assignments)]
193    fn emit_n(&mut self, opcode: i64, ops: &[&crate::core::operand::Operand]) {
194        assert!(opcode < Opcode::Invalid as i64 && opcode >= 0);
195        let opcode: Opcode = unsafe { core::mem::transmute(opcode as u32) };
196        let encoding = opcode.encoding();
197
198        let mut inst = Inst::new(opcode).encode();
199        let mut label_use = None;
200        let mut reloc = None;
201
202        let isign3 = match ops {
203            [] => 0,
204            [op0] => op0.op_type() as u32,
205            [op0, op1] => op0.op_type() as u32 + ((op1.op_type() as u32) << 3),
206            [op0, op1, op2, ..] => {
207                op0.op_type() as u32 + ((op1.op_type() as u32) << 3) + ((op2.op_type() as u32) << 6)
208            }
209        };
210
211        let isign4 = match ops {
212            [] => 0,
213            [op0] => op0.op_type() as u32,
214            [op0, op1] => op0.op_type() as u32 + ((op1.op_type() as u32) << 3),
215            [op0, op1, op2] => {
216                op0.op_type() as u32 + ((op1.op_type() as u32) << 3) + ((op2.op_type() as u32) << 6)
217            }
218            [op0, op1, op2, op3, ..] => {
219                op0.op_type() as u32
220                    + ((op1.op_type() as u32) << 3)
221                    + ((op2.op_type() as u32) << 6)
222                    + ((op3.op_type() as u32) << 9)
223            }
224        };
225        let mut short = false;
226        match encoding {
227            Encoding::Bimm12HiRs1Bimm12lo => {
228                let rs1 = ops[0].id();
229                let imm = if ops[1].is_imm() {
230                    ops[1].as_::<Imm>().value() as i32
231                } else if ops[1].is_label() {
232                    label_use = Some((ops[1], LabelUse::RVB12));
233                    0
234                } else {
235                    self.last_error = Some(AsmError::InvalidOperand);
236                    return;
237                };
238
239                inst = inst.set_rs1(rs1).set_bimm12lohi(imm);
240            }
241
242            Encoding::Bimm12HiRs1Rs2Bimm12lo => {
243                let rs1 = ops[0].id();
244                let rs2 = ops[1].id();
245
246                let imm = if ops[2].is_imm() {
247                    ops[2].as_::<Imm>().value() as i32
248                } else if ops[2].is_label() {
249                    label_use = Some((ops[2], LabelUse::RVB12));
250                    0
251                } else {
252                    self.last_error = Some(AsmError::InvalidOperand);
253                    return;
254                };
255
256                inst = inst.set_rs1(rs1).set_rs2(rs2).set_bimm12lohi(imm);
257            }
258
259            Encoding::Bimm12HiRs2Rs1Bimm12lo => {
260                let rs1 = ops[0].id();
261                let rs2 = ops[1].id();
262                let imm = if ops[2].is_imm() {
263                    ops[2].as_::<Imm>().value() as i32
264                } else if ops[2].is_label() {
265                    label_use = Some((ops[2], LabelUse::RVB12));
266                    0
267                } else {
268                    self.last_error = Some(AsmError::InvalidOperand);
269                    return;
270                };
271
272                inst = inst.set_rs2(rs2).set_rs1(rs1).set_bimm12lohi(imm);
273            }
274
275            Encoding::Bimm12HiRs2Bimm12lo => {
276                let rs2 = ops[0].id();
277                let imm = if ops[1].is_imm() {
278                    ops[1].as_::<Imm>().value() as i32
279                } else if ops[1].is_label() {
280                    label_use = Some((ops[1], LabelUse::RVB12));
281                    0
282                } else {
283                    self.last_error = Some(AsmError::InvalidOperand);
284                    return;
285                };
286
287                inst = inst.set_rs2(rs2).set_bimm12lohi(imm);
288            }
289
290            Encoding::CImm12 => {
291                short = true;
292                let imm = if ops[0].is_imm() {
293                    ops[0].as_::<Imm>().value() as i32
294                } else if ops[0].is_label() {
295                    label_use = Some((ops[0], LabelUse::RVCJump));
296                    0
297                } else {
298                    self.last_error = Some(AsmError::InvalidOperand);
299                    return;
300                };
301
302                inst = inst.set_c_imm12(imm)
303            }
304
305            Encoding::CIndex => {
306                short = true;
307                let imm = if ops[0].is_imm() {
308                    ops[0].as_::<Imm>().value() as i32
309                } else {
310                    self.last_error = Some(AsmError::InvalidOperand);
311                    return;
312                };
313                inst = inst.set_c_index(imm as _);
314            }
315
316            Encoding::CMopT => {
317                short = true;
318                let imm = if ops[0].is_imm() {
319                    ops[0].as_::<Imm>().value() as i32
320                } else {
321                    self.last_error = Some(AsmError::InvalidOperand);
322                    return;
323                };
324
325                inst = inst.set_c_mop_t(imm as _);
326            }
327
328            Encoding::CNzimm10hiCNzimm10lo => {
329                short = true;
330                let imm = if ops[0].is_imm() {
331                    ops[0].as_::<Imm>().value() as i32
332                } else {
333                    self.last_error = Some(AsmError::InvalidOperand);
334                    return;
335                };
336
337                if imm == 0 || !(-1024..=1024).contains(&imm) {
338                    self.last_error = Some(AsmError::InvalidOperand);
339                    return;
340                }
341
342                inst = inst.set_c_nzimm10lohi(imm);
343            }
344
345            Encoding::CNzimm6hiCNzimm6lo => {
346                short = true;
347                let imm = if ops[0].is_imm() {
348                    ops[0].as_::<Imm>().value() as i32
349                } else {
350                    self.last_error = Some(AsmError::InvalidOperand);
351                    return;
352                };
353
354                if imm == 0 || imm > 64 {
355                    self.last_error = Some(AsmError::InvalidOperand);
356                    return;
357                }
358
359                inst = inst.set_c_nzimm6lohi(imm)
360            }
361
362            Encoding::CRlistCSpimm => {
363                short = true;
364                todo!()
365            }
366
367            Encoding::CRs1N0 => {
368                short = true;
369                let rs1 = ops[0].id();
370                inst = inst.set_rs1_n0(rs1);
371            }
372
373            Encoding::CRs2CUimm8spS => {
374                short = true;
375                let rs2 = ops[0].id();
376                let imm = if ops[1].is_imm() {
377                    ops[1].as_::<Imm>().value() as i32
378                } else {
379                    self.last_error = Some(AsmError::InvalidOperand);
380                    return;
381                };
382                if !(0..=256).contains(&imm) {
383                    self.last_error = Some(AsmError::InvalidOperand);
384                    return;
385                }
386                inst = inst.set_c_uimm8lohi(imm as _).set_c_rs2(rs2);
387            }
388
389            Encoding::CRs2CUimm9spS => {
390                short = true;
391                let rs2 = ops[0].id();
392                let imm = if ops[1].is_imm() {
393                    ops[1].as_::<Imm>().value() as i32
394                } else {
395                    self.last_error = Some(AsmError::InvalidOperand);
396                    return;
397                };
398                if !(0..=511).contains(&imm) {
399                    self.last_error = Some(AsmError::InvalidOperand);
400                    return;
401                }
402                inst = inst.set_c_rs2(rs2).set_c_uimm9sp_s(imm as _);
403            }
404
405            Encoding::CSreg1CSreg2 => {
406                short = true;
407                todo!()
408            }
409
410            Encoding::CsrZimm => {
411                let csr_imm = if ops[0].is_imm() {
412                    ops[0].as_::<Imm>().value() as i32
413                } else {
414                    self.last_error = Some(AsmError::InvalidOperand);
415                    return;
416                };
417
418                let zimm = if ops[1].is_imm() {
419                    ops[1].as_::<Imm>().value()
420                } else {
421                    self.last_error = Some(AsmError::InvalidOperand);
422                    return;
423                };
424
425                inst = inst.set_csr(csr_imm as _).set_zimm(zimm as _);
426            }
427
428            Encoding::Empty => {}
429            Encoding::FmPredSuccRs1Rd => {
430                let fm = if ops[0].is_imm() {
431                    ops[0].as_::<Imm>().value() as u8
432                } else {
433                    self.last_error = Some(AsmError::InvalidOperand);
434                    return;
435                };
436
437                let pred = if ops[1].is_imm() {
438                    ops[1].as_::<Imm>().value() as u8
439                } else {
440                    self.last_error = Some(AsmError::InvalidOperand);
441                    return;
442                };
443
444                let succ = if ops[2].is_imm() {
445                    ops[2].as_::<Imm>().value() as u8
446                } else {
447                    self.last_error = Some(AsmError::InvalidOperand);
448                    return;
449                };
450
451                let rs1 = ops[3].id();
452                let rd = ops[4].id();
453
454                inst = inst
455                    .set_fm(fm as _)
456                    .set_pred(pred as _)
457                    .set_succ(succ as _)
458                    .set_rs1(rs1)
459                    .set_rd(rd);
460            }
461
462            Encoding::Imm12HiRs1Rs2Imm12lo => {
463                if isign3 == enc_ops3!(Reg, Reg, Imm) {
464                    let rs1 = ops[0].id();
465                    let rs2 = ops[1].id();
466                    let imm = ops[2].as_::<Imm>().value() as i32;
467
468                    inst = inst.set_rs1(rs1).set_rs2(rs2).set_imm12lohi(imm);
469                } else {
470                    self.last_error = Some(AsmError::InvalidOperand);
471                    return;
472                };
473            }
474
475            Encoding::Imm12Rs1Rd => {
476                if isign3 == enc_ops3!(Reg, Reg, Imm) {
477                    let rs1 = ops[0].id();
478                    let rd = ops[1].id();
479                    let imm = ops[2].as_::<Imm>().value() as i32;
480
481                    inst = inst.set_rs1(rs1).set_rd(rd).set_imm12(imm);
482                } else {
483                    self.last_error = Some(AsmError::InvalidOperand);
484                    return;
485                }
486            }
487
488            Encoding::Jimm20 => {
489                if isign3 == enc_ops1!(Imm) {
490                    let imm = ops[0].as_::<Imm>().value() as i32;
491                    inst = inst.set_jimm20(imm);
492                } else if isign3 == enc_ops1!(Label) {
493                    label_use = Some((ops[0], LabelUse::RVJal20));
494                    inst = inst.set_jimm20(0);
495                } else if isign3 == enc_ops1!(Sym) {
496                    let sym = ops[0].as_::<Sym>();
497
498                    let _distance = self.buffer.symbol_distance(sym);
499                    // TODO: Should this work only with NEAR symbols?
500                    reloc = Some((sym, Reloc::RiscvGotHi20))
501                } else {
502                    self.last_error = Some(AsmError::InvalidOperand);
503                    return;
504                }
505            }
506
507            Encoding::MopRT30MopRT2726MopRT2120RdRs1 => {
508                todo!()
509            }
510            Encoding::MopRrT30MopRrT2726RdRs1Rs2 => {
511                todo!()
512            }
513
514            Encoding::NfVmRs1Vd => {
515                if isign3 == enc_ops3!(Reg, Reg, Reg) {
516                    let vd = ops[0].id();
517                    let rs1 = ops[1].id();
518                    let vm = ops[2].id();
519
520                    inst = inst.set_vd(vd).set_rs1(rs1).set_vm(vm);
521                } else {
522                    self.last_error = Some(AsmError::InvalidOperand);
523                    return;
524                }
525            }
526
527            Encoding::NfVmRs1Vs3 => {
528                if isign3 == enc_ops3!(Reg, Reg, Reg) {
529                    let vs3 = ops[0].id();
530                    let rs1 = ops[1].id();
531                    let vm = ops[2].id();
532
533                    inst = inst.set_vs3(vs3).set_rs1(rs1).set_vm(vm);
534                } else {
535                    self.last_error = Some(AsmError::InvalidOperand);
536                    return;
537                }
538            }
539
540            Encoding::NfVmRs2Rs1Vd => {
541                if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) {
542                    let vd = ops[0].id();
543                    let rs1 = ops[1].id();
544                    let vm = ops[3].id();
545                    let rs2 = ops[2].id();
546                    inst = inst.set_rs1(rs1).set_rs2(rs2).set_vd(vd).set_vm(vm);
547                } else {
548                    self.last_error = Some(AsmError::InvalidOperand);
549                    return;
550                }
551            }
552
553            Encoding::NfVmRs2Rs1Vs3 => {
554                if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) {
555                    let vs3 = ops[0].id();
556                    let rs1 = ops[1].id();
557                    let vm = ops[3].id();
558                    let rs2 = ops[2].id();
559                    inst = inst.set_rs1(rs1).set_rs2(rs2).set_vs3(vs3).set_vm(vm);
560                } else {
561                    self.last_error = Some(AsmError::InvalidOperand);
562                    return;
563                }
564            }
565
566            Encoding::NfVmVs2Rs1Vd => {
567                if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) {
568                    let vd = ops[0].id();
569                    let rs1 = ops[1].id();
570                    let vs2 = ops[2].id();
571                    let vm = ops[3].id();
572
573                    inst = inst.set_rs1(rs1).set_vd(vd).set_vs2(vs2).set_vm(vm);
574                } else {
575                    self.last_error = Some(AsmError::InvalidOperand);
576                    return;
577                }
578            }
579
580            Encoding::NfVmVs2Rs1Vs3 => {
581                if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) {
582                    let vs3 = ops[0].id();
583                    let rs1 = ops[1].id();
584                    let vs2 = ops[2].id();
585                    let vm = ops[3].id();
586
587                    inst = inst.set_vs3(vs3).set_rs1(rs1).set_vs2(vs2).set_vm(vm);
588                } else {
589                    self.last_error = Some(AsmError::InvalidOperand);
590                    return;
591                }
592            }
593
594            Encoding::Rd => {
595                if isign3 == enc_ops1!(Reg) {
596                    let rd = ops[0].id();
597                    inst = inst.set_rd(rd);
598                } else {
599                    self.last_error = Some(AsmError::InvalidOperand);
600                    return;
601                }
602            }
603
604            Encoding::RdCUimm8sphiCUimm8splo => {
605                if isign3 == enc_ops2!(Reg, Imm) {
606                    let rd = ops[0].id();
607                    let imm = ops[1].as_::<Imm>().value() as u32;
608
609                    inst = inst.set_rd(rd).set_c_uimm8splohi(imm);
610                } else {
611                    self.last_error = Some(AsmError::InvalidOperand);
612                    return;
613                }
614            }
615
616            Encoding::RdCUimm9sphiCUimm9splo => {
617                if isign3 == enc_ops2!(Reg, Imm) {
618                    let rd = ops[0].id();
619                    let imm = ops[1].as_::<Imm>().value() as u32;
620
621                    inst = inst.set_rd(rd).set_c_uimm9splohi(imm);
622                } else {
623                    self.last_error = Some(AsmError::InvalidOperand);
624                    return;
625                }
626            }
627
628            Encoding::RdCsr => {
629                if isign3 == enc_ops2!(Reg, Imm) {
630                    let rd = ops[0].id();
631                    let csr = ops[1].as_::<Imm>().value() as u32;
632                    inst = inst.set_rd(rd).set_csr(csr);
633                } else {
634                    self.last_error = Some(AsmError::InvalidOperand);
635                    return;
636                }
637            }
638
639            Encoding::RdCsrZimm => {
640                if isign3 == enc_ops3!(Reg, Imm, Imm) {
641                    let rd = ops[0].id();
642                    let csr = ops[1].as_::<Imm>().value() as u32;
643                    let zimm = ops[2].as_::<Imm>().value() as i32;
644                    inst = inst.set_rd(rd).set_csr(csr).set_zimm(zimm);
645                } else {
646                    self.last_error = Some(AsmError::InvalidOperand);
647                    return;
648                }
649            }
650            Encoding::RdImm20 => {
651                if isign3 == enc_ops2!(Reg, Imm) {
652                    let rd = ops[0].id();
653                    let imm = ops[1].as_::<Imm>().value() as i32;
654                    inst = inst.set_rd(rd).set_imm20(imm);
655                } else if isign3 == enc_ops2!(Reg, Label) {
656                    let rd = ops[0].id();
657                    label_use = Some((ops[0], LabelUse::RVPCRelHi20));
658                    inst = inst.set_rd(rd).set_imm20(0);
659                } else if isign3 == enc_ops2!(Reg, Sym) {
660                    /*let rd = ops[0].id();
661                    let sym = ops[1].as_::<Sym>();
662
663                    reloc = Some((sym, Reloc::RiscvGotHi20));
664                    inst = inst.set_rd(rd).set_imm20(0);*/
665                    todo!()
666                } else {
667                    self.last_error = Some(AsmError::InvalidOperand);
668                    return;
669                };
670            }
671
672            Encoding::RdJimm20 => {
673                if isign3 == enc_ops2!(Reg, Imm) {
674                    let rd = ops[0].id();
675                    let imm = ops[1].as_::<Imm>().value() as i32;
676                    inst = inst.set_rd(rd).set_jimm20(imm);
677                } else if isign3 == enc_ops2!(Reg, Label) {
678                    let rd = ops[0].id();
679                    label_use = Some((ops[0], LabelUse::RVJal20));
680                    inst = inst.set_rd(rd).set_jimm20(0);
681                } else if isign3 == enc_ops2!(Reg, Sym) {
682                    let rd = ops[0].id();
683                    let sym = ops[1].as_::<Sym>();
684
685                    reloc = Some((sym, Reloc::RiscvGotHi20));
686                    inst = inst.set_rd(rd).set_jimm20(0);
687                    todo!()
688                } else {
689                    self.last_error = Some(AsmError::InvalidOperand);
690                    return;
691                };
692            }
693
694            Encoding::RdN0CImm6loCImm6hi => {
695                short = true;
696                if isign3 == enc_ops2!(Reg, Imm) {
697                    let rd = ops[0].id();
698                    let imm = ops[1].as_::<Imm>().value() as i32;
699                    inst = inst.set_rd_n0(rd).set_c_imm6lohi(imm);
700                } else {
701                    self.last_error = Some(AsmError::InvalidOperand);
702                    return;
703                }
704            }
705
706            Encoding::RdN0CRs2N0 => {
707                short = true;
708                if isign3 == enc_ops2!(Reg, Reg) {
709                    let rd = ops[0].id();
710                    let rs1 = ops[1].id();
711                    inst = inst.set_rd_n0(rd).set_c_rs2(rs1);
712                } else {
713                    self.last_error = Some(AsmError::InvalidOperand);
714                    return;
715                }
716            }
717
718            Encoding::RdN0CUimm8sphiCUimm8splo => {
719                short = true;
720                if isign3 == enc_ops2!(Reg, Imm) {
721                    let rd = ops[0].id();
722                    let imm = ops[1].as_::<Imm>().value() as i32;
723                    inst = inst.set_rd_n0(rd).set_c_uimm8splohi(imm as _);
724                } else {
725                    self.last_error = Some(AsmError::InvalidOperand);
726                    return;
727                }
728            }
729
730            Encoding::RdN0CUimm9sphiCUimm9splo => {
731                short = true;
732                if isign3 == enc_ops2!(Reg, Imm) {
733                    let rd = ops[0].id();
734                    let imm = ops[1].as_::<Imm>().value() as i32;
735                    inst = inst.set_rd_n0(rd).set_c_uimm9splohi(imm as _);
736                } else {
737                    self.last_error = Some(AsmError::InvalidOperand);
738                    return;
739                }
740            }
741
742            Encoding::RdN2CNzimm18hiCNzimm18lo => {
743                short = true;
744                if isign3 == enc_ops2!(Reg, Imm) {
745                    let rd = ops[0].id();
746                    let imm = ops[1].as_::<Imm>().value() as i32;
747                    if imm == 0 {
748                        self.last_error = Some(AsmError::InvalidOperand);
749                        return;
750                    } else {
751                        inst = inst.set_rd_n2(rd).set_c_nzimm18lohi(imm);
752                    }
753                } else {
754                    self.last_error = Some(AsmError::InvalidOperand);
755                    return;
756                }
757            }
758
759            Encoding::RdPCNzuimm10 => {
760                if isign3 == enc_ops2!(Reg, Imm) {
761                    let rd = ops[0].id();
762                    let imm = ops[1].as_::<Imm>().value() as i32;
763                    inst = inst.set_rd_p(rd).set_c_nzimm10lohi(imm);
764                } else {
765                    self.last_error = Some(AsmError::InvalidOperand);
766                    return;
767                }
768            }
769
770            Encoding::RdPRs1PCUimm1 => {
771                if isign3 == enc_ops2!(Reg, Reg) {
772                    let rd = ops[0].id();
773                    let rs1 = ops[1].id();
774                    let imm = ops[2].as_::<Imm>().value() as i32;
775
776                    inst = inst.set_rd_p(rd).set_rs1_p(rs1).set_c_uimm1(imm as _);
777                } else {
778                    self.last_error = Some(AsmError::InvalidOperand);
779                    return;
780                }
781            }
782
783            Encoding::RdPRs1PCUimm2 => {
784                if isign3 == enc_ops2!(Reg, Reg) {
785                    let rd = ops[0].id();
786                    let rs1 = ops[1].id();
787                    let imm = ops[2].as_::<Imm>().value() as i32;
788
789                    inst = inst.set_rd_p(rd).set_rs1_p(rs1).set_c_uimm2(imm as _);
790                } else {
791                    self.last_error = Some(AsmError::InvalidOperand);
792                    return;
793                }
794            }
795
796            Encoding::RdPRs1PCUimm7loCUimm7hi => {
797                if isign3 == enc_ops2!(Reg, Reg) {
798                    let rd = ops[0].id();
799                    let rs1 = ops[1].id();
800                    let imm = ops[2].as_::<Imm>().value() as i32;
801                    inst = inst.set_rd(rd).set_rs1(rs1).set_c_uimm7lohi(imm as _);
802                } else {
803                    self.last_error = Some(AsmError::InvalidOperand);
804                    return;
805                }
806            }
807
808            Encoding::RdPRs1PCUimm8loCUimm8hi => {
809                if isign3 == enc_ops2!(Reg, Reg) {
810                    let rd = ops[0].id();
811                    let rs1 = ops[1].id();
812                    let imm = ops[2].as_::<Imm>().value() as i32;
813                    inst = inst.set_rd(rd).set_rs1(rs1).set_c_uimm8lohi(imm as _);
814                } else {
815                    self.last_error = Some(AsmError::InvalidOperand);
816                    return;
817                }
818            }
819
820            Encoding::RdRs1 => {
821                if isign3 == enc_ops2!(Reg, Reg) {
822                    let rd = ops[0].id();
823                    let rs1 = ops[1].id();
824                    inst = inst.set_rd(rd).set_rs1(rs1);
825                } else {
826                    self.last_error = Some(AsmError::InvalidOperand);
827                    return;
828                }
829            }
830
831            Encoding::RdRs1AqRl => {
832                if isign3 == enc_ops3!(Reg, Reg, Imm) {
833                    let rd = ops[0].id();
834                    let rs1 = ops[1].id();
835                    let imm = ops[2].as_::<Imm>().value() as i32;
836                    inst = inst.set_rd(rd).set_rs1(rs1).set_aqrl(imm as _);
837                } else {
838                    self.last_error = Some(AsmError::InvalidOperand);
839                    return;
840                }
841            }
842
843            Encoding::RdRs1Csr => {
844                if isign3 == enc_ops3!(Reg, Reg, Imm) {
845                    let rd = ops[0].id();
846                    let rs1 = ops[1].id();
847                    let imm = ops[2].as_::<Imm>().value() as i32;
848                    inst = inst.set_rd(rd).set_rs1(rs1).set_csr(imm as _);
849                } else {
850                    self.last_error = Some(AsmError::InvalidOperand);
851                    return;
852                }
853            }
854
855            Encoding::RdRs1Imm12 => {
856                if isign3 == enc_ops3!(Reg, Reg, Imm) {
857                    let rd = ops[0].id();
858                    let rs1 = ops[1].id();
859                    let imm = ops[2].as_::<Imm>().value() as i32;
860                    inst = inst.set_rd(rd).set_rs1(rs1).set_imm12(imm);
861                } else if isign3 == enc_ops3!(Reg, Reg, Label) {
862                    let rd = ops[0].id();
863                    let rs1 = ops[1].id();
864                    let off = self.buffer.cur_offset();
865                    self.buffer
866                        .use_label_at_offset(off, ops[2].as_(), LabelUse::RVPCRelHi20);
867                    self.auipc(*ops[0], imm(0));
868                    label_use = Some((ops[2], LabelUse::RVPCRelLo12I));
869                    inst = inst.set_rd(rd).set_rs1(rs1).set_imm12(0);
870                } else {
871                    self.last_error = Some(AsmError::InvalidOperand);
872                    return;
873                }
874            }
875
876            Encoding::RdRs1N0 => {
877                short = true;
878                if isign3 == enc_ops2!(Reg, Reg) {
879                    let _rd = ops[0].id();
880                    let _rs1 = ops[1].id();
881                    todo!()
882                } else {
883                    self.last_error = Some(AsmError::InvalidOperand);
884                    return;
885                }
886            }
887
888            Encoding::RdRs1Rm => {
889                if isign3 == enc_ops3!(Reg, Reg, Imm) {
890                    let rd = ops[0].id();
891                    let rs1 = ops[1].id();
892                    let rm = ops[2].as_::<Imm>().value() as i32;
893                    inst = inst.set_rd(rd).set_rs1(rs1).set_rm(rm as _);
894                } else {
895                    self.last_error = Some(AsmError::InvalidOperand);
896                    return;
897                }
898            }
899            Encoding::RdRs1Rnum => {
900                if isign3 == enc_ops3!(Reg, Reg, Imm) {
901                    let rd = ops[0].id();
902                    let rs1 = ops[1].id();
903                    let rm = ops[2].as_::<Imm>().value() as i32;
904                    inst = inst.set_rd(rd).set_rs1(rs1).set_rnum(rm as _);
905                } else {
906                    self.last_error = Some(AsmError::InvalidOperand);
907                    return;
908                }
909            }
910
911            Encoding::RdRs1Rs2 => {
912                if isign3 == enc_ops3!(Reg, Reg, Reg) {
913                    let rd = ops[0].id();
914                    let rs1 = ops[1].id();
915                    let rs2 = ops[2].id();
916                    inst = inst.set_rd(rd).set_rs1(rs1).set_rs2(rs2);
917                } else {
918                    self.last_error = Some(AsmError::InvalidOperand);
919                    return;
920                }
921            }
922
923            Encoding::RdRs1Rs2AqRl => {
924                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
925                    let rd = ops[0].id();
926                    let rs1 = ops[1].id();
927                    let rs2 = ops[2].id();
928                    let imm = ops[3].as_::<Imm>().value() as i32;
929                    inst = inst.set_rd(rd).set_rs1(rs1).set_rs2(rs2).set_aqrl(imm as _);
930                } else {
931                    self.last_error = Some(AsmError::InvalidOperand);
932                    return;
933                }
934            }
935
936            Encoding::RdRs1Rs2Bs => {
937                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
938                    let rd = ops[0].id();
939                    let rs1 = ops[1].id();
940                    let rs2 = ops[2].id();
941                    let imm = ops[3].as_::<Imm>().value() as i32;
942                    inst = inst.set_rd(rd).set_rs1(rs1).set_rs2(rs2).set_bs(imm as _);
943                } else {
944                    self.last_error = Some(AsmError::InvalidOperand);
945                    return;
946                }
947            }
948
949            Encoding::RdRs1Rs2EqRs1 => {
950                if isign3 == enc_ops3!(Reg, Reg, Reg) {
951                    let rd = ops[0].id();
952                    let rs1 = ops[1].id();
953                    let rs2 = ops[2].id();
954                    inst = inst.set_rd(rd).set_rs1(rs1).set_rs2_eq_rs1(rs2);
955                } else {
956                    self.last_error = Some(AsmError::InvalidOperand);
957                    return;
958                }
959            }
960
961            Encoding::RdRs1Rs2Rm => {
962                if isign4 == enc_ops4!(Reg, Reg, Reg, Imm) {
963                    let rd = ops[0].id();
964                    let rs1 = ops[1].id();
965                    let rs2 = ops[2].id();
966                    let rm = ops[3].as_::<Imm>().value() as i32;
967                    inst = inst.set_rd(rd).set_rs1(rs1).set_rs2(rs2).set_rm(rm as _);
968                } else {
969                    self.last_error = Some(AsmError::InvalidOperand);
970                    return;
971                }
972            }
973
974            Encoding::RdRs1Rs2Rs3Rm => {
975                if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) && ops[4].op_type() == OperandType::Imm {
976                    let rd = ops[0].id();
977                    let rs1 = ops[1].id();
978                    let rs2 = ops[2].id();
979                    let rs3 = ops[3].id();
980                    let rm = ops[4].as_::<Imm>().value() as i32;
981
982                    inst = inst
983                        .set_rd(rd)
984                        .set_rs1(rs1)
985                        .set_rs2(rs2)
986                        .set_rs3(rs3)
987                        .set_rm(rm as _);
988                } else {
989                    self.last_error = Some(AsmError::InvalidOperand);
990                    return;
991                }
992            }
993
994            Encoding::RdRs1Shamtw => {
995                if isign3 == enc_ops3!(Reg, Reg, Imm) {
996                    let rd = ops[0].id();
997                    let rs1 = ops[1].id();
998                    let shamt = ops[2].as_::<Imm>().value() as i32;
999                    inst = inst.set_rd(rd).set_rs1(rs1).set_shamtw(shamt as _);
1000                } else {
1001                    self.last_error = Some(AsmError::InvalidOperand);
1002                    return;
1003                }
1004            }
1005            Encoding::RdRs2 => {
1006                if isign3 == enc_ops2!(Reg, Reg) {
1007                    let rd = ops[0].id();
1008                    let rs1 = ops[1].id();
1009                    inst = inst.set_rd(rd).set_rs1(rs1);
1010                } else {
1011                    self.last_error = Some(AsmError::InvalidOperand);
1012                    return;
1013                }
1014            }
1015
1016            Encoding::RdZimm => {
1017                if isign3 == enc_ops2!(Reg, Imm) {
1018                    let rd = ops[0].id();
1019                    let imm = ops[1].as_::<Imm>().value() as i32;
1020                    inst = inst.set_rd(rd).set_zimm(imm);
1021                } else {
1022                    self.last_error = Some(AsmError::InvalidOperand);
1023                    return;
1024                }
1025            }
1026
1027            Encoding::Rs1 => {
1028                if isign3 == enc_ops1!(Reg) {
1029                    let rs1 = ops[0].id();
1030                    inst = inst.set_rs1(rs1);
1031                } else {
1032                    self.last_error = Some(AsmError::InvalidOperand);
1033                    return;
1034                }
1035            }
1036
1037            Encoding::Rs1Csr => {
1038                if isign3 == enc_ops2!(Reg, Imm) {
1039                    let rs1 = ops[0].id();
1040                    let csr = ops[1].as_::<Imm>().value() as i32;
1041                    inst = inst.set_rs1(rs1).set_csr(csr as _);
1042                } else {
1043                    self.last_error = Some(AsmError::InvalidOperand);
1044                    return;
1045                }
1046            }
1047
1048            Encoding::Rs1Imm12hi => {
1049                if isign3 == enc_ops2!(Reg, Imm) {
1050                    let rs1 = ops[0].id();
1051                    let imm = ops[1].as_::<Imm>().value() as i32;
1052                    inst = inst.set_rs1(rs1).set_imm12hi_raw(imm as _);
1053                } else {
1054                    self.last_error = Some(AsmError::InvalidOperand);
1055                    return;
1056                }
1057            }
1058
1059            Encoding::Rs1N0 => {
1060                short = true;
1061                if isign3 == enc_ops1!(Reg) {
1062                    let rs1 = ops[0].id();
1063                    inst = inst.set_rs1_n0(rs1);
1064                } else {
1065                    self.last_error = Some(AsmError::InvalidOperand);
1066                    return;
1067                }
1068            }
1069
1070            Encoding::Rs1PCBimm9loCBimm9hi => {
1071                short = true;
1072                if isign3 == enc_ops2!(Reg, Imm) {
1073                    let rs1 = ops[0].id();
1074                    let imm = ops[1].as_::<Imm>().value();
1075
1076                    inst = inst.set_rs1(rs1).set_c_bimm9lohi(imm as _);
1077                } else if isign3 == enc_ops2!(Reg, Label) {
1078                    let rs1 = ops[0].id();
1079                    label_use = Some((ops[1], LabelUse::RVCB9));
1080                    inst = inst.set_rs1(rs1).set_c_bimm9lohi(0);
1081                } else {
1082                    self.last_error = Some(AsmError::InvalidOperand);
1083                    return;
1084                }
1085            }
1086
1087            Encoding::Rs1PRs2PCUimm7loCUimm7hi => {
1088                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1089                    let rs1 = ops[0].id();
1090                    let rs2 = ops[1].id();
1091                    let imm = ops[2].as_::<Imm>().value() as i32;
1092                    inst = inst.set_rs1_p(rs1).set_rs2_p(rs2).set_c_uimm7lohi(imm as _);
1093                } else {
1094                    self.last_error = Some(AsmError::InvalidOperand);
1095                    return;
1096                }
1097            }
1098
1099            Encoding::Rs1PRs2PCUimm8loCUimm8hi => {
1100                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1101                    let rs1 = ops[0].id();
1102                    let rs2 = ops[1].id();
1103                    let imm = ops[2].as_::<Imm>().value() as i32;
1104                    inst = inst.set_rs1_p(rs1).set_rs2_p(rs2).set_c_uimm8lohi(imm as _);
1105                } else {
1106                    self.last_error = Some(AsmError::InvalidOperand);
1107                    return;
1108                }
1109            }
1110
1111            Encoding::Rs1PRs2PCUimm8hiCUimm8lo => {
1112                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1113                    let rs1 = ops[0].id();
1114                    let rs2 = ops[1].id();
1115                    let imm = ops[2].as_::<Imm>().value() as i32;
1116                    inst = inst.set_rs1_p(rs1).set_rs2_p(rs2).set_c_uimm8lohi(imm as _);
1117                } else {
1118                    self.last_error = Some(AsmError::InvalidOperand);
1119                    return;
1120                }
1121            }
1122
1123            Encoding::Rs1Rd => {
1124                if isign3 == enc_ops2!(Reg, Reg) {
1125                    let rd = ops[0].id();
1126                    let rs1 = ops[1].id();
1127
1128                    inst = inst.set_rd(rd).set_rs1(rs1);
1129                } else {
1130                    self.last_error = Some(AsmError::InvalidOperand);
1131                    return;
1132                }
1133            }
1134
1135            Encoding::Rs1Rs2 => {
1136                if isign3 == enc_ops2!(Reg, Reg) {
1137                    let rs1 = ops[0].id();
1138                    let rs2 = ops[1].id();
1139                    inst = inst.set_rs1(rs1).set_rs2(rs2);
1140                } else {
1141                    self.last_error = Some(AsmError::InvalidOperand);
1142                    return;
1143                }
1144            }
1145
1146            Encoding::Rs1Vd => {
1147                if isign3 == enc_ops2!(Reg, Reg) {
1148                    let rs1 = ops[1].id();
1149                    let vd = ops[0].id();
1150                    inst = inst.set_vd(vd).set_rs1(rs1);
1151                } else {
1152                    self.last_error = Some(AsmError::InvalidOperand);
1153                    return;
1154                }
1155            }
1156            Encoding::Rs1Vs3 => {
1157                if isign3 == enc_ops2!(Reg, Reg) {
1158                    let rs1 = ops[1].id();
1159                    let vs3 = ops[0].id();
1160                    inst = inst.set_rs1(rs1).set_vs3(vs3);
1161                } else {
1162                    self.last_error = Some(AsmError::InvalidOperand);
1163                    return;
1164                }
1165            }
1166
1167            Encoding::Rs2PRs1PCUimm1 => {
1168                short = true;
1169                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1170                    let rs1 = ops[0].id();
1171                    let rs2 = ops[1].id();
1172                    let imm = ops[2].as_::<Imm>().value() as i32;
1173                    inst = inst.set_rs1_p(rs1).set_rs2_p(rs2).set_c_uimm1(imm as _);
1174                } else {
1175                    self.last_error = Some(AsmError::InvalidOperand);
1176                    return;
1177                }
1178            }
1179
1180            Encoding::Rs2PRs1PCUimm2 => {
1181                short = true;
1182                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1183                    let rs1 = ops[0].id();
1184                    let rs2 = ops[1].id();
1185                    let imm = ops[2].as_::<Imm>().value() as i32;
1186                    inst = inst.set_rs1_p(rs1).set_rs2_p(rs2).set_c_uimm2(imm as _);
1187                } else {
1188                    self.last_error = Some(AsmError::InvalidOperand);
1189                    return;
1190                }
1191            }
1192            Encoding::Rs2Rs1Rd => {
1193                if isign3 == enc_ops3!(Reg, Reg, Reg) {
1194                    let rd = ops[0].id();
1195                    let rs1 = ops[1].id();
1196                    let rs2 = ops[2].id();
1197
1198                    inst = inst.set_rd(rd).set_rs1(rs1).set_rs2(rs2);
1199                } else {
1200                    self.last_error = Some(AsmError::InvalidOperand);
1201                    return;
1202                }
1203            }
1204
1205            Encoding::Simm5Vd => {
1206                if isign3 == enc_ops2!(Reg, Imm) {
1207                    let vd = ops[0].id();
1208                    let imm = ops[1].as_::<Imm>().value() as i8;
1209                    inst = inst.set_vd(vd).set_simm5(imm as _);
1210                } else {
1211                    self.last_error = Some(AsmError::InvalidOperand);
1212                    return;
1213                }
1214            }
1215
1216            Encoding::VmVs2Rd => {
1217                if isign3 == enc_ops3!(Reg, Reg, Reg) {
1218                    let rd = ops[0].id();
1219                    let vs2 = ops[1].id();
1220                    let vm = ops[2].id();
1221                    inst = inst.set_rd(rd).set_vs2(vs2).set_vm(vm);
1222                } else {
1223                    self.last_error = Some(AsmError::InvalidOperand);
1224                    return;
1225                }
1226            }
1227
1228            Encoding::VmVd => {
1229                if isign3 == enc_ops2!(Reg, Reg) {
1230                    let vd = ops[0].id();
1231                    let vm = ops[1].id();
1232                    inst = inst.set_vd(vd).set_vm(vm);
1233                } else {
1234                    self.last_error = Some(AsmError::InvalidOperand);
1235                    return;
1236                }
1237            }
1238
1239            Encoding::VmVs2Rs1Vd => {
1240                if isign3 == enc_ops4!(Reg, Reg, Reg, Reg) {
1241                    let rs1 = ops[2].id();
1242                    let vs2 = ops[1].id();
1243                    let vm = ops[3].id();
1244                    let vd = ops[0].id();
1245                    inst = inst.set_vd(vd).set_vm(vm).set_rs1(rs1).set_vs2(vs2);
1246                } else {
1247                    self.last_error = Some(AsmError::InvalidOperand);
1248                    return;
1249                }
1250            }
1251
1252            Encoding::VmVs2Simm5Vd => {
1253                if isign3 == enc_ops4!(Reg, Reg, Imm, Reg) {
1254                    let simm5 = ops[2].as_::<Imm>().value() as i32;
1255                    let vs2 = ops[1].id();
1256                    let vm = ops[3].id();
1257                    let vd = ops[0].id();
1258                    inst = inst.set_vd(vd).set_vm(vm).set_simm5(simm5).set_vs2(vs2);
1259                } else {
1260                    self.last_error = Some(AsmError::InvalidOperand);
1261                    return;
1262                }
1263            }
1264
1265            Encoding::VmVs2Vd => {
1266                if isign3 == enc_ops3!(Reg, Reg, Reg) {
1267                    let vd = ops[0].id();
1268                    let vs2 = ops[1].id();
1269                    let vm = ops[2].id();
1270
1271                    inst = inst.set_vd(vd).set_vs2(vs2).set_vm(vm);
1272                } else {
1273                    self.last_error = Some(AsmError::InvalidOperand);
1274                    return;
1275                }
1276            }
1277
1278            Encoding::VmVs2Vs1Vd => {
1279                if isign4 == enc_ops4!(Reg, Reg, Reg, Reg) {
1280                    let vd = ops[0].id();
1281                    let vs1 = ops[1].id();
1282                    let vs2 = ops[2].id();
1283                    let vm = ops[3].id();
1284                    inst = inst.set_vd(vd).set_vs1(vs1).set_vs2(vs2).set_vm(vm);
1285                } else {
1286                    self.last_error = Some(AsmError::InvalidOperand);
1287                    return;
1288                }
1289            }
1290
1291            Encoding::VmVs2Zimm5Vd => {
1292                if isign4 == enc_ops4!(Reg, Reg, Imm, Reg) {
1293                    let vd = ops[0].id();
1294                    let vs2 = ops[1].id();
1295                    let vm = ops[3].id();
1296                    let zimm5 = ops[2].as_::<Imm>().value() as i8;
1297                    inst = inst
1298                        .set_vd(vd)
1299                        .set_vs2(vs2)
1300                        .set_vm(vm)
1301                        .set_zimm5(zimm5 as _);
1302                } else {
1303                    self.last_error = Some(AsmError::InvalidOperand);
1304                    return;
1305                }
1306            }
1307
1308            Encoding::Vs1Vd => {
1309                if isign3 == enc_ops2!(Reg, Reg) {
1310                    let vd = ops[0].id();
1311                    let vs1 = ops[1].id();
1312                    inst = inst.set_vd(vd).set_vs1(vs1);
1313                } else {
1314                    self.last_error = Some(AsmError::InvalidOperand);
1315                    return;
1316                }
1317            }
1318
1319            Encoding::Vs2Rd => {
1320                if isign3 == enc_ops2!(Reg, Reg) {
1321                    let rd = ops[0].id();
1322                    let vs2 = ops[1].id();
1323                    inst = inst.set_rd(rd).set_vs2(vs2);
1324                } else {
1325                    self.last_error = Some(AsmError::InvalidOperand);
1326                    return;
1327                }
1328            }
1329
1330            Encoding::Vs2Rs1Vd => {
1331                if isign4 == enc_ops3!(Reg, Reg, Reg) {
1332                    let rs1 = ops[1].id();
1333                    let vs2 = ops[2].id();
1334                    let vd = ops[0].id();
1335                    inst = inst.set_vd(vd).set_vs2(vs2).set_rs1(rs1);
1336                } else {
1337                    self.last_error = Some(AsmError::InvalidOperand);
1338                    return;
1339                }
1340            }
1341
1342            Encoding::Vs2Simm5Vd => {
1343                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1344                    let vd = ops[0].id();
1345                    let vs2 = ops[1].id();
1346                    let imm = ops[2].as_::<Imm>().value();
1347
1348                    inst = inst.set_vd(vd).set_vs2(vs2).set_simm5(imm as _);
1349                } else {
1350                    self.last_error = Some(AsmError::InvalidOperand);
1351                    return;
1352                }
1353            }
1354
1355            Encoding::Vs2Vd => {
1356                if isign3 == enc_ops2!(Reg, Reg) {
1357                    let vd = ops[0].id();
1358                    let vs2 = ops[1].id();
1359                    inst = inst.set_vd(vd).set_vs2(vs2);
1360                } else {
1361                    self.last_error = Some(AsmError::InvalidOperand);
1362                    return;
1363                }
1364            }
1365
1366            Encoding::Vs2Vs1Vd => {
1367                if isign4 == enc_ops3!(Reg, Reg, Reg) {
1368                    let vd = ops[0].id();
1369                    let vs1 = ops[1].id();
1370                    let vs2 = ops[2].id();
1371
1372                    inst = inst.set_vd(vd).set_vs1(vs1).set_vs2(vs2);
1373                } else {
1374                    self.last_error = Some(AsmError::InvalidOperand);
1375                    return;
1376                }
1377            }
1378
1379            Encoding::Vs2Zimm5Vd => {
1380                if isign3 == enc_ops3!(Reg, Imm, Reg) {
1381                    let vd = ops[0].id();
1382                    let vs2 = ops[1].id();
1383                    let zimm5 = ops[2].as_::<Imm>().value() as i8;
1384                    inst = inst.set_vd(vd).set_vs2(vs2).set_zimm5(zimm5 as _);
1385                } else {
1386                    self.last_error = Some(AsmError::InvalidOperand);
1387                    return;
1388                }
1389            }
1390
1391            Encoding::Zimm10ZimmRd => {
1392                if isign3 == enc_ops3!(Reg, Imm, Imm) {
1393                    let rd = ops[0].id();
1394                    let uimm = ops[1].as_::<Imm>().value() as i8;
1395                    let vtypei = ops[2].as_::<Imm>().value() as i8;
1396                    inst = inst.set_rd(rd).set_zimm10(vtypei as _).set_zimm(uimm as _);
1397                } else {
1398                    self.last_error = Some(AsmError::InvalidOperand);
1399                    return;
1400                }
1401            }
1402
1403            Encoding::Zimm11Rs1Rd => {
1404                if isign3 == enc_ops3!(Reg, Reg, Imm) {
1405                    let rd = ops[0].id();
1406                    let rs1 = ops[1].id();
1407                    let imm = ops[2].as_::<Imm>().value() as i32;
1408                    inst = inst.set_rd(rd).set_rs1(rs1).set_zimm11(imm);
1409                } else {
1410                    self.last_error = Some(AsmError::InvalidOperand);
1411                    return;
1412                }
1413            }
1414
1415            Encoding::Zimm6HiVmVs2Zimm6loVd => {
1416                if isign4 == enc_ops4!(Reg, Reg, Imm, Reg) {
1417                    let vd = ops[0].id();
1418                    let vs2 = ops[1].id();
1419                    let imm = ops[2].as_::<Imm>().value();
1420                    let vm = ops[3].id();
1421
1422                    inst = inst
1423                        .set_vd(vd)
1424                        .set_vs2(vs2)
1425                        .set_zimm6lohi(imm as _)
1426                        .set_vm(vm);
1427                } else {
1428                    self.last_error = Some(AsmError::InvalidOperand);
1429                    return;
1430                }
1431            }
1432            Encoding::RdRs1N0CNzimm6loCNzimm6hi => {
1433                short = true;
1434                if isign3 == enc_ops2!(Reg, Imm) {
1435                    let rd = ops[0].id();
1436                    let imm = ops[1].as_::<Imm>().value() as i32;
1437                    if imm == 0 {
1438                        self.last_error = Some(AsmError::InvalidOperand);
1439                        return;
1440                    } else {
1441                        inst = inst.set_rd_n0(rd).set_c_nzimm6lohi(imm);
1442                    }
1443                } else {
1444                    self.last_error = Some(AsmError::InvalidOperand);
1445                    return;
1446                }
1447            }
1448            _ => todo!("unimplemented encoding: {encoding:?}"),
1449        }
1450        let offset = self.buffer.cur_offset();
1451        if let Some((label, kind)) = label_use {
1452            self.buffer
1453                .use_label_at_offset(offset, label.as_::<Label>(), kind);
1454        }
1455
1456        if let Some((sym, kind)) = reloc {
1457            let target = RelocTarget::Sym(sym);
1458            self.buffer.add_reloc_at_offset(offset, kind, target, 0);
1459        }
1460
1461        if short {
1462            self.buffer.put2(inst.value as u16);
1463        } else {
1464            self.buffer.put4(inst.value);
1465        }
1466    }
1467}
1468
1469impl super::emitter::EmitterExplicit for Assembler<'_> {}