Skip to main content

asmkit/riscv/
assembler.rs

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