diff mbox series

[v7,16/21] target/loongarch: Add disassembler

Message ID 1634561247-25499-17-git-send-email-gaosong@loongson.cn
State New
Headers show
Series Add LoongArch linux-user emulation support | expand

Commit Message

gaosong Oct. 18, 2021, 12:47 p.m. UTC
This patch add support for disassembling via option '-d in_asm'.

Signed-off-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Acked-by: Richard Henderson <richard.henderson@linaro.org>
---
 MAINTAINERS             |    1 +
 disas/loongarch.c       | 2511 +++++++++++++++++++++++++++++++++++++++++++++++
 disas/meson.build       |    1 +
 include/disas/dis-asm.h |    2 +
 meson.build             |    1 +
 5 files changed, 2516 insertions(+)
 create mode 100644 disas/loongarch.c

Comments

WANG Xuerui Oct. 18, 2021, 3:38 p.m. UTC | #1
Hi Song,

On 10/18/21 20:47, Song Gao wrote:
> This patch add support for disassembling via option '-d in_asm'.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> Acked-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   MAINTAINERS             |    1 +
>   disas/loongarch.c       | 2511 +++++++++++++++++++++++++++++++++++++++++++++++
>   disas/meson.build       |    1 +
>   include/disas/dis-asm.h |    2 +
>   meson.build             |    1 +
>   5 files changed, 2516 insertions(+)
>   create mode 100644 disas/loongarch.c

Is content of this patch auto-generated from any sort of data tables, or 
is the big big decoder function hand-written? I didn't see similarities 
between this and the binutils support being upstreamed.

For now any implementation would suffice, and I already saw one or two 
bugs in the output during my TCG host work, but it surely would be nice 
to switch to generated decoder in the future. The loongarch-opcodes 
tables could be extended to support peculiarities as exhibited in the 
v1.00 ISA manual and binutils implementation, via additional attributes, 
and I'm open to such contributions.

>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7df13cc..5ba80ec 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -214,6 +214,7 @@ LoongArch TCG CPUS
>   M: Song Gao <gaosong@loongson.cn>
>   S: Maintained
>   F: target/loongarch/
> +F: disas/loongarch.c
>   
>   M68K TCG CPUs
>   M: Laurent Vivier <laurent@vivier.eu>
> diff --git a/disas/loongarch.c b/disas/loongarch.c
> new file mode 100644
> index 0000000..0647a99
> --- /dev/null
> +++ b/disas/loongarch.c
> @@ -0,0 +1,2511 @@
> +/*
> + * QEMU LoongArch Disassembler
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited.
> + *
> + * SPDX-License-Identifier: LGPL-2.1+
> + */
> +
> +#include "qemu/osdep.h"
> +#include "disas/dis-asm.h"
> +
> +#define INSNLEN 4
> +
> +/* enums */
> +typedef enum {
> +    la_op_illegal = 0,
> +    la_op_clo_w = 1,
> +    la_op_clz_w = 2,
> +    la_op_cto_w = 3,
> +    la_op_ctz_w = 4,
> +    la_op_clo_d = 5,
> +    la_op_clz_d = 6,
> +    la_op_cto_d = 7,
> +    la_op_ctz_d = 8,
> +    la_op_revb_2h = 9,
> +    la_op_revb_4h = 10,
> +    la_op_revb_2w = 11,
> +    la_op_revb_d = 12,
> +    la_op_revh_2w = 13,
> +    la_op_revh_d = 14,
> +    la_op_bitrev_4b = 15,
> +    la_op_bitrev_8b = 16,
> +    la_op_bitrev_w = 17,
> +    la_op_bitrev_d = 18,
> +    la_op_ext_w_h = 19,
> +    la_op_ext_w_b = 20,
> +    la_op_rdtime_d = 21,
> +    la_op_cpucfg = 22,
> +    la_op_asrtle_d = 23,
> +    la_op_asrtgt_d = 24,
> +    la_op_alsl_w = 25,
> +    la_op_alsl_wu = 26,
> +    la_op_bytepick_w = 27,
> +    la_op_bytepick_d = 28,
> +    la_op_add_w = 29,
> +    la_op_add_d = 30,
> +    la_op_sub_w = 31,
> +    la_op_sub_d = 32,
> +    la_op_slt = 33,
> +    la_op_sltu = 34,
> +    la_op_maskeqz = 35,
> +    la_op_masknez = 36,
> +    la_op_nor = 37,
> +    la_op_and = 38,
> +    la_op_or = 39,
> +    la_op_xor = 40,
> +    la_op_orn = 41,
> +    la_op_andn = 42,
> +    la_op_sll_w = 43,
> +    la_op_srl_w = 44,
> +    la_op_sra_w = 45,
> +    la_op_sll_d = 46,
> +    la_op_srl_d = 47,
> +    la_op_sra_d = 48,
> +    la_op_rotr_w = 49,
> +    la_op_rotr_d = 50,
> +    la_op_mul_w = 51,
> +    la_op_mulh_w = 52,
> +    la_op_mulh_wu = 53,
> +    la_op_mul_d = 54,
> +    la_op_mulh_d = 55,
> +    la_op_mulh_du = 56,
> +    la_op_mulw_d_w = 57,
> +    la_op_mulw_d_wu = 58,
> +    la_op_div_w = 59,
> +    la_op_mod_w = 60,
> +    la_op_div_wu = 61,
> +    la_op_mod_wu = 62,
> +    la_op_div_d = 63,
> +    la_op_mod_d = 64,
> +    la_op_div_du = 65,
> +    la_op_mod_du = 66,
> +    la_op_crc_w_b_w = 67,
> +    la_op_crc_w_h_w = 68,
> +    la_op_crc_w_w_w = 69,
> +    la_op_crc_w_d_w = 70,
> +    la_op_crcc_w_b_w = 71,
> +    la_op_crcc_w_h_w = 72,
> +    la_op_crcc_w_w_w = 73,
> +    la_op_crcc_w_d_w = 74,
> +    la_op_break = 75,
> +    la_op_syscall = 76,
> +    la_op_alsl_d = 77,
> +    la_op_slli_w = 78,
> +    la_op_slli_d = 79,
> +    la_op_srli_w = 80,
> +    la_op_srli_d = 81,
> +    la_op_srai_w = 82,
> +    la_op_srai_d = 83,
> +    la_op_rotri_w = 84,
> +    la_op_rotri_d = 85,
> +    la_op_bstrins_w = 86,
> +    la_op_bstrpick_w = 87,
> +    la_op_bstrins_d = 88,
> +    la_op_bstrpick_d = 89,
> +    la_op_fadd_s = 90,
> +    la_op_fadd_d = 91,
> +    la_op_fsub_s = 92,
> +    la_op_fsub_d = 93,
> +    la_op_fmul_s = 94,
> +    la_op_fmul_d = 95,
> +    la_op_fdiv_s = 96,
> +    la_op_fdiv_d = 97,
> +    la_op_fmax_s = 98,
> +    la_op_fmax_d = 99,
> +    la_op_fmin_s = 100,
> +    la_op_fmin_d = 101,
> +    la_op_fmaxa_s = 102,
> +    la_op_fmaxa_d = 103,
> +    la_op_fmina_s = 104,
> +    la_op_fmina_d = 105,
> +    la_op_fscaleb_s = 106,
> +    la_op_fscaleb_d = 107,
> +    la_op_fcopysign_s = 108,
> +    la_op_fcopysign_d = 109,
> +    la_op_fabs_s = 110,
> +    la_op_fabs_d = 111,
> +    la_op_fneg_s = 112,
> +    la_op_fneg_d = 113,
> +    la_op_flogb_s = 114,
> +    la_op_flogb_d = 115,
> +    la_op_fclass_s = 116,
> +    la_op_fclass_d = 117,
> +    la_op_fsqrt_s = 118,
> +    la_op_fsqrt_d = 119,
> +    la_op_frecip_s = 120,
> +    la_op_frecip_d = 121,
> +    la_op_frsqrt_s = 122,
> +    la_op_frsqrt_d = 123,
> +    la_op_fmov_s = 124,
> +    la_op_fmov_d = 125,
> +    la_op_movgr2fr_w = 126,
> +    la_op_movgr2fr_d = 127,
> +    la_op_movgr2frh_w = 128,
> +    la_op_movfr2gr_s = 129,
> +    la_op_movfr2gr_d = 130,
> +    la_op_movfrh2gr_s = 131,
> +    la_op_movgr2fcsr = 132,
> +    la_op_movfcsr2gr = 133,
> +    la_op_movfr2cf = 134,
> +    la_op_movcf2fr = 135,
> +    la_op_movgr2cf = 136,
> +    la_op_movcf2gr = 137,
> +    la_op_fcvt_s_d = 138,
> +    la_op_fcvt_d_s = 139,
> +    la_op_ftintrm_w_s = 140,
> +    la_op_ftintrm_w_d = 141,
> +    la_op_ftintrm_l_s = 142,
> +    la_op_ftintrm_l_d = 143,
> +    la_op_ftintrp_w_s = 144,
> +    la_op_ftintrp_w_d = 145,
> +    la_op_ftintrp_l_s = 146,
> +    la_op_ftintrp_l_d = 147,
> +    la_op_ftintrz_w_s = 148,
> +    la_op_ftintrz_w_d = 149,
> +    la_op_ftintrz_l_s = 150,
> +    la_op_ftintrz_l_d = 151,
> +    la_op_ftintrne_w_s = 152,
> +    la_op_ftintrne_w_d = 153,
> +    la_op_ftintrne_l_s = 154,
> +    la_op_ftintrne_l_d = 155,
> +    la_op_ftint_w_s = 156,
> +    la_op_ftint_w_d = 157,
> +    la_op_ftint_l_s = 158,
> +    la_op_ftint_l_d = 159,
> +    la_op_ffint_s_w = 160,
> +    la_op_ffint_s_l = 161,
> +    la_op_ffint_d_w = 162,
> +    la_op_ffint_d_l = 163,
> +    la_op_frint_s = 164,
> +    la_op_frint_d = 165,
> +    la_op_slti = 166,
> +    la_op_sltui = 167,
> +    la_op_addi_w = 168,
> +    la_op_addi_d = 169,
> +    la_op_lu52i_d = 170,
> +    la_op_addi = 171,
> +    la_op_ori = 172,
> +    la_op_xori = 173,
> +    la_op_rdtimel_w = 174,
> +    la_op_rdtimeh_w = 175,
> +    la_op_fmadd_s = 176,
> +    la_op_fmadd_d = 177,
> +    la_op_fmsub_s = 178,
> +    la_op_fmsub_d = 179,
> +    la_op_fnmadd_s = 180,
> +    la_op_fnmadd_d = 181,
> +    la_op_fnmsub_s = 182,
> +    la_op_fnmsub_d = 183,
> +    la_op_fcmp_cond_s = 184,
> +    la_op_fcmp_cond_d = 185,
> +    la_op_fsel = 186,
> +    la_op_addu16i_d = 187,
> +    la_op_lu12i_w = 188,
> +    la_op_lu32i_d = 189,
> +    la_op_pcaddi = 190,
> +    la_op_pcalau12i = 191,
> +    la_op_pcaddu12i = 192,
> +    la_op_pcaddu18i = 193,
> +    la_op_ll_w = 194,
> +    la_op_sc_w = 195,
> +    la_op_ll_d = 196,
> +    la_op_sc_d = 197,
> +    la_op_ldptr_w = 198,
> +    la_op_stptr_w = 199,
> +    la_op_ldptr_d = 200,
> +    la_op_stptr_d = 201,
> +    la_op_ld_b = 202,
> +    la_op_ld_h = 203,
> +    la_op_ld_w = 204,
> +    la_op_ld_d = 205,
> +    la_op_st_b = 206,
> +    la_op_st_h = 207,
> +    la_op_st_w = 208,
> +    la_op_st_d = 209,
> +    la_op_ld_bu = 210,
> +    la_op_ld_hu = 211,
> +    la_op_ld_wu = 212,
> +    la_op_preld = 213,
> +    la_op_fld_s = 214,
> +    la_op_fst_s = 215,
> +    la_op_fld_d = 216,
> +    la_op_fst_d = 217,
> +    la_op_ldx_b = 218,
> +    la_op_ldx_h = 219,
> +    la_op_ldx_w = 220,
> +    la_op_ldx_d = 221,
> +    la_op_stx_b = 222,
> +    la_op_stx_h = 223,
> +    la_op_stx_w = 224,
> +    la_op_stx_d = 225,
> +    la_op_ldx_bu = 226,
> +    la_op_ldx_hu = 227,
> +    la_op_ldx_wu = 228,
> +    la_op_fldx_s = 229,
> +    la_op_fldx_d = 230,
> +    la_op_fstx_s = 231,
> +    la_op_fstx_d = 232,
> +    la_op_amswap_w = 233,
> +    la_op_amswap_d = 234,
> +    la_op_amadd_w = 235,
> +    la_op_amadd_d = 236,
> +    la_op_amand_w = 237,
> +    la_op_amand_d = 238,
> +    la_op_amor_w = 239,
> +    la_op_amor_d = 240,
> +    la_op_amxor_w = 241,
> +    la_op_amxor_d = 242,
> +    la_op_ammax_w = 243,
> +    la_op_ammax_d = 244,
> +    la_op_ammin_w = 245,
> +    la_op_ammin_d = 246,
> +    la_op_ammax_wu = 247,
> +    la_op_ammax_du = 248,
> +    la_op_ammin_wu = 249,
> +    la_op_ammin_du = 250,
> +    la_op_amswap_db_w = 251,
> +    la_op_amswap_db_d = 252,
> +    la_op_amadd_db_w = 253,
> +    la_op_amadd_db_d = 254,
> +    la_op_amand_db_w = 255,
> +    la_op_amand_db_d = 256,
> +    la_op_amor_db_w = 257,
> +    la_op_amor_db_d = 258,
> +    la_op_amxor_db_w = 259,
> +    la_op_amxor_db_d = 260,
> +    la_op_ammax_db_w = 261,
> +    la_op_ammax_db_d = 262,
> +    la_op_ammin_db_w = 263,
> +    la_op_ammin_db_d = 264,
> +    la_op_ammax_db_wu = 265,
> +    la_op_ammax_db_du = 266,
> +    la_op_ammin_db_wu = 267,
> +    la_op_ammin_db_du = 268,
> +    la_op_dbar = 269,
> +    la_op_ibar = 270,
> +    la_op_fldgt_s = 271,
> +    la_op_fldgt_d = 272,
> +    la_op_fldle_s = 273,
> +    la_op_fldle_d = 274,
> +    la_op_fstgt_s = 275,
> +    la_op_fstgt_d = 276,
> +    ls_op_fstle_s = 277,
> +    la_op_fstle_d = 278,
> +    la_op_ldgt_b = 279,
> +    la_op_ldgt_h = 280,
> +    la_op_ldgt_w = 281,
> +    la_op_ldgt_d = 282,
> +    la_op_ldle_b = 283,
> +    la_op_ldle_h = 284,
> +    la_op_ldle_w = 285,
> +    la_op_ldle_d = 286,
> +    la_op_stgt_b = 287,
> +    la_op_stgt_h = 288,
> +    la_op_stgt_w = 289,
> +    la_op_stgt_d = 290,
> +    la_op_stle_b = 291,
> +    la_op_stle_h = 292,
> +    la_op_stle_w = 293,
> +    la_op_stle_d = 294,
> +    la_op_beqz = 295,
> +    la_op_bnez = 296,
> +    la_op_bceqz = 297,
> +    la_op_bcnez = 298,
> +    la_op_jirl = 299,
> +    la_op_b = 300,
> +    la_op_bl = 301,
> +    la_op_beq = 302,
> +    la_op_bne = 303,
> +    la_op_blt = 304,
> +    la_op_bge = 305,
> +    la_op_bltu = 306,
> +    la_op_bgeu = 307,
> +
> +} la_op;
> +
> +typedef enum {
> +    la_codec_illegal,
> +    la_codec_empty,
> +    la_codec_2r,
> +    la_codec_2r_u5,
> +    la_codec_2r_u6,
> +    la_codec_2r_2bw,
> +    la_codec_2r_2bd,
> +    la_codec_3r,
> +    la_codec_3r_rd0,
> +    la_codec_3r_sa2,
> +    la_codec_3r_sa3,
> +    la_codec_4r,
> +    la_codec_r_im20,
> +    la_codec_2r_im16,
> +    la_codec_2r_im14,
> +    la_codec_r_im14,
> +    la_codec_2r_im12,
> +    la_codec_im5_r_im12,
> +    la_codec_2r_im8,
> +    la_codec_r_sd,
> +    la_codec_r_sj,
> +    la_codec_r_cd,
> +    la_codec_r_cj,
> +    la_codec_r_seq,
> +    la_codec_code,
> +    la_codec_whint,
> +    la_codec_invtlb,
> +    la_codec_r_ofs21,
> +    la_codec_cj_ofs21,
> +    la_codec_ofs26,
> +    la_codec_cond,
> +    la_codec_sel,
> +
> +} la_codec;
> +
> +#define la_fmt_illegal         "nte"
> +#define la_fmt_empty           "nt"
> +#define la_fmt_sd_rj           "ntA,1"
> +#define la_fmt_rd_sj           "nt0,B"

These two seems to be related to the unused "scrX" register bank, and 
can be removed.

Please remove other unused formats while you're at it.

