qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: Song Gao <gaosong@loongson.cn>, qemu-devel@nongnu.org
Cc: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Subject: Re: [RESEND PATCH v9 16/28] target/loongarch: Add disassembler
Date: Tue, 9 Nov 2021 13:01:18 +0100	[thread overview]
Message-ID: <ac1ec5f7-6c6c-ec33-9575-47bbc01b2be2@linaro.org> (raw)
In-Reply-To: <1636340895-5255-17-git-send-email-gaosong@loongson.cn>

On 11/8/21 4:08 AM, Song Gao wrote:
> +/* operand extractors */
> +#define IM_12 12
> +#define IM_14 14
> +#define IM_15 15
> +#define IM_16 16
> +#define IM_20 20
> +#define IM_21 21
> +#define IM_26 26
> +
> +static uint32_t operand_r1(uint32_t insn)
> +{
> +    return insn & 0x1f;
> +}
> +
> +static uint32_t operand_r2(uint32_t insn)
> +{
> +    return (insn >> 5) & 0x1f;
> +}
> +
> +static uint32_t operand_r3(uint32_t insn)
> +{
> +    return (insn >> 10) & 0x1f;
> +}
> +
> +static uint32_t operand_r4(uint32_t insn)
> +{
> +    return (insn >> 15) & 0x1f;
> +}
> +
> +static uint32_t operand_u6(uint32_t insn)
> +{
> +    return (insn >> 10) & 0x3f;
> +}
> +
> +static uint32_t operand_bw1(uint32_t insn)
> +{
> +    return (insn >> 10) & 0x1f;
> +}
> +
> +static uint32_t operand_bw2(uint32_t insn)
> +{
> +    return (insn >> 16) & 0x1f;
> +}
> +
> +static uint32_t operand_bd1(uint32_t insn)
> +{
> +    return (insn >> 10) & 0x3f;
> +}
> +
> +static uint32_t operand_bd2(uint32_t insn)
> +{
> +    return (insn >> 16) & 0x3f;
> +}
> +
> +static uint32_t operand_sa(uint32_t insn)
> +{
> +    return (insn >> 15) & 0x3;
> +}
> +
> +static int32_t operand_im20(uint32_t insn)
> +{
> +    int32_t imm = (int32_t)((insn >> 5) & 0xfffff);
> +    return imm > (1 << 19) ? imm - (1 << 20) : imm;
> +}
> +
> +static int32_t operand_im16(uint32_t insn)
> +{
> +    int32_t imm = (int32_t)((insn >> 10) & 0xffff);
> +    return imm > (1 << 15) ? imm - (1 << 16) : imm;
> +}
> +
> +static int32_t operand_im14(uint32_t insn)
> +{
> +    int32_t imm = (int32_t)((insn >> 10) & 0x3fff);
> +    return imm > (1 << 13) ? imm - (1 << 14) : imm;
> +}
> +
> +static int32_t operand_im12(uint32_t insn)
> +{
> +    int32_t imm = (int32_t)((insn >> 10) & 0xfff);
> +    return imm > (1 << 11) ? imm - (1 << 12) : imm;
> +}
> +
> +static uint32_t operand_cd(uint32_t insn)
> +{
> +    return insn & 0x7;
> +}
> +
> +static uint32_t operand_cj(uint32_t insn)
> +{
> +    return (insn >> 5) & 0x7;
> +}
> +
> +static uint32_t operand_code(uint32_t insn)
> +{
> +    return insn & 0x7fff;
> +}
> +
> +static int32_t operand_whint(uint32_t insn)
> +{
> +    int32_t imm = (int32_t)(insn & 0x7fff);
> +    return imm > (1 << 14) ? imm - (1 << 15) : imm;
> +}
> +
> +static int32_t operand_ofs21(uint32_t insn)
> +{
> +    int32_t imm = (((int32_t)insn & 0x1f) << 16) |
> +        ((insn >> 10) & 0xffff);
> +    return imm > (1 << 20) ? imm - (1 << 21) : imm;
> +}
> +
> +static int32_t operand_ofs26(uint32_t insn)
> +{
> +    int32_t imm = (((int32_t)insn & 0x3ff) << 16) |
> +        ((insn >> 10) & 0xffff);
> +    return imm > (1 << 25) ? imm - (1 << 26) : imm;
> +}
> +
> +static uint32_t operand_fcond(uint32_t insn)
> +{
> +    return (insn >> 15) & 0x1f;
> +}
> +
> +static uint32_t operand_sel(uint32_t insn)
> +{
> +    return (insn >> 15) & 0x7;
> +}
> +
> +/* decode operands */
> +static void decode_insn_operands(la_decode *dec)
> +{
> +    uint32_t insn = dec->insn;
> +    switch (dec->codec) {
> +    case la_codec_2r:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        break;
> +    case la_codec_2r_u5:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        break;
> +    case la_codec_2r_u6:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_u6(insn);
> +        break;
> +    case la_codec_2r_2bw:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_bw1(insn);
> +        dec->r4 = operand_bw2(insn);
> +        break;
> +    case la_codec_2r_2bd:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_bd1(insn);
> +        dec->r4 = operand_bd2(insn);
> +        break;
> +    case la_codec_3r:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        break;
> +    case la_codec_3r_rd0:
> +        dec->r1 = 0;
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        break;
> +    case la_codec_3r_sa:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        dec->r4 = operand_sa(insn);
> +        break;
> +    case la_codec_4r:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        dec->r4 = operand_r4(insn);
> +        break;
> +    case la_codec_r_im20:
> +        dec->r1 = operand_r1(insn);
> +        dec->imm = operand_im20(insn);
> +        dec->bit = IM_20;
> +        break;
> +    case la_codec_2r_im16:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->imm = operand_im16(insn);
> +        dec->bit = IM_16;
> +        break;
> +    case la_codec_2r_im14:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->imm = operand_im14(insn);
> +        dec->bit = IM_14;
> +        break;
> +    case la_codec_2r_im12:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->imm = operand_im12(insn);
> +        dec->bit = IM_12;
> +        break;
> +    case la_codec_r_cd:
> +        dec->r1 = operand_cd(insn);
> +        dec->r2 = operand_r2(insn);
> +        break;
> +    case la_codec_r_cj:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_cj(insn);
> +        break;
> +    case la_codec_code:
> +        dec->code = operand_code(insn);
> +        break;
> +    case la_codec_whint:
> +        dec->imm = operand_whint(insn);
> +        dec->bit = IM_15;
> +        break;
> +    case la_codec_r_ofs21:
> +        dec->imm = operand_ofs21(insn);
> +        dec->bit = IM_21;
> +        dec->r2 = operand_r2(insn);
> +        break;
> +    case la_codec_cj_ofs21:
> +        dec->imm = operand_ofs21(insn);
> +        dec->bit = IM_21;
> +        dec->r2 = operand_cj(insn);
> +        break;
> +    case la_codec_ofs26:
> +        dec->imm = operand_ofs26(insn);
> +        dec->bit = IM_26;
> +        break;
> +    case la_codec_cond:
> +        dec->r1 = operand_cd(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        dec->r4 = operand_fcond(insn);
> +        break;
> +    case la_codec_sel:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        dec->r4 = operand_sel(insn);
> +        break;
> +    }
> +}

All of this operand extraction has already been done by decodetree.  We do not need to 
re-do it.

> +/* format instruction */
> +static void append(char *s1, const char *s2, size_t n)
> +{
> +    size_t l1 = strlen(s1);
> +    if (n - l1 - 1 > 0) {
> +        strncat(s1, s2, n - l1);
> +    }
> +}
> +
> +static void format_insn(char *buf, size_t buflen,  const char* name,
> +                        const char *fmt, la_decode *dec)
> +{
> +    char tmp[16];

Better to use GString, with no pre-set buflen in the caller.  Or simply output to 
fprintf_func directly; there's no real need to cache it here.

I suggest a better organization is

typedef struct {
     disassemble_info *info;
     uint32_t insn;
} DisasContext;

#define output(C, INSN, FMT, ...) \
     (C)->info->fprintf_func((C)->info->stream, "%08x  %-9s " FMT, \
                             (C)->insn, INSN, ##__VA_ARGS__)

static void output_rdrjrk(DisasContext *ctx,
                           const arg_fmt_rdrjrk *a,
                           const char *mnemonic)
{
     output(ctx, mnemonic, "%s,%s,%s",
            regnames[a->rd], regnames[a->rj], regnames[a->rk]);
}

#define INSN(insn, type) \
     static void trans_##insn(DisasContext *ctx, arg_fmt_##type *a)
     { output_##type(ctx, a, #insn); }

INSN(add_w, rdrjrk)

etc.

This way you have type checking between insns.decode and the list of INSN macros.  The 
complete output for the instruction is done via a single printf.

> +int print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
> +{
> +    bfd_byte buffer[INSNLEN];
> +    unsigned long insn;

uint32_t insn.

> +    int status;
> +
> +    status = (*info->read_memory_func)(memaddr, buffer, INSNLEN, info);
> +    if (status == 0) {
> +        insn = (uint32_t) bfd_getl32(buffer);
> +        (*info->fprintf_func)(info->stream, "%08" PRIx64 " ", insn);

This errors out, because of mismatch between "unsigned long" and "uint64_t" on 32-bit 
hosts.  But better to fold into the single output, per above.

> +    } else {
> +        (*info->memory_error_func)(status, memaddr, info);
> +        return -1;
> +    }
> +
> +    dec.pc = memaddr;
> +    dec.insn = insn;
> +    if (!decode(info, insn)) {
> +        (*info->fprintf_func)(info->stream, "illegal");

Using the above scheme, this becomes

     output(&ctx, illegal, "")


r~


  reply	other threads:[~2021-11-09 12:03 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-08  3:07 [RESEND PATCH v9 00/28] Add LoongArch linux-user emulation support Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 01/28] target/loongarch: Add README Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 02/28] target/loongarch: Add core definition Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 03/28] target/loongarch: Add main translation routines Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 04/28] target/loongarch: Add fixed point arithmetic instruction translation Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 05/28] target/loongarch: Add fixed point shift " Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 06/28] target/loongarch: Add fixed point bit " Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 07/28] target/loongarch: Add fixed point load/store " Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 08/28] target/loongarch: Add fixed point atomic " Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 09/28] target/loongarch: Add fixed point extra " Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 10/28] target/loongarch: Add floating point arithmetic " Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 11/28] target/loongarch: Add floating point comparison " Song Gao
