xref: /openbmc/qemu/disas/riscv-xthead.c (revision e9206163)
1 /*
2  * QEMU RISC-V Disassembler for xthead.
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  */
6 
7 #include "qemu/osdep.h"
8 #include "disas/riscv.h"
9 #include "disas/riscv-xthead.h"
10 
11 typedef enum {
12     /* 0 is reserved for rv_op_illegal. */
13     /* XTheadBa */
14     rv_op_th_addsl = 1,
15     /* XTheadBb */
16     rv_op_th_srri,
17     rv_op_th_srriw,
18     rv_op_th_ext,
19     rv_op_th_extu,
20     rv_op_th_ff0,
21     rv_op_th_ff1,
22     rv_op_th_rev,
23     rv_op_th_revw,
24     rv_op_th_tstnbz,
25     /* XTheadBs */
26     rv_op_th_tst,
27     /* XTheadCmo */
28     rv_op_th_dcache_call,
29     rv_op_th_dcache_ciall,
30     rv_op_th_dcache_iall,
31     rv_op_th_dcache_cpa,
32     rv_op_th_dcache_cipa,
33     rv_op_th_dcache_ipa,
34     rv_op_th_dcache_cva,
35     rv_op_th_dcache_civa,
36     rv_op_th_dcache_iva,
37     rv_op_th_dcache_csw,
38     rv_op_th_dcache_cisw,
39     rv_op_th_dcache_isw,
40     rv_op_th_dcache_cpal1,
41     rv_op_th_dcache_cval1,
42     rv_op_th_icache_iall,
43     rv_op_th_icache_ialls,
44     rv_op_th_icache_ipa,
45     rv_op_th_icache_iva,
46     rv_op_th_l2cache_call,
47     rv_op_th_l2cache_ciall,
48     rv_op_th_l2cache_iall,
49     /* XTheadCondMov */
50     rv_op_th_mveqz,
51     rv_op_th_mvnez,
52     /* XTheadFMemIdx */
53     rv_op_th_flrd,
54     rv_op_th_flrw,
55     rv_op_th_flurd,
56     rv_op_th_flurw,
57     rv_op_th_fsrd,
58     rv_op_th_fsrw,
59     rv_op_th_fsurd,
60     rv_op_th_fsurw,
61     /* XTheadFmv */
62     rv_op_th_fmv_hw_x,
63     rv_op_th_fmv_x_hw,
64     /* XTheadMac */
65     rv_op_th_mula,
66     rv_op_th_mulah,
67     rv_op_th_mulaw,
68     rv_op_th_muls,
69     rv_op_th_mulsw,
70     rv_op_th_mulsh,
71     /* XTheadMemIdx */
72     rv_op_th_lbia,
73     rv_op_th_lbib,
74     rv_op_th_lbuia,
75     rv_op_th_lbuib,
76     rv_op_th_lhia,
77     rv_op_th_lhib,
78     rv_op_th_lhuia,
79     rv_op_th_lhuib,
80     rv_op_th_lwia,
81     rv_op_th_lwib,
82     rv_op_th_lwuia,
83     rv_op_th_lwuib,
84     rv_op_th_ldia,
85     rv_op_th_ldib,
86     rv_op_th_sbia,
87     rv_op_th_sbib,
88     rv_op_th_shia,
89     rv_op_th_shib,
90     rv_op_th_swia,
91     rv_op_th_swib,
92     rv_op_th_sdia,
93     rv_op_th_sdib,
94     rv_op_th_lrb,
95     rv_op_th_lrbu,
96     rv_op_th_lrh,
97     rv_op_th_lrhu,
98     rv_op_th_lrw,
99     rv_op_th_lrwu,
100     rv_op_th_lrd,
101     rv_op_th_srb,
102     rv_op_th_srh,
103     rv_op_th_srw,
104     rv_op_th_srd,
105     rv_op_th_lurb,
106     rv_op_th_lurbu,
107     rv_op_th_lurh,
108     rv_op_th_lurhu,
109     rv_op_th_lurw,
110     rv_op_th_lurwu,
111     rv_op_th_lurd,
112     rv_op_th_surb,
113     rv_op_th_surh,
114     rv_op_th_surw,
115     rv_op_th_surd,
116     /* XTheadMemPair */
117     rv_op_th_ldd,
118     rv_op_th_lwd,
119     rv_op_th_lwud,
120     rv_op_th_sdd,
121     rv_op_th_swd,
122     /* XTheadSync */
123     rv_op_th_sfence_vmas,
124     rv_op_th_sync,
125     rv_op_th_sync_i,
126     rv_op_th_sync_is,
127     rv_op_th_sync_s,
128 } rv_xthead_op;
129 
130 const rv_opcode_data xthead_opcode_data[] = {
131     { "th.illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 },
132     /* XTheadBa */
133     { "th.addsl", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
134     /* XTheadBb */
135     { "th.srri", rv_codec_r2_imm6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
136     { "th.srriw", rv_codec_r2_imm5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
137     { "th.ext", rv_codec_r2_immhl, rv_fmt_rd_rs1_immh_imml, NULL, 0, 0, 0 },
138     { "th.extu", rv_codec_r2_immhl, rv_fmt_rd_rs1_immh_imml, NULL, 0, 0, 0 },
139     { "th.ff0", rv_codec_r2, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
140     { "th.ff1", rv_codec_r2, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
141     { "th.rev", rv_codec_r2, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
142     { "th.revw", rv_codec_r2, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
143     { "th.tstnbz", rv_codec_r2, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
144     /* XTheadBs */
145     { "th.tst", rv_codec_r2_imm6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
146     /* XTheadCmo */
147     { "th.dcache.call", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
148     { "th.dcache.ciall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
149     { "th.dcache.iall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
150     { "th.dcache.cpa", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
151     { "th.dcache.cipa", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
152     { "th.dcache.ipa", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
153     { "th.dcache.cva", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
154     { "th.dcache.civa", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
155     { "th.dcache.iva", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
156     { "th.dcache.csw", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
157     { "th.dcache.cisw", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
158     { "th.dcache.isw", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
159     { "th.dcache.cpal1", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
160     { "th.dcache.cval1", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
161     { "th.icache.iall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
162     { "th.icache.ialls", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
163     { "th.icache.ipa", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
164     { "th.icache.iva", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
165     { "th.l2cache.call", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
166     { "th.l2cache.ciall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
167     { "th.l2cache.iall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
168     /* XTheadCondMov */
169     { "th.mveqz", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
170     { "th.mvnez", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
171     /* XTheadFMemIdx */
172     { "th.flrd", rv_codec_r_imm2, rv_fmt_frd_rs1_rs2_imm, NULL, 0, 0, 0 },
173     { "th.flrw", rv_codec_r_imm2, rv_fmt_frd_rs1_rs2_imm, NULL, 0, 0, 0 },
174     { "th.flurd", rv_codec_r_imm2, rv_fmt_frd_rs1_rs2_imm, NULL, 0, 0, 0 },
175     { "th.flurw", rv_codec_r_imm2, rv_fmt_frd_rs1_rs2_imm, NULL, 0, 0, 0 },
176     { "th.fsrd", rv_codec_r_imm2, rv_fmt_frd_rs1_rs2_imm, NULL, 0, 0, 0 },
177     { "th.fsrw", rv_codec_r_imm2, rv_fmt_frd_rs1_rs2_imm, NULL, 0, 0, 0 },
178     { "th.fsurd", rv_codec_r_imm2, rv_fmt_frd_rs1_rs2_imm, NULL, 0, 0, 0 },
179     { "th.fsurw", rv_codec_r_imm2, rv_fmt_frd_rs1_rs2_imm, NULL, 0, 0, 0 },
180     /* XTheadFmv */
181     { "th.fmv.hw.x", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
182     { "th.fmv.x.hw", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
183     /* XTheadMac */
184     { "th.mula", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
185     { "th.mulaw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
186     { "th.mulah", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
187     { "th.muls", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
188     { "th.mulsw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
189     { "th.mulsh", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
190     /* XTheadMemIdx */
191     { "th.lbia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
192     { "th.lbib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml, NULL, 0, 0, 0 },
193     { "th.lbuia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
194     { "th.lbuib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
195     { "th.lhia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
196     { "th.lhib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
197     { "th.lhuia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
198     { "th.lhuib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
199     { "th.lwia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
200     { "th.lwib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
201     { "th.lwuia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
202     { "th.lwuib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
203     { "th.ldia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
204     { "th.ldib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
205     { "th.sbia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
206     { "th.sbib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
207     { "th.shia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
208     { "th.shib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
209     { "th.swia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
210     { "th.swib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
211     { "th.sdia", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
212     { "th.sdib", rv_codec_r2_imm2_imm5, rv_fmt_rd_rs1_immh_imml_addr, NULL, 0, 0, 0 },
213     { "th.lrb", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
214     { "th.lrbu", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
215     { "th.lrh", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
216     { "th.lrhu", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
217     { "th.lrw", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
218     { "th.lrwu", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
219     { "th.lrd", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
220     { "th.srb", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
221     { "th.srh", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
222     { "th.srw", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
223     { "th.srd", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
224     { "th.lurb", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
225     { "th.lurbu", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
226     { "th.lurh", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
227     { "th.lurhu", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
228     { "th.lurw", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
229     { "th.lurwu", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
230     { "th.lurd", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
231     { "th.surb", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
232     { "th.surh", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
233     { "th.surw", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
234     { "th.surd", rv_codec_r_imm2, rv_fmt_rd_rs1_rs2_imm, NULL, 0, 0, 0 },
235     /* XTheadMemPair */
236     { "th.ldd", rv_codec_r_imm2, rv_fmt_rd2_imm, NULL, 0, 0, 0 },
237     { "th.lwd", rv_codec_r_imm2, rv_fmt_rd2_imm, NULL, 0, 0, 0 },
238     { "th.lwud", rv_codec_r_imm2, rv_fmt_rd2_imm, NULL, 0, 0, 0 },
239     { "th.sdd", rv_codec_r_imm2, rv_fmt_rd2_imm, NULL, 0, 0, 0 },
240     { "th.swd", rv_codec_r_imm2, rv_fmt_rd2_imm, NULL, 0, 0, 0 },
241     /* XTheadSync */
242     { "th.sfence.vmas", rv_codec_r, rv_fmt_rs1_rs2, NULL, 0, 0, 0 },
243     { "th.sync", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
244     { "th.sync.i", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
245     { "th.sync.is", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
246     { "th.sync.s", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
247 };
248 
249 void decode_xtheadba(rv_decode *dec, rv_isa isa)
250 {
251     rv_inst inst = dec->inst;
252     rv_opcode op = rv_op_illegal;
253 
254     switch (((inst >> 0) & 0b11)) {
255     case 3:
256         switch (((inst >> 2) & 0b11111)) {
257         case 2:
258             /* custom-0 */
259             switch ((inst >> 12) & 0b111) {
260             case 1:
261                 switch ((inst >> 25) & 0b1111111) {
262                 case 0b0000000:
263                 case 0b0000001:
264                 case 0b0000010:
265                 case 0b0000011: op = rv_op_th_addsl; break;
266                 }
267                 break;
268             }
269             break;
270             /* custom-0 */
271         }
272         break;
273     }
274 
275     dec->op = op;
276 }
277 
278 void decode_xtheadbb(rv_decode *dec, rv_isa isa)
279 {
280     rv_inst inst = dec->inst;
281     rv_opcode op = rv_op_illegal;
282 
283     switch (((inst >> 0) & 0b11)) {
284     case 3:
285         switch (((inst >> 2) & 0b11111)) {
286         case 2:
287             /* custom-0 */
288             switch ((inst >> 12) & 0b111) {
289             case 1:
290                 switch ((inst >> 25) & 0b1111111) {
291                 case 0b0001010: op = rv_op_th_srriw; break;
292                 case 0b1000000:
293                     if (((inst >> 20) & 0b11111) == 0) {
294                         op = rv_op_th_tstnbz;
295                     }
296                     break;
297                 case 0b1000001:
298                     if (((inst >> 20) & 0b11111) == 0) {
299                         op = rv_op_th_rev;
300                     }
301                     break;
302                 case 0b1000010:
303                     if (((inst >> 20) & 0b11111) == 0) {
304                         op = rv_op_th_ff0;
305                     }
306                     break;
307                 case 0b1000011:
308                     if (((inst >> 20) & 0b11111) == 0) {
309                         op = rv_op_th_ff1;
310                     }
311                     break;
312                 case 0b1000100:
313                 case 0b1001000:
314                     if (((inst >> 20) & 0b11111) == 0) {
315                         op = rv_op_th_revw;
316                     }
317                     break;
318                 case 0b0000100:
319                 case 0b0000101: op = rv_op_th_srri; break;
320                 }
321                 break;
322             case 2: op = rv_op_th_ext; break;
323             case 3: op = rv_op_th_extu; break;
324             }
325             break;
326             /* custom-0 */
327         }
328         break;
329     }
330 
331     dec->op = op;
332 }
333 
334 void decode_xtheadbs(rv_decode *dec, rv_isa isa)
335 {
336     rv_inst inst = dec->inst;
337     rv_opcode op = rv_op_illegal;
338 
339     switch (((inst >> 0) & 0b11)) {
340     case 3:
341         switch (((inst >> 2) & 0b11111)) {
342         case 2:
343             /* custom-0 */
344             switch ((inst >> 12) & 0b111) {
345             case 1:
346                 switch ((inst >> 26) & 0b111111) {
347                 case 0b100010: op = rv_op_th_tst; break;
348                 }
349                 break;
350             }
351             break;
352             /* custom-0 */
353         }
354         break;
355     }
356 
357     dec->op = op;
358 }
359 
360 void decode_xtheadcmo(rv_decode *dec, rv_isa isa)
361 {
362     rv_inst inst = dec->inst;
363     rv_opcode op = rv_op_illegal;
364 
365     switch (((inst >> 0) & 0b11)) {
366     case 3:
367         switch (((inst >> 2) & 0b11111)) {
368         case 2:
369             /* custom-0 */
370             switch ((inst >> 12) & 0b111) {
371             case 0:
372                 switch ((inst >> 20 & 0b111111111111)) {
373                 case 0b000000000001:
374                     if (((inst >> 20) & 0b11111) == 0) {
375                         op = rv_op_th_dcache_call;
376                     }
377                     break;
378                 case 0b000000000011:
379                     if (((inst >> 20) & 0b11111) == 0) {
380                         op = rv_op_th_dcache_ciall;
381                     }
382                     break;
383                 case 0b000000000010:
384                     if (((inst >> 20) & 0b11111) == 0) {
385                         op = rv_op_th_dcache_iall;
386                     }
387                     break;
388                 case 0b000000101001: op = rv_op_th_dcache_cpa; break;
389                 case 0b000000101011: op = rv_op_th_dcache_cipa; break;
390                 case 0b000000101010: op = rv_op_th_dcache_ipa; break;
391                 case 0b000000100101: op = rv_op_th_dcache_cva; break;
392                 case 0b000000100111: op = rv_op_th_dcache_civa; break;
393                 case 0b000000100110: op = rv_op_th_dcache_iva; break;
394                 case 0b000000100001: op = rv_op_th_dcache_csw; break;
395                 case 0b000000100011: op = rv_op_th_dcache_cisw; break;
396                 case 0b000000100010: op = rv_op_th_dcache_isw; break;
397                 case 0b000000101000: op = rv_op_th_dcache_cpal1; break;
398                 case 0b000000100100: op = rv_op_th_dcache_cval1; break;
399                 case 0b000000010000:
400                     if (((inst >> 20) & 0b11111) == 0) {
401                         op = rv_op_th_icache_iall;
402                     }
403                     break;
404                 case 0b000000010001:
405                     if (((inst >> 20) & 0b11111) == 0) {
406                         op = rv_op_th_icache_ialls;
407                     }
408                     break;
409                 case 0b000000111000: op = rv_op_th_icache_ipa; break;
410                 case 0b000000110000: op = rv_op_th_icache_iva; break;
411                 case 0b000000010101:
412                     if (((inst >> 20) & 0b11111) == 0) {
413                         op = rv_op_th_l2cache_call;
414                     }
415                     break;
416                 case 0b000000010111:
417                     if (((inst >> 20) & 0b11111) == 0) {
418                         op = rv_op_th_l2cache_ciall;
419                     }
420                     break;
421                 case 0b000000010110:
422                     if (((inst >> 20) & 0b11111) == 0) {
423                         op = rv_op_th_l2cache_iall;
424                     }
425                     break;
426                 }
427                 break;
428             }
429             break;
430             /* custom-0 */
431         }
432         break;
433     }
434 
435     dec->op = op;
436 }
437 
438 void decode_xtheadcondmov(rv_decode *dec, rv_isa isa)
439 {
440     rv_inst inst = dec->inst;
441     rv_opcode op = rv_op_illegal;
442 
443     switch (((inst >> 0) & 0b11)) {
444     case 3:
445         switch (((inst >> 2) & 0b11111)) {
446         case 2:
447             /* custom-0 */
448             switch ((inst >> 12) & 0b111) {
449             case 1:
450                 switch ((inst >> 25) & 0b1111111) {
451                 case 0b0100000: op = rv_op_th_mveqz; break;
452                 case 0b0100001: op = rv_op_th_mvnez; break;
453                 }
454                 break;
455             }
456             break;
457             /* custom-0 */
458         }
459         break;
460     }
461 
462     dec->op = op;
463 }
464 
465 void decode_xtheadfmemidx(rv_decode *dec, rv_isa isa)
466 {
467     rv_inst inst = dec->inst;
468     rv_opcode op = rv_op_illegal;
469 
470     switch (((inst >> 0) & 0b11)) {
471     case 3:
472         switch (((inst >> 2) & 0b11111)) {
473         case 2:
474             /* custom-0 */
475             switch ((inst >> 12) & 0b111) {
476             case 6:
477                 switch ((inst >> 27) & 0b11111) {
478                 case 8: op = rv_op_th_flrw; break;
479                 case 10: op = rv_op_th_flurw; break;
480                 case 12: op = rv_op_th_flrd; break;
481                 case 14: op = rv_op_th_flurd; break;
482                 }
483                 break;
484             case 7:
485                 switch ((inst >> 27) & 0b11111) {
486                 case 8: op = rv_op_th_fsrw; break;
487                 case 10: op = rv_op_th_fsurw; break;
488                 case 12: op = rv_op_th_fsrd; break;
489                 case 14: op = rv_op_th_fsurd; break;
490                 }
491                 break;
492             }
493             break;
494             /* custom-0 */
495         }
496         break;
497     }
498 
499     dec->op = op;
500 }
501 
502 void decode_xtheadfmv(rv_decode *dec, rv_isa isa)
503 {
504     rv_inst inst = dec->inst;
505     rv_opcode op = rv_op_illegal;
506 
507     switch (((inst >> 0) & 0b11)) {
508     case 3:
509         switch (((inst >> 2) & 0b11111)) {
510         case 2:
511             /* custom-0 */
512             switch ((inst >> 12) & 0b111) {
513             case 1:
514                 switch ((inst >> 25) & 0b1111111) {
515                 case 0b1010000:
516                     if (((inst >> 20) & 0b11111) == 0) {
517                         op = rv_op_th_fmv_hw_x;
518                     }
519                     break;
520                 case 0b1100000:
521                     if (((inst >> 20) & 0b11111) == 0) {
522                         op = rv_op_th_fmv_x_hw;
523                     }
524                     break;
525                 }
526                 break;
527             }
528             break;
529             /* custom-0 */
530         }
531         break;
532     }
533 
534     dec->op = op;
535 }
536 
537 void decode_xtheadmac(rv_decode *dec, rv_isa isa)
538 {
539     rv_inst inst = dec->inst;
540     rv_opcode op = rv_op_illegal;
541 
542     switch (((inst >> 0) & 0b11)) {
543     case 3:
544         switch (((inst >> 2) & 0b11111)) {
545         case 2:
546             /* custom-0 */
547             switch ((inst >> 12) & 0b111) {
548             case 1:
549                 switch ((inst >> 25) & 0b1111111) {
550                 case 0b0010000: op = rv_op_th_mula; break;
551                 case 0b0010001: op = rv_op_th_muls; break;
552                 case 0b0010010: op = rv_op_th_mulaw; break;
553                 case 0b0010011: op = rv_op_th_mulsw; break;
554                 case 0b0010100: op = rv_op_th_mulah; break;
555                 case 0b0010101: op = rv_op_th_mulsh; break;
556                 }
557                 break;
558             }
559             break;
560             /* custom-0 */
561         }
562         break;
563     }
564 
565     dec->op = op;
566 }
567 
568 void decode_xtheadmemidx(rv_decode *dec, rv_isa isa)
569 {
570     rv_inst inst = dec->inst;
571     rv_opcode op = rv_op_illegal;
572 
573     switch (((inst >> 0) & 0b11)) {
574     case 3:
575         switch (((inst >> 2) & 0b11111)) {
576         case 2:
577             /* custom-0 */
578             switch ((inst >> 12) & 0b111) {
579             case 4:
580                 switch ((inst >> 27) & 0b11111) {
581                 case 0: op = rv_op_th_lrb; break;
582                 case 1: op = rv_op_th_lbib; break;
583                 case 2: op = rv_op_th_lurb; break;
584                 case 3: op = rv_op_th_lbia; break;
585                 case 4: op = rv_op_th_lrh; break;
586                 case 5: op = rv_op_th_lhib; break;
587                 case 6: op = rv_op_th_lurh; break;
588                 case 7: op = rv_op_th_lhia; break;
589                 case 8: op = rv_op_th_lrw; break;
590                 case 9: op = rv_op_th_lwib; break;
591                 case 10: op = rv_op_th_lurw; break;
592                 case 11: op = rv_op_th_lwia; break;
593                 case 12: op = rv_op_th_lrd; break;
594                 case 13: op = rv_op_th_ldib; break;
595                 case 14: op = rv_op_th_lurd; break;
596                 case 15: op = rv_op_th_ldia; break;
597                 case 16: op = rv_op_th_lrbu; break;
598                 case 17: op = rv_op_th_lbuib; break;
599                 case 18: op = rv_op_th_lurbu; break;
600                 case 19: op = rv_op_th_lbuia; break;
601                 case 20: op = rv_op_th_lrhu; break;
602                 case 21: op = rv_op_th_lhuib; break;
603                 case 22: op = rv_op_th_lurhu; break;
604                 case 23: op = rv_op_th_lhuia; break;
605                 case 24: op = rv_op_th_lrwu; break;
606                 case 25: op = rv_op_th_lwuib; break;
607                 case 26: op = rv_op_th_lurwu; break;
608                 case 27: op = rv_op_th_lwuia; break;
609                 }
610                 break;
611             case 5:
612                 switch ((inst >> 27) & 0b11111) {
613                 case 0: op = rv_op_th_srb; break;
614                 case 1: op = rv_op_th_sbib; break;
615                 case 2: op = rv_op_th_surb; break;
616                 case 3: op = rv_op_th_sbia; break;
617                 case 4: op = rv_op_th_srh; break;
618                 case 5: op = rv_op_th_shib; break;
619                 case 6: op = rv_op_th_surh; break;
620                 case 7: op = rv_op_th_shia; break;
621                 case 8: op = rv_op_th_srw; break;
622                 case 9: op = rv_op_th_swib; break;
623                 case 10: op = rv_op_th_surw; break;
624                 case 11: op = rv_op_th_swia; break;
625                 case 12: op = rv_op_th_srd; break;
626                 case 13: op = rv_op_th_sdib; break;
627                 case 14: op = rv_op_th_surd; break;
628                 case 15: op = rv_op_th_sdia; break;
629                 }
630                 break;
631                 break;
632             }
633             break;
634             /* custom-0 */
635         }
636         break;
637     }
638 
639     dec->op = op;
640 }
641 
642 void decode_xtheadmempair(rv_decode *dec, rv_isa isa)
643 {
644     rv_inst inst = dec->inst;
645     rv_opcode op = rv_op_illegal;
646 
647     switch (((inst >> 0) & 0b11)) {
648     case 3:
649         switch (((inst >> 2) & 0b11111)) {
650         case 2:
651             /* custom-0 */
652             switch ((inst >> 12) & 0b111) {
653             case 4:
654                 switch ((inst >> 27) & 0b11111) {
655                 case 28: op = rv_op_th_lwd; break;
656                 case 30: op = rv_op_th_lwud; break;
657                 case 31: op = rv_op_th_ldd; break;
658                 }
659                 break;
660             case 5:
661                 switch ((inst >> 27) & 0b11111) {
662                 case 28: op = rv_op_th_swd; break;
663                 case 31: op = rv_op_th_sdd; break;
664                 }
665                 break;
666             }
667             break;
668             /* custom-0 */
669         }
670         break;
671     }
672 
673     dec->op = op;
674 }
675 
676 void decode_xtheadsync(rv_decode *dec, rv_isa isa)
677 {
678     rv_inst inst = dec->inst;
679     rv_opcode op = rv_op_illegal;
680 
681     switch (((inst >> 0) & 0b11)) {
682     case 3:
683         switch (((inst >> 2) & 0b11111)) {
684         case 2:
685             /* custom-0 */
686             switch ((inst >> 12) & 0b111) {
687             case 0:
688                 switch ((inst >> 25) & 0b1111111) {
689                 case 0b0000010: op = rv_op_th_sfence_vmas; break;
690                 case 0b0000000:
691                     switch ((inst >> 20) & 0b11111) {
692                     case 0b11000: op = rv_op_th_sync; break;
693                     case 0b11010: op = rv_op_th_sync_i; break;
694                     case 0b11011: op = rv_op_th_sync_is; break;
695                     case 0b11001: op = rv_op_th_sync_s; break;
696                     }
697                     break;
698                 }
699                 break;
700             }
701             break;
702             /* custom-0 */
703         }
704         break;
705     }
706 
707     dec->op = op;
708 }
709