> +#define la_fmt_rd_rj           "nt0,1"
> +#define la_fmt_rj_rk           "nt1,2"
> +#define la_fmt_rj_seq          "nt1,x"
> +#define la_fmt_rd_si20         "nt0,i(x)"
> +#define la_fmt_rd_rj_ui5       "nt0,1,C"
> +#define la_fmt_rd_rj_ui6       "nt0,1.C"
Dot instead of comma?
> +#define la_fmt_rd_rj_level     "nt0,1,x"
> +#define la_fmt_rd_rj_msbw_lsbw "nt0,1,C,D"
> +#define la_fmt_rd_rj_msbd_lsbd "nt0,1,C,D"
> +#define la_fmt_rd_rj_si12      "nt0,1,i(x)"
> +#define la_fmt_hint_rj_si12    "ntE,1,i(x)"
> +#define la_fmt_rd_rj_csr       "nt0,1,x"
> +#define la_fmt_rd_csr          "nt0,x"
> +#define la_fmt_rd_rj_si14      "nt0,1,i(x)"
> +#define la_fmt_rd_rj_si16      "nt0,1,i(x)"
> +#define la_fmt_rd_rj_rk        "nt0,1,2"
> +#define la_fmt_fd_rj_rk        "nt3,1,2"
> +#define la_fmt_rd_rj_rk_sa2    "nt0,1,2,D"
> +#define la_fmt_rd_rj_rk_sa3    "nt0,1,2,D"
> +#define la_fmt_fd_rj           "nt3,1"
> +#define la_fmt_rd_fj           "nt0,4"
> +#define la_fmt_fd_fj           "nt3,4"
> +#define la_fmt_fd_fj_si12      "nt3,4,i(x)"
> +#define la_fmt_fcsrd_rj        "ntF,1"
> +#define la_fmt_rd_fcsrs        "nt0,G"
> +#define la_fmt_cd_fj           "ntH,4"
> +#define la_fmt_fd_cj           "nt3,I"
> +#define la_fmt_fd_fj_fk        "nt3,4,5"
> +#define la_fmt_code            "ntJ"
> +#define la_fmt_whint           "ntx"
> +#define la_fmt_invtlb          "ntx,1,2"
> +#define la_fmt_offs26          "nto(X)p"
> +#define la_fmt_rj_offs21       "nt1,o(X)p"
> +#define la_fmt_cj_offs21       "ntQ,o(X)p"
> +#define la_fmt_rd_rj_offs16    "nt0,1,o(X)"
> +#define la_fmt_rj_rd_offs16    "nt1,0,o(X)p"
> +#define la_fmt_s_cd_fj_fk      "K.stH,4,5"
> +#define la_fmt_d_cd_fj_fk      "K.dtH,4,5"
> +#define la_fmt_fd_fj_fk_fa     "nt3,4,5,6"
> +#define la_fmt_fd_fj_fk_ca     "nt3,4,5,L"
> +#define la_fmt_cop_rj_si12     "ntM,1,i(x)"
> +
> +/* structures */
> +typedef struct {
> +    uint32_t pc;
> +    uint32_t insn;
> +    int32_t imm;
> +    int32_t imm2;
> +    uint16_t op;
> +    uint16_t code;
> +    uint8_t codec;
> +    uint8_t r1;
> +    uint8_t r2;
> +    uint8_t r3;
> +    uint8_t r4;
> +    uint8_t bit;
> +} la_decode;
> +
> +typedef struct {
> +    const char * const name;
> +    const la_codec codec;
> +    const char * const format;
> +} la_opcode_data;
> +
> +/* reg names */
> +const char * const loongarch_r_normal_name[32] = {
> +  "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7",
> +  "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
> +  "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23",
> +  "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31",
We could print ABI names for a lot more readability, what do you think?
> +};
> +
> +const char * const loongarch_f_normal_name[32] = {
> +  "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
> +  "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
> +  "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
> +  "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
> +};
> +
> +const char * const loongarch_cr_normal_name[4] = {
> +  "$scr0", "$scr1", "$scr2", "$scr3",
> +};
Is this register bank used in this code?
> +
> +const char * const loongarch_c_normal_name[8] = {
> +  "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7",
> +};
Register bank is named "fcc" but array name suggests "c". 
"loongarch_fcc_normal_names" would be better. (And fix names of the 
other arrays to use plural form.)
> +
> +/* instruction data */
> +static const  la_opcode_data opcode_data[] = {
Nit: 1 extra space after "const".
> +    { "illegal", la_codec_illegal, la_fmt_illegal },
> +    { "clo.w", la_codec_2r, la_fmt_rd_rj },
> +    { "clz.w", la_codec_2r, la_fmt_rd_rj },
> +    { "cto.w", la_codec_2r, la_fmt_rd_rj },
> +    { "ctz.w", la_codec_2r, la_fmt_rd_rj },
> +    { "clo.d", la_codec_2r, la_fmt_rd_rj },
> +    { "clz.d", la_codec_2r, la_fmt_rd_rj },
> +    { "cto.d", la_codec_2r, la_fmt_rd_rj },
> +    { "ctz_d", la_codec_2r, la_fmt_rd_rj },
> +    { "revb.2h", la_codec_2r, la_fmt_rd_rj },
> +    { "revb.4h", la_codec_2r, la_fmt_rd_rj },
> +    { "revb.2w", la_codec_2r, la_fmt_rd_rj },
> +    { "revb.d", la_codec_2r, la_fmt_rd_rj },
> +    { "revh.2w", la_codec_2r, la_fmt_rd_rj },
> +    { "revh.d", la_codec_2r, la_fmt_rd_rj },
> +    { "bitrev.4b", la_codec_2r, la_fmt_rd_rj },
> +    { "bitrev.8b", la_codec_2r, la_fmt_rd_rj },
> +    { "bitrev.w", la_codec_2r, la_fmt_rd_rj },
> +    { "bitrev.d", la_codec_2r, la_fmt_rd_rj },
> +    { "ext.w.h", la_codec_2r, la_fmt_rd_rj },
> +    { "ext.w.b", la_codec_2r, la_fmt_rd_rj },
> +    { "rdtime.d", la_codec_2r, la_fmt_rd_rj },
> +    { "cpucfg", la_codec_2r, la_fmt_rd_rj },
> +    { "asrtle.d", la_codec_3r_rd0, la_fmt_rj_rk },
> +    { "asrtgt.d", la_codec_3r_rd0, la_fmt_rj_rk },
> +    { "alsl.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
> +    { "alsl.wu", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
> +    { "bytepick.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
> +    { "bytepick.d", la_codec_3r_sa3, la_fmt_rd_rj_rk_sa3 },
> +    { "add.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "add.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "sub.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "sub.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "slt", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "sltu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "maskeqz", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "masknez", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "nor", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "and", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "or", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "xor", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "orn", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "andn", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "sll.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "srl.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "sra.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "sll.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "srl.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "sra.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "rotr.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "rotr.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mul.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mulh.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mulh.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mul.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mulh.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mulh.du", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mulw.d.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mulw.d.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "div.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mod.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "div.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mod.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "div.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mod.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "div.du", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "mod.du", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "crc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "crc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "crc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "crc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "crcc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "crcc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "crcc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "crcc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "break", la_codec_code, la_fmt_code },
> +    { "syscall", la_codec_code, la_fmt_code },
> +    { "alsl.d", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
> +    { "slli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
> +    { "slli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
> +    { "srli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
> +    { "srli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
> +    { "srai.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
> +    { "srai.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
> +    { "rotri.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
> +    { "rotri.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
> +    { "bstrins.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw },
> +    { "bstrpick.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw },
> +    { "bstrins.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd },
> +    { "bstrpick.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd },
> +    { "fadd.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fadd.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fsub.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fsub.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmul.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmul.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fdiv.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fdiv.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmax.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmax.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmin.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmin.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmaxa.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmaxa.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmina.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fmina.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fscaleb.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fscaleb.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fcopysign.s", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fcopysign.d", la_codec_3r, la_fmt_fd_fj_fk },
> +    { "fabs.s", la_codec_2r, la_fmt_fd_fj },
> +    { "fabs.d", la_codec_2r, la_fmt_fd_fj },
> +    { "fneg.s", la_codec_2r, la_fmt_fd_fj },
> +    { "fneg.d", la_codec_2r, la_fmt_fd_fj },
> +    { "flogb.s", la_codec_2r, la_fmt_fd_fj },
> +    { "flogb.d", la_codec_2r, la_fmt_fd_fj },
> +    { "fclass.s", la_codec_2r, la_fmt_fd_fj },
> +    { "fclass.d", la_codec_2r, la_fmt_fd_fj },
> +    { "fsqrt.s", la_codec_2r, la_fmt_fd_fj },
> +    { "fsqrt.d", la_codec_2r, la_fmt_fd_fj },
> +    { "frecip.s", la_codec_2r, la_fmt_fd_fj },
> +    { "frecip.d", la_codec_2r, la_fmt_fd_fj },
> +    { "frsqrt.s", la_codec_2r, la_fmt_fd_fj },
> +    { "frsqrt.d", la_codec_2r, la_fmt_fd_fj },
> +    { "fmov.s", la_codec_2r, la_fmt_fd_fj },
> +    { "fmov.d", la_codec_2r, la_fmt_fd_fj },
> +    { "movgr2fr.w", la_codec_2r, la_fmt_fd_rj },
> +    { "movgr2fr.d", la_codec_2r, la_fmt_fd_rj },
> +    { "movgr2frh.w", la_codec_2r, la_fmt_fd_rj },
> +    { "movfr2gr.s", la_codec_2r, la_fmt_rd_fj },
> +    { "movfr2gr.d", la_codec_2r, la_fmt_rd_fj },
> +    { "movfrh2gr.s", la_codec_2r, la_fmt_rd_fj },
> +    { "movgr2fcsr", la_codec_2r, la_fmt_fcsrd_rj },
> +    { "movfcsr2gr", la_codec_2r, la_fmt_rd_fcsrs },
> +    { "movfr2cf", la_codec_r_cd, la_fmt_cd_fj },
> +    { "movcf2fr", la_codec_r_cj, la_fmt_fd_cj },
> +    { "movgr2cf", la_codec_r_cd, la_fmt_cd_fj },
> +    { "movcf2gr", la_codec_r_cj, la_fmt_fd_cj },
> +    { "fcvt.s.d", la_codec_2r, la_fmt_fd_fj },
> +    { "fcvt.d.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrm.w.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrm.w.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrm.l.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrm.l.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrp.w.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrp.w.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrp.l.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrp.l.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrz.w.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrz.w.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrz.l.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrz.l.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrne.w.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrne.w.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrne.l.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftintrne.l.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftint.w.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftint.w.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ftint.l.s", la_codec_2r, la_fmt_fd_fj },
> +    { "ftint.l.d", la_codec_2r, la_fmt_fd_fj },
> +    { "ffint.s.w", la_codec_2r, la_fmt_fd_fj },
> +    { "ffint.s.l", la_codec_2r, la_fmt_fd_fj },
> +    { "ffint.d.w", la_codec_2r, la_fmt_fd_fj },
> +    { "ffint.d.l", la_codec_2r, la_fmt_fd_fj },
> +    { "frint.s", la_codec_2r, la_fmt_fd_fj },
> +    { "frint.d", la_codec_2r, la_fmt_fd_fj },
> +    { "slti", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "sltui", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "addi.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "addi.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "lu52i.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "addi", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "ori", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "xori", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "rdtimel.w", la_codec_2r, la_fmt_rd_rj },
> +    { "rdtimeh.w", la_codec_2r, la_fmt_rd_rj },
> +    { "fmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
> +    { "fmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
> +    { "fmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
> +    { "fmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
> +    { "fnmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
> +    { "fnmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
> +    { "fnmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
> +    { "fnmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
> +    { "fcmp.cond.s", la_codec_cond, la_fmt_s_cd_fj_fk },
> +    { "fcmp.cond.d", la_codec_cond, la_fmt_d_cd_fj_fk },
> +    { "fsel", la_codec_sel, la_fmt_fd_fj_fk_ca },
> +    { "addu16i.d", la_codec_2r_im16, la_fmt_rd_rj_si16 },
> +    { "lu12i.w", la_codec_r_im20, la_fmt_rd_si20 },
> +    { "lu32i.d", la_codec_r_im20, la_fmt_rd_si20 },
> +    { "pcaddi", la_codec_r_im20, la_fmt_rd_si20 },
> +    { "pcalau12i", la_codec_r_im20, la_fmt_rd_si20 },
> +    { "pcaddu12i", la_codec_r_im20, la_fmt_rd_si20 },
> +    { "pcaddu18i", la_codec_r_im20, la_fmt_rd_si20 },
> +    { "ll.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
> +    { "sc.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
> +    { "ll.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
> +    { "sc.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
> +    { "ldptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
> +    { "stptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
> +    { "ldptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
> +    { "stptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
> +    { "ld.b", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "ld.h", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "ld.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "ld.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "st.b", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "st.h", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "st.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "st.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "ld.bu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "ld.hu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "ld.wu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
> +    { "preld", la_codec_2r_im12, la_fmt_hint_rj_si12 },
> +    { "fld.s", la_codec_2r_im12, la_fmt_fd_fj_si12 },
> +    { "fst.s", la_codec_2r_im12, la_fmt_fd_fj_si12 },
> +    { "fld.d", la_codec_2r_im12, la_fmt_fd_fj_si12 },
> +    { "fst.d", la_codec_2r_im12, la_fmt_fd_fj_si12 },
> +    { "ldx.b", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldx.h", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldx.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldx.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stx.b", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stx.h", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stx.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stx.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldx.bu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldx.hu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldx.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "fldx.s", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fldx.d", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fstx.s", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fstx.d", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "amswap.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amswap.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amadd.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amadd.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amand.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amand.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amor.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amor.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amxor.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amxor.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammax.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammax.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammin.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammin.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammax.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammax.du", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammin.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammin.du", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amswap.db.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amswap.db.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amadd.db.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amadd.db.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amand.db.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amand.db.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amor.db.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amor.db.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amxor.db.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "amxor.db.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammax.db.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammax.db.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammin.db.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammin.db.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammax.db.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammax.db.du", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammin.db.wu", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ammin.db.du", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "dbar", la_codec_whint, la_fmt_whint },
> +    { "ibar", la_codec_whint, la_fmt_whint },
> +    { "fldgt.s", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fldgt.d", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fldle.s", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fldle.d", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fstgt.s", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fstgt.d", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fstle.s", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "fstle.d", la_codec_3r, la_fmt_fd_rj_rk },
> +    { "ldgt.b", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldgt.h", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldgt.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldgt.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldle.b", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldle.h", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldle.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "ldle.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stgt.b", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stgt.h", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stgt.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stgt.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stle.b", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stle.h", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stle.w", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "stle.d", la_codec_3r, la_fmt_rd_rj_rk },
> +    { "beqz", la_codec_r_ofs21, la_fmt_rj_offs21 },
> +    { "bnez", la_codec_r_ofs21, la_fmt_rj_offs21 },
> +    { "bceqz", la_codec_cj_ofs21, la_fmt_cj_offs21 },
> +    { "bcnez", la_codec_cj_ofs21, la_fmt_cj_offs21 },
> +    { "jirl", la_codec_2r_im16, la_fmt_rd_rj_offs16 },
> +    { "b", la_codec_ofs26, la_fmt_offs26 },
> +    { "bl", la_codec_ofs26, la_fmt_offs26 },
> +    { "beq", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
> +    { "bne", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
> +    { "blt", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
> +    { "bge", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
> +    { "bltu", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
> +    { "bgeu", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
> +
> +};
> +
> +
> +/* decode opcode */
> +static void decode_insn_opcode(la_decode *dec)
> +{
> +    uint32_t insn = dec->insn;
> +    uint16_t op = la_op_illegal;
> +    switch ((insn >> 26) & 0x3f) {
> +    case 0x0:
> +        switch ((insn >> 22) & 0xf) {
> +        case 0x0:
> +            switch ((insn >> 18) & 0xf) {
> +            case 0x0:
> +                switch ((insn >> 15) & 0x7) {
> +                case 0x0:
> +                    switch ((insn >> 10) & 0x1f) {
> +                    case 0x4:
> +                        op = la_op_clo_w;
> +                        break;
> +                    case 0x5:
> +                        op = la_op_clz_w;
> +                        break;
> +                    case 0x6:
> +                        op = la_op_cto_w;
> +                        break;
> +                    case 0x7:
> +                        op = la_op_ctz_w;
> +                        break;
> +                    case 0x8:
> +                        op = la_op_clo_d;
> +                        break;
> +                    case 0x9:
> +                        op = la_op_clz_d;
> +                        break;
> +                    case 0xa:
> +                        op = la_op_cto_d;
> +                        break;
> +                    case 0xb:
> +                        op = la_op_ctz_d;
> +                        break;
> +                    case 0xc:
> +                        op = la_op_revb_2h;
> +                        break;
> +                    case 0xd:
> +                        op = la_op_revb_4h;
> +                        break;
> +                    case 0xe:
> +                        op = la_op_revb_2w;
> +                        break;
> +                    case 0xf:
> +                        op = la_op_revb_d;
> +                        break;
> +                    case 0x10:
> +                        op = la_op_revh_2w;
> +                        break;
> +                    case 0x11:
> +                        op = la_op_revh_d;
> +                        break;
> +                    case 0x12:
> +                        op = la_op_bitrev_4b;
> +                        break;
> +                    case 0x13:
> +                        op = la_op_bitrev_8b;
> +                        break;
> +                    case 0x14:
> +                        op = la_op_bitrev_w;
> +                        break;
> +                    case 0x15:
> +                        op = la_op_bitrev_d;
> +                        break;
> +                    case 0x16:
> +                        op = la_op_ext_w_h;
> +                        break;
> +                    case 0x17:
> +                        op = la_op_ext_w_b;
> +                        break;
> +                    case 0x18:
> +                        op = la_op_rdtimel_w;
> +                        break;
> +                    case 0x19:
> +                        op = la_op_rdtimeh_w;
> +                        break;
> +                    case 0x1a:
> +                        op = la_op_rdtime_d;
> +                        break;
> +                    case 0x1b:
> +                        op = la_op_cpucfg;
> +                        break;
> +                    }
> +                    break;
> +                case 0x2:
> +                    switch (insn & 0x0000001f) {
> +                    case 0x00000000:
> +                        op = la_op_asrtle_d;
> +                        break;
> +                    }
> +                    break;
> +                case 0x3:
> +                    switch (insn & 0x0000001f) {
> +                    case 0x00000000:
> +                        op = la_op_asrtgt_d;
> +                        break;
> +                    }
> +                    break;
> +                }
> +                break;
> +            case 0x1:
> +                switch ((insn >> 17) & 0x1) {
> +                case 0x0:
> +                    op = la_op_alsl_w;
> +                    break;
> +                case 0x1:
> +                    op = la_op_alsl_wu;
> +                    break;
> +                }
> +                break;
> +            case 0x2:
> +                switch ((insn >> 17) & 0x1) {
> +                case 0x0:
> +                    op = la_op_bytepick_w;
> +                    break;
> +                }
> +                break;
> +            case 0x3:
> +                op = la_op_bytepick_d;
> +                break;
> +            case 0x4:
> +                switch ((insn >> 15) & 0x7) {
> +                case 0x0:
> +                    op = la_op_add_w;
> +                    break;
> +                case 0x1:
> +                    op = la_op_add_d;
> +                    break;
> +                case 0x2:
> +                    op = la_op_sub_w;
> +                    break;
> +                case 0x3:
> +                    op = la_op_sub_d;
> +                    break;
> +                case 0x4:
> +                    op = la_op_slt;
> +                    break;
> +                case 0x5:
> +                    op = la_op_sltu;
> +                    break;
> +                case 0x6:
> +                    op = la_op_maskeqz;
> +                    break;
> +                case 0x7:
> +                    op = la_op_masknez;
> +                    break;
> +                }
> +                break;
> +            case 0x5:
> +                switch ((insn >> 15) & 0x7) {
> +                case 0x0:
> +                    op = la_op_nor;
> +                    break;
> +                case 0x1:
> +                    op = la_op_and;
> +                    break;
> +                case 0x2:
> +                    op = la_op_or;
> +                    break;
> +                case 0x3:
> +                    op = la_op_xor;
> +                    break;
> +                case 0x4:
> +                    op = la_op_orn;
> +                    break;
> +                case 0x5:
> +                    op = la_op_andn;
> +                    break;
> +                case 0x6:
> +                    op = la_op_sll_w;
> +                    break;
> +                case 0x7:
> +                    op = la_op_srl_w;
> +                    break;
> +                }
> +                break;
> +            case 0x6:
> +                switch ((insn >> 15) & 0x7) {
> +                case 0x0:
> +                    op = la_op_sra_w;
> +                    break;
> +                case 0x1:
> +                    op = la_op_sll_d;
> +                    break;
> +                case 0x2:
> +                    op = la_op_srl_d;
> +                    break;
> +                case 0x3:
> +                    op = la_op_sra_d;
> +                    break;
> +                case 0x6:
> +                    op = la_op_rotr_w;
> +                    break;
> +                case 0x7:
> +                    op = la_op_rotr_d;
> +                    break;
> +                }
> +                break;
> +            case 0x7:
> +                switch ((insn >> 15) & 0x7) {
> +                case 0x0:
> +                    op = la_op_mul_w;
> +                    break;
> +                case 0x1:
> +                    op = la_op_mulh_w;
> +                    break;
> +                case 0x2:
> +                    op = la_op_mulh_wu;
> +                    break;
> +                case 0x3:
> +                    op = la_op_mul_d;
> +                    break;
> +                case 0x4:
> +                    op = la_op_mulh_d;
> +                    break;
> +                case 0x5:
> +                    op = la_op_mulh_du;
> +                    break;
> +                case 0x6:
> +                    op = la_op_mulw_d_w;
> +                    break;
> +                case 0x7:
> +                    op = la_op_mulw_d_wu;
> +                    break;
> +                }
> +                break;
> +            case 0x8:
> +                switch ((insn >> 15) & 0x7) {
> +                case 0x0:
> +                    op = la_op_div_w;
> +                    break;
> +                case 0x1:
> +                    op = la_op_mod_w;
> +                    break;
> +                case 0x2:
> +                    op = la_op_div_wu;
> +                    break;
> +                case 0x3:
> +                    op = la_op_mod_wu;
> +                    break;
> +                case 0x4:
> +                    op = la_op_div_d;
> +                    break;
> +                case 0x5:
> +                    op = la_op_mod_d;
> +                    break;
> +                case 0x6:
> +                    op = la_op_div_du;
> +                    break;
> +                case 0x7:
> +                    op = la_op_mod_du;
> +                    break;
> +                }
> +                break;
> +            case 0x9:
> +                switch ((insn >> 15) & 0x7) {
> +                case 0x0:
> +                    op = la_op_crc_w_b_w;
> +                    break;
> +                case 0x1:
> +                    op = la_op_crc_w_h_w;
> +                    break;
> +                case 0x2:
> +                    op = la_op_crc_w_w_w;
> +                    break;
> +                case 0x3:
> +                    op = la_op_crc_w_d_w;
> +                    break;
> +                case 0x4:
> +                    op = la_op_crcc_w_b_w;
> +                    break;
> +                case 0x5:
> +                    op = la_op_crcc_w_h_w;
> +                    break;
> +                case 0x6:
> +                    op = la_op_crcc_w_w_w;
> +                    break;
> +                case 0x7:
> +                    op = la_op_crcc_w_d_w;
> +                    break;
> +                }
> +                break;
> +            case 0xa:
> +                switch ((insn >> 15) & 0x7) {
> +                case 0x4:
> +                    op = la_op_break;
> +                    break;
> +                case 0x6:
> +                    op = la_op_syscall;
> +                    break;
> +                }
> +                break;
> +            case 0xb:
> +                switch ((insn >> 17) & 0x1) {
> +                case 0x0:
> +                    op = la_op_alsl_d;
> +                    break;
> +                }
> +                break;
> +            }
> +            break;
> +        case 0x1:
> +            switch ((insn >> 21) & 0x1) {
> +            case 0x0:
> +                switch ((insn >> 16) & 0x1f) {
> +                case 0x0:
> +                    switch ((insn >> 15) & 0x1) {
> +                    case 0x1:
> +                        op = la_op_slli_w;
> +                        break;
> +                    }
> +                    break;
> +                case 0x1:
> +                    op = la_op_slli_d;
> +                    break;
> +                case 0x4:
> +                    switch ((insn >> 15) & 0x1) {
> +                    case 0x1:
> +                        op = la_op_srli_w;
> +                        break;
> +                    }
> +                    break;
> +                case 0x5:
> +                    op = la_op_srli_d;
> +                    break;
> +                case 0x8:
> +                    switch ((insn >> 15) & 0x1) {
> +                    case 0x1:
> +                        op = la_op_srai_w;
> +                        break;
> +                    }
> +                    break;
> +                case 0x9:
> +                    op = la_op_srai_d;
> +                    break;
> +                case 0xc:
> +                    switch ((insn >> 15) & 0x1) {
> +                    case 0x1:
> +                        op = la_op_rotri_w;
> +                        break;
> +                    }
> +                    break;
> +                case 0xd:
> +                    op = la_op_rotri_d;
> +                    break;
> +                }
> +                break;
> +            case 0x1:
> +                switch ((insn >> 15) & 0x1) {
> +                case 0x0:
> +                    op = la_op_bstrins_w;
> +                    break;
> +                case 0x1:
> +                    op = la_op_bstrpick_w;
> +                    break;
> +                }
> +                break;
> +            }
> +            break;
> +        case 0x2:
> +            op = la_op_bstrins_d;
> +            break;
> +        case 0x3:
> +            op = la_op_bstrpick_d;
> +            break;
> +        case 0x4:
> +            switch ((insn >> 15) & 0x7f) {
> +            case 0x1:
> +                op = la_op_fadd_s;
> +                break;
> +            case 0x2:
> +                op = la_op_fadd_d;
> +                break;
> +            case 0x5:
> +                op = la_op_fsub_s;
> +                break;
> +            case 0x6:
> +                op = la_op_fsub_d;
> +                break;
> +            case 0x9:
> +                op = la_op_fmul_s;
> +                break;
> +            case 0xa:
> +                op = la_op_fmul_d;
> +                break;
> +            case 0xd:
> +                op = la_op_fdiv_s;
> +                break;
> +            case 0xe:
> +                op = la_op_fdiv_d;
> +                break;
> +            case 0x11:
> +                op = la_op_fmax_s;
> +                break;
> +            case 0x12:
> +                op = la_op_fmax_d;
> +                break;
> +            case 0x15:
> +                op = la_op_fmin_s;
> +                break;
> +            case 0x16:
> +                op = la_op_fmin_d;
> +                break;
> +            case 0x19:
> +                op = la_op_fmaxa_s;
> +                break;
> +            case 0x1a:
> +                op = la_op_fmaxa_d;
> +                break;
> +            case 0x1d:
> +                op = la_op_fmina_s;
> +                break;
> +            case 0x1e:
> +                op = la_op_fmina_d;
> +                break;
> +            case 0x21:
> +                op = la_op_fscaleb_s;
> +                break;
> +            case 0x22:
> +                op = la_op_fscaleb_d;
> +                break;
> +            case 0x25:
> +                op = la_op_fcopysign_s;
> +                break;
> +            case 0x26:
> +                op = la_op_fcopysign_d;
> +                break;
> +            case 0x28:
> +                switch ((insn >> 10) & 0x1f) {
> +                case 0x1:
> +                    op = la_op_fabs_s;
> +                    break;
> +                case 0x2:
> +                    op = la_op_fabs_d;
> +                    break;
> +                case 0x5:
> +                    op = la_op_fneg_s;
> +                    break;
> +                case 0x6:
> +                    op = la_op_fneg_d;
> +                    break;
> +                case 0x9:
> +                    op = la_op_flogb_s;
> +                    break;
> +                case 0xa:
> +                    op = la_op_flogb_d;
> +                    break;
> +                case 0xd:
> +                    op = la_op_fclass_s;
> +                    break;
> +                case 0xe:
> +                    op = la_op_fclass_d;
> +                    break;
> +                case 0x11:
> +                    op = la_op_fsqrt_s;
> +                    break;
> +                case 0x12:
> +                    op = la_op_fsqrt_d;
> +                    break;
> +                case 0x15:
> +                    op = la_op_frecip_s;
> +                    break;
> +                case 0x16:
> +                    op = la_op_frecip_d;
> +                    break;
> +                case 0x19:
> +                    op = la_op_frsqrt_s;
> +                    break;
> +                case 0x1a:
> +                    op = la_op_frsqrt_d;
> +                    break;
> +                }
> +                break;
> +            case 0x29:
> +                switch ((insn >> 10) & 0x1f) {
> +                case 0x5:
> +                    op = la_op_fmov_s;
> +                    break;
> +                case 0x6:
> +                    op = la_op_fmov_d;
> +                    break;
> +                case 0x9:
> +                    op = la_op_movgr2fr_w;
> +                    break;
> +                case 0xa:
> +                    op = la_op_movgr2fr_d;
> +                    break;
> +                case 0xb:
> +                    op = la_op_movgr2frh_w;
> +                    break;
> +                case 0xd:
> +                    op = la_op_movfr2gr_s;
> +                    break;
> +                case 0xe:
> +                    op = la_op_movfr2gr_d;
> +                    break;
> +                case 0xf:
> +                    op = la_op_movfrh2gr_s;
> +                    break;
> +                case 0x10:
> +                    op = la_op_movgr2fcsr;
> +                    break;
> +                case 0x12:
> +                    op = la_op_movfcsr2gr;
> +                    break;
> +                case 0x14:
> +                    switch ((insn >> 3) & 0x3) {
> +                    case 0x0:
> +                        op = la_op_movfr2cf;
> +                        break;
> +                    }
> +                    break;
> +                case 0x15:
> +                    switch ((insn >> 8) & 0x3) {
> +                    case 0x0:
> +                        op = la_op_movcf2fr;
> +                        break;
> +                    }
> +                    break;
> +                case 0x16:
> +                    switch ((insn >> 3) & 0x3) {
> +                    case 0x0:
> +                        op = la_op_movgr2cf;
> +                        break;
> +                    }
> +                    break;
> +                case 0x17:
> +                    switch ((insn >> 8) & 0x3) {
> +                    case 0x0:
> +                        op = la_op_movcf2gr;
> +                        break;
> +                    }
> +                    break;
> +                }
> +                break;
> +            case 0x32:
> +                switch ((insn >> 10) & 0x1f) {
> +                case 0x6:
> +                    op = la_op_fcvt_s_d;
> +                    break;
> +                case 0x9:
> +                    op = la_op_fcvt_d_s;
> +                    break;
> +                }
> +                break;
> +            case 0x34:
> +                switch ((insn >> 10) & 0x1f) {
> +                case 0x1:
> +                    op = la_op_ftintrm_w_s;
> +                    break;
> +                case 0x2:
> +                    op = la_op_ftintrm_w_d;
> +                    break;
> +                case 0x9:
> +                    op = la_op_ftintrm_l_s;
> +                    break;
> +                case 0xa:
> +                    op = la_op_ftintrm_l_d;
> +                    break;
> +                case 0x11:
> +                    op = la_op_ftintrp_w_s;
> +                    break;
> +                case 0x12:
> +                    op = la_op_ftintrp_w_d;
> +                    break;
> +                case 0x19:
> +                    op = la_op_ftintrp_l_s;
> +                    break;
> +                case 0x1a:
> +                    op = la_op_ftintrp_l_d;
> +                    break;
> +                }
> +                break;
> +            case 0x35:
> +                switch ((insn >> 10) & 0x1f) {
> +                case 0x1:
> +                    op = la_op_ftintrz_w_s;
> +                    break;
> +                case 0x2:
> +                    op = la_op_ftintrz_w_d;
> +                    break;
> +                case 0x9:
> +                    op = la_op_ftintrz_l_s;
> +                    break;
> +                case 0xa:
> +                    op = la_op_ftintrz_l_d;
> +                    break;
> +                case 0x11:
> +                    op = la_op_ftintrne_w_s;
> +                    break;
> +                case 0x12:
> +                    op = la_op_ftintrne_w_d;
> +                    break;
> +                case 0x19:
> +                    op = la_op_ftintrne_l_s;
> +                    break;
> +                case 0x1a:
> +                    op = la_op_ftintrne_l_d;
> +                    break;
> +                }
> +                break;
> +            case 0x36:
> +                switch ((insn >> 10) & 0x1f) {
> +                case 0x1:
> +                    op = la_op_ftint_w_s;
> +                    break;
> +                case 0x2:
> +                    op = la_op_ftint_w_d;
> +                    break;
> +                case 0x9:
> +                    op = la_op_ftint_l_s;
> +                    break;
> +                case 0xa:
> +                    op = la_op_ftint_l_d;
> +                    break;
> +                }
> +                break;
> +            case 0x3a:
> +                switch ((insn >> 10) & 0x1f) {
> +                case 0x4:
> +                    op = la_op_ffint_s_w;
> +                    break;
> +                case 0x6:
> +                    op = la_op_ffint_s_l;
> +                    break;
> +                case 0x8:
> +                    op = la_op_ffint_d_w;
> +                    break;
> +                case 0xa:
> +                    op = la_op_ffint_d_l;
> +                    break;
> +                }
> +                break;
> +            case 0x3c:
> +                switch ((insn >> 10) & 0x1f) {
> +                case 0x11:
> +                    op = la_op_frint_s;
> +                    break;
> +                case 0x12:
> +                    op = la_op_frint_d;
> +                    break;
> +                }
> +                break;
> +            }
> +            break;
> +        case 0x8:
> +            op = la_op_slti;
> +            break;
> +        case 0x9:
> +            op = la_op_sltui;
> +            break;
> +        case 0xa:
> +            op = la_op_addi_w;
> +            break;
> +        case 0xb:
> +            op = la_op_addi_d;
> +            break;
> +        case 0xc:
> +            op = la_op_lu52i_d;
> +            break;
> +        case 0xd:
> +            op = la_op_addi;
> +            break;
> +        case 0xe:
> +            op = la_op_ori;
> +            break;
> +        case 0xf:
> +            op = la_op_xori;
> +            break;
> +        }
> +        break;
> +    case 0x2:
> +        switch ((insn >> 20) & 0x3f) {
> +        case 0x1:
> +            op = la_op_fmadd_s;
> +            break;
> +        case 0x2:
> +            op = la_op_fmadd_d;
> +            break;
> +        case 0x5:
> +            op = la_op_fmsub_s;
> +            break;
> +        case 0x6:
> +            op = la_op_fmsub_d;
> +            break;
> +        case 0x9:
> +            op = la_op_fnmadd_s;
> +            break;
> +        case 0xa:
> +            op = la_op_fnmadd_d;
> +            break;
> +        case 0xd:
> +            op = la_op_fnmsub_s;
> +            break;
> +        case 0xe:
> +            op = la_op_fnmsub_d;
> +            break;
> +        }
> +        break;
> +    case 0x3:
> +        switch ((insn >> 20) & 0x3f) {
> +        case 0x1:
> +            switch ((insn >> 3) & 0x3) {
> +            case 0x0:
> +                op = la_op_fcmp_cond_s;
> +                break;
> +            }
> +            break;
> +        case 0x2:
> +            switch ((insn >> 3) & 0x3) {
> +            case 0x0:
> +                op = la_op_fcmp_cond_d;
> +                break;
> +            }
> +            break;
> +        case 0x10:
> +            switch ((insn >> 18) & 0x3) {
> +            case 0x0:
> +                op = la_op_fsel;
> +                break;
> +            }
> +            break;
> +        }
> +        break;
> +    case 0x4:
> +        op = la_op_addu16i_d;
> +        break;
> +    case 0x5:
> +        switch ((insn >> 25) & 0x1) {
> +        case 0x0:
> +            op = la_op_lu12i_w;
> +            break;
> +        case 0x1:
> +            op = la_op_lu32i_d;
> +            break;
> +        }
> +        break;
> +    case 0x6:
> +        switch ((insn >> 25) & 0x1) {
> +        case 0x0:
> +            op = la_op_pcaddi;
> +            break;
> +        case 0x1:
> +            op = la_op_pcalau12i;
> +            break;
> +        }
> +        break;
> +    case 0x7:
> +        switch ((insn >> 25) & 0x1) {
> +        case 0x0:
> +            op = la_op_pcaddu12i;
> +            break;
> +        case 0x1:
> +            op = la_op_pcaddu18i;
> +            break;
> +        }
> +        break;
> +    case 0x8:
> +        switch ((insn >> 24) & 0x3) {
> +        case 0x0:
> +            op = la_op_ll_w;
> +            break;
> +        case 0x1:
> +            op = la_op_sc_w;
> +            break;
> +        case 0x2:
> +            op = la_op_ll_d;
> +            break;
> +        case 0x3:
> +            op = la_op_sc_d;
> +            break;
> +        }
> +        break;
> +    case 0x9:
> +        switch ((insn >> 24) & 0x3) {
> +        case 0x0:
> +            op = la_op_ldptr_w;
> +            break;
> +        case 0x1:
> +            op = la_op_stptr_w;
> +            break;
> +        case 0x2:
> +            op = la_op_ldptr_d;
> +            break;
> +        case 0x3:
> +            op = la_op_stptr_d;
> +            break;
> +        }
> +        break;
> +    case 0xa:
> +        switch ((insn >> 22) & 0xf) {
> +        case 0x0:
> +            op = la_op_ld_b;
> +            break;
> +        case 0x1:
> +            op = la_op_ld_h;
> +            break;
> +        case 0x2:
> +            op = la_op_ld_w;
> +            break;
> +        case 0x3:
> +            op = la_op_ld_d;
> +            break;
> +        case 0x4:
> +            op = la_op_st_b;
> +            break;
> +        case 0x5:
> +            op = la_op_st_h;
> +            break;
> +        case 0x6:
> +            op = la_op_st_w;
> +            break;
> +        case 0x7:
> +            op = la_op_st_d;
> +            break;
> +        case 0x8:
> +            op = la_op_ld_bu;
> +            break;
> +        case 0x9:
> +            op = la_op_ld_hu;
> +            break;
> +        case 0xa:
> +            op = la_op_ld_wu;
> +            break;
> +        case 0xb:
> +            op = la_op_preld;
> +            break;
> +        case 0xc:
> +            op = la_op_fld_s;
> +            break;
> +        case 0xd:
> +            op = la_op_fst_s;
> +            break;
> +        case 0xe:
> +            op = la_op_fld_d;
> +            break;
> +        case 0xf:
> +            op = la_op_fst_d;
> +            break;
> +        }
> +        break;
> +    case 0xe:
> +        switch ((insn >> 15) & 0x7ff) {
> +        case 0x0:
> +            op = la_op_ldx_b;
> +            break;
> +        case 0x8:
> +            op = la_op_ldx_h;
> +            break;
> +        case 0x10:
> +            op = la_op_ldx_w;
> +            break;
> +        case 0x18:
> +            op = la_op_ldx_d;
> +            break;
> +        case 0x20:
> +            op = la_op_stx_b;
> +            break;
> +        case 0x28:
> +            op = la_op_stx_h;
> +            break;
> +        case 0x30:
> +            op = la_op_stx_w;
> +            break;
> +        case 0x38:
> +            op = la_op_stx_d;
> +            break;
> +        case 0x40:
> +            op = la_op_ldx_bu;
> +            break;
> +        case 0x48:
> +            op = la_op_ldx_hu;
> +            break;
> +        case 0x50:
> +            op = la_op_ldx_wu;
> +            break;
> +        case 0x60:
> +            op = la_op_fldx_s;
> +            break;
> +        case 0x68:
> +            op = la_op_fldx_d;
> +            break;
> +        case 0x70:
> +            op = la_op_fstx_s;
> +            break;
> +        case 0x78:
> +            op = la_op_fstx_d;
> +            break;
> +        case 0xc0:
> +            op = la_op_amswap_w;
> +            break;
> +        case 0xc1:
> +            op = la_op_amswap_d;
> +            break;
> +        case 0xc2:
> +            op = la_op_amadd_w;
> +            break;
> +        case 0xc3:
> +            op = la_op_amadd_d;
> +            break;
> +        case 0xc4:
> +            op = la_op_amand_w;
> +            break;
> +        case 0xc5:
> +            op = la_op_amand_d;
> +            break;
> +        case 0xc6:
> +            op = la_op_amor_w;
> +            break;
> +        case 0xc7:
> +            op = la_op_amor_d;
> +            break;
> +        case 0xc8:
> +            op = la_op_amxor_w;
> +            break;
> +        case 0xc9:
> +            op = la_op_amxor_d;
> +            break;
> +        case 0xca:
> +            op = la_op_ammax_w;
> +            break;
> +        case 0xcb:
> +            op = la_op_ammax_d;
> +            break;
> +        case 0xcc:
> +            op = la_op_ammin_w;
> +            break;
> +        case 0xcd:
> +            op = la_op_ammin_d;
> +            break;
> +        case 0xce:
> +            op = la_op_ammax_wu;
> +            break;
> +        case 0xcf:
> +            op = la_op_ammax_du;
> +            break;
> +        case 0xd0:
> +            op = la_op_ammin_wu;
> +             break;
> +        case 0xd1:
> +            op = la_op_ammin_du;
> +            break;
> +        case 0xd2:
> +            op = la_op_amswap_db_w;
> +            break;
> +        case 0xd3:
> +            op = la_op_amswap_db_d;
> +            break;
> +        case 0xd4:
> +            op = la_op_amadd_db_w;
> +            break;
> +        case 0xd5:
> +            op = la_op_amadd_db_d;
> +            break;
> +        case 0xd6:
> +            op = la_op_amand_db_w;
> +            break;
> +        case 0xd7:
> +            op = la_op_amand_db_d;
> +            break;
> +        case 0xd8:
> +            op = la_op_amor_db_w;
> +            break;
> +        case 0xd9:
> +            op = la_op_amor_db_d;
> +            break;
> +        case 0xda:
> +            op = la_op_amxor_db_w;
> +            break;
> +        case 0xdb:
> +            op = la_op_amxor_db_d;
> +            break;
> +        case 0xdc:
> +            op = la_op_ammax_db_w;
> +            break;
> +        case 0xdd:
> +            op = la_op_ammax_db_d;
> +            break;
> +        case 0xde:
> +            op = la_op_ammin_db_w;
> +            break;
> +        case 0xdf:
> +            op = la_op_ammin_db_d;
> +            break;
> +        case 0xe0:
> +            op = la_op_ammax_db_wu;
> +            break;
> +        case 0xe1:
> +            op = la_op_ammax_db_du;
> +            break;
> +        case 0xe2:
> +            op = la_op_ammin_db_wu;
> +            break;
> +        case 0xe3:
> +            op = la_op_ammin_db_du;
> +            break;
> +        case 0xe4:
> +            op = la_op_dbar;
> +            break;
> +        case 0xe5:
> +            op = la_op_ibar;
> +            break;
> +        case 0xe8:
> +            op = la_op_fldgt_s;
> +            break;
> +        case 0xe9:
> +            op = la_op_fldgt_d;
> +            break;
> +        case 0xea:
> +            op = la_op_fldle_s;
> +            break;
> +        case 0xeb:
> +            op = la_op_fldle_d;
> +            break;
> +        case 0xec:
> +            op = la_op_fstgt_s;
> +            break;
> +        case 0xed:
> +            op = la_op_fstgt_d;
> +            break;
> +        case 0xee:
> +            op = ls_op_fstle_s;
> +            break;
> +        case 0xef:
> +            op = la_op_fstle_d;
> +            break;
> +        case 0xf0:
> +            op = la_op_ldgt_b;
> +            break;
> +        case 0xf1:
> +            op = la_op_ldgt_h;
> +            break;
> +        case 0xf2:
> +            op = la_op_ldgt_w;
> +            break;
> +        case 0xf3:
> +            op = la_op_ldgt_d;
> +            break;
> +        case 0xf4:
> +            op = la_op_ldle_b;
> +            break;
> +        case 0xf5:
> +            op = la_op_ldle_h;
> +            break;
> +        case 0xf6:
> +            op = la_op_ldle_w;
> +            break;
> +        case 0xf7:
> +            op = la_op_ldle_d;
> +            break;
> +        case 0xf8:
> +            op = la_op_stgt_b;
> +            break;
> +        case 0xf9:
> +            op = la_op_stgt_h;
> +            break;
> +        case 0xfa:
> +            op = la_op_stgt_w;
> +            break;
> +        case 0xfb:
> +            op = la_op_stgt_d;
> +            break;
> +        case 0xfc:
> +            op = la_op_stle_b;
> +            break;
> +        case 0xfd:
> +            op = la_op_stle_h;
> +            break;
> +        case 0xfe:
> +            op = la_op_stle_w;
> +            break;
> +        case 0xff:
> +            op = la_op_stle_d;
> +            break;
> +        }
> +        break;
> +    case 0x10:
> +        op = la_op_beqz;
> +        break;
> +    case 0x11:
> +        op = la_op_bnez;
> +        break;
> +    case 0x12:
> +        switch ((insn >> 8) & 0x3) {
> +        case 0x0:
> +            op = la_op_bceqz;
> +            break;
> +        case 0x1:
> +            op = la_op_bcnez;
> +            break;
> +        }
> +        break;
> +    case 0x13:
> +        op = la_op_jirl;
> +        break;
> +    case 0x14:
> +        op = la_op_b;
> +        break;
> +    case 0x15:
> +        op = la_op_bl;
> +        break;
> +    case 0x16:
> +        op = la_op_beq;
> +        break;
> +    case 0x17:
> +        op = la_op_bne;
> +        break;
> +    case 0x18:
> +        op = la_op_blt;
> +        break;
> +    case 0x19:
> +        op = la_op_bge;
> +        break;
> +    case 0x1a:
> +        op = la_op_bltu;
> +        break;
> +    case 0x1b:
> +        op = la_op_bgeu;
> +        break;
> +    default:
> +        op = la_op_illegal;
> +        break;
> +    }
> +    dec->op = op;
> +}
> +
> +/* operand extractors */
> +#define IM_5  5
> +#define IM_8  8
> +#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_sa2(uint32_t insn)
> +{
> +    return (insn >> 15) & 0x3;
> +}
> +
> +static uint32_t operand_sa3(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 int32_t operand_im8(uint32_t insn)
> +{
> +    int32_t imm = (int32_t)((insn >> 10) & 0xff);
> +    return imm > (1 << 7) ? imm - (1 << 8) : imm;
> +}
> +
> +static uint32_t operand_sd(uint32_t insn)
> +{
> +    return insn & 0x3;
> +}
> +
> +static uint32_t operand_sj(uint32_t insn)
> +{
> +    return (insn >> 5) & 0x3;
> +}
> +
> +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_invop(uint32_t insn)
> +{
> +    int32_t imm = (int32_t)(insn & 0x1f);
> +    return imm > (1 << 4) ? imm - (1 << 5) : 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;
> +    dec->codec = opcode_data[dec->op].codec;
> +    switch (dec->codec) {
> +    case la_codec_illegal:
> +    case la_codec_empty:
> +        break;
> +    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_sa2:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        dec->r4 = operand_sa2(insn);
> +        break;
> +    case la_codec_3r_sa3:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        dec->r4 = operand_sa3(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_r_im14:
> +        dec->r1 = operand_r1(insn);
> +        dec->imm = operand_im14(insn);
> +        dec->bit = IM_14;
> +        break;
> +    case la_codec_im5_r_im12:
> +        dec->imm2 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->imm = operand_im12(insn);
> +        dec->bit = IM_12;
> +        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_2r_im8:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_r2(insn);
> +        dec->imm = operand_im8(insn);
> +        dec->bit = IM_8;
> +        break;
> +    case la_codec_r_sd:
> +        dec->r1 = operand_sd(insn);
> +        dec->r2 = operand_r2(insn);
> +        break;
> +    case la_codec_r_sj:
> +        dec->r1 = operand_r1(insn);
> +        dec->r2 = operand_sj(insn);
> +        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_r_seq:
> +        dec->r1 = 0;
> +        dec->r2 = operand_r1(insn);
> +        dec->imm = operand_im8(insn);
> +        dec->bit = IM_8;
> +        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_invtlb:
> +        dec->imm = operand_invop(insn);
> +        dec->bit = IM_5;
> +        dec->r2 = operand_r2(insn);
> +        dec->r3 = operand_r3(insn);
> +        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;
> +    }
> +}
> +
> +/* 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, size_t tab, la_decode *dec)
> +{
> +    char tmp[16];
> +    const char *fmt;
> +
> +    fmt = opcode_data[dec->op].format;
> +    while (*fmt) {
> +        switch (*fmt) {
> +        case 'n': /* name */
> +            append(buf, opcode_data[dec->op].name, buflen);
> +            break;
> +        case 's':
> +            append(buf, "s", buflen);
> +            break;
> +        case 'd':
> +            append(buf, "d", buflen);
> +            break;
> +        case 'e': /* illegal */
> +            snprintf(tmp, sizeof(tmp), "%x", dec->insn);
> +            append(buf, tmp, buflen);
> +            break;
> +        case 't':
> +            while (strlen(buf) < tab) {
> +                append(buf, " ", buflen);
> +            }
> +            break;
> +        case '(':
> +            append(buf, "(", buflen);
> +            break;
> +        case ',':
> +            append(buf, ",", buflen);
> +            break;
> +        case '.':
> +            append(buf, ".", buflen);
> +            break;
> +        case ')':
> +            append(buf, ")", buflen);
> +            break;
> +        case '0': /* rd */
> +            append(buf, loongarch_r_normal_name[dec->r1], buflen);
> +            break;
> +        case '1': /* rj */
> +            append(buf, loongarch_r_normal_name[dec->r2], buflen);
> +            break;
> +        case '2': /* rk */
> +            append(buf, loongarch_r_normal_name[dec->r3], buflen);
> +            break;
> +        case '3': /* fd */
> +            append(buf, loongarch_f_normal_name[dec->r1], buflen);
> +            break;
> +        case '4': /* fj */
> +            append(buf, loongarch_f_normal_name[dec->r2], buflen);
> +            break;
> +        case '5': /* fk */
> +            append(buf, loongarch_f_normal_name[dec->r3], buflen);
> +            break;
> +        case '6': /* fa */
> +            append(buf, loongarch_f_normal_name[dec->r4], buflen);
> +            break;
> +        case 'A': /* sd */
> +            append(buf, loongarch_cr_normal_name[dec->r1], buflen);
> +            break;
> +        case 'B': /* sj */
> +            append(buf, loongarch_cr_normal_name[dec->r2], buflen);
> +            break;
> +        case 'C': /* r3 */
> +            snprintf(tmp, sizeof(tmp), "%x", dec->r3);
> +            append(buf, tmp, buflen);
> +            break;
> +        case 'D': /* r4 */
> +            snprintf(tmp, sizeof(tmp), "%x", dec->r4);
> +            append(buf, tmp, buflen);
> +            break;
> +        case 'E': /* r1 */
> +            snprintf(tmp, sizeof(tmp), "%x", dec->r1);
> +            append(buf, tmp, buflen);
> +            break;
> +        case 'F': /* fcsrd */
> +            append(buf, loongarch_r_normal_name[dec->r1], buflen);
> +            break;
> +        case 'G': /* fcsrs */
> +            append(buf, loongarch_r_normal_name[dec->r2], buflen);
> +            break;
> +        case 'H': /* cd */
> +            append(buf, loongarch_c_normal_name[dec->r1], buflen);
> +            break;
> +        case 'I': /* cj */
> +            append(buf, loongarch_c_normal_name[dec->r2], buflen);
> +            break;
> +        case 'J': /* code */
> +            snprintf(tmp, sizeof(tmp), "0x%x", dec->code);
> +            append(buf, tmp, buflen);
> +            break;
> +        case 'K': /* cond */
> +            switch (dec->r4) {
> +            case 0x0:
> +                append(buf, "caf", buflen);
> +                break;
> +            case 0x1:
> +                append(buf, "saf", buflen);
> +                break;
> +            case 0x2:
> +                append(buf, "clt", buflen);
> +                break;
> +            case 0x3:
> +                append(buf, "slt", buflen);
> +                break;
> +            case 0x4:
> +                append(buf, "ceq", buflen);
> +                break;
> +            case 0x5:
> +                append(buf, "seq", buflen);
> +                break;
> +            case 0x6:
> +                append(buf, "cle", buflen);
> +                break;
> +            case 0x7:
> +                append(buf, "sle", buflen);
> +                break;
> +            case 0x8:
> +                append(buf, "cun", buflen);
> +                break;
> +            case 0x9:
> +                append(buf, "sun", buflen);
> +                break;
> +            case 0xA:
> +                append(buf, "cult", buflen);
> +                break;
> +            case 0xB:
> +                append(buf, "sult", buflen);
> +                break;
> +            case 0xC:
> +                append(buf, "cueq", buflen);
> +                break;
> +            case 0xD:
> +                append(buf, "sueq", buflen);
> +                break;
> +            case 0xE:
> +                append(buf, "cule", buflen);
> +                break;
> +            case 0xF:
> +                append(buf, "sule", buflen);
> +                break;
> +            case 0x10:
> +                append(buf, "cne", buflen);
> +                break;
> +            case 0x11:
> +                append(buf, "sne", buflen);
> +                break;
> +            case 0x14:
> +                append(buf, "cor", buflen);
> +                break;
> +            case 0x15:
> +                append(buf, "sor", buflen);
> +                break;
> +            case 0x18:
> +                append(buf, "cune", buflen);
> +                break;
> +            case 0x19:
> +                append(buf, "sune", buflen);
> +                break;
> +            }
> +            break;
> +        case 'L': /* ca */
> +            append(buf, loongarch_c_normal_name[dec->r4], buflen);
> +            break;
> +        case 'M': /* cop */
> +            snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm2) & 0x1f);
> +            append(buf, tmp, buflen);
> +            break;
> +        case 'i': /* sixx d */
> +            snprintf(tmp, sizeof(tmp), "%d", dec->imm);
> +            append(buf, tmp, buflen);
> +            break;
> +        case 'o': /* offset */
> +            snprintf(tmp, sizeof(tmp), "%d", (dec->imm) << 2);
> +            append(buf, tmp, buflen);
> +            break;
> +        case 'x': /* sixx x */
> +            switch (dec->bit) {
> +            case IM_5:
> +                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x1f);
> +                append(buf, tmp, buflen);
> +                break;
> +            case IM_8:
> +                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xff);
> +                append(buf, tmp, buflen);
> +                break;
> +            case IM_12:
> +                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfff);
> +                append(buf, tmp, buflen);
> +                break;
> +            case IM_14:
> +                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x3fff);
> +                append(buf, tmp, buflen);
> +                break;
> +            case IM_15:
> +                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x7fff);
> +                append(buf, tmp, buflen);
> +                break;
> +            case IM_16:
> +                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xffff);
> +                append(buf, tmp, buflen);
> +                break;
> +            case IM_20:
> +                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfffff);
> +                append(buf, tmp, buflen);
> +                break;
> +            default:
> +                snprintf(tmp, sizeof(tmp), "0x%x", dec->imm);
> +                append(buf, tmp, buflen);
> +                break;
> +            }
> +            break;
> +        case 'X': /* offset x*/
> +            switch (dec->bit) {
> +            case IM_16:
> +                snprintf(tmp, sizeof(tmp), "0x%x",
> +                    ((dec->imm) << 2) & 0xffff);
> +                append(buf, tmp, buflen);
> +                break;
> +            case IM_21:
> +                snprintf(tmp, sizeof(tmp), "0x%x",
> +                    ((dec->imm) << 2) & 0x1fffff);
> +                append(buf, tmp, buflen);
> +                break;
> +            case IM_26:
> +                snprintf(tmp, sizeof(tmp), "0x%x",
> +                    ((dec->imm) << 2) & 0x3ffffff);
> +                append(buf, tmp, buflen);
> +                break;
> +            default:
> +                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) << 2);
> +                append(buf, tmp, buflen);
> +                break;
> +            }
> +            break;
> +        case 'p': /* pc */
> +            snprintf(tmp, sizeof(tmp), "  # 0x%"PRIx32"",
> +                dec->pc + ((dec->imm) << 2));
> +            append(buf, tmp, buflen);
> +            break;
> +        default:
> +            break;
> +        }
> +        fmt++;
> +    }
> +}
> +
> +/* disassemble instruction */
> +static void
> +disasm_insn(char *buf, size_t buflen, bfd_vma pc, unsigned long int insn)
> +{
> +    la_decode dec = { 0 };
> +    dec.pc = pc;
> +    dec.insn = insn;
> +    decode_insn_opcode(&dec);
> +    decode_insn_operands(&dec);
> +    format_insn(buf, buflen, 16, &dec);
> +}
> +
> +int
> +print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
> +{
> +    char buf[128] = { 0 };
> +    bfd_byte buffer[INSNLEN];
> +    unsigned long 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);
> +    } else {
> +        (*info->memory_error_func)(status, memaddr, info);
> +        return -1;
> +    }
> +    disasm_insn(buf, sizeof(buf), memaddr, insn);
> +    (*info->fprintf_func)(info->stream, "\t%s", buf);
> +    return INSNLEN;
> +}
> diff --git a/disas/meson.build b/disas/meson.build
> index 449f99e..a1bd8b8 100644
> --- a/disas/meson.build
> +++ b/disas/meson.build
> @@ -9,6 +9,7 @@ common_ss.add(when: 'CONFIG_CRIS_DIS', if_true: files('cris.c'))
>   common_ss.add(when: 'CONFIG_HEXAGON_DIS', if_true: files('hexagon.c'))
>   common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c'))
>   common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c'))
> +common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: files('loongarch.c'))
>   common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c'))
>   common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c'))
>   common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c'))
> diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
> index 524f291..009a03a 100644
> --- a/include/disas/dis-asm.h
> +++ b/include/disas/dis-asm.h
> @@ -253,6 +253,7 @@ enum bfd_architecture
>   #define bfd_mach_rx            0x75
>   #define bfd_mach_rx_v2         0x76
>   #define bfd_mach_rx_v3         0x77
> +  bfd_arch_loongarch,
>     bfd_arch_last
>     };
>   #define bfd_mach_s390_31 31
> @@ -462,6 +463,7 @@ int print_insn_riscv32          (bfd_vma, disassemble_info*);
>   int print_insn_riscv64          (bfd_vma, disassemble_info*);
>   int print_insn_rx(bfd_vma, disassemble_info *);
>   int print_insn_hexagon(bfd_vma, disassemble_info *);
> +int print_insn_loongarch(bfd_vma, disassemble_info *);
>   
>   #ifdef CONFIG_CAPSTONE
>   bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
> diff --git a/meson.build b/meson.build
> index 6b7487b..c272e58 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -1797,6 +1797,7 @@ disassemblers = {
>     'sh4' : ['CONFIG_SH4_DIS'],
>     'sparc' : ['CONFIG_SPARC_DIS'],
>     'xtensa' : ['CONFIG_XTENSA_DIS'],
> +  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
>   }
>   if link_language == 'cpp'
>     disassemblers += {
Richard Henderson Oct. 18, 2021, 5:29 p.m. UTC | #2
On 10/18/21 8:38 AM, WANG Xuerui wrote:
> 
> For now any implementation would suffice, and I already saw one or two bugs in the output 
> during my TCG host work, but it surely would be nice to switch to generated decoder in the 
> future. The loongarch-opcodes tables could be extended to support peculiarities as 
> exhibited in the v1.00 ISA manual and binutils implementation, via additional attributes, 
> and I'm open to such contributions.

Perhaps it would be easiest to re-use the decodetree description?
See e.g. target/openrisc/disas.c.


r~
WANG Xuerui Oct. 18, 2021, 6:18 p.m. UTC | #3
On 10/19/21 01:29, Richard Henderson wrote:
> On 10/18/21 8:38 AM, WANG Xuerui wrote:
>>
>> For now any implementation would suffice, and I already saw one or 
>> two bugs in the output during my TCG host work, but it surely would 
>> be nice to switch to generated decoder in the future. The 
>> loongarch-opcodes tables could be extended to support peculiarities 
>> as exhibited in the v1.00 ISA manual and binutils implementation, via 
>> additional attributes, and I'm open to such contributions.
>
> Perhaps it would be easiest to re-use the decodetree description?
> See e.g. target/openrisc/disas.c.
>
Indeed; I didn't thought of disassemblers in target/ instead of disas/. 
That would be the most elegant way forward!
>
> r~
>
Richard Henderson Oct. 18, 2021, 6:33 p.m. UTC | #4
On 10/18/21 11:18 AM, WANG Xuerui wrote:
> 
> On 10/19/21 01:29, Richard Henderson wrote:
>> On 10/18/21 8:38 AM, WANG Xuerui wrote:
>>>
>>> For now any implementation would suffice, and I already saw one or two bugs in the 
>>> output during my TCG host work, but it surely would be nice to switch to generated 
>>> decoder in the future. The loongarch-opcodes tables could be extended to support 
>>> peculiarities as exhibited in the v1.00 ISA manual and binutils implementation, via 
>>> additional attributes, and I'm open to such contributions.
>>
>> Perhaps it would be easiest to re-use the decodetree description?
>> See e.g. target/openrisc/disas.c.
>>
> Indeed; I didn't thought of disassemblers in target/ instead of disas/. That would be the 
> most elegant way forward!


The one quirk will be that so far using decodetree for disas is limited to the target, 
whereas you'll want this for host as well.  It shouldn't be a big deal, just a small 
matter of the correct build rules.


r~
Philippe Mathieu-Daudé Oct. 18, 2021, 6:57 p.m. UTC | #5
On 10/18/21 20:33, Richard Henderson wrote:
> On 10/18/21 11:18 AM, WANG Xuerui wrote:
>> On 10/19/21 01:29, Richard Henderson wrote:
>>> On 10/18/21 8:38 AM, WANG Xuerui wrote:
>>>>
>>>> For now any implementation would suffice, and I already saw one or
>>>> two bugs in the output during my TCG host work, but it surely would
>>>> be nice to switch to generated decoder in the future. The
>>>> loongarch-opcodes tables could be extended to support peculiarities
>>>> as exhibited in the v1.00 ISA manual and binutils implementation,
>>>> via additional attributes, and I'm open to such contributions.
>>>
>>> Perhaps it would be easiest to re-use the decodetree description?
>>> See e.g. target/openrisc/disas.c.
>>>
>> Indeed; I didn't thought of disassemblers in target/ instead of
>> disas/. That would be the most elegant way forward!
> 
> 
> The one quirk will be that so far using decodetree for disas is limited
> to the target, whereas you'll want this for host as well.  It shouldn't
> be a big deal, just a small matter of the correct build rules.

Oh, good to know. OTOH I expect very few developers to look at
host disas.
gaosong Oct. 20, 2021, 6:37 a.m. UTC | #6
Hi, all.

On 10/19/2021 02:57 AM, Philippe Mathieu-Daudé wrote:
> On 10/18/21 20:33, Richard Henderson wrote:
>> On 10/18/21 11:18 AM, WANG Xuerui wrote:
>>> On 10/19/21 01:29, Richard Henderson wrote:
>>>> On 10/18/21 8:38 AM, WANG Xuerui wrote:
>>>>>
>>>>> For now any implementation would suffice, and I already saw one or
>>>>> two bugs in the output during my TCG host work, but it surely would
>>>>> be nice to switch to generated decoder in the future. The
>>>>> loongarch-opcodes tables could be extended to support peculiarities
>>>>> as exhibited in the v1.00 ISA manual and binutils implementation,
>>>>> via additional attributes, and I'm open to such contributions.
>>>>
>>>> Perhaps it would be easiest to re-use the decodetree description?
>>>> See e.g. target/openrisc/disas.c.
>>>>
>>> Indeed; I didn't thought of disassemblers in target/ instead of
>>> disas/. That would be the most elegant way forward!
>>
>>
>> The one quirk will be that so far using decodetree for disas is limited
>> to the target, whereas you'll want this for host as well.  It shouldn't
>> be a big deal, just a small matter of the correct build rules.
> 
> Oh, good to know. OTOH I expect very few developers to look at
> host disas.
> 

Sorry to reply too late, I asked for leave yesterday.

This patch refers to disas/riscv.c. 

I didn't notice target/openrisc/disas.c before.  Thanks for Richard' advice.


Thanks
Song Gao
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 7df13cc..5ba80ec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -214,6 +214,7 @@  LoongArch TCG CPUS
 M: Song Gao <gaosong@loongson.cn>
 S: Maintained
 F: target/loongarch/
+F: disas/loongarch.c
 
 M68K TCG CPUs
 M: Laurent Vivier <laurent@vivier.eu>
diff --git a/disas/loongarch.c b/disas/loongarch.c
new file mode 100644
index 0000000..0647a99
--- /dev/null
+++ b/disas/loongarch.c
@@ -0,0 +1,2511 @@ 
+/*
+ * QEMU LoongArch Disassembler
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited.
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+
+#define INSNLEN 4
+
+/* enums */
+typedef enum {
+    la_op_illegal = 0,
+    la_op_clo_w = 1,
+    la_op_clz_w = 2,
+    la_op_cto_w = 3,
+    la_op_ctz_w = 4,
+    la_op_clo_d = 5,
+    la_op_clz_d = 6,
+    la_op_cto_d = 7,
+    la_op_ctz_d = 8,
+    la_op_revb_2h = 9,
+    la_op_revb_4h = 10,
+    la_op_revb_2w = 11,
+    la_op_revb_d = 12,
+    la_op_revh_2w = 13,
+    la_op_revh_d = 14,
+    la_op_bitrev_4b = 15,
+    la_op_bitrev_8b = 16,
+    la_op_bitrev_w = 17,
+    la_op_bitrev_d = 18,
+    la_op_ext_w_h = 19,
+    la_op_ext_w_b = 20,
+    la_op_rdtime_d = 21,
+    la_op_cpucfg = 22,
+    la_op_asrtle_d = 23,
+    la_op_asrtgt_d = 24,
+    la_op_alsl_w = 25,
+    la_op_alsl_wu = 26,
+    la_op_bytepick_w = 27,
+    la_op_bytepick_d = 28,
+    la_op_add_w = 29,
+    la_op_add_d = 30,
+    la_op_sub_w = 31,
+    la_op_sub_d = 32,
+    la_op_slt = 33,
+    la_op_sltu = 34,
+    la_op_maskeqz = 35,
+    la_op_masknez = 36,
+    la_op_nor = 37,
+    la_op_and = 38,
+    la_op_or = 39,
+    la_op_xor = 40,
+    la_op_orn = 41,
+    la_op_andn = 42,
+    la_op_sll_w = 43,
+    la_op_srl_w = 44,
+    la_op_sra_w = 45,
+    la_op_sll_d = 46,
+    la_op_srl_d = 47,
+    la_op_sra_d = 48,
+    la_op_rotr_w = 49,
+    la_op_rotr_d = 50,
+    la_op_mul_w = 51,
+    la_op_mulh_w = 52,
+    la_op_mulh_wu = 53,
+    la_op_mul_d = 54,
+    la_op_mulh_d = 55,
+    la_op_mulh_du = 56,
+    la_op_mulw_d_w = 57,
+    la_op_mulw_d_wu = 58,
+    la_op_div_w = 59,
+    la_op_mod_w = 60,
+    la_op_div_wu = 61,
+    la_op_mod_wu = 62,
+    la_op_div_d = 63,
+    la_op_mod_d = 64,
+    la_op_div_du = 65,
+    la_op_mod_du = 66,
+    la_op_crc_w_b_w = 67,
+    la_op_crc_w_h_w = 68,
+    la_op_crc_w_w_w = 69,
+    la_op_crc_w_d_w = 70,
+    la_op_crcc_w_b_w = 71,
+    la_op_crcc_w_h_w = 72,
+    la_op_crcc_w_w_w = 73,
+    la_op_crcc_w_d_w = 74,
+    la_op_break = 75,
+    la_op_syscall = 76,
+    la_op_alsl_d = 77,
+    la_op_slli_w = 78,
+    la_op_slli_d = 79,
+    la_op_srli_w = 80,
+    la_op_srli_d = 81,
+    la_op_srai_w = 82,
+    la_op_srai_d = 83,
+    la_op_rotri_w = 84,
+    la_op_rotri_d = 85,
+    la_op_bstrins_w = 86,
+    la_op_bstrpick_w = 87,
+    la_op_bstrins_d = 88,
+    la_op_bstrpick_d = 89,
+    la_op_fadd_s = 90,
+    la_op_fadd_d = 91,
+    la_op_fsub_s = 92,
+    la_op_fsub_d = 93,
+    la_op_fmul_s = 94,
+    la_op_fmul_d = 95,
+    la_op_fdiv_s = 96,
+    la_op_fdiv_d = 97,
+    la_op_fmax_s = 98,
+    la_op_fmax_d = 99,
+    la_op_fmin_s = 100,
+    la_op_fmin_d = 101,
+    la_op_fmaxa_s = 102,
+    la_op_fmaxa_d = 103,
+    la_op_fmina_s = 104,
+    la_op_fmina_d = 105,
+    la_op_fscaleb_s = 106,
+    la_op_fscaleb_d = 107,
+    la_op_fcopysign_s = 108,
+    la_op_fcopysign_d = 109,
+    la_op_fabs_s = 110,
+    la_op_fabs_d = 111,
+    la_op_fneg_s = 112,
+    la_op_fneg_d = 113,
+    la_op_flogb_s = 114,
+    la_op_flogb_d = 115,
+    la_op_fclass_s = 116,
+    la_op_fclass_d = 117,
+    la_op_fsqrt_s = 118,
+    la_op_fsqrt_d = 119,
+    la_op_frecip_s = 120,
+    la_op_frecip_d = 121,
+    la_op_frsqrt_s = 122,
+    la_op_frsqrt_d = 123,
+    la_op_fmov_s = 124,
+    la_op_fmov_d = 125,
+    la_op_movgr2fr_w = 126,
+    la_op_movgr2fr_d = 127,
+    la_op_movgr2frh_w = 128,
+    la_op_movfr2gr_s = 129,
+    la_op_movfr2gr_d = 130,
+    la_op_movfrh2gr_s = 131,
+    la_op_movgr2fcsr = 132,
+    la_op_movfcsr2gr = 133,
+    la_op_movfr2cf = 134,
+    la_op_movcf2fr = 135,
+    la_op_movgr2cf = 136,
+    la_op_movcf2gr = 137,
+    la_op_fcvt_s_d = 138,
+    la_op_fcvt_d_s = 139,
+    la_op_ftintrm_w_s = 140,
+    la_op_ftintrm_w_d = 141,
+    la_op_ftintrm_l_s = 142,
+    la_op_ftintrm_l_d = 143,
+    la_op_ftintrp_w_s = 144,
+    la_op_ftintrp_w_d = 145,
+    la_op_ftintrp_l_s = 146,
+    la_op_ftintrp_l_d = 147,
+    la_op_ftintrz_w_s = 148,
+    la_op_ftintrz_w_d = 149,
+    la_op_ftintrz_l_s = 150,
+    la_op_ftintrz_l_d = 151,
+    la_op_ftintrne_w_s = 152,
+    la_op_ftintrne_w_d = 153,
+    la_op_ftintrne_l_s = 154,
+    la_op_ftintrne_l_d = 155,
+    la_op_ftint_w_s = 156,
+    la_op_ftint_w_d = 157,
+    la_op_ftint_l_s = 158,
+    la_op_ftint_l_d = 159,
+    la_op_ffint_s_w = 160,
+    la_op_ffint_s_l = 161,
+    la_op_ffint_d_w = 162,
+    la_op_ffint_d_l = 163,
+    la_op_frint_s = 164,
+    la_op_frint_d = 165,
+    la_op_slti = 166,
+    la_op_sltui = 167,
+    la_op_addi_w = 168,
+    la_op_addi_d = 169,
+    la_op_lu52i_d = 170,
+    la_op_addi = 171,
+    la_op_ori = 172,
+    la_op_xori = 173,
+    la_op_rdtimel_w = 174,
+    la_op_rdtimeh_w = 175,
+    la_op_fmadd_s = 176,
+    la_op_fmadd_d = 177,
+    la_op_fmsub_s = 178,
+    la_op_fmsub_d = 179,
+    la_op_fnmadd_s = 180,
+    la_op_fnmadd_d = 181,
+    la_op_fnmsub_s = 182,
+    la_op_fnmsub_d = 183,
+    la_op_fcmp_cond_s = 184,
+    la_op_fcmp_cond_d = 185,
+    la_op_fsel = 186,
+    la_op_addu16i_d = 187,
+    la_op_lu12i_w = 188,
+    la_op_lu32i_d = 189,
+    la_op_pcaddi = 190,
+    la_op_pcalau12i = 191,
+    la_op_pcaddu12i = 192,
+    la_op_pcaddu18i = 193,
+    la_op_ll_w = 194,
+    la_op_sc_w = 195,
+    la_op_ll_d = 196,
+    la_op_sc_d = 197,
+    la_op_ldptr_w = 198,
+    la_op_stptr_w = 199,
+    la_op_ldptr_d = 200,
+    la_op_stptr_d = 201,
+    la_op_ld_b = 202,
+    la_op_ld_h = 203,
+    la_op_ld_w = 204,
+    la_op_ld_d = 205,
+    la_op_st_b = 206,
+    la_op_st_h = 207,
+    la_op_st_w = 208,
+    la_op_st_d = 209,
+    la_op_ld_bu = 210,
+    la_op_ld_hu = 211,
+    la_op_ld_wu = 212,
+    la_op_preld = 213,
+    la_op_fld_s = 214,
+    la_op_fst_s = 215,
+    la_op_fld_d = 216,
+    la_op_fst_d = 217,
+    la_op_ldx_b = 218,
+    la_op_ldx_h = 219,
+    la_op_ldx_w = 220,
+    la_op_ldx_d = 221,
+    la_op_stx_b = 222,
+    la_op_stx_h = 223,
+    la_op_stx_w = 224,
+    la_op_stx_d = 225,
+    la_op_ldx_bu = 226,
+    la_op_ldx_hu = 227,
+    la_op_ldx_wu = 228,
+    la_op_fldx_s = 229,
+    la_op_fldx_d = 230,
+    la_op_fstx_s = 231,
+    la_op_fstx_d = 232,
+    la_op_amswap_w = 233,
+    la_op_amswap_d = 234,
+    la_op_amadd_w = 235,
+    la_op_amadd_d = 236,
+    la_op_amand_w = 237,
+    la_op_amand_d = 238,
+    la_op_amor_w = 239,
+    la_op_amor_d = 240,
+    la_op_amxor_w = 241,
+    la_op_amxor_d = 242,
+    la_op_ammax_w = 243,
+    la_op_ammax_d = 244,
+    la_op_ammin_w = 245,
+    la_op_ammin_d = 246,
+    la_op_ammax_wu = 247,
+    la_op_ammax_du = 248,
+    la_op_ammin_wu = 249,
+    la_op_ammin_du = 250,
+    la_op_amswap_db_w = 251,
+    la_op_amswap_db_d = 252,
+    la_op_amadd_db_w = 253,
+    la_op_amadd_db_d = 254,
+    la_op_amand_db_w = 255,
+    la_op_amand_db_d = 256,
+    la_op_amor_db_w = 257,
+    la_op_amor_db_d = 258,
+    la_op_amxor_db_w = 259,
+    la_op_amxor_db_d = 260,
+    la_op_ammax_db_w = 261,
+    la_op_ammax_db_d = 262,
+    la_op_ammin_db_w = 263,
+    la_op_ammin_db_d = 264,
+    la_op_ammax_db_wu = 265,
+    la_op_ammax_db_du = 266,
+    la_op_ammin_db_wu = 267,
+    la_op_ammin_db_du = 268,
+    la_op_dbar = 269,
+    la_op_ibar = 270,
+    la_op_fldgt_s = 271,
+    la_op_fldgt_d = 272,
+    la_op_fldle_s = 273,
+    la_op_fldle_d = 274,
+    la_op_fstgt_s = 275,
+    la_op_fstgt_d = 276,
+    ls_op_fstle_s = 277,
+    la_op_fstle_d = 278,
+    la_op_ldgt_b = 279,
+    la_op_ldgt_h = 280,
+    la_op_ldgt_w = 281,
+    la_op_ldgt_d = 282,
+    la_op_ldle_b = 283,
+    la_op_ldle_h = 284,
+    la_op_ldle_w = 285,
+    la_op_ldle_d = 286,
+    la_op_stgt_b = 287,
+    la_op_stgt_h = 288,
+    la_op_stgt_w = 289,
+    la_op_stgt_d = 290,
+    la_op_stle_b = 291,
+    la_op_stle_h = 292,
+    la_op_stle_w = 293,
+    la_op_stle_d = 294,
+    la_op_beqz = 295,
+    la_op_bnez = 296,
+    la_op_bceqz = 297,
+    la_op_bcnez = 298,
+    la_op_jirl = 299,
+    la_op_b = 300,
+    la_op_bl = 301,
+    la_op_beq = 302,
+    la_op_bne = 303,
+    la_op_blt = 304,
+    la_op_bge = 305,
+    la_op_bltu = 306,
+    la_op_bgeu = 307,
+
+} la_op;
+
+typedef enum {
+    la_codec_illegal,
+    la_codec_empty,
+    la_codec_2r,
+    la_codec_2r_u5,
+    la_codec_2r_u6,
+    la_codec_2r_2bw,
+    la_codec_2r_2bd,
+    la_codec_3r,
+    la_codec_3r_rd0,
+    la_codec_3r_sa2,
+    la_codec_3r_sa3,
+    la_codec_4r,
+    la_codec_r_im20,
+    la_codec_2r_im16,
+    la_codec_2r_im14,
+    la_codec_r_im14,
+    la_codec_2r_im12,
+    la_codec_im5_r_im12,
+    la_codec_2r_im8,
+    la_codec_r_sd,
+    la_codec_r_sj,
+    la_codec_r_cd,
+    la_codec_r_cj,
+    la_codec_r_seq,
+    la_codec_code,
+    la_codec_whint,
+    la_codec_invtlb,
+    la_codec_r_ofs21,
+    la_codec_cj_ofs21,
+    la_codec_ofs26,
+    la_codec_cond,
+    la_codec_sel,
+
+} la_codec;
+
+#define la_fmt_illegal         "nte"
+#define la_fmt_empty           "nt"
+#define la_fmt_sd_rj           "ntA,1"
+#define la_fmt_rd_sj           "nt0,B"
+#define la_fmt_rd_rj           "nt0,1"
+#define la_fmt_rj_rk           "nt1,2"
+#define la_fmt_rj_seq          "nt1,x"
+#define la_fmt_rd_si20         "nt0,i(x)"
+#define la_fmt_rd_rj_ui5       "nt0,1,C"
+#define la_fmt_rd_rj_ui6       "nt0,1.C"
+#define la_fmt_rd_rj_level     "nt0,1,x"
+#define la_fmt_rd_rj_msbw_lsbw "nt0,1,C,D"
+#define la_fmt_rd_rj_msbd_lsbd "nt0,1,C,D"
+#define la_fmt_rd_rj_si12      "nt0,1,i(x)"
+#define la_fmt_hint_rj_si12    "ntE,1,i(x)"
+#define la_fmt_rd_rj_csr       "nt0,1,x"
+#define la_fmt_rd_csr          "nt0,x"
+#define la_fmt_rd_rj_si14      "nt0,1,i(x)"
+#define la_fmt_rd_rj_si16      "nt0,1,i(x)"
+#define la_fmt_rd_rj_rk        "nt0,1,2"
+#define la_fmt_fd_rj_rk        "nt3,1,2"
+#define la_fmt_rd_rj_rk_sa2    "nt0,1,2,D"
+#define la_fmt_rd_rj_rk_sa3    "nt0,1,2,D"
+#define la_fmt_fd_rj           "nt3,1"
+#define la_fmt_rd_fj           "nt0,4"
+#define la_fmt_fd_fj           "nt3,4"
+#define la_fmt_fd_fj_si12      "nt3,4,i(x)"
+#define la_fmt_fcsrd_rj        "ntF,1"
+#define la_fmt_rd_fcsrs        "nt0,G"
+#define la_fmt_cd_fj           "ntH,4"
+#define la_fmt_fd_cj           "nt3,I"
+#define la_fmt_fd_fj_fk        "nt3,4,5"
+#define la_fmt_code            "ntJ"
+#define la_fmt_whint           "ntx"
+#define la_fmt_invtlb          "ntx,1,2"
+#define la_fmt_offs26          "nto(X)p"
+#define la_fmt_rj_offs21       "nt1,o(X)p"
+#define la_fmt_cj_offs21       "ntQ,o(X)p"
+#define la_fmt_rd_rj_offs16    "nt0,1,o(X)"
+#define la_fmt_rj_rd_offs16    "nt1,0,o(X)p"
+#define la_fmt_s_cd_fj_fk      "K.stH,4,5"
+#define la_fmt_d_cd_fj_fk      "K.dtH,4,5"
+#define la_fmt_fd_fj_fk_fa     "nt3,4,5,6"
+#define la_fmt_fd_fj_fk_ca     "nt3,4,5,L"
+#define la_fmt_cop_rj_si12     "ntM,1,i(x)"
+
+/* structures */
+typedef struct {
+    uint32_t pc;
+    uint32_t insn;
+    int32_t imm;
+    int32_t imm2;
+    uint16_t op;
+    uint16_t code;
+    uint8_t codec;
+    uint8_t r1;
+    uint8_t r2;
+    uint8_t r3;
+    uint8_t r4;
+    uint8_t bit;
+} la_decode;
+
+typedef struct {
+    const char * const name;
+    const la_codec codec;
+    const char * const format;
+} la_opcode_data;
+
+/* reg names */
+const char * const loongarch_r_normal_name[32] = {
+  "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7",
+  "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
+  "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23",
+  "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31",
+};
+
+const char * const loongarch_f_normal_name[32] = {
+  "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
+  "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
+  "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
+  "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
+};
+
+const char * const loongarch_cr_normal_name[4] = {
+  "$scr0", "$scr1", "$scr2", "$scr3",
+};
+
+const char * const loongarch_c_normal_name[8] = {
+  "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7",
+};
+
+/* instruction data */
+static const  la_opcode_data opcode_data[] = {
+    { "illegal", la_codec_illegal, la_fmt_illegal },
+    { "clo.w", la_codec_2r, la_fmt_rd_rj },
+    { "clz.w", la_codec_2r, la_fmt_rd_rj },
+    { "cto.w", la_codec_2r, la_fmt_rd_rj },
+    { "ctz.w", la_codec_2r, la_fmt_rd_rj },
+    { "clo.d", la_codec_2r, la_fmt_rd_rj },
+    { "clz.d", la_codec_2r, la_fmt_rd_rj },
+    { "cto.d", la_codec_2r, la_fmt_rd_rj },
+    { "ctz_d", la_codec_2r, la_fmt_rd_rj },
+    { "revb.2h", la_codec_2r, la_fmt_rd_rj },
+    { "revb.4h", la_codec_2r, la_fmt_rd_rj },
+    { "revb.2w", la_codec_2r, la_fmt_rd_rj },
+    { "revb.d", la_codec_2r, la_fmt_rd_rj },
+    { "revh.2w", la_codec_2r, la_fmt_rd_rj },
+    { "revh.d", la_codec_2r, la_fmt_rd_rj },
+    { "bitrev.4b", la_codec_2r, la_fmt_rd_rj },
+    { "bitrev.8b", la_codec_2r, la_fmt_rd_rj },
+    { "bitrev.w", la_codec_2r, la_fmt_rd_rj },
+    { "bitrev.d", la_codec_2r, la_fmt_rd_rj },
+    { "ext.w.h", la_codec_2r, la_fmt_rd_rj },
+    { "ext.w.b", la_codec_2r, la_fmt_rd_rj },
+    { "rdtime.d", la_codec_2r, la_fmt_rd_rj },
+    { "cpucfg", la_codec_2r, la_fmt_rd_rj },
+    { "asrtle.d", la_codec_3r_rd0, la_fmt_rj_rk },
+    { "asrtgt.d", la_codec_3r_rd0, la_fmt_rj_rk },
+    { "alsl.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
+    { "alsl.wu", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
+    { "bytepick.w", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
+    { "bytepick.d", la_codec_3r_sa3, la_fmt_rd_rj_rk_sa3 },
+    { "add.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "add.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "sub.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "sub.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "slt", la_codec_3r, la_fmt_rd_rj_rk },
+    { "sltu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "maskeqz", la_codec_3r, la_fmt_rd_rj_rk },
+    { "masknez", la_codec_3r, la_fmt_rd_rj_rk },
+    { "nor", la_codec_3r, la_fmt_rd_rj_rk },
+    { "and", la_codec_3r, la_fmt_rd_rj_rk },
+    { "or", la_codec_3r, la_fmt_rd_rj_rk },
+    { "xor", la_codec_3r, la_fmt_rd_rj_rk },
+    { "orn", la_codec_3r, la_fmt_rd_rj_rk },
+    { "andn", la_codec_3r, la_fmt_rd_rj_rk },
+    { "sll.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "srl.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "sra.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "sll.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "srl.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "sra.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "rotr.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "rotr.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mul.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mulh.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mulh.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mul.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mulh.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mulh.du", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mulw.d.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mulw.d.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "div.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mod.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "div.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mod.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "div.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mod.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "div.du", la_codec_3r, la_fmt_rd_rj_rk },
+    { "mod.du", la_codec_3r, la_fmt_rd_rj_rk },
+    { "crc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "crc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "crc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "crc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "crcc.w.b.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "crcc.w.h.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "crcc.w.w.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "crcc.w.d.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "break", la_codec_code, la_fmt_code },
+    { "syscall", la_codec_code, la_fmt_code },
+    { "alsl.d", la_codec_3r_sa2, la_fmt_rd_rj_rk_sa2 },
+    { "slli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
+    { "slli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
+    { "srli.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
+    { "srli.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
+    { "srai.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
+    { "srai.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
+    { "rotri.w", la_codec_2r_u5, la_fmt_rd_rj_ui5 },
+    { "rotri.d", la_codec_2r_u6, la_fmt_rd_rj_ui6 },
+    { "bstrins.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw },
+    { "bstrpick.w", la_codec_2r_2bw, la_fmt_rd_rj_msbw_lsbw },
+    { "bstrins.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd },
+    { "bstrpick.d", la_codec_2r_2bd, la_fmt_rd_rj_msbd_lsbd },
+    { "fadd.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fadd.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fsub.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fsub.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmul.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmul.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fdiv.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fdiv.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmax.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmax.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmin.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmin.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmaxa.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmaxa.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmina.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fmina.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fscaleb.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fscaleb.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fcopysign.s", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fcopysign.d", la_codec_3r, la_fmt_fd_fj_fk },
+    { "fabs.s", la_codec_2r, la_fmt_fd_fj },
+    { "fabs.d", la_codec_2r, la_fmt_fd_fj },
+    { "fneg.s", la_codec_2r, la_fmt_fd_fj },
+    { "fneg.d", la_codec_2r, la_fmt_fd_fj },
+    { "flogb.s", la_codec_2r, la_fmt_fd_fj },
+    { "flogb.d", la_codec_2r, la_fmt_fd_fj },
+    { "fclass.s", la_codec_2r, la_fmt_fd_fj },
+    { "fclass.d", la_codec_2r, la_fmt_fd_fj },
+    { "fsqrt.s", la_codec_2r, la_fmt_fd_fj },
+    { "fsqrt.d", la_codec_2r, la_fmt_fd_fj },
+    { "frecip.s", la_codec_2r, la_fmt_fd_fj },
+    { "frecip.d", la_codec_2r, la_fmt_fd_fj },
+    { "frsqrt.s", la_codec_2r, la_fmt_fd_fj },
+    { "frsqrt.d", la_codec_2r, la_fmt_fd_fj },
+    { "fmov.s", la_codec_2r, la_fmt_fd_fj },
+    { "fmov.d", la_codec_2r, la_fmt_fd_fj },
+    { "movgr2fr.w", la_codec_2r, la_fmt_fd_rj },
+    { "movgr2fr.d", la_codec_2r, la_fmt_fd_rj },
+    { "movgr2frh.w", la_codec_2r, la_fmt_fd_rj },
+    { "movfr2gr.s", la_codec_2r, la_fmt_rd_fj },
+    { "movfr2gr.d", la_codec_2r, la_fmt_rd_fj },
+    { "movfrh2gr.s", la_codec_2r, la_fmt_rd_fj },
+    { "movgr2fcsr", la_codec_2r, la_fmt_fcsrd_rj },
+    { "movfcsr2gr", la_codec_2r, la_fmt_rd_fcsrs },
+    { "movfr2cf", la_codec_r_cd, la_fmt_cd_fj },
+    { "movcf2fr", la_codec_r_cj, la_fmt_fd_cj },
+    { "movgr2cf", la_codec_r_cd, la_fmt_cd_fj },
+    { "movcf2gr", la_codec_r_cj, la_fmt_fd_cj },
+    { "fcvt.s.d", la_codec_2r, la_fmt_fd_fj },
+    { "fcvt.d.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrm.w.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrm.w.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrm.l.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrm.l.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrp.w.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrp.w.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrp.l.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrp.l.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrz.w.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrz.w.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrz.l.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrz.l.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrne.w.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrne.w.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrne.l.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftintrne.l.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftint.w.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftint.w.d", la_codec_2r, la_fmt_fd_fj },
+    { "ftint.l.s", la_codec_2r, la_fmt_fd_fj },
+    { "ftint.l.d", la_codec_2r, la_fmt_fd_fj },
+    { "ffint.s.w", la_codec_2r, la_fmt_fd_fj },
+    { "ffint.s.l", la_codec_2r, la_fmt_fd_fj },
+    { "ffint.d.w", la_codec_2r, la_fmt_fd_fj },
+    { "ffint.d.l", la_codec_2r, la_fmt_fd_fj },
+    { "frint.s", la_codec_2r, la_fmt_fd_fj },
+    { "frint.d", la_codec_2r, la_fmt_fd_fj },
+    { "slti", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "sltui", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "addi.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "addi.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "lu52i.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "addi", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "ori", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "xori", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "rdtimel.w", la_codec_2r, la_fmt_rd_rj },
+    { "rdtimeh.w", la_codec_2r, la_fmt_rd_rj },
+    { "fmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
+    { "fmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
+    { "fmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
+    { "fmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
+    { "fnmadd.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
+    { "fnmadd.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
+    { "fnmsub.s", la_codec_4r, la_fmt_fd_fj_fk_fa },
+    { "fnmsub.d", la_codec_4r, la_fmt_fd_fj_fk_fa },
+    { "fcmp.cond.s", la_codec_cond, la_fmt_s_cd_fj_fk },
+    { "fcmp.cond.d", la_codec_cond, la_fmt_d_cd_fj_fk },
+    { "fsel", la_codec_sel, la_fmt_fd_fj_fk_ca },
+    { "addu16i.d", la_codec_2r_im16, la_fmt_rd_rj_si16 },
+    { "lu12i.w", la_codec_r_im20, la_fmt_rd_si20 },
+    { "lu32i.d", la_codec_r_im20, la_fmt_rd_si20 },
+    { "pcaddi", la_codec_r_im20, la_fmt_rd_si20 },
+    { "pcalau12i", la_codec_r_im20, la_fmt_rd_si20 },
+    { "pcaddu12i", la_codec_r_im20, la_fmt_rd_si20 },
+    { "pcaddu18i", la_codec_r_im20, la_fmt_rd_si20 },
+    { "ll.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+    { "sc.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+    { "ll.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+    { "sc.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+    { "ldptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+    { "stptr.w", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+    { "ldptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+    { "stptr.d", la_codec_2r_im14, la_fmt_rd_rj_si14 },
+    { "ld.b", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "ld.h", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "ld.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "ld.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "st.b", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "st.h", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "st.w", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "st.d", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "ld.bu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "ld.hu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "ld.wu", la_codec_2r_im12, la_fmt_rd_rj_si12 },
+    { "preld", la_codec_2r_im12, la_fmt_hint_rj_si12 },
+    { "fld.s", la_codec_2r_im12, la_fmt_fd_fj_si12 },
+    { "fst.s", la_codec_2r_im12, la_fmt_fd_fj_si12 },
+    { "fld.d", la_codec_2r_im12, la_fmt_fd_fj_si12 },
+    { "fst.d", la_codec_2r_im12, la_fmt_fd_fj_si12 },
+    { "ldx.b", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldx.h", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldx.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldx.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stx.b", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stx.h", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stx.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stx.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldx.bu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldx.hu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldx.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "fldx.s", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fldx.d", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fstx.s", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fstx.d", la_codec_3r, la_fmt_fd_rj_rk },
+    { "amswap.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amswap.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amadd.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amadd.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amand.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amand.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amor.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amor.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amxor.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amxor.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammax.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammax.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammin.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammin.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammax.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammax.du", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammin.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammin.du", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amswap.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amswap.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amadd.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amadd.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amand.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amand.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amor.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amor.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amxor.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "amxor.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammax.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammax.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammin.db.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammin.db.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammax.db.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammax.db.du", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammin.db.wu", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ammin.db.du", la_codec_3r, la_fmt_rd_rj_rk },
+    { "dbar", la_codec_whint, la_fmt_whint },
+    { "ibar", la_codec_whint, la_fmt_whint },
+    { "fldgt.s", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fldgt.d", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fldle.s", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fldle.d", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fstgt.s", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fstgt.d", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fstle.s", la_codec_3r, la_fmt_fd_rj_rk },
+    { "fstle.d", la_codec_3r, la_fmt_fd_rj_rk },
+    { "ldgt.b", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldgt.h", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldgt.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldgt.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldle.b", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldle.h", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldle.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "ldle.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stgt.b", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stgt.h", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stgt.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stgt.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stle.b", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stle.h", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stle.w", la_codec_3r, la_fmt_rd_rj_rk },
+    { "stle.d", la_codec_3r, la_fmt_rd_rj_rk },
+    { "beqz", la_codec_r_ofs21, la_fmt_rj_offs21 },
+    { "bnez", la_codec_r_ofs21, la_fmt_rj_offs21 },
+    { "bceqz", la_codec_cj_ofs21, la_fmt_cj_offs21 },
+    { "bcnez", la_codec_cj_ofs21, la_fmt_cj_offs21 },
+    { "jirl", la_codec_2r_im16, la_fmt_rd_rj_offs16 },
+    { "b", la_codec_ofs26, la_fmt_offs26 },
+    { "bl", la_codec_ofs26, la_fmt_offs26 },
+    { "beq", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+    { "bne", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+    { "blt", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+    { "bge", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+    { "bltu", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+    { "bgeu", la_codec_2r_im16, la_fmt_rj_rd_offs16 },
+
+};
+
+
+/* decode opcode */
+static void decode_insn_opcode(la_decode *dec)
+{
+    uint32_t insn = dec->insn;
+    uint16_t op = la_op_illegal;
+    switch ((insn >> 26) & 0x3f) {
+    case 0x0:
+        switch ((insn >> 22) & 0xf) {
+        case 0x0:
+            switch ((insn >> 18) & 0xf) {
+            case 0x0:
+                switch ((insn >> 15) & 0x7) {
+                case 0x0:
+                    switch ((insn >> 10) & 0x1f) {
+                    case 0x4:
+                        op = la_op_clo_w;
+                        break;
+                    case 0x5:
+                        op = la_op_clz_w;
+                        break;
+                    case 0x6:
+                        op = la_op_cto_w;
+                        break;
+                    case 0x7:
+                        op = la_op_ctz_w;
+                        break;
+                    case 0x8:
+                        op = la_op_clo_d;
+                        break;
+                    case 0x9:
+                        op = la_op_clz_d;
+                        break;
+                    case 0xa:
+                        op = la_op_cto_d;
+                        break;
+                    case 0xb:
+                        op = la_op_ctz_d;
+                        break;
+                    case 0xc:
+                        op = la_op_revb_2h;
+                        break;
+                    case 0xd:
+                        op = la_op_revb_4h;
+                        break;
+                    case 0xe:
+                        op = la_op_revb_2w;
+                        break;
+                    case 0xf:
+                        op = la_op_revb_d;
+                        break;
+                    case 0x10:
+                        op = la_op_revh_2w;
+                        break;
+                    case 0x11:
+                        op = la_op_revh_d;
+                        break;
+                    case 0x12:
+                        op = la_op_bitrev_4b;
+                        break;
+                    case 0x13:
+                        op = la_op_bitrev_8b;
+                        break;
+                    case 0x14:
+                        op = la_op_bitrev_w;
+                        break;
+                    case 0x15:
+                        op = la_op_bitrev_d;
+                        break;
+                    case 0x16:
+                        op = la_op_ext_w_h;
+                        break;
+                    case 0x17:
+                        op = la_op_ext_w_b;
+                        break;
+                    case 0x18:
+                        op = la_op_rdtimel_w;
+                        break;
+                    case 0x19:
+                        op = la_op_rdtimeh_w;
+                        break;
+                    case 0x1a:
+                        op = la_op_rdtime_d;
+                        break;
+                    case 0x1b:
+                        op = la_op_cpucfg;
+                        break;
+                    }
+                    break;
+                case 0x2:
+                    switch (insn & 0x0000001f) {
+                    case 0x00000000:
+                        op = la_op_asrtle_d;
+                        break;
+                    }
+                    break;
+                case 0x3:
+                    switch (insn & 0x0000001f) {
+                    case 0x00000000:
+                        op = la_op_asrtgt_d;
+                        break;
+                    }
+                    break;
+                }
+                break;
+            case 0x1:
+                switch ((insn >> 17) & 0x1) {
+                case 0x0:
+                    op = la_op_alsl_w;
+                    break;
+                case 0x1:
+                    op = la_op_alsl_wu;
+                    break;
+                }
+                break;
+            case 0x2:
+                switch ((insn >> 17) & 0x1) {
+                case 0x0:
+                    op = la_op_bytepick_w;
+                    break;
+                }
+                break;
+            case 0x3:
+                op = la_op_bytepick_d;
+                break;
+            case 0x4:
+                switch ((insn >> 15) & 0x7) {
+                case 0x0:
+                    op = la_op_add_w;
+                    break;
+                case 0x1:
+                    op = la_op_add_d;
+                    break;
+                case 0x2:
+                    op = la_op_sub_w;
+                    break;
+                case 0x3:
+                    op = la_op_sub_d;
+                    break;
+                case 0x4:
+                    op = la_op_slt;
+                    break;
+                case 0x5:
+                    op = la_op_sltu;
+                    break;
+                case 0x6:
+                    op = la_op_maskeqz;
+                    break;
+                case 0x7:
+                    op = la_op_masknez;
+                    break;
+                }
+                break;
+            case 0x5:
+                switch ((insn >> 15) & 0x7) {
+                case 0x0:
+                    op = la_op_nor;
+                    break;
+                case 0x1:
+                    op = la_op_and;
+                    break;
+                case 0x2:
+                    op = la_op_or;
+                    break;
+                case 0x3:
+                    op = la_op_xor;
+                    break;
+                case 0x4:
+                    op = la_op_orn;
+                    break;
+                case 0x5:
+                    op = la_op_andn;
+                    break;
+                case 0x6:
+                    op = la_op_sll_w;
+                    break;
+                case 0x7:
+                    op = la_op_srl_w;
+                    break;
+                }
+                break;
+            case 0x6:
+                switch ((insn >> 15) & 0x7) {
+                case 0x0:
+                    op = la_op_sra_w;
+                    break;
+                case 0x1:
+                    op = la_op_sll_d;
+                    break;
+                case 0x2:
+                    op = la_op_srl_d;
+                    break;
+                case 0x3:
+                    op = la_op_sra_d;
+                    break;
+                case 0x6:
+                    op = la_op_rotr_w;
+                    break;
+                case 0x7:
+                    op = la_op_rotr_d;
+                    break;
+                }
+                break;
+            case 0x7:
+                switch ((insn >> 15) & 0x7) {
+                case 0x0:
+                    op = la_op_mul_w;
+                    break;
+                case 0x1:
+                    op = la_op_mulh_w;
+                    break;
+                case 0x2:
+                    op = la_op_mulh_wu;
+                    break;
+                case 0x3:
+                    op = la_op_mul_d;
+                    break;
+                case 0x4:
+                    op = la_op_mulh_d;
+                    break;
+                case 0x5:
+                    op = la_op_mulh_du;
+                    break;
+                case 0x6:
+                    op = la_op_mulw_d_w;
+                    break;
+                case 0x7:
+                    op = la_op_mulw_d_wu;
+                    break;
+                }
+                break;
+            case 0x8:
+                switch ((insn >> 15) & 0x7) {
+                case 0x0:
+                    op = la_op_div_w;
+                    break;
+                case 0x1:
+                    op = la_op_mod_w;
+                    break;
+                case 0x2:
+                    op = la_op_div_wu;
+                    break;
+                case 0x3:
+                    op = la_op_mod_wu;
+                    break;
+                case 0x4:
+                    op = la_op_div_d;
+                    break;
+                case 0x5:
+                    op = la_op_mod_d;
+                    break;
+                case 0x6:
+                    op = la_op_div_du;
+                    break;
+                case 0x7:
+                    op = la_op_mod_du;
+                    break;
+                }
+                break;
+            case 0x9:
+                switch ((insn >> 15) & 0x7) {
+                case 0x0:
+                    op = la_op_crc_w_b_w;
+                    break;
+                case 0x1:
+                    op = la_op_crc_w_h_w;
+                    break;
+                case 0x2:
+                    op = la_op_crc_w_w_w;
+                    break;
+                case 0x3:
+                    op = la_op_crc_w_d_w;
+                    break;
+                case 0x4:
+                    op = la_op_crcc_w_b_w;
+                    break;
+                case 0x5:
+                    op = la_op_crcc_w_h_w;
+                    break;
+                case 0x6:
+                    op = la_op_crcc_w_w_w;
+                    break;
+                case 0x7:
+                    op = la_op_crcc_w_d_w;
+                    break;
+                }
+                break;
+            case 0xa:
+                switch ((insn >> 15) & 0x7) {
+                case 0x4:
+                    op = la_op_break;
+                    break;
+                case 0x6:
+                    op = la_op_syscall;
+                    break;
+                }
+                break;
+            case 0xb:
+                switch ((insn >> 17) & 0x1) {
+                case 0x0:
+                    op = la_op_alsl_d;
+                    break;
+                }
+                break;
+            }
+            break;
+        case 0x1:
+            switch ((insn >> 21) & 0x1) {
+            case 0x0:
+                switch ((insn >> 16) & 0x1f) {
+                case 0x0:
+                    switch ((insn >> 15) & 0x1) {
+                    case 0x1:
+                        op = la_op_slli_w;
+                        break;
+                    }
+                    break;
+                case 0x1:
+                    op = la_op_slli_d;
+                    break;
+                case 0x4:
+                    switch ((insn >> 15) & 0x1) {
+                    case 0x1:
+                        op = la_op_srli_w;
+                        break;
+                    }
+                    break;
+                case 0x5:
+                    op = la_op_srli_d;
+                    break;
+                case 0x8:
+                    switch ((insn >> 15) & 0x1) {
+                    case 0x1:
+                        op = la_op_srai_w;
+                        break;
+                    }
+                    break;
+                case 0x9:
+                    op = la_op_srai_d;
+                    break;
+                case 0xc:
+                    switch ((insn >> 15) & 0x1) {
+                    case 0x1:
+                        op = la_op_rotri_w;
+                        break;
+                    }
+                    break;
+                case 0xd:
+                    op = la_op_rotri_d;
+                    break;
+                }
+                break;
+            case 0x1:
+                switch ((insn >> 15) & 0x1) {
+                case 0x0:
+                    op = la_op_bstrins_w;
+                    break;
+                case 0x1:
+                    op = la_op_bstrpick_w;
+                    break;
+                }
+                break;
+            }
+            break;
+        case 0x2:
+            op = la_op_bstrins_d;
+            break;
+        case 0x3:
+            op = la_op_bstrpick_d;
+            break;
+        case 0x4:
+            switch ((insn >> 15) & 0x7f) {
+            case 0x1:
+                op = la_op_fadd_s;
+                break;
+            case 0x2:
+                op = la_op_fadd_d;
+                break;
+            case 0x5:
+                op = la_op_fsub_s;
+                break;
+            case 0x6:
+                op = la_op_fsub_d;
+                break;
+            case 0x9:
+                op = la_op_fmul_s;
+                break;
+            case 0xa:
+                op = la_op_fmul_d;
+                break;
+            case 0xd:
+                op = la_op_fdiv_s;
+                break;
+            case 0xe:
+                op = la_op_fdiv_d;
+                break;
+            case 0x11:
+                op = la_op_fmax_s;
+                break;
+            case 0x12:
+                op = la_op_fmax_d;
+                break;
+            case 0x15:
+                op = la_op_fmin_s;
+                break;
+            case 0x16:
+                op = la_op_fmin_d;
+                break;
+            case 0x19:
+                op = la_op_fmaxa_s;
+                break;
+            case 0x1a:
+                op = la_op_fmaxa_d;
+                break;
+            case 0x1d:
+                op = la_op_fmina_s;
+                break;
+            case 0x1e:
+                op = la_op_fmina_d;
+                break;
+            case 0x21:
+                op = la_op_fscaleb_s;
+                break;
+            case 0x22:
+                op = la_op_fscaleb_d;
+                break;
+            case 0x25:
+                op = la_op_fcopysign_s;
+                break;
+            case 0x26:
+                op = la_op_fcopysign_d;
+                break;
+            case 0x28:
+                switch ((insn >> 10) & 0x1f) {
+                case 0x1:
+                    op = la_op_fabs_s;
+                    break;
+                case 0x2:
+                    op = la_op_fabs_d;
+                    break;
+                case 0x5:
+                    op = la_op_fneg_s;
+                    break;
+                case 0x6:
+                    op = la_op_fneg_d;
+                    break;
+                case 0x9:
+                    op = la_op_flogb_s;
+                    break;
+                case 0xa:
+                    op = la_op_flogb_d;
+                    break;
+                case 0xd:
+                    op = la_op_fclass_s;
+                    break;
+                case 0xe:
+                    op = la_op_fclass_d;
+                    break;
+                case 0x11:
+                    op = la_op_fsqrt_s;
+                    break;
+                case 0x12:
+                    op = la_op_fsqrt_d;
+                    break;
+                case 0x15:
+                    op = la_op_frecip_s;
+                    break;
+                case 0x16:
+                    op = la_op_frecip_d;
+                    break;
+                case 0x19:
+                    op = la_op_frsqrt_s;
+                    break;
+                case 0x1a:
+                    op = la_op_frsqrt_d;
+                    break;
+                }
+                break;
+            case 0x29:
+                switch ((insn >> 10) & 0x1f) {
+                case 0x5:
+                    op = la_op_fmov_s;
+                    break;
+                case 0x6:
+                    op = la_op_fmov_d;
+                    break;
+                case 0x9:
+                    op = la_op_movgr2fr_w;
+                    break;
+                case 0xa:
+                    op = la_op_movgr2fr_d;
+                    break;
+                case 0xb:
+                    op = la_op_movgr2frh_w;
+                    break;
+                case 0xd:
+                    op = la_op_movfr2gr_s;
+                    break;
+                case 0xe:
+                    op = la_op_movfr2gr_d;
+                    break;
+                case 0xf:
+                    op = la_op_movfrh2gr_s;
+                    break;
+                case 0x10:
+                    op = la_op_movgr2fcsr;
+                    break;
+                case 0x12:
+                    op = la_op_movfcsr2gr;
+                    break;
+                case 0x14:
+                    switch ((insn >> 3) & 0x3) {
+                    case 0x0:
+                        op = la_op_movfr2cf;
+                        break;
+                    }
+                    break;
+                case 0x15:
+                    switch ((insn >> 8) & 0x3) {
+                    case 0x0:
+                        op = la_op_movcf2fr;
+                        break;
+                    }
+                    break;
+                case 0x16:
+                    switch ((insn >> 3) & 0x3) {
+                    case 0x0:
+                        op = la_op_movgr2cf;
+                        break;
+                    }
+                    break;
+                case 0x17:
+                    switch ((insn >> 8) & 0x3) {
+                    case 0x0:
+                        op = la_op_movcf2gr;
+                        break;
+                    }
+                    break;
+                }
+                break;
+            case 0x32:
+                switch ((insn >> 10) & 0x1f) {
+                case 0x6:
+                    op = la_op_fcvt_s_d;
+                    break;
+                case 0x9:
+                    op = la_op_fcvt_d_s;
+                    break;
+                }
+                break;
+            case 0x34:
+                switch ((insn >> 10) & 0x1f) {
+                case 0x1:
+                    op = la_op_ftintrm_w_s;
+                    break;
+                case 0x2:
+                    op = la_op_ftintrm_w_d;
+                    break;
+                case 0x9:
+                    op = la_op_ftintrm_l_s;
+                    break;
+                case 0xa:
+                    op = la_op_ftintrm_l_d;
+                    break;
+                case 0x11:
+                    op = la_op_ftintrp_w_s;
+                    break;
+                case 0x12:
+                    op = la_op_ftintrp_w_d;
+                    break;
+                case 0x19:
+                    op = la_op_ftintrp_l_s;
+                    break;
+                case 0x1a:
+                    op = la_op_ftintrp_l_d;
+                    break;
+                }
+                break;
+            case 0x35:
+                switch ((insn >> 10) & 0x1f) {
+                case 0x1:
+                    op = la_op_ftintrz_w_s;
+                    break;
+                case 0x2:
+                    op = la_op_ftintrz_w_d;
+                    break;
+                case 0x9:
+                    op = la_op_ftintrz_l_s;
+                    break;
+                case 0xa:
+                    op = la_op_ftintrz_l_d;
+                    break;
+                case 0x11:
+                    op = la_op_ftintrne_w_s;
+                    break;
+                case 0x12:
+                    op = la_op_ftintrne_w_d;
+                    break;
+                case 0x19:
+                    op = la_op_ftintrne_l_s;
+                    break;
+                case 0x1a:
+                    op = la_op_ftintrne_l_d;
+                    break;
+                }
+                break;
+            case 0x36:
+                switch ((insn >> 10) & 0x1f) {
+                case 0x1:
+                    op = la_op_ftint_w_s;
+                    break;
+                case 0x2:
+                    op = la_op_ftint_w_d;
+                    break;
+                case 0x9:
+                    op = la_op_ftint_l_s;
+                    break;
+                case 0xa:
+                    op = la_op_ftint_l_d;
+                    break;
+                }
+                break;
+            case 0x3a:
+                switch ((insn >> 10) & 0x1f) {
+                case 0x4:
+                    op = la_op_ffint_s_w;
+                    break;
+                case 0x6:
+                    op = la_op_ffint_s_l;
+                    break;
+                case 0x8:
+                    op = la_op_ffint_d_w;
+                    break;
+                case 0xa:
+                    op = la_op_ffint_d_l;
+                    break;
+                }
+                break;
+            case 0x3c:
+                switch ((insn >> 10) & 0x1f) {
+                case 0x11:
+                    op = la_op_frint_s;
+                    break;
+                case 0x12:
+                    op = la_op_frint_d;
+                    break;
+                }
+                break;
+            }
+            break;
+        case 0x8:
+            op = la_op_slti;
+            break;
+        case 0x9:
+            op = la_op_sltui;
+            break;
+        case 0xa:
+            op = la_op_addi_w;
+            break;
+        case 0xb:
+            op = la_op_addi_d;
+            break;
+        case 0xc:
+            op = la_op_lu52i_d;
+            break;
+        case 0xd:
+            op = la_op_addi;
+            break;
+        case 0xe:
+            op = la_op_ori;
+            break;
+        case 0xf:
+            op = la_op_xori;
+            break;
+        }
+        break;
+    case 0x2:
+        switch ((insn >> 20) & 0x3f) {
+        case 0x1:
+            op = la_op_fmadd_s;
+            break;
+        case 0x2:
+            op = la_op_fmadd_d;
+            break;
+        case 0x5:
+            op = la_op_fmsub_s;
+            break;
+        case 0x6:
+            op = la_op_fmsub_d;
+            break;
+        case 0x9:
+            op = la_op_fnmadd_s;
+            break;
+        case 0xa:
+            op = la_op_fnmadd_d;
+            break;
+        case 0xd:
+            op = la_op_fnmsub_s;
+            break;
+        case 0xe:
+            op = la_op_fnmsub_d;
+            break;
+        }
+        break;
+    case 0x3:
+        switch ((insn >> 20) & 0x3f) {
+        case 0x1:
+            switch ((insn >> 3) & 0x3) {
+            case 0x0:
+                op = la_op_fcmp_cond_s;
+                break;
+            }
+            break;
+        case 0x2:
+            switch ((insn >> 3) & 0x3) {
+            case 0x0:
+                op = la_op_fcmp_cond_d;
+                break;
+            }
+            break;
+        case 0x10:
+            switch ((insn >> 18) & 0x3) {
+            case 0x0:
+                op = la_op_fsel;
+                break;
+            }
+            break;
+        }
+        break;
+    case 0x4:
+        op = la_op_addu16i_d;
+        break;
+    case 0x5:
+        switch ((insn >> 25) & 0x1) {
+        case 0x0:
+            op = la_op_lu12i_w;
+            break;
+        case 0x1:
+            op = la_op_lu32i_d;
+            break;
+        }
+        break;
+    case 0x6:
+        switch ((insn >> 25) & 0x1) {
+        case 0x0:
+            op = la_op_pcaddi;
+            break;
+        case 0x1:
+            op = la_op_pcalau12i;
+            break;
+        }
+        break;
+    case 0x7:
+        switch ((insn >> 25) & 0x1) {
+        case 0x0:
+            op = la_op_pcaddu12i;
+            break;
+        case 0x1:
+            op = la_op_pcaddu18i;
+            break;
+        }
+        break;
+    case 0x8:
+        switch ((insn >> 24) & 0x3) {
+        case 0x0:
+            op = la_op_ll_w;
+            break;
+        case 0x1:
+            op = la_op_sc_w;
+            break;
+        case 0x2:
+            op = la_op_ll_d;
+            break;
+        case 0x3:
+            op = la_op_sc_d;
+            break;
+        }
+        break;
+    case 0x9:
+        switch ((insn >> 24) & 0x3) {
+        case 0x0:
+            op = la_op_ldptr_w;
+            break;
+        case 0x1:
+            op = la_op_stptr_w;
+            break;
+        case 0x2:
+            op = la_op_ldptr_d;
+            break;
+        case 0x3:
+            op = la_op_stptr_d;
+            break;
+        }
+        break;
+    case 0xa:
+        switch ((insn >> 22) & 0xf) {
+        case 0x0:
+            op = la_op_ld_b;
+            break;
+        case 0x1:
+            op = la_op_ld_h;
+            break;
+        case 0x2:
+            op = la_op_ld_w;
+            break;
+        case 0x3:
+            op = la_op_ld_d;
+            break;
+        case 0x4:
+            op = la_op_st_b;
+            break;
+        case 0x5:
+            op = la_op_st_h;
+            break;
+        case 0x6:
+            op = la_op_st_w;
+            break;
+        case 0x7:
+            op = la_op_st_d;
+            break;
+        case 0x8:
+            op = la_op_ld_bu;
+            break;
+        case 0x9:
+            op = la_op_ld_hu;
+            break;
+        case 0xa:
+            op = la_op_ld_wu;
+            break;
+        case 0xb:
+            op = la_op_preld;
+            break;
+        case 0xc:
+            op = la_op_fld_s;
+            break;
+        case 0xd:
+            op = la_op_fst_s;
+            break;
+        case 0xe:
+            op = la_op_fld_d;
+            break;
+        case 0xf:
+            op = la_op_fst_d;
+            break;
+        }
+        break;
+    case 0xe:
+        switch ((insn >> 15) & 0x7ff) {
+        case 0x0:
+            op = la_op_ldx_b;
+            break;
+        case 0x8:
+            op = la_op_ldx_h;
+            break;
+        case 0x10:
+            op = la_op_ldx_w;
+            break;
+        case 0x18:
+            op = la_op_ldx_d;
+            break;
+        case 0x20:
+            op = la_op_stx_b;
+            break;
+        case 0x28:
+            op = la_op_stx_h;
+            break;
+        case 0x30:
+            op = la_op_stx_w;
+            break;
+        case 0x38:
+            op = la_op_stx_d;
+            break;
+        case 0x40:
+            op = la_op_ldx_bu;
+            break;
+        case 0x48:
+            op = la_op_ldx_hu;
+            break;
+        case 0x50:
+            op = la_op_ldx_wu;
+            break;
+        case 0x60:
+            op = la_op_fldx_s;
+            break;
+        case 0x68:
+            op = la_op_fldx_d;
+            break;
+        case 0x70:
+            op = la_op_fstx_s;
+            break;
+        case 0x78:
+            op = la_op_fstx_d;
+            break;
+        case 0xc0:
+            op = la_op_amswap_w;
+            break;
+        case 0xc1:
+            op = la_op_amswap_d;
+            break;
+        case 0xc2:
+            op = la_op_amadd_w;
+            break;
+        case 0xc3:
+            op = la_op_amadd_d;
+            break;
+        case 0xc4:
+            op = la_op_amand_w;
+            break;
+        case 0xc5:
+            op = la_op_amand_d;
+            break;
+        case 0xc6:
+            op = la_op_amor_w;
+            break;
+        case 0xc7:
+            op = la_op_amor_d;
+            break;
+        case 0xc8:
+            op = la_op_amxor_w;
+            break;
+        case 0xc9:
+            op = la_op_amxor_d;
+            break;
+        case 0xca:
+            op = la_op_ammax_w;
+            break;
+        case 0xcb:
+            op = la_op_ammax_d;
+            break;
+        case 0xcc:
+            op = la_op_ammin_w;
+            break;
+        case 0xcd:
+            op = la_op_ammin_d;
+            break;
+        case 0xce:
+            op = la_op_ammax_wu;
+            break;
+        case 0xcf:
+            op = la_op_ammax_du;
+            break;
+        case 0xd0:
+            op = la_op_ammin_wu;
+             break;
+        case 0xd1:
+            op = la_op_ammin_du;
+            break;
+        case 0xd2:
+            op = la_op_amswap_db_w;
+            break;
+        case 0xd3:
+            op = la_op_amswap_db_d;
+            break;
+        case 0xd4:
+            op = la_op_amadd_db_w;
+            break;
+        case 0xd5:
+            op = la_op_amadd_db_d;
+            break;
+        case 0xd6:
+            op = la_op_amand_db_w;
+            break;
+        case 0xd7:
+            op = la_op_amand_db_d;
+            break;
+        case 0xd8:
+            op = la_op_amor_db_w;
+            break;
+        case 0xd9:
+            op = la_op_amor_db_d;
+            break;
+        case 0xda:
+            op = la_op_amxor_db_w;
+            break;
+        case 0xdb:
+            op = la_op_amxor_db_d;
+            break;
+        case 0xdc:
+            op = la_op_ammax_db_w;
+            break;
+        case 0xdd:
+            op = la_op_ammax_db_d;
+            break;
+        case 0xde:
+            op = la_op_ammin_db_w;
+            break;
+        case 0xdf:
+            op = la_op_ammin_db_d;
+            break;
+        case 0xe0:
+            op = la_op_ammax_db_wu;
+            break;
+        case 0xe1:
+            op = la_op_ammax_db_du;
+            break;
+        case 0xe2:
+            op = la_op_ammin_db_wu;
+            break;
+        case 0xe3:
+            op = la_op_ammin_db_du;
+            break;
+        case 0xe4:
+            op = la_op_dbar;
+            break;
+        case 0xe5:
+            op = la_op_ibar;
+            break;
+        case 0xe8:
+            op = la_op_fldgt_s;
+            break;
+        case 0xe9:
+            op = la_op_fldgt_d;
+            break;
+        case 0xea:
+            op = la_op_fldle_s;
+            break;
+        case 0xeb:
+            op = la_op_fldle_d;
+            break;
+        case 0xec:
+            op = la_op_fstgt_s;
+            break;
+        case 0xed:
+            op = la_op_fstgt_d;
+            break;
+        case 0xee:
+            op = ls_op_fstle_s;
+            break;
+        case 0xef:
+            op = la_op_fstle_d;
+            break;
+        case 0xf0:
+            op = la_op_ldgt_b;
+            break;
+        case 0xf1:
+            op = la_op_ldgt_h;
+            break;
+        case 0xf2:
+            op = la_op_ldgt_w;
+            break;
+        case 0xf3:
+            op = la_op_ldgt_d;
+            break;
+        case 0xf4:
+            op = la_op_ldle_b;
+            break;
+        case 0xf5:
+            op = la_op_ldle_h;
+            break;
+        case 0xf6:
+            op = la_op_ldle_w;
+            break;
+        case 0xf7:
+            op = la_op_ldle_d;
+            break;
+        case 0xf8:
+            op = la_op_stgt_b;
+            break;
+        case 0xf9:
+            op = la_op_stgt_h;
+            break;
+        case 0xfa:
+            op = la_op_stgt_w;
+            break;
+        case 0xfb:
+            op = la_op_stgt_d;
+            break;
+        case 0xfc:
+            op = la_op_stle_b;
+            break;
+        case 0xfd:
+            op = la_op_stle_h;
+            break;
+        case 0xfe:
+            op = la_op_stle_w;
+            break;
+        case 0xff:
+            op = la_op_stle_d;
+            break;
+        }
+        break;
+    case 0x10:
+        op = la_op_beqz;
+        break;
+    case 0x11:
+        op = la_op_bnez;
+        break;
+    case 0x12:
+        switch ((insn >> 8) & 0x3) {
+        case 0x0:
+            op = la_op_bceqz;
+            break;
+        case 0x1:
+            op = la_op_bcnez;
+            break;
+        }
+        break;
+    case 0x13:
+        op = la_op_jirl;
+        break;
+    case 0x14:
+        op = la_op_b;
+        break;
+    case 0x15:
+        op = la_op_bl;
+        break;
+    case 0x16:
+        op = la_op_beq;
+        break;
+    case 0x17:
+        op = la_op_bne;
+        break;
+    case 0x18:
+        op = la_op_blt;
+        break;
+    case 0x19:
+        op = la_op_bge;
+        break;
+    case 0x1a:
+        op = la_op_bltu;
+        break;
+    case 0x1b:
+        op = la_op_bgeu;
+        break;
+    default:
+        op = la_op_illegal;
+        break;
+    }
+    dec->op = op;
+}
+
+/* operand extractors */
+#define IM_5  5
+#define IM_8  8
+#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_sa2(uint32_t insn)
+{
+    return (insn >> 15) & 0x3;
+}
+
+static uint32_t operand_sa3(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 int32_t operand_im8(uint32_t insn)
+{
+    int32_t imm = (int32_t)((insn >> 10) & 0xff);
+    return imm > (1 << 7) ? imm - (1 << 8) : imm;
+}
+
+static uint32_t operand_sd(uint32_t insn)
+{
+    return insn & 0x3;
+}
+
+static uint32_t operand_sj(uint32_t insn)
+{
+    return (insn >> 5) & 0x3;
+}
+
+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_invop(uint32_t insn)
+{
+    int32_t imm = (int32_t)(insn & 0x1f);
+    return imm > (1 << 4) ? imm - (1 << 5) : 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;
+    dec->codec = opcode_data[dec->op].codec;
+    switch (dec->codec) {
+    case la_codec_illegal:
+    case la_codec_empty:
+        break;
+    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_sa2:
+        dec->r1 = operand_r1(insn);
+        dec->r2 = operand_r2(insn);
+        dec->r3 = operand_r3(insn);
+        dec->r4 = operand_sa2(insn);
+        break;
+    case la_codec_3r_sa3:
+        dec->r1 = operand_r1(insn);
+        dec->r2 = operand_r2(insn);
+        dec->r3 = operand_r3(insn);
+        dec->r4 = operand_sa3(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_r_im14:
+        dec->r1 = operand_r1(insn);
+        dec->imm = operand_im14(insn);
+        dec->bit = IM_14;
+        break;
+    case la_codec_im5_r_im12:
+        dec->imm2 = operand_r1(insn);
+        dec->r2 = operand_r2(insn);
+        dec->imm = operand_im12(insn);
+        dec->bit = IM_12;
+        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_2r_im8:
+        dec->r1 = operand_r1(insn);
+        dec->r2 = operand_r2(insn);
+        dec->imm = operand_im8(insn);
+        dec->bit = IM_8;
+        break;
+    case la_codec_r_sd:
+        dec->r1 = operand_sd(insn);
+        dec->r2 = operand_r2(insn);
+        break;
+    case la_codec_r_sj:
+        dec->r1 = operand_r1(insn);
+        dec->r2 = operand_sj(insn);
+        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_r_seq:
+        dec->r1 = 0;
+        dec->r2 = operand_r1(insn);
+        dec->imm = operand_im8(insn);
+        dec->bit = IM_8;
+        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_invtlb:
+        dec->imm = operand_invop(insn);
+        dec->bit = IM_5;
+        dec->r2 = operand_r2(insn);
+        dec->r3 = operand_r3(insn);
+        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;
+    }
+}
+
+/* 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, size_t tab, la_decode *dec)
+{
+    char tmp[16];
+    const char *fmt;
+
+    fmt = opcode_data[dec->op].format;
+    while (*fmt) {
+        switch (*fmt) {
+        case 'n': /* name */
+            append(buf, opcode_data[dec->op].name, buflen);
+            break;
+        case 's':
+            append(buf, "s", buflen);
+            break;
+        case 'd':
+            append(buf, "d", buflen);
+            break;
+        case 'e': /* illegal */
+            snprintf(tmp, sizeof(tmp), "%x", dec->insn);
+            append(buf, tmp, buflen);
+            break;
+        case 't':
+            while (strlen(buf) < tab) {
+                append(buf, " ", buflen);
+            }
+            break;
+        case '(':
+            append(buf, "(", buflen);
+            break;
+        case ',':
+            append(buf, ",", buflen);
+            break;
+        case '.':
+            append(buf, ".", buflen);
+            break;
+        case ')':
+            append(buf, ")", buflen);
+            break;
+        case '0': /* rd */
+            append(buf, loongarch_r_normal_name[dec->r1], buflen);
+            break;
+        case '1': /* rj */
+            append(buf, loongarch_r_normal_name[dec->r2], buflen);
+            break;
+        case '2': /* rk */
+            append(buf, loongarch_r_normal_name[dec->r3], buflen);
+            break;
+        case '3': /* fd */
+            append(buf, loongarch_f_normal_name[dec->r1], buflen);
+            break;
+        case '4': /* fj */
+            append(buf, loongarch_f_normal_name[dec->r2], buflen);
+            break;
+        case '5': /* fk */
+            append(buf, loongarch_f_normal_name[dec->r3], buflen);
+            break;
+        case '6': /* fa */
+            append(buf, loongarch_f_normal_name[dec->r4], buflen);
+            break;
+        case 'A': /* sd */
+            append(buf, loongarch_cr_normal_name[dec->r1], buflen);
+            break;
+        case 'B': /* sj */
+            append(buf, loongarch_cr_normal_name[dec->r2], buflen);
+            break;
+        case 'C': /* r3 */
+            snprintf(tmp, sizeof(tmp), "%x", dec->r3);
+            append(buf, tmp, buflen);
+            break;
+        case 'D': /* r4 */
+            snprintf(tmp, sizeof(tmp), "%x", dec->r4);
+            append(buf, tmp, buflen);
+            break;
+        case 'E': /* r1 */
+            snprintf(tmp, sizeof(tmp), "%x", dec->r1);
+            append(buf, tmp, buflen);
+            break;
+        case 'F': /* fcsrd */
+            append(buf, loongarch_r_normal_name[dec->r1], buflen);
+            break;
+        case 'G': /* fcsrs */
+            append(buf, loongarch_r_normal_name[dec->r2], buflen);
+            break;
+        case 'H': /* cd */
+            append(buf, loongarch_c_normal_name[dec->r1], buflen);
+            break;
+        case 'I': /* cj */
+            append(buf, loongarch_c_normal_name[dec->r2], buflen);
+            break;
+        case 'J': /* code */
+            snprintf(tmp, sizeof(tmp), "0x%x", dec->code);
+            append(buf, tmp, buflen);
+            break;
+        case 'K': /* cond */
+            switch (dec->r4) {
+            case 0x0:
+                append(buf, "caf", buflen);
+                break;
+            case 0x1:
+                append(buf, "saf", buflen);
+                break;
+            case 0x2:
+                append(buf, "clt", buflen);
+                break;
+            case 0x3:
+                append(buf, "slt", buflen);
+                break;
+            case 0x4:
+                append(buf, "ceq", buflen);
+                break;
+            case 0x5:
+                append(buf, "seq", buflen);
+                break;
+            case 0x6:
+                append(buf, "cle", buflen);
+                break;
+            case 0x7:
+                append(buf, "sle", buflen);
+                break;
+            case 0x8:
+                append(buf, "cun", buflen);
+                break;
+            case 0x9:
+                append(buf, "sun", buflen);
+                break;
+            case 0xA:
+                append(buf, "cult", buflen);
+                break;
+            case 0xB:
+                append(buf, "sult", buflen);
+                break;
+            case 0xC:
+                append(buf, "cueq", buflen);
+                break;
+            case 0xD:
+                append(buf, "sueq", buflen);
+                break;
+            case 0xE:
+                append(buf, "cule", buflen);
+                break;
+            case 0xF:
+                append(buf, "sule", buflen);
+                break;
+            case 0x10:
+                append(buf, "cne", buflen);
+                break;
+            case 0x11:
+                append(buf, "sne", buflen);
+                break;
+            case 0x14:
+                append(buf, "cor", buflen);
+                break;
+            case 0x15:
+                append(buf, "sor", buflen);
+                break;
+            case 0x18:
+                append(buf, "cune", buflen);
+                break;
+            case 0x19:
+                append(buf, "sune", buflen);
+                break;
+            }
+            break;
+        case 'L': /* ca */
+            append(buf, loongarch_c_normal_name[dec->r4], buflen);
+            break;
+        case 'M': /* cop */
+            snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm2) & 0x1f);
+            append(buf, tmp, buflen);
+            break;
+        case 'i': /* sixx d */
+            snprintf(tmp, sizeof(tmp), "%d", dec->imm);
+            append(buf, tmp, buflen);
+            break;
+        case 'o': /* offset */
+            snprintf(tmp, sizeof(tmp), "%d", (dec->imm) << 2);
+            append(buf, tmp, buflen);
+            break;
+        case 'x': /* sixx x */
+            switch (dec->bit) {
+            case IM_5:
+                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x1f);
+                append(buf, tmp, buflen);
+                break;
+            case IM_8:
+                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xff);
+                append(buf, tmp, buflen);
+                break;
+            case IM_12:
+                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfff);
+                append(buf, tmp, buflen);
+                break;
+            case IM_14:
+                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x3fff);
+                append(buf, tmp, buflen);
+                break;
+            case IM_15:
+                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0x7fff);
+                append(buf, tmp, buflen);
+                break;
+            case IM_16:
+                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xffff);
+                append(buf, tmp, buflen);
+                break;
+            case IM_20:
+                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) & 0xfffff);
+                append(buf, tmp, buflen);
+                break;
+            default:
+                snprintf(tmp, sizeof(tmp), "0x%x", dec->imm);
+                append(buf, tmp, buflen);
+                break;
+            }
+            break;
+        case 'X': /* offset x*/
+            switch (dec->bit) {
+            case IM_16:
+                snprintf(tmp, sizeof(tmp), "0x%x",
+                    ((dec->imm) << 2) & 0xffff);
+                append(buf, tmp, buflen);
+                break;
+            case IM_21:
+                snprintf(tmp, sizeof(tmp), "0x%x",
+                    ((dec->imm) << 2) & 0x1fffff);
+                append(buf, tmp, buflen);
+                break;
+            case IM_26:
+                snprintf(tmp, sizeof(tmp), "0x%x",
+                    ((dec->imm) << 2) & 0x3ffffff);
+                append(buf, tmp, buflen);
+                break;
+            default:
+                snprintf(tmp, sizeof(tmp), "0x%x", (dec->imm) << 2);
+                append(buf, tmp, buflen);
+                break;
+            }
+            break;
+        case 'p': /* pc */
+            snprintf(tmp, sizeof(tmp), "  # 0x%"PRIx32"",
+                dec->pc + ((dec->imm) << 2));
+            append(buf, tmp, buflen);
+            break;
+        default:
+            break;
+        }
+        fmt++;
+    }
+}
+
+/* disassemble instruction */
+static void
+disasm_insn(char *buf, size_t buflen, bfd_vma pc, unsigned long int insn)
+{
+    la_decode dec = { 0 };
+    dec.pc = pc;
+    dec.insn = insn;
+    decode_insn_opcode(&dec);
+    decode_insn_operands(&dec);
+    format_insn(buf, buflen, 16, &dec);
+}
+
+int
+print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
+{
+    char buf[128] = { 0 };
+    bfd_byte buffer[INSNLEN];
+    unsigned long 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);
+    } else {
+        (*info->memory_error_func)(status, memaddr, info);
+        return -1;
+    }
+    disasm_insn(buf, sizeof(buf), memaddr, insn);
+    (*info->fprintf_func)(info->stream, "\t%s", buf);
+    return INSNLEN;
+}
diff --git a/disas/meson.build b/disas/meson.build
index 449f99e..a1bd8b8 100644
--- a/disas/meson.build
+++ b/disas/meson.build
@@ -9,6 +9,7 @@  common_ss.add(when: 'CONFIG_CRIS_DIS', if_true: files('cris.c'))
 common_ss.add(when: 'CONFIG_HEXAGON_DIS', if_true: files('hexagon.c'))
 common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c'))
 common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c'))
+common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: files('loongarch.c'))
 common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c'))
 common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c'))
 common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c'))
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 524f291..009a03a 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -253,6 +253,7 @@  enum bfd_architecture
 #define bfd_mach_rx            0x75
 #define bfd_mach_rx_v2         0x76
 #define bfd_mach_rx_v3         0x77
+  bfd_arch_loongarch,
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -462,6 +463,7 @@  int print_insn_riscv32          (bfd_vma, disassemble_info*);
 int print_insn_riscv64          (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
+int print_insn_loongarch(bfd_vma, disassemble_info *);
 
 #ifdef CONFIG_CAPSTONE
 bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
diff --git a/meson.build b/meson.build
index 6b7487b..c272e58 100644
--- a/meson.build
+++ b/meson.build
@@ -1797,6 +1797,7 @@  disassemblers = {
   'sh4' : ['CONFIG_SH4_DIS'],
   'sparc' : ['CONFIG_SPARC_DIS'],
   'xtensa' : ['CONFIG_XTENSA_DIS'],
+  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
 }
 if link_language == 'cpp'
   disassemblers += {