2021-11-08  3:07 ` [RESEND PATCH v9 12/28] target/loongarch: Add floating point conversion " Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 13/28] target/loongarch: Add floating point move " Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 14/28] target/loongarch: Add floating point load/store " Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 15/28] target/loongarch: Add branch " Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 16/28] target/loongarch: Add disassembler Song Gao
2021-11-09 12:01   ` Richard Henderson [this message]
2021-11-09 12:02   ` Richard Henderson
2021-11-08  3:08 ` [RESEND PATCH v9 17/28] linux-user: Add LoongArch generic header files Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 18/28] linux-user: Add LoongArch specific structures Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 19/28] linux-user: Add LoongArch signal support Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 20/28] linux-user: Add LoongArch elf support Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 21/28] linux-user: Add LoongArch syscall support Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 22/28] linux-user: Add LoongArch cpu_loop support Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 23/28] default-configs: Add loongarch linux-user support Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 24/28] target/loongarch: Add target build suport Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 25/28] target/loongarch: 'make check-tcg' support Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 26/28] scripts: add loongarch64 binfmt config Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 27/28] linux-user: Add safe syscall handling for loongarch64 hosts Song Gao
2021-11-08  3:08 ` [RESEND PATCH v9 28/28] linux-user/host/loongarch64: Populate host_signal.h Song Gao
2021-11-09 12:12 ` [RESEND PATCH v9 00/28] Add LoongArch linux-user emulation support Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ac1ec5f7-6c6c-ec33-9575-47bbc01b2be2@linaro.org \
    --to=richard.henderson@linaro.org \
    --cc=gaosong@loongson.cn \
    --cc=qemu-devel@nongnu.org \
    --cc=yangxiaojuan@loongson.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).