2022-06-06 15:43:06 +03:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/*
|
|
|
|
* QEMU LoongArch Disassembler
|
|
|
|
*
|
|
|
|
* Copyright (c) 2021 Loongson Technology Corporation Limited.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "disas/dis-asm.h"
|
|
|
|
#include "qemu/bitops.h"
|
2022-06-06 15:43:15 +03:00
|
|
|
#include "cpu-csr.h"
|
2022-06-06 15:43:06 +03:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
disassemble_info *info;
|
|
|
|
uint64_t pc;
|
|
|
|
uint32_t insn;
|
|
|
|
} DisasContext;
|
|
|
|
|
|
|
|
static inline int plus_1(DisasContext *ctx, int x)
|
|
|
|
{
|
|
|
|
return x + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int shl_2(DisasContext *ctx, int x)
|
|
|
|
{
|
|
|
|
return x << 2;
|
|
|
|
}
|
|
|
|
|
2022-06-06 15:43:15 +03:00
|
|
|
#define CSR_NAME(REG) \
|
|
|
|
[LOONGARCH_CSR_##REG] = (#REG)
|
|
|
|
|
|
|
|
static const char * const csr_names[] = {
|
|
|
|
CSR_NAME(CRMD),
|
|
|
|
CSR_NAME(PRMD),
|
|
|
|
CSR_NAME(EUEN),
|
|
|
|
CSR_NAME(MISC),
|
|
|
|
CSR_NAME(ECFG),
|
|
|
|
CSR_NAME(ESTAT),
|
|
|
|
CSR_NAME(ERA),
|
|
|
|
CSR_NAME(BADV),
|
|
|
|
CSR_NAME(BADI),
|
|
|
|
CSR_NAME(EENTRY),
|
|
|
|
CSR_NAME(TLBIDX),
|
|
|
|
CSR_NAME(TLBEHI),
|
|
|
|
CSR_NAME(TLBELO0),
|
|
|
|
CSR_NAME(TLBELO1),
|
|
|
|
CSR_NAME(ASID),
|
|
|
|
CSR_NAME(PGDL),
|
|
|
|
CSR_NAME(PGDH),
|
|
|
|
CSR_NAME(PGD),
|
|
|
|
CSR_NAME(PWCL),
|
|
|
|
CSR_NAME(PWCH),
|
|
|
|
CSR_NAME(STLBPS),
|
|
|
|
CSR_NAME(RVACFG),
|
|
|
|
CSR_NAME(CPUID),
|
|
|
|
CSR_NAME(PRCFG1),
|
|
|
|
CSR_NAME(PRCFG2),
|
|
|
|
CSR_NAME(PRCFG3),
|
|
|
|
CSR_NAME(SAVE(0)),
|
|
|
|
CSR_NAME(SAVE(1)),
|
|
|
|
CSR_NAME(SAVE(2)),
|
|
|
|
CSR_NAME(SAVE(3)),
|
|
|
|
CSR_NAME(SAVE(4)),
|
|
|
|
CSR_NAME(SAVE(5)),
|
|
|
|
CSR_NAME(SAVE(6)),
|
|
|
|
CSR_NAME(SAVE(7)),
|
|
|
|
CSR_NAME(SAVE(8)),
|
|
|
|
CSR_NAME(SAVE(9)),
|
|
|
|
CSR_NAME(SAVE(10)),
|
|
|
|
CSR_NAME(SAVE(11)),
|
|
|
|
CSR_NAME(SAVE(12)),
|
|
|
|
CSR_NAME(SAVE(13)),
|
|
|
|
CSR_NAME(SAVE(14)),
|
|
|
|
CSR_NAME(SAVE(15)),
|
|
|
|
CSR_NAME(TID),
|
|
|
|
CSR_NAME(TCFG),
|
|
|
|
CSR_NAME(TVAL),
|
|
|
|
CSR_NAME(CNTC),
|
|
|
|
CSR_NAME(TICLR),
|
|
|
|
CSR_NAME(LLBCTL),
|
|
|
|
CSR_NAME(IMPCTL1),
|
|
|
|
CSR_NAME(IMPCTL2),
|
|
|
|
CSR_NAME(TLBRENTRY),
|
|
|
|
CSR_NAME(TLBRBADV),
|
|
|
|
CSR_NAME(TLBRERA),
|
|
|
|
CSR_NAME(TLBRSAVE),
|
|
|
|
CSR_NAME(TLBRELO0),
|
|
|
|
CSR_NAME(TLBRELO1),
|
|
|
|
CSR_NAME(TLBREHI),
|
|
|
|
CSR_NAME(TLBRPRMD),
|
|
|
|
CSR_NAME(MERRCTL),
|
|
|
|
CSR_NAME(MERRINFO1),
|
|
|
|
CSR_NAME(MERRINFO2),
|
|
|
|
CSR_NAME(MERRENTRY),
|
|
|
|
CSR_NAME(MERRERA),
|
|
|
|
CSR_NAME(MERRSAVE),
|
|
|
|
CSR_NAME(CTAG),
|
|
|
|
CSR_NAME(DMW(0)),
|
|
|
|
CSR_NAME(DMW(1)),
|
|
|
|
CSR_NAME(DMW(2)),
|
|
|
|
CSR_NAME(DMW(3)),
|
|
|
|
CSR_NAME(DBG),
|
|
|
|
CSR_NAME(DERA),
|
|
|
|
CSR_NAME(DSAVE),
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *get_csr_name(unsigned num)
|
|
|
|
{
|
|
|
|
return ((num < ARRAY_SIZE(csr_names)) && (csr_names[num] != NULL)) ?
|
|
|
|
csr_names[num] : "Undefined CSR";
|
|
|
|
}
|
|
|
|
|
2022-06-06 15:43:06 +03:00
|
|
|
#define output(C, INSN, FMT, ...) \
|
|
|
|
{ \
|
|
|
|
(C)->info->fprintf_func((C)->info->stream, "%08x %-9s\t" FMT, \
|
|
|
|
(C)->insn, INSN, ##__VA_ARGS__); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "decode-insns.c.inc"
|
|
|
|
|
|
|
|
int print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
|
|
|
|
{
|
|
|
|
bfd_byte buffer[4];
|
|
|
|
uint32_t insn;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
status = (*info->read_memory_func)(memaddr, buffer, 4, info);
|
|
|
|
if (status != 0) {
|
|
|
|
(*info->memory_error_func)(status, memaddr, info);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
insn = bfd_getl32(buffer);
|
|
|
|
DisasContext ctx = {
|
|
|
|
.info = info,
|
|
|
|
.pc = memaddr,
|
|
|
|
.insn = insn
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!decode(&ctx, insn)) {
|
|
|
|
output(&ctx, "illegal", "");
|
|
|
|
}
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_r_i(DisasContext *ctx, arg_r_i *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, %d", a->rd, a->imm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rrr(DisasContext *ctx, arg_rrr *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, r%d, r%d", a->rd, a->rj, a->rk);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rr_i(DisasContext *ctx, arg_rr_i *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, r%d, %d", a->rd, a->rj, a->imm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, r%d, r%d, %d", a->rd, a->rj, a->rk, a->sa);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rr(DisasContext *ctx, arg_rr *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, r%d", a->rd, a->rj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, r%d, %d, %d", a->rd, a->rj, a->ms, a->ls);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_hint_r_i(DisasContext *ctx, arg_hint_r_i *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "%d, r%d, %d", a->hint, a->rj, a->imm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_i(DisasContext *ctx, arg_i *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "%d", a->imm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rr_jk(DisasContext *ctx, arg_rr_jk *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, r%d", a->rj, a->rk);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_ff(DisasContext *ctx, arg_ff *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "f%d, f%d", a->fd, a->fj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_fff(DisasContext *ctx, arg_fff *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "f%d, f%d, f%d", a->fd, a->fj, a->fk);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_ffff(DisasContext *ctx, arg_ffff *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "f%d, f%d, f%d, f%d", a->fd, a->fj, a->fk, a->fa);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_fffc(DisasContext *ctx, arg_fffc *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "f%d, f%d, f%d, %d", a->fd, a->fj, a->fk, a->ca);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_fr(DisasContext *ctx, arg_fr *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "f%d, r%d", a->fd, a->rj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rf(DisasContext *ctx, arg_rf *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, f%d", a->rd, a->fj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_fcsrd_r(DisasContext *ctx, arg_fcsrd_r *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "fcsr%d, r%d", a->fcsrd, a->rj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_r_fcsrs(DisasContext *ctx, arg_r_fcsrs *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, fcsr%d", a->rd, a->fcsrs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_cf(DisasContext *ctx, arg_cf *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "fcc%d, f%d", a->cd, a->fj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_fc(DisasContext *ctx, arg_fc *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "f%d, fcc%d", a->fd, a->cj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_cr(DisasContext *ctx, arg_cr *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "fcc%d, r%d", a->cd, a->rj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rc(DisasContext *ctx, arg_rc *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, fcc%d", a->rd, a->cj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_frr(DisasContext *ctx, arg_frr *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "f%d, r%d, r%d", a->fd, a->rj, a->rk);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_fr_i(DisasContext *ctx, arg_fr_i *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "f%d, r%d, %d", a->fd, a->rj, a->imm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_r_offs(DisasContext *ctx, arg_r_offs *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, %d # 0x%" PRIx64, a->rj, a->offs,
|
|
|
|
ctx->pc + a->offs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_c_offs(DisasContext *ctx, arg_c_offs *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "fcc%d, %d # 0x%" PRIx64, a->cj, a->offs,
|
|
|
|
ctx->pc + a->offs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_offs(DisasContext *ctx, arg_offs *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "%d # 0x%" PRIx64, a->offs, ctx->pc + a->offs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rr_offs(DisasContext *ctx, arg_rr_offs *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, r%d, %d # 0x%" PRIx64, a->rj,
|
|
|
|
a->rd, a->offs, ctx->pc + a->offs);
|
|
|
|
}
|
|
|
|
|
2022-06-06 15:43:15 +03:00
|
|
|
static void output_r_csr(DisasContext *ctx, arg_r_csr *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, %d # %s", a->rd, a->csr, get_csr_name(a->csr));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_rr_csr(DisasContext *ctx, arg_rr_csr *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, r%d, %d # %s",
|
|
|
|
a->rd, a->rj, a->csr, get_csr_name(a->csr));
|
|
|
|
}
|
|
|
|
|
2022-06-06 15:43:17 +03:00
|
|
|
static void output_empty(DisasContext *ctx, arg_empty *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_i_rr(DisasContext *ctx, arg_i_rr *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "%d, r%d, r%d", a->imm, a->rj, a->rk);
|
|
|
|
}
|
|
|
|
|
2022-06-06 15:43:18 +03:00
|
|
|
static void output_cop_r_i(DisasContext *ctx, arg_cop_r_i *a,
|
|
|
|
const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "%d, r%d, %d", a->cop, a->rj, a->imm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void output_j_i(DisasContext *ctx, arg_j_i *a, const char *mnemonic)
|
|
|
|
{
|
|
|
|
output(ctx, mnemonic, "r%d, %d", a->rj, a->imm);
|
|
|
|
}
|
|
|
|
|
2022-06-06 15:43:06 +03:00
|
|
|
#define INSN(insn, type) \
|
|
|
|
static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
|
|
|
|
{ \
|
|
|
|
output_##type(ctx, a, #insn); \
|
|
|
|
return true; \
|
|
|
|
}
|
|
|
|
|
|
|
|
INSN(clo_w, rr)
|
|
|
|
INSN(clz_w, rr)
|
|
|
|
INSN(cto_w, rr)
|
|
|
|
INSN(ctz_w, rr)
|
|
|
|
INSN(clo_d, rr)
|
|
|
|
INSN(clz_d, rr)
|
|
|
|
INSN(cto_d, rr)
|
|
|
|
INSN(ctz_d, rr)
|
|
|
|
INSN(revb_2h, rr)
|
|
|
|
INSN(revb_4h, rr)
|
|
|
|
INSN(revb_2w, rr)
|
|
|
|
INSN(revb_d, rr)
|
|
|
|
INSN(revh_2w, rr)
|
|
|
|
INSN(revh_d, rr)
|
|
|
|
INSN(bitrev_4b, rr)
|
|
|
|
INSN(bitrev_8b, rr)
|
|
|
|
INSN(bitrev_w, rr)
|
|
|
|
INSN(bitrev_d, rr)
|
|
|
|
INSN(ext_w_h, rr)
|
|
|
|
INSN(ext_w_b, rr)
|
2022-06-06 15:43:19 +03:00
|
|
|
INSN(rdtimel_w, rr)
|
|
|
|
INSN(rdtimeh_w, rr)
|
|
|
|
INSN(rdtime_d, rr)
|
2022-06-06 15:43:06 +03:00
|
|
|
INSN(cpucfg, rr)
|
|
|
|
INSN(asrtle_d, rr_jk)
|
|
|
|
INSN(asrtgt_d, rr_jk)
|
|
|
|
INSN(alsl_w, rrr_sa)
|
|
|
|
INSN(alsl_wu, rrr_sa)
|
|
|
|
INSN(bytepick_w, rrr_sa)
|
|
|
|
INSN(bytepick_d, rrr_sa)
|
|
|
|
INSN(add_w, rrr)
|
|
|
|
INSN(add_d, rrr)
|
|
|
|
INSN(sub_w, rrr)
|
|
|
|
INSN(sub_d, rrr)
|
|
|
|
INSN(slt, rrr)
|
|
|
|
INSN(sltu, rrr)
|
|
|
|
INSN(maskeqz, rrr)
|
|
|
|
INSN(masknez, rrr)
|
|
|
|
INSN(nor, rrr)
|
|
|
|
INSN(and, rrr)
|
|
|
|
INSN(or, rrr)
|
|
|
|
INSN(xor, rrr)
|
|
|
|
INSN(orn, rrr)
|
|
|
|
INSN(andn, rrr)
|
|
|
|
INSN(sll_w, rrr)
|
|
|
|
INSN(srl_w, rrr)
|
|
|
|
INSN(sra_w, rrr)
|
|
|
|
INSN(sll_d, rrr)
|
|
|
|
INSN(srl_d, rrr)
|
|
|
|
INSN(sra_d, rrr)
|
|
|
|
INSN(rotr_w, rrr)
|
|
|
|
INSN(rotr_d, rrr)
|
|
|
|
INSN(mul_w, rrr)
|
|
|
|
INSN(mulh_w, rrr)
|
|
|
|
INSN(mulh_wu, rrr)
|
|
|
|
INSN(mul_d, rrr)
|
|
|
|
INSN(mulh_d, rrr)
|
|
|
|
INSN(mulh_du, rrr)
|
|
|
|
INSN(mulw_d_w, rrr)
|
|
|
|
INSN(mulw_d_wu, rrr)
|
|
|
|
INSN(div_w, rrr)
|
|
|
|
INSN(mod_w, rrr)
|
|
|
|
INSN(div_wu, rrr)
|
|
|
|
INSN(mod_wu, rrr)
|
|
|
|
INSN(div_d, rrr)
|
|
|
|
INSN(mod_d, rrr)
|
|
|
|
INSN(div_du, rrr)
|
|
|
|
INSN(mod_du, rrr)
|
|
|
|
INSN(crc_w_b_w, rrr)
|
|
|
|
INSN(crc_w_h_w, rrr)
|
|
|
|
INSN(crc_w_w_w, rrr)
|
|
|
|
INSN(crc_w_d_w, rrr)
|
|
|
|
INSN(crcc_w_b_w, rrr)
|
|
|
|
INSN(crcc_w_h_w, rrr)
|
|
|
|
INSN(crcc_w_w_w, rrr)
|
|
|
|
INSN(crcc_w_d_w, rrr)
|
|
|
|
INSN(break, i)
|
|
|
|
INSN(syscall, i)
|
|
|
|
INSN(alsl_d, rrr_sa)
|
|
|
|
INSN(slli_w, rr_i)
|
|
|
|
INSN(slli_d, rr_i)
|
|
|
|
INSN(srli_w, rr_i)
|
|
|
|
INSN(srli_d, rr_i)
|
|
|
|
INSN(srai_w, rr_i)
|
|
|
|
INSN(srai_d, rr_i)
|
|
|
|
INSN(rotri_w, rr_i)
|
|
|
|
INSN(rotri_d, rr_i)
|
|
|
|
INSN(bstrins_w, rr_ms_ls)
|
|
|
|
INSN(bstrpick_w, rr_ms_ls)
|
|
|
|
INSN(bstrins_d, rr_ms_ls)
|
|
|
|
INSN(bstrpick_d, rr_ms_ls)
|
|
|
|
INSN(fadd_s, fff)
|
|
|
|
INSN(fadd_d, fff)
|
|
|
|
INSN(fsub_s, fff)
|
|
|
|
INSN(fsub_d, fff)
|
|
|
|
INSN(fmul_s, fff)
|
|
|
|
INSN(fmul_d, fff)
|
|
|
|
INSN(fdiv_s, fff)
|
|
|
|
INSN(fdiv_d, fff)
|
|
|
|
INSN(fmax_s, fff)
|
|
|
|
INSN(fmax_d, fff)
|
|
|
|
INSN(fmin_s, fff)
|
|
|
|
INSN(fmin_d, fff)
|
|
|
|
INSN(fmaxa_s, fff)
|
|
|
|
INSN(fmaxa_d, fff)
|
|
|
|
INSN(fmina_s, fff)
|
|
|
|
INSN(fmina_d, fff)
|
|
|
|
INSN(fscaleb_s, fff)
|
|
|
|
INSN(fscaleb_d, fff)
|
|
|
|
INSN(fcopysign_s, fff)
|
|
|
|
INSN(fcopysign_d, fff)
|
|
|
|
INSN(fabs_s, ff)
|
|
|
|
INSN(fabs_d, ff)
|
|
|
|
INSN(fneg_s, ff)
|
|
|
|
INSN(fneg_d, ff)
|
|
|
|
INSN(flogb_s, ff)
|
|
|
|
INSN(flogb_d, ff)
|
|
|
|
INSN(fclass_s, ff)
|
|
|
|
INSN(fclass_d, ff)
|
|
|
|
INSN(fsqrt_s, ff)
|
|
|
|
INSN(fsqrt_d, ff)
|
|
|
|
INSN(frecip_s, ff)
|
|
|
|
INSN(frecip_d, ff)
|
|
|
|
INSN(frsqrt_s, ff)
|
|
|
|
INSN(frsqrt_d, ff)
|
|
|
|
INSN(fmov_s, ff)
|
|
|
|
INSN(fmov_d, ff)
|
|
|
|
INSN(movgr2fr_w, fr)
|
|
|
|
INSN(movgr2fr_d, fr)
|
|
|
|
INSN(movgr2frh_w, fr)
|
|
|
|
INSN(movfr2gr_s, rf)
|
|
|
|
INSN(movfr2gr_d, rf)
|
|
|
|
INSN(movfrh2gr_s, rf)
|
|
|
|
INSN(movgr2fcsr, fcsrd_r)
|
|
|
|
INSN(movfcsr2gr, r_fcsrs)
|
|
|
|
INSN(movfr2cf, cf)
|
|
|
|
INSN(movcf2fr, fc)
|
|
|
|
INSN(movgr2cf, cr)
|
|
|
|
INSN(movcf2gr, rc)
|
|
|
|
INSN(fcvt_s_d, ff)
|
|
|
|
INSN(fcvt_d_s, ff)
|
|
|
|
INSN(ftintrm_w_s, ff)
|
|
|
|
INSN(ftintrm_w_d, ff)
|
|
|
|
INSN(ftintrm_l_s, ff)
|
|
|
|
INSN(ftintrm_l_d, ff)
|
|
|
|
INSN(ftintrp_w_s, ff)
|
|
|
|
INSN(ftintrp_w_d, ff)
|
|
|
|
INSN(ftintrp_l_s, ff)
|
|
|
|
INSN(ftintrp_l_d, ff)
|
|
|
|
INSN(ftintrz_w_s, ff)
|
|
|
|
INSN(ftintrz_w_d, ff)
|
|
|
|
INSN(ftintrz_l_s, ff)
|
|
|
|
INSN(ftintrz_l_d, ff)
|
|
|
|
INSN(ftintrne_w_s, ff)
|
|
|
|
INSN(ftintrne_w_d, ff)
|
|
|
|
INSN(ftintrne_l_s, ff)
|
|
|
|
INSN(ftintrne_l_d, ff)
|
|
|
|
INSN(ftint_w_s, ff)
|
|
|
|
INSN(ftint_w_d, ff)
|
|
|
|
INSN(ftint_l_s, ff)
|
|
|
|
INSN(ftint_l_d, ff)
|
|
|
|
INSN(ffint_s_w, ff)
|
|
|
|
INSN(ffint_s_l, ff)
|
|
|
|
INSN(ffint_d_w, ff)
|
|
|
|
INSN(ffint_d_l, ff)
|
|
|
|
INSN(frint_s, ff)
|
|
|
|
INSN(frint_d, ff)
|
|
|
|
INSN(slti, rr_i)
|
|
|
|
INSN(sltui, rr_i)
|
|
|
|
INSN(addi_w, rr_i)
|
|
|
|
INSN(addi_d, rr_i)
|
|
|
|
INSN(lu52i_d, rr_i)
|
|
|
|
INSN(andi, rr_i)
|
|
|
|
INSN(ori, rr_i)
|
|
|
|
INSN(xori, rr_i)
|
|
|
|
INSN(fmadd_s, ffff)
|
|
|
|
INSN(fmadd_d, ffff)
|
|
|
|
INSN(fmsub_s, ffff)
|
|
|
|
INSN(fmsub_d, ffff)
|
|
|
|
INSN(fnmadd_s, ffff)
|
|
|
|
INSN(fnmadd_d, ffff)
|
|
|
|
INSN(fnmsub_s, ffff)
|
|
|
|
INSN(fnmsub_d, ffff)
|
|
|
|
INSN(fsel, fffc)
|
|
|
|
INSN(addu16i_d, rr_i)
|
|
|
|
INSN(lu12i_w, r_i)
|
|
|
|
INSN(lu32i_d, r_i)
|
|
|
|
INSN(ll_w, rr_i)
|
|
|
|
INSN(sc_w, rr_i)
|
|
|
|
INSN(ll_d, rr_i)
|
|
|
|
INSN(sc_d, rr_i)
|
|
|
|
INSN(ldptr_w, rr_i)
|
|
|
|
INSN(stptr_w, rr_i)
|
|
|
|
INSN(ldptr_d, rr_i)
|
|
|
|
INSN(stptr_d, rr_i)
|
|
|
|
INSN(ld_b, rr_i)
|
|
|
|
INSN(ld_h, rr_i)
|
|
|
|
INSN(ld_w, rr_i)
|
|
|
|
INSN(ld_d, rr_i)
|
|
|
|
INSN(st_b, rr_i)
|
|
|
|
INSN(st_h, rr_i)
|
|
|
|
INSN(st_w, rr_i)
|
|
|
|
INSN(st_d, rr_i)
|
|
|
|
INSN(ld_bu, rr_i)
|
|
|
|
INSN(ld_hu, rr_i)
|
|
|
|
INSN(ld_wu, rr_i)
|
|
|
|
INSN(preld, hint_r_i)
|
|
|
|
INSN(fld_s, fr_i)
|
|
|
|
INSN(fst_s, fr_i)
|
|
|
|
INSN(fld_d, fr_i)
|
|
|
|
INSN(fst_d, fr_i)
|
|
|
|
INSN(ldx_b, rrr)
|
|
|
|
INSN(ldx_h, rrr)
|
|
|
|
INSN(ldx_w, rrr)
|
|
|
|
INSN(ldx_d, rrr)
|
|
|
|
INSN(stx_b, rrr)
|
|
|
|
INSN(stx_h, rrr)
|
|
|
|
INSN(stx_w, rrr)
|
|
|
|
INSN(stx_d, rrr)
|
|
|
|
INSN(ldx_bu, rrr)
|
|
|
|
INSN(ldx_hu, rrr)
|
|
|
|
INSN(ldx_wu, rrr)
|
|
|
|
INSN(fldx_s, frr)
|
|
|
|
INSN(fldx_d, frr)
|
|
|
|
INSN(fstx_s, frr)
|
|
|
|
INSN(fstx_d, frr)
|
|
|
|
INSN(amswap_w, rrr)
|
|
|
|
INSN(amswap_d, rrr)
|
|
|
|
INSN(amadd_w, rrr)
|
|
|
|
INSN(amadd_d, rrr)
|
|
|
|
INSN(amand_w, rrr)
|
|
|
|
INSN(amand_d, rrr)
|
|
|
|
INSN(amor_w, rrr)
|
|
|
|
INSN(amor_d, rrr)
|
|
|
|
INSN(amxor_w, rrr)
|
|
|
|
INSN(amxor_d, rrr)
|
|
|
|
INSN(ammax_w, rrr)
|
|
|
|
INSN(ammax_d, rrr)
|
|
|
|
INSN(ammin_w, rrr)
|
|
|
|
INSN(ammin_d, rrr)
|
|
|
|
INSN(ammax_wu, rrr)
|
|
|
|
INSN(ammax_du, rrr)
|
|
|
|
INSN(ammin_wu, rrr)
|
|
|
|
INSN(ammin_du, rrr)
|
|
|
|
INSN(amswap_db_w, rrr)
|
|
|
|
INSN(amswap_db_d, rrr)
|
|
|
|
INSN(amadd_db_w, rrr)
|
|
|
|
INSN(amadd_db_d, rrr)
|
|
|
|
INSN(amand_db_w, rrr)
|
|
|
|
INSN(amand_db_d, rrr)
|
|
|
|
INSN(amor_db_w, rrr)
|
|
|
|
INSN(amor_db_d, rrr)
|
|
|
|
INSN(amxor_db_w, rrr)
|
|
|
|
INSN(amxor_db_d, rrr)
|
|
|
|
INSN(ammax_db_w, rrr)
|
|
|
|
INSN(ammax_db_d, rrr)
|
|
|
|
INSN(ammin_db_w, rrr)
|
|
|
|
INSN(ammin_db_d, rrr)
|
|
|
|
INSN(ammax_db_wu, rrr)
|
|
|
|
INSN(ammax_db_du, rrr)
|
|
|
|
INSN(ammin_db_wu, rrr)
|
|
|
|
INSN(ammin_db_du, rrr)
|
|
|
|
INSN(dbar, i)
|
|
|
|
INSN(ibar, i)
|
|
|
|
INSN(fldgt_s, frr)
|
|
|
|
INSN(fldgt_d, frr)
|
|
|
|
INSN(fldle_s, frr)
|
|
|
|
INSN(fldle_d, frr)
|
|
|
|
INSN(fstgt_s, frr)
|
|
|
|
INSN(fstgt_d, frr)
|
|
|
|
INSN(fstle_s, frr)
|
|
|
|
INSN(fstle_d, frr)
|
|
|
|
INSN(ldgt_b, rrr)
|
|
|
|
INSN(ldgt_h, rrr)
|
|
|
|
INSN(ldgt_w, rrr)
|
|
|
|
INSN(ldgt_d, rrr)
|
|
|
|
INSN(ldle_b, rrr)
|
|
|
|
INSN(ldle_h, rrr)
|
|
|
|
INSN(ldle_w, rrr)
|
|
|
|
INSN(ldle_d, rrr)
|
|
|
|
INSN(stgt_b, rrr)
|
|
|
|
INSN(stgt_h, rrr)
|
|
|
|
INSN(stgt_w, rrr)
|
|
|
|
INSN(stgt_d, rrr)
|
|
|
|
INSN(stle_b, rrr)
|
|
|
|
INSN(stle_h, rrr)
|
|
|
|
INSN(stle_w, rrr)
|
|
|
|
INSN(stle_d, rrr)
|
|
|
|
INSN(beqz, r_offs)
|
|
|
|
INSN(bnez, r_offs)
|
|
|
|
INSN(bceqz, c_offs)
|
|
|
|
INSN(bcnez, c_offs)
|
2023-01-18 03:32:38 +03:00
|
|
|
INSN(jirl, rr_i)
|
2022-06-06 15:43:06 +03:00
|
|
|
INSN(b, offs)
|
|
|
|
INSN(bl, offs)
|
|
|
|
INSN(beq, rr_offs)
|
|
|
|
INSN(bne, rr_offs)
|
|
|
|
INSN(blt, rr_offs)
|
|
|
|
INSN(bge, rr_offs)
|
|
|
|
INSN(bltu, rr_offs)
|
|
|
|
INSN(bgeu, rr_offs)
|
2022-06-06 15:43:15 +03:00
|
|
|
INSN(csrrd, r_csr)
|
|
|
|
INSN(csrwr, r_csr)
|
|
|
|
INSN(csrxchg, rr_csr)
|
2022-06-06 15:43:16 +03:00
|
|
|
INSN(iocsrrd_b, rr)
|
|
|
|
INSN(iocsrrd_h, rr)
|
|
|
|
INSN(iocsrrd_w, rr)
|
|
|
|
INSN(iocsrrd_d, rr)
|
|
|
|
INSN(iocsrwr_b, rr)
|
|
|
|
INSN(iocsrwr_h, rr)
|
|
|
|
INSN(iocsrwr_w, rr)
|
|
|
|
INSN(iocsrwr_d, rr)
|
2022-06-06 15:43:17 +03:00
|
|
|
INSN(tlbsrch, empty)
|
|
|
|
INSN(tlbrd, empty)
|
|
|
|
INSN(tlbwr, empty)
|
|
|
|
INSN(tlbfill, empty)
|
|
|
|
INSN(tlbclr, empty)
|
|
|
|
INSN(tlbflush, empty)
|
|
|
|
INSN(invtlb, i_rr)
|
2022-06-06 15:43:18 +03:00
|
|
|
INSN(cacop, cop_r_i)
|
|
|
|
INSN(lddir, rr_i)
|
|
|
|
INSN(ldpte, j_i)
|
|
|
|
INSN(ertn, empty)
|
|
|
|
INSN(idle, i)
|
|
|
|
INSN(dbcl, i)
|
2022-06-06 15:43:06 +03:00
|
|
|
|
|
|
|
#define output_fcmp(C, PREFIX, SUFFIX) \
|
|
|
|
{ \
|
|
|
|
(C)->info->fprintf_func((C)->info->stream, "%08x %s%s\tfcc%d, f%d, f%d", \
|
|
|
|
(C)->insn, PREFIX, SUFFIX, a->cd, \
|
|
|
|
a->fj, a->fk); \
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool output_cff_fcond(DisasContext *ctx, arg_cff_fcond * a,
|
|
|
|
const char *suffix)
|
|
|
|
{
|
|
|
|
bool ret = true;
|
|
|
|
switch (a->fcond) {
|
|
|
|
case 0x0:
|
|
|
|
output_fcmp(ctx, "fcmp_caf_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x1:
|
|
|
|
output_fcmp(ctx, "fcmp_saf_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x2:
|
|
|
|
output_fcmp(ctx, "fcmp_clt_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x3:
|
|
|
|
output_fcmp(ctx, "fcmp_slt_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x4:
|
|
|
|
output_fcmp(ctx, "fcmp_ceq_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x5:
|
|
|
|
output_fcmp(ctx, "fcmp_seq_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x6:
|
|
|
|
output_fcmp(ctx, "fcmp_cle_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x7:
|
|
|
|
output_fcmp(ctx, "fcmp_sle_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x8:
|
|
|
|
output_fcmp(ctx, "fcmp_cun_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x9:
|
|
|
|
output_fcmp(ctx, "fcmp_sun_", suffix);
|
|
|
|
break;
|
|
|
|
case 0xA:
|
|
|
|
output_fcmp(ctx, "fcmp_cult_", suffix);
|
|
|
|
break;
|
|
|
|
case 0xB:
|
|
|
|
output_fcmp(ctx, "fcmp_sult_", suffix);
|
|
|
|
break;
|
|
|
|
case 0xC:
|
|
|
|
output_fcmp(ctx, "fcmp_cueq_", suffix);
|
|
|
|
break;
|
|
|
|
case 0xD:
|
|
|
|
output_fcmp(ctx, "fcmp_sueq_", suffix);
|
|
|
|
break;
|
|
|
|
case 0xE:
|
|
|
|
output_fcmp(ctx, "fcmp_cule_", suffix);
|
|
|
|
break;
|
|
|
|
case 0xF:
|
|
|
|
output_fcmp(ctx, "fcmp_sule_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x10:
|
|
|
|
output_fcmp(ctx, "fcmp_cne_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x11:
|
|
|
|
output_fcmp(ctx, "fcmp_sne_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x14:
|
|
|
|
output_fcmp(ctx, "fcmp_cor_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x15:
|
|
|
|
output_fcmp(ctx, "fcmp_sor_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x18:
|
|
|
|
output_fcmp(ctx, "fcmp_cune_", suffix);
|
|
|
|
break;
|
|
|
|
case 0x19:
|
|
|
|
output_fcmp(ctx, "fcmp_sune_", suffix);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FCMP_INSN(suffix) \
|
|
|
|
static bool trans_fcmp_cond_##suffix(DisasContext *ctx, \
|
|
|
|
arg_cff_fcond * a) \
|
|
|
|
{ \
|
|
|
|
return output_cff_fcond(ctx, a, #suffix); \
|
|
|
|
}
|
|
|
|
|
|
|
|
FCMP_INSN(s)
|
|
|
|
FCMP_INSN(d)
|
2023-01-18 03:54:50 +03:00
|
|
|
|
|
|
|
#define PCADD_INSN(name) \
|
|
|
|
static bool trans_##name(DisasContext *ctx, arg_##name *a) \
|
|
|
|
{ \
|
|
|
|
output(ctx, #name, "r%d, %d # 0x%" PRIx64, \
|
|
|
|
a->rd, a->imm, gen_##name(ctx->pc, a->imm)); \
|
|
|
|
return true; \
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint64_t gen_pcaddi(uint64_t pc, int imm)
|
|
|
|
{
|
|
|
|
return pc + (imm << 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint64_t gen_pcalau12i(uint64_t pc, int imm)
|
|
|
|
{
|
|
|
|
return (pc + (imm << 12)) & ~0xfff;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint64_t gen_pcaddu12i(uint64_t pc, int imm)
|
|
|
|
{
|
|
|
|
return pc + (imm << 12);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint64_t gen_pcaddu18i(uint64_t pc, int imm)
|
|
|
|
{
|
|
|
|
return pc + ((uint64_t)(imm) << 18);
|
|
|
|
}
|
|
|
|
|
|
|
|
PCADD_INSN(pcaddi)
|
|
|
|
PCADD_INSN(pcalau12i)
|
|
|
|
PCADD_INSN(pcaddu12i)
|
|
|
|
PCADD_INSN(pcaddu18i)
|