1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * QEMU LoongArch Disassembler
5 * Copyright (c) 2021 Loongson Technology Corporation Limited.
8 #include "qemu/osdep.h"
9 #include "disas/dis-asm.h"
10 #include "qemu/bitops.h"
14 disassemble_info
*info
;
19 static inline int plus_1(DisasContext
*ctx
, int x
)
24 static inline int shl_2(DisasContext
*ctx
, int x
)
29 #define CSR_NAME(REG) \
30 [LOONGARCH_CSR_##REG] = (#REG)
32 static const char * const csr_names
[] = {
107 static const char *get_csr_name(unsigned num
)
109 return ((num
< ARRAY_SIZE(csr_names
)) && (csr_names
[num
] != NULL
)) ?
110 csr_names
[num
] : "Undefined CSR";
113 #define output(C, INSN, FMT, ...) \
115 (C)->info->fprintf_func((C)->info->stream, "%08x %-9s\t" FMT, \
116 (C)->insn, INSN, ##__VA_ARGS__); \
119 #include "decode-insns.c.inc"
121 int print_insn_loongarch(bfd_vma memaddr
, struct disassemble_info
*info
)
127 status
= (*info
->read_memory_func
)(memaddr
, buffer
, 4, info
);
129 (*info
->memory_error_func
)(status
, memaddr
, info
);
132 insn
= bfd_getl32(buffer
);
139 if (!decode(&ctx
, insn
)) {
140 output(&ctx
, "illegal", "");
145 static void output_r_i(DisasContext
*ctx
, arg_r_i
*a
, const char *mnemonic
)
147 output(ctx
, mnemonic
, "r%d, %d", a
->rd
, a
->imm
);
150 static void output_rrr(DisasContext
*ctx
, arg_rrr
*a
, const char *mnemonic
)
152 output(ctx
, mnemonic
, "r%d, r%d, r%d", a
->rd
, a
->rj
, a
->rk
);
155 static void output_rr_i(DisasContext
*ctx
, arg_rr_i
*a
, const char *mnemonic
)
157 output(ctx
, mnemonic
, "r%d, r%d, %d", a
->rd
, a
->rj
, a
->imm
);
160 static void output_rrr_sa(DisasContext
*ctx
, arg_rrr_sa
*a
,
161 const char *mnemonic
)
163 output(ctx
, mnemonic
, "r%d, r%d, r%d, %d", a
->rd
, a
->rj
, a
->rk
, a
->sa
);
166 static void output_rr(DisasContext
*ctx
, arg_rr
*a
, const char *mnemonic
)
168 output(ctx
, mnemonic
, "r%d, r%d", a
->rd
, a
->rj
);
171 static void output_rr_ms_ls(DisasContext
*ctx
, arg_rr_ms_ls
*a
,
172 const char *mnemonic
)
174 output(ctx
, mnemonic
, "r%d, r%d, %d, %d", a
->rd
, a
->rj
, a
->ms
, a
->ls
);
177 static void output_hint_r_i(DisasContext
*ctx
, arg_hint_r_i
*a
,
178 const char *mnemonic
)
180 output(ctx
, mnemonic
, "%d, r%d, %d", a
->hint
, a
->rj
, a
->imm
);
183 static void output_i(DisasContext
*ctx
, arg_i
*a
, const char *mnemonic
)
185 output(ctx
, mnemonic
, "%d", a
->imm
);
188 static void output_rr_jk(DisasContext
*ctx
, arg_rr_jk
*a
,
189 const char *mnemonic
)
191 output(ctx
, mnemonic
, "r%d, r%d", a
->rj
, a
->rk
);
194 static void output_ff(DisasContext
*ctx
, arg_ff
*a
, const char *mnemonic
)
196 output(ctx
, mnemonic
, "f%d, f%d", a
->fd
, a
->fj
);
199 static void output_fff(DisasContext
*ctx
, arg_fff
*a
, const char *mnemonic
)
201 output(ctx
, mnemonic
, "f%d, f%d, f%d", a
->fd
, a
->fj
, a
->fk
);
204 static void output_ffff(DisasContext
*ctx
, arg_ffff
*a
, const char *mnemonic
)
206 output(ctx
, mnemonic
, "f%d, f%d, f%d, f%d", a
->fd
, a
->fj
, a
->fk
, a
->fa
);
209 static void output_fffc(DisasContext
*ctx
, arg_fffc
*a
, const char *mnemonic
)
211 output(ctx
, mnemonic
, "f%d, f%d, f%d, %d", a
->fd
, a
->fj
, a
->fk
, a
->ca
);
214 static void output_fr(DisasContext
*ctx
, arg_fr
*a
, const char *mnemonic
)
216 output(ctx
, mnemonic
, "f%d, r%d", a
->fd
, a
->rj
);
219 static void output_rf(DisasContext
*ctx
, arg_rf
*a
, const char *mnemonic
)
221 output(ctx
, mnemonic
, "r%d, f%d", a
->rd
, a
->fj
);
224 static void output_fcsrd_r(DisasContext
*ctx
, arg_fcsrd_r
*a
,
225 const char *mnemonic
)
227 output(ctx
, mnemonic
, "fcsr%d, r%d", a
->fcsrd
, a
->rj
);
230 static void output_r_fcsrs(DisasContext
*ctx
, arg_r_fcsrs
*a
,
231 const char *mnemonic
)
233 output(ctx
, mnemonic
, "r%d, fcsr%d", a
->rd
, a
->fcsrs
);
236 static void output_cf(DisasContext
*ctx
, arg_cf
*a
, const char *mnemonic
)
238 output(ctx
, mnemonic
, "fcc%d, f%d", a
->cd
, a
->fj
);
241 static void output_fc(DisasContext
*ctx
, arg_fc
*a
, const char *mnemonic
)
243 output(ctx
, mnemonic
, "f%d, fcc%d", a
->fd
, a
->cj
);
246 static void output_cr(DisasContext
*ctx
, arg_cr
*a
, const char *mnemonic
)
248 output(ctx
, mnemonic
, "fcc%d, r%d", a
->cd
, a
->rj
);
251 static void output_rc(DisasContext
*ctx
, arg_rc
*a
, const char *mnemonic
)
253 output(ctx
, mnemonic
, "r%d, fcc%d", a
->rd
, a
->cj
);
256 static void output_frr(DisasContext
*ctx
, arg_frr
*a
, const char *mnemonic
)
258 output(ctx
, mnemonic
, "f%d, r%d, r%d", a
->fd
, a
->rj
, a
->rk
);
261 static void output_fr_i(DisasContext
*ctx
, arg_fr_i
*a
, const char *mnemonic
)
263 output(ctx
, mnemonic
, "f%d, r%d, %d", a
->fd
, a
->rj
, a
->imm
);
266 static void output_r_offs(DisasContext
*ctx
, arg_r_offs
*a
,
267 const char *mnemonic
)
269 output(ctx
, mnemonic
, "r%d, %d # 0x%" PRIx64
, a
->rj
, a
->offs
,
273 static void output_c_offs(DisasContext
*ctx
, arg_c_offs
*a
,
274 const char *mnemonic
)
276 output(ctx
, mnemonic
, "fcc%d, %d # 0x%" PRIx64
, a
->cj
, a
->offs
,
280 static void output_offs(DisasContext
*ctx
, arg_offs
*a
,
281 const char *mnemonic
)
283 output(ctx
, mnemonic
, "%d # 0x%" PRIx64
, a
->offs
, ctx
->pc
+ a
->offs
);
286 static void output_rr_offs(DisasContext
*ctx
, arg_rr_offs
*a
,
287 const char *mnemonic
)
289 output(ctx
, mnemonic
, "r%d, r%d, %d # 0x%" PRIx64
, a
->rj
,
290 a
->rd
, a
->offs
, ctx
->pc
+ a
->offs
);
293 static void output_r_csr(DisasContext
*ctx
, arg_r_csr
*a
,
294 const char *mnemonic
)
296 output(ctx
, mnemonic
, "r%d, %d # %s", a
->rd
, a
->csr
, get_csr_name(a
->csr
));
299 static void output_rr_csr(DisasContext
*ctx
, arg_rr_csr
*a
,
300 const char *mnemonic
)
302 output(ctx
, mnemonic
, "r%d, r%d, %d # %s",
303 a
->rd
, a
->rj
, a
->csr
, get_csr_name(a
->csr
));
306 static void output_empty(DisasContext
*ctx
, arg_empty
*a
,
307 const char *mnemonic
)
309 output(ctx
, mnemonic
, "");
312 static void output_i_rr(DisasContext
*ctx
, arg_i_rr
*a
, const char *mnemonic
)
314 output(ctx
, mnemonic
, "%d, r%d, r%d", a
->imm
, a
->rj
, a
->rk
);
317 static void output_cop_r_i(DisasContext
*ctx
, arg_cop_r_i
*a
,
318 const char *mnemonic
)
320 output(ctx
, mnemonic
, "%d, r%d, %d", a
->cop
, a
->rj
, a
->imm
);
323 static void output_j_i(DisasContext
*ctx
, arg_j_i
*a
, const char *mnemonic
)
325 output(ctx
, mnemonic
, "r%d, %d", a
->rj
, a
->imm
);
328 #define INSN(insn, type) \
329 static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
331 output_##type(ctx, a, #insn); \
359 INSN(asrtle_d
, rr_jk
)
360 INSN(asrtgt_d
, rr_jk
)
362 INSN(alsl_wu
, rrr_sa
)
363 INSN(bytepick_w
, rrr_sa
)
364 INSN(bytepick_d
, rrr_sa
)
407 INSN(crcc_w_b_w
, rrr
)
408 INSN(crcc_w_h_w
, rrr
)
409 INSN(crcc_w_w_w
, rrr
)
410 INSN(crcc_w_d_w
, rrr
)
422 INSN(bstrins_w
, rr_ms_ls
)
423 INSN(bstrpick_w
, rr_ms_ls
)
424 INSN(bstrins_d
, rr_ms_ls
)
425 INSN(bstrpick_d
, rr_ms_ls
)
444 INSN(fcopysign_s
, fff
)
445 INSN(fcopysign_d
, fff
)
464 INSN(movgr2frh_w
, fr
)
467 INSN(movfrh2gr_s
, rf
)
468 INSN(movgr2fcsr
, fcsrd_r
)
469 INSN(movfcsr2gr
, r_fcsrs
)
476 INSN(ftintrm_w_s
, ff
)
477 INSN(ftintrm_w_d
, ff
)
478 INSN(ftintrm_l_s
, ff
)
479 INSN(ftintrm_l_d
, ff
)
480 INSN(ftintrp_w_s
, ff
)
481 INSN(ftintrp_w_d
, ff
)
482 INSN(ftintrp_l_s
, ff
)
483 INSN(ftintrp_l_d
, ff
)
484 INSN(ftintrz_w_s
, ff
)
485 INSN(ftintrz_w_d
, ff
)
486 INSN(ftintrz_l_s
, ff
)
487 INSN(ftintrz_l_d
, ff
)
488 INSN(ftintrne_w_s
, ff
)
489 INSN(ftintrne_w_d
, ff
)
490 INSN(ftintrne_l_s
, ff
)
491 INSN(ftintrne_l_d
, ff
)
519 INSN(addu16i_d
, rr_i
)
545 INSN(preld
, hint_r_i
)
583 INSN(amswap_db_w
, rrr
)
584 INSN(amswap_db_d
, rrr
)
585 INSN(amadd_db_w
, rrr
)
586 INSN(amadd_db_d
, rrr
)
587 INSN(amand_db_w
, rrr
)
588 INSN(amand_db_d
, rrr
)
591 INSN(amxor_db_w
, rrr
)
592 INSN(amxor_db_d
, rrr
)
593 INSN(ammax_db_w
, rrr
)
594 INSN(ammax_db_d
, rrr
)
595 INSN(ammin_db_w
, rrr
)
596 INSN(ammin_db_d
, rrr
)
597 INSN(ammax_db_wu
, rrr
)
598 INSN(ammax_db_du
, rrr
)
599 INSN(ammin_db_wu
, rrr
)
600 INSN(ammin_db_du
, rrr
)
642 INSN(csrxchg
, rr_csr
)
656 INSN(tlbflush
, empty
)
665 #define output_fcmp(C, PREFIX, SUFFIX) \
667 (C)->info->fprintf_func((C)->info->stream, "%08x %s%s\tfcc%d, f%d, f%d", \
668 (C)->insn, PREFIX, SUFFIX, a->cd, \
672 static bool output_cff_fcond(DisasContext
*ctx
, arg_cff_fcond
* a
,
678 output_fcmp(ctx
, "fcmp_caf_", suffix
);
681 output_fcmp(ctx
, "fcmp_saf_", suffix
);
684 output_fcmp(ctx
, "fcmp_clt_", suffix
);
687 output_fcmp(ctx
, "fcmp_slt_", suffix
);
690 output_fcmp(ctx
, "fcmp_ceq_", suffix
);
693 output_fcmp(ctx
, "fcmp_seq_", suffix
);
696 output_fcmp(ctx
, "fcmp_cle_", suffix
);
699 output_fcmp(ctx
, "fcmp_sle_", suffix
);
702 output_fcmp(ctx
, "fcmp_cun_", suffix
);
705 output_fcmp(ctx
, "fcmp_sun_", suffix
);
708 output_fcmp(ctx
, "fcmp_cult_", suffix
);
711 output_fcmp(ctx
, "fcmp_sult_", suffix
);
714 output_fcmp(ctx
, "fcmp_cueq_", suffix
);
717 output_fcmp(ctx
, "fcmp_sueq_", suffix
);
720 output_fcmp(ctx
, "fcmp_cule_", suffix
);
723 output_fcmp(ctx
, "fcmp_sule_", suffix
);
726 output_fcmp(ctx
, "fcmp_cne_", suffix
);
729 output_fcmp(ctx
, "fcmp_sne_", suffix
);
732 output_fcmp(ctx
, "fcmp_cor_", suffix
);
735 output_fcmp(ctx
, "fcmp_sor_", suffix
);
738 output_fcmp(ctx
, "fcmp_cune_", suffix
);
741 output_fcmp(ctx
, "fcmp_sune_", suffix
);
749 #define FCMP_INSN(suffix) \
750 static bool trans_fcmp_cond_##suffix(DisasContext *ctx, \
753 return output_cff_fcond(ctx, a, #suffix); \