cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

mips16e_translate.c.inc (30554B)


      1/*
      2 *  MIPS16 extension (Code Compaction) ASE translation routines
      3 *
      4 *  Copyright (c) 2004-2005 Jocelyn Mayer
      5 *  Copyright (c) 2006 Marius Groeger (FPU operations)
      6 *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
      7 *  Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
      8 *
      9 * SPDX-License-Identifier: LGPL-2.1-or-later
     10 */
     11
     12/* MIPS16 major opcodes */
     13enum {
     14  M16_OPC_ADDIUSP = 0x00,
     15  M16_OPC_ADDIUPC = 0x01,
     16  M16_OPC_B = 0x02,
     17  M16_OPC_JAL = 0x03,
     18  M16_OPC_BEQZ = 0x04,
     19  M16_OPC_BNEQZ = 0x05,
     20  M16_OPC_SHIFT = 0x06,
     21  M16_OPC_LD = 0x07,
     22  M16_OPC_RRIA = 0x08,
     23  M16_OPC_ADDIU8 = 0x09,
     24  M16_OPC_SLTI = 0x0a,
     25  M16_OPC_SLTIU = 0x0b,
     26  M16_OPC_I8 = 0x0c,
     27  M16_OPC_LI = 0x0d,
     28  M16_OPC_CMPI = 0x0e,
     29  M16_OPC_SD = 0x0f,
     30  M16_OPC_LB = 0x10,
     31  M16_OPC_LH = 0x11,
     32  M16_OPC_LWSP = 0x12,
     33  M16_OPC_LW = 0x13,
     34  M16_OPC_LBU = 0x14,
     35  M16_OPC_LHU = 0x15,
     36  M16_OPC_LWPC = 0x16,
     37  M16_OPC_LWU = 0x17,
     38  M16_OPC_SB = 0x18,
     39  M16_OPC_SH = 0x19,
     40  M16_OPC_SWSP = 0x1a,
     41  M16_OPC_SW = 0x1b,
     42  M16_OPC_RRR = 0x1c,
     43  M16_OPC_RR = 0x1d,
     44  M16_OPC_EXTEND = 0x1e,
     45  M16_OPC_I64 = 0x1f
     46};
     47
     48/* I8 funct field */
     49enum {
     50  I8_BTEQZ = 0x0,
     51  I8_BTNEZ = 0x1,
     52  I8_SWRASP = 0x2,
     53  I8_ADJSP = 0x3,
     54  I8_SVRS = 0x4,
     55  I8_MOV32R = 0x5,
     56  I8_MOVR32 = 0x7
     57};
     58
     59/* RRR f field */
     60enum {
     61  RRR_DADDU = 0x0,
     62  RRR_ADDU = 0x1,
     63  RRR_DSUBU = 0x2,
     64  RRR_SUBU = 0x3
     65};
     66
     67/* RR funct field */
     68enum {
     69  RR_JR = 0x00,
     70  RR_SDBBP = 0x01,
     71  RR_SLT = 0x02,
     72  RR_SLTU = 0x03,
     73  RR_SLLV = 0x04,
     74  RR_BREAK = 0x05,
     75  RR_SRLV = 0x06,
     76  RR_SRAV = 0x07,
     77  RR_DSRL = 0x08,
     78  RR_CMP = 0x0a,
     79  RR_NEG = 0x0b,
     80  RR_AND = 0x0c,
     81  RR_OR = 0x0d,
     82  RR_XOR = 0x0e,
     83  RR_NOT = 0x0f,
     84  RR_MFHI = 0x10,
     85  RR_CNVT = 0x11,
     86  RR_MFLO = 0x12,
     87  RR_DSRA = 0x13,
     88  RR_DSLLV = 0x14,
     89  RR_DSRLV = 0x16,
     90  RR_DSRAV = 0x17,
     91  RR_MULT = 0x18,
     92  RR_MULTU = 0x19,
     93  RR_DIV = 0x1a,
     94  RR_DIVU = 0x1b,
     95  RR_DMULT = 0x1c,
     96  RR_DMULTU = 0x1d,
     97  RR_DDIV = 0x1e,
     98  RR_DDIVU = 0x1f
     99};
    100
    101/* I64 funct field */
    102enum {
    103  I64_LDSP = 0x0,
    104  I64_SDSP = 0x1,
    105  I64_SDRASP = 0x2,
    106  I64_DADJSP = 0x3,
    107  I64_LDPC = 0x4,
    108  I64_DADDIU5 = 0x5,
    109  I64_DADDIUPC = 0x6,
    110  I64_DADDIUSP = 0x7
    111};
    112
    113/* RR ry field for CNVT */
    114enum {
    115  RR_RY_CNVT_ZEB = 0x0,
    116  RR_RY_CNVT_ZEH = 0x1,
    117  RR_RY_CNVT_ZEW = 0x2,
    118  RR_RY_CNVT_SEB = 0x4,
    119  RR_RY_CNVT_SEH = 0x5,
    120  RR_RY_CNVT_SEW = 0x6,
    121};
    122
    123static int xlat(int r)
    124{
    125  static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
    126
    127  return map[r];
    128}
    129
    130static void gen_mips16_save(DisasContext *ctx,
    131                            int xsregs, int aregs,
    132                            int do_ra, int do_s0, int do_s1,
    133                            int framesize)
    134{
    135    TCGv t0 = tcg_temp_new();
    136    TCGv t1 = tcg_temp_new();
    137    TCGv t2 = tcg_temp_new();
    138    int args, astatic;
    139
    140    switch (aregs) {
    141    case 0:
    142    case 1:
    143    case 2:
    144    case 3:
    145    case 11:
    146        args = 0;
    147        break;
    148    case 4:
    149    case 5:
    150    case 6:
    151    case 7:
    152        args = 1;
    153        break;
    154    case 8:
    155    case 9:
    156    case 10:
    157        args = 2;
    158        break;
    159    case 12:
    160    case 13:
    161        args = 3;
    162        break;
    163    case 14:
    164        args = 4;
    165        break;
    166    default:
    167        gen_reserved_instruction(ctx);
    168        return;
    169    }
    170
    171    switch (args) {
    172    case 4:
    173        gen_base_offset_addr(ctx, t0, 29, 12);
    174        gen_load_gpr(t1, 7);
    175        tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
    176        /* Fall through */
    177    case 3:
    178        gen_base_offset_addr(ctx, t0, 29, 8);
    179        gen_load_gpr(t1, 6);
    180        tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
    181        /* Fall through */
    182    case 2:
    183        gen_base_offset_addr(ctx, t0, 29, 4);
    184        gen_load_gpr(t1, 5);
    185        tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
    186        /* Fall through */
    187    case 1:
    188        gen_base_offset_addr(ctx, t0, 29, 0);
    189        gen_load_gpr(t1, 4);
    190        tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
    191    }
    192
    193    gen_load_gpr(t0, 29);
    194
    195#define DECR_AND_STORE(reg) do {                                 \
    196        tcg_gen_movi_tl(t2, -4);                                 \
    197        gen_op_addr_add(ctx, t0, t0, t2);                        \
    198        gen_load_gpr(t1, reg);                                   \
    199        tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
    200    } while (0)
    201
    202    if (do_ra) {
    203        DECR_AND_STORE(31);
    204    }
    205
    206    switch (xsregs) {
    207    case 7:
    208        DECR_AND_STORE(30);
    209        /* Fall through */
    210    case 6:
    211        DECR_AND_STORE(23);
    212        /* Fall through */
    213    case 5:
    214        DECR_AND_STORE(22);
    215        /* Fall through */
    216    case 4:
    217        DECR_AND_STORE(21);
    218        /* Fall through */
    219    case 3:
    220        DECR_AND_STORE(20);
    221        /* Fall through */
    222    case 2:
    223        DECR_AND_STORE(19);
    224        /* Fall through */
    225    case 1:
    226        DECR_AND_STORE(18);
    227    }
    228
    229    if (do_s1) {
    230        DECR_AND_STORE(17);
    231    }
    232    if (do_s0) {
    233        DECR_AND_STORE(16);
    234    }
    235
    236    switch (aregs) {
    237    case 0:
    238    case 4:
    239    case 8:
    240    case 12:
    241    case 14:
    242        astatic = 0;
    243        break;
    244    case 1:
    245    case 5:
    246    case 9:
    247    case 13:
    248        astatic = 1;
    249        break;
    250    case 2:
    251    case 6:
    252    case 10:
    253        astatic = 2;
    254        break;
    255    case 3:
    256    case 7:
    257        astatic = 3;
    258        break;
    259    case 11:
    260        astatic = 4;
    261        break;
    262    default:
    263        gen_reserved_instruction(ctx);
    264        return;
    265    }
    266
    267    if (astatic > 0) {
    268        DECR_AND_STORE(7);
    269        if (astatic > 1) {
    270            DECR_AND_STORE(6);
    271            if (astatic > 2) {
    272                DECR_AND_STORE(5);
    273                if (astatic > 3) {
    274                    DECR_AND_STORE(4);
    275                }
    276            }
    277        }
    278    }
    279#undef DECR_AND_STORE
    280
    281    tcg_gen_movi_tl(t2, -framesize);
    282    gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
    283    tcg_temp_free(t0);
    284    tcg_temp_free(t1);
    285    tcg_temp_free(t2);
    286}
    287
    288static void gen_mips16_restore(DisasContext *ctx,
    289                               int xsregs, int aregs,
    290                               int do_ra, int do_s0, int do_s1,
    291                               int framesize)
    292{
    293    int astatic;
    294    TCGv t0 = tcg_temp_new();
    295    TCGv t1 = tcg_temp_new();
    296    TCGv t2 = tcg_temp_new();
    297
    298    tcg_gen_movi_tl(t2, framesize);
    299    gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
    300
    301#define DECR_AND_LOAD(reg) do {                            \
    302        tcg_gen_movi_tl(t2, -4);                           \
    303        gen_op_addr_add(ctx, t0, t0, t2);                  \
    304        tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
    305        gen_store_gpr(t1, reg);                            \
    306    } while (0)
    307
    308    if (do_ra) {
    309        DECR_AND_LOAD(31);
    310    }
    311
    312    switch (xsregs) {
    313    case 7:
    314        DECR_AND_LOAD(30);
    315        /* Fall through */
    316    case 6:
    317        DECR_AND_LOAD(23);
    318        /* Fall through */
    319    case 5:
    320        DECR_AND_LOAD(22);
    321        /* Fall through */
    322    case 4:
    323        DECR_AND_LOAD(21);
    324        /* Fall through */
    325    case 3:
    326        DECR_AND_LOAD(20);
    327        /* Fall through */
    328    case 2:
    329        DECR_AND_LOAD(19);
    330        /* Fall through */
    331    case 1:
    332        DECR_AND_LOAD(18);
    333    }
    334
    335    if (do_s1) {
    336        DECR_AND_LOAD(17);
    337    }
    338    if (do_s0) {
    339        DECR_AND_LOAD(16);
    340    }
    341
    342    switch (aregs) {
    343    case 0:
    344    case 4:
    345    case 8:
    346    case 12:
    347    case 14:
    348        astatic = 0;
    349        break;
    350    case 1:
    351    case 5:
    352    case 9:
    353    case 13:
    354        astatic = 1;
    355        break;
    356    case 2:
    357    case 6:
    358    case 10:
    359        astatic = 2;
    360        break;
    361    case 3:
    362    case 7:
    363        astatic = 3;
    364        break;
    365    case 11:
    366        astatic = 4;
    367        break;
    368    default:
    369        gen_reserved_instruction(ctx);
    370        return;
    371    }
    372
    373    if (astatic > 0) {
    374        DECR_AND_LOAD(7);
    375        if (astatic > 1) {
    376            DECR_AND_LOAD(6);
    377            if (astatic > 2) {
    378                DECR_AND_LOAD(5);
    379                if (astatic > 3) {
    380                    DECR_AND_LOAD(4);
    381                }
    382            }
    383        }
    384    }
    385#undef DECR_AND_LOAD
    386
    387    tcg_gen_movi_tl(t2, framesize);
    388    gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
    389    tcg_temp_free(t0);
    390    tcg_temp_free(t1);
    391    tcg_temp_free(t2);
    392}
    393
    394#if defined(TARGET_MIPS64)
    395static void decode_i64_mips16(DisasContext *ctx,
    396                              int ry, int funct, int16_t offset,
    397                              int extended)
    398{
    399    switch (funct) {
    400    case I64_LDSP:
    401        check_insn(ctx, ISA_MIPS3);
    402        check_mips_64(ctx);
    403        offset = extended ? offset : offset << 3;
    404        gen_ld(ctx, OPC_LD, ry, 29, offset);
    405        break;
    406    case I64_SDSP:
    407        check_insn(ctx, ISA_MIPS3);
    408        check_mips_64(ctx);
    409        offset = extended ? offset : offset << 3;
    410        gen_st(ctx, OPC_SD, ry, 29, offset);
    411        break;
    412    case I64_SDRASP:
    413        check_insn(ctx, ISA_MIPS3);
    414        check_mips_64(ctx);
    415        offset = extended ? offset : (ctx->opcode & 0xff) << 3;
    416        gen_st(ctx, OPC_SD, 31, 29, offset);
    417        break;
    418    case I64_DADJSP:
    419        check_insn(ctx, ISA_MIPS3);
    420        check_mips_64(ctx);
    421        offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
    422        gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
    423        break;
    424    case I64_LDPC:
    425        check_insn(ctx, ISA_MIPS3);
    426        check_mips_64(ctx);
    427        if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
    428            gen_reserved_instruction(ctx);
    429        } else {
    430            offset = extended ? offset : offset << 3;
    431            gen_ld(ctx, OPC_LDPC, ry, 0, offset);
    432        }
    433        break;
    434    case I64_DADDIU5:
    435        check_insn(ctx, ISA_MIPS3);
    436        check_mips_64(ctx);
    437        offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
    438        gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
    439        break;
    440    case I64_DADDIUPC:
    441        check_insn(ctx, ISA_MIPS3);
    442        check_mips_64(ctx);
    443        offset = extended ? offset : offset << 2;
    444        gen_addiupc(ctx, ry, offset, 1, extended);
    445        break;
    446    case I64_DADDIUSP:
    447        check_insn(ctx, ISA_MIPS3);
    448        check_mips_64(ctx);
    449        offset = extended ? offset : offset << 2;
    450        gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
    451        break;
    452    }
    453}
    454#endif
    455
    456static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
    457{
    458    int extend = translator_lduw(env, &ctx->base, ctx->base.pc_next + 2);
    459    int op, rx, ry, funct, sa;
    460    int16_t imm, offset;
    461
    462    ctx->opcode = (ctx->opcode << 16) | extend;
    463    op = (ctx->opcode >> 11) & 0x1f;
    464    sa = (ctx->opcode >> 22) & 0x1f;
    465    funct = (ctx->opcode >> 8) & 0x7;
    466    rx = xlat((ctx->opcode >> 8) & 0x7);
    467    ry = xlat((ctx->opcode >> 5) & 0x7);
    468    offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
    469                              | ((ctx->opcode >> 21) & 0x3f) << 5
    470                              | (ctx->opcode & 0x1f));
    471
    472    /*
    473     * The extended opcodes cleverly reuse the opcodes from their 16-bit
    474     * counterparts.
    475     */
    476    switch (op) {
    477    case M16_OPC_ADDIUSP:
    478        gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
    479        break;
    480    case M16_OPC_ADDIUPC:
    481        gen_addiupc(ctx, rx, imm, 0, 1);
    482        break;
    483    case M16_OPC_B:
    484        gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
    485        /* No delay slot, so just process as a normal instruction */
    486        break;
    487    case M16_OPC_BEQZ:
    488        gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
    489        /* No delay slot, so just process as a normal instruction */
    490        break;
    491    case M16_OPC_BNEQZ:
    492        gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
    493        /* No delay slot, so just process as a normal instruction */
    494        break;
    495    case M16_OPC_SHIFT:
    496        switch (ctx->opcode & 0x3) {
    497        case 0x0:
    498            gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
    499            break;
    500        case 0x1:
    501#if defined(TARGET_MIPS64)
    502            check_mips_64(ctx);
    503            gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
    504#else
    505            gen_reserved_instruction(ctx);
    506#endif
    507            break;
    508        case 0x2:
    509            gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
    510            break;
    511        case 0x3:
    512            gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
    513            break;
    514        }
    515        break;
    516#if defined(TARGET_MIPS64)
    517    case M16_OPC_LD:
    518        check_insn(ctx, ISA_MIPS3);
    519        check_mips_64(ctx);
    520        gen_ld(ctx, OPC_LD, ry, rx, offset);
    521        break;
    522#endif
    523    case M16_OPC_RRIA:
    524        imm = ctx->opcode & 0xf;
    525        imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
    526        imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
    527        imm = (int16_t) (imm << 1) >> 1;
    528        if ((ctx->opcode >> 4) & 0x1) {
    529#if defined(TARGET_MIPS64)
    530            check_mips_64(ctx);
    531            gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
    532#else
    533            gen_reserved_instruction(ctx);
    534#endif
    535        } else {
    536            gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
    537        }
    538        break;
    539    case M16_OPC_ADDIU8:
    540        gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
    541        break;
    542    case M16_OPC_SLTI:
    543        gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
    544        break;
    545    case M16_OPC_SLTIU:
    546        gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
    547        break;
    548    case M16_OPC_I8:
    549        switch (funct) {
    550        case I8_BTEQZ:
    551            gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
    552            break;
    553        case I8_BTNEZ:
    554            gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
    555            break;
    556        case I8_SWRASP:
    557            gen_st(ctx, OPC_SW, 31, 29, imm);
    558            break;
    559        case I8_ADJSP:
    560            gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
    561            break;
    562        case I8_SVRS:
    563            check_insn(ctx, ISA_MIPS_R1);
    564            {
    565                int xsregs = (ctx->opcode >> 24) & 0x7;
    566                int aregs = (ctx->opcode >> 16) & 0xf;
    567                int do_ra = (ctx->opcode >> 6) & 0x1;
    568                int do_s0 = (ctx->opcode >> 5) & 0x1;
    569                int do_s1 = (ctx->opcode >> 4) & 0x1;
    570                int framesize = (((ctx->opcode >> 20) & 0xf) << 4
    571                                 | (ctx->opcode & 0xf)) << 3;
    572
    573                if (ctx->opcode & (1 << 7)) {
    574                    gen_mips16_save(ctx, xsregs, aregs,
    575                                    do_ra, do_s0, do_s1,
    576                                    framesize);
    577                } else {
    578                    gen_mips16_restore(ctx, xsregs, aregs,
    579                                       do_ra, do_s0, do_s1,
    580                                       framesize);
    581                }
    582            }
    583            break;
    584        default:
    585            gen_reserved_instruction(ctx);
    586            break;
    587        }
    588        break;
    589    case M16_OPC_LI:
    590        tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
    591        break;
    592    case M16_OPC_CMPI:
    593        tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
    594        break;
    595#if defined(TARGET_MIPS64)
    596    case M16_OPC_SD:
    597        check_insn(ctx, ISA_MIPS3);
    598        check_mips_64(ctx);
    599        gen_st(ctx, OPC_SD, ry, rx, offset);
    600        break;
    601#endif
    602    case M16_OPC_LB:
    603        gen_ld(ctx, OPC_LB, ry, rx, offset);
    604        break;
    605    case M16_OPC_LH:
    606        gen_ld(ctx, OPC_LH, ry, rx, offset);
    607        break;
    608    case M16_OPC_LWSP:
    609        gen_ld(ctx, OPC_LW, rx, 29, offset);
    610        break;
    611    case M16_OPC_LW:
    612        gen_ld(ctx, OPC_LW, ry, rx, offset);
    613        break;
    614    case M16_OPC_LBU:
    615        gen_ld(ctx, OPC_LBU, ry, rx, offset);
    616        break;
    617    case M16_OPC_LHU:
    618        gen_ld(ctx, OPC_LHU, ry, rx, offset);
    619        break;
    620    case M16_OPC_LWPC:
    621        gen_ld(ctx, OPC_LWPC, rx, 0, offset);
    622        break;
    623#if defined(TARGET_MIPS64)
    624    case M16_OPC_LWU:
    625        check_insn(ctx, ISA_MIPS3);
    626        check_mips_64(ctx);
    627        gen_ld(ctx, OPC_LWU, ry, rx, offset);
    628        break;
    629#endif
    630    case M16_OPC_SB:
    631        gen_st(ctx, OPC_SB, ry, rx, offset);
    632        break;
    633    case M16_OPC_SH:
    634        gen_st(ctx, OPC_SH, ry, rx, offset);
    635        break;
    636    case M16_OPC_SWSP:
    637        gen_st(ctx, OPC_SW, rx, 29, offset);
    638        break;
    639    case M16_OPC_SW:
    640        gen_st(ctx, OPC_SW, ry, rx, offset);
    641        break;
    642#if defined(TARGET_MIPS64)
    643    case M16_OPC_I64:
    644        decode_i64_mips16(ctx, ry, funct, offset, 1);
    645        break;
    646#endif
    647    default:
    648        gen_reserved_instruction(ctx);
    649        break;
    650    }
    651
    652    return 4;
    653}
    654
    655static int decode_ase_mips16e(CPUMIPSState *env, DisasContext *ctx)
    656{
    657    int rx, ry;
    658    int sa;
    659    int op, cnvt_op, op1, offset;
    660    int funct;
    661    int n_bytes;
    662
    663    op = (ctx->opcode >> 11) & 0x1f;
    664    sa = (ctx->opcode >> 2) & 0x7;
    665    sa = sa == 0 ? 8 : sa;
    666    rx = xlat((ctx->opcode >> 8) & 0x7);
    667    cnvt_op = (ctx->opcode >> 5) & 0x7;
    668    ry = xlat((ctx->opcode >> 5) & 0x7);
    669    op1 = offset = ctx->opcode & 0x1f;
    670
    671    n_bytes = 2;
    672
    673    switch (op) {
    674    case M16_OPC_ADDIUSP:
    675        {
    676            int16_t imm = ((uint8_t) ctx->opcode) << 2;
    677
    678            gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
    679        }
    680        break;
    681    case M16_OPC_ADDIUPC:
    682        gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
    683        break;
    684    case M16_OPC_B:
    685        offset = (ctx->opcode & 0x7ff) << 1;
    686        offset = (int16_t)(offset << 4) >> 4;
    687        gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
    688        /* No delay slot, so just process as a normal instruction */
    689        break;
    690    case M16_OPC_JAL:
    691        offset = translator_lduw(env, &ctx->base, ctx->base.pc_next + 2);
    692        offset = (((ctx->opcode & 0x1f) << 21)
    693                  | ((ctx->opcode >> 5) & 0x1f) << 16
    694                  | offset) << 2;
    695        op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
    696        gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
    697        n_bytes = 4;
    698        break;
    699    case M16_OPC_BEQZ:
    700        gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
    701                           ((int8_t)ctx->opcode) << 1, 0);
    702        /* No delay slot, so just process as a normal instruction */
    703        break;
    704    case M16_OPC_BNEQZ:
    705        gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
    706                           ((int8_t)ctx->opcode) << 1, 0);
    707        /* No delay slot, so just process as a normal instruction */
    708        break;
    709    case M16_OPC_SHIFT:
    710        switch (ctx->opcode & 0x3) {
    711        case 0x0:
    712            gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
    713            break;
    714        case 0x1:
    715#if defined(TARGET_MIPS64)
    716            check_insn(ctx, ISA_MIPS3);
    717            check_mips_64(ctx);
    718            gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
    719#else
    720            gen_reserved_instruction(ctx);
    721#endif
    722            break;
    723        case 0x2:
    724            gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
    725            break;
    726        case 0x3:
    727            gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
    728            break;
    729        }
    730        break;
    731#if defined(TARGET_MIPS64)
    732    case M16_OPC_LD:
    733        check_insn(ctx, ISA_MIPS3);
    734        check_mips_64(ctx);
    735        gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
    736        break;
    737#endif
    738    case M16_OPC_RRIA:
    739        {
    740            int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
    741
    742            if ((ctx->opcode >> 4) & 1) {
    743#if defined(TARGET_MIPS64)
    744                check_insn(ctx, ISA_MIPS3);
    745                check_mips_64(ctx);
    746                gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
    747#else
    748                gen_reserved_instruction(ctx);
    749#endif
    750            } else {
    751                gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
    752            }
    753        }
    754        break;
    755    case M16_OPC_ADDIU8:
    756        {
    757            int16_t imm = (int8_t) ctx->opcode;
    758
    759            gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
    760        }
    761        break;
    762    case M16_OPC_SLTI:
    763        {
    764            int16_t imm = (uint8_t) ctx->opcode;
    765            gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
    766        }
    767        break;
    768    case M16_OPC_SLTIU:
    769        {
    770            int16_t imm = (uint8_t) ctx->opcode;
    771            gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
    772        }
    773        break;
    774    case M16_OPC_I8:
    775        {
    776            int reg32;
    777
    778            funct = (ctx->opcode >> 8) & 0x7;
    779            switch (funct) {
    780            case I8_BTEQZ:
    781                gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
    782                                   ((int8_t)ctx->opcode) << 1, 0);
    783                break;
    784            case I8_BTNEZ:
    785                gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
    786                                   ((int8_t)ctx->opcode) << 1, 0);
    787                break;
    788            case I8_SWRASP:
    789                gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
    790                break;
    791            case I8_ADJSP:
    792                gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
    793                              ((int8_t)ctx->opcode) << 3);
    794                break;
    795            case I8_SVRS:
    796                check_insn(ctx, ISA_MIPS_R1);
    797                {
    798                    int do_ra = ctx->opcode & (1 << 6);
    799                    int do_s0 = ctx->opcode & (1 << 5);
    800                    int do_s1 = ctx->opcode & (1 << 4);
    801                    int framesize = ctx->opcode & 0xf;
    802
    803                    if (framesize == 0) {
    804                        framesize = 128;
    805                    } else {
    806                        framesize = framesize << 3;
    807                    }
    808
    809                    if (ctx->opcode & (1 << 7)) {
    810                        gen_mips16_save(ctx, 0, 0,
    811                                        do_ra, do_s0, do_s1, framesize);
    812                    } else {
    813                        gen_mips16_restore(ctx, 0, 0,
    814                                           do_ra, do_s0, do_s1, framesize);
    815                    }
    816                }
    817                break;
    818            case I8_MOV32R:
    819                {
    820                    int rz = xlat(ctx->opcode & 0x7);
    821
    822                    reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
    823                        ((ctx->opcode >> 5) & 0x7);
    824                    gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
    825                }
    826                break;
    827            case I8_MOVR32:
    828                reg32 = ctx->opcode & 0x1f;
    829                gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
    830                break;
    831            default:
    832                gen_reserved_instruction(ctx);
    833                break;
    834            }
    835        }
    836        break;
    837    case M16_OPC_LI:
    838        {
    839            int16_t imm = (uint8_t) ctx->opcode;
    840
    841            gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
    842        }
    843        break;
    844    case M16_OPC_CMPI:
    845        {
    846            int16_t imm = (uint8_t) ctx->opcode;
    847            gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
    848        }
    849        break;
    850#if defined(TARGET_MIPS64)
    851    case M16_OPC_SD:
    852        check_insn(ctx, ISA_MIPS3);
    853        check_mips_64(ctx);
    854        gen_st(ctx, OPC_SD, ry, rx, offset << 3);
    855        break;
    856#endif
    857    case M16_OPC_LB:
    858        gen_ld(ctx, OPC_LB, ry, rx, offset);
    859        break;
    860    case M16_OPC_LH:
    861        gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
    862        break;
    863    case M16_OPC_LWSP:
    864        gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
    865        break;
    866    case M16_OPC_LW:
    867        gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
    868        break;
    869    case M16_OPC_LBU:
    870        gen_ld(ctx, OPC_LBU, ry, rx, offset);
    871        break;
    872    case M16_OPC_LHU:
    873        gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
    874        break;
    875    case M16_OPC_LWPC:
    876        gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
    877        break;
    878#if defined(TARGET_MIPS64)
    879    case M16_OPC_LWU:
    880        check_insn(ctx, ISA_MIPS3);
    881        check_mips_64(ctx);
    882        gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
    883        break;
    884#endif
    885    case M16_OPC_SB:
    886        gen_st(ctx, OPC_SB, ry, rx, offset);
    887        break;
    888    case M16_OPC_SH:
    889        gen_st(ctx, OPC_SH, ry, rx, offset << 1);
    890        break;
    891    case M16_OPC_SWSP:
    892        gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
    893        break;
    894    case M16_OPC_SW:
    895        gen_st(ctx, OPC_SW, ry, rx, offset << 2);
    896        break;
    897    case M16_OPC_RRR:
    898        {
    899            int rz = xlat((ctx->opcode >> 2) & 0x7);
    900            int mips32_op;
    901
    902            switch (ctx->opcode & 0x3) {
    903            case RRR_ADDU:
    904                mips32_op = OPC_ADDU;
    905                break;
    906            case RRR_SUBU:
    907                mips32_op = OPC_SUBU;
    908                break;
    909#if defined(TARGET_MIPS64)
    910            case RRR_DADDU:
    911                mips32_op = OPC_DADDU;
    912                check_insn(ctx, ISA_MIPS3);
    913                check_mips_64(ctx);
    914                break;
    915            case RRR_DSUBU:
    916                mips32_op = OPC_DSUBU;
    917                check_insn(ctx, ISA_MIPS3);
    918                check_mips_64(ctx);
    919                break;
    920#endif
    921            default:
    922                gen_reserved_instruction(ctx);
    923                goto done;
    924            }
    925
    926            gen_arith(ctx, mips32_op, rz, rx, ry);
    927        done:
    928            ;
    929        }
    930        break;
    931    case M16_OPC_RR:
    932        switch (op1) {
    933        case RR_JR:
    934            {
    935                int nd = (ctx->opcode >> 7) & 0x1;
    936                int link = (ctx->opcode >> 6) & 0x1;
    937                int ra = (ctx->opcode >> 5) & 0x1;
    938
    939                if (nd) {
    940                    check_insn(ctx, ISA_MIPS_R1);
    941                }
    942
    943                if (link) {
    944                    op = OPC_JALR;
    945                } else {
    946                    op = OPC_JR;
    947                }
    948
    949                gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
    950                                   (nd ? 0 : 2));
    951            }
    952            break;
    953        case RR_SDBBP:
    954            if (is_uhi(extract32(ctx->opcode, 5, 6))) {
    955                gen_helper_do_semihosting(cpu_env);
    956            } else {
    957                /*
    958                 * XXX: not clear which exception should be raised
    959                 *      when in debug mode...
    960                 */
    961                check_insn(ctx, ISA_MIPS_R1);
    962                generate_exception_end(ctx, EXCP_DBp);
    963            }
    964            break;
    965        case RR_SLT:
    966            gen_slt(ctx, OPC_SLT, 24, rx, ry);
    967            break;
    968        case RR_SLTU:
    969            gen_slt(ctx, OPC_SLTU, 24, rx, ry);
    970            break;
    971        case RR_BREAK:
    972            generate_exception_end(ctx, EXCP_BREAK);
    973            break;
    974        case RR_SLLV:
    975            gen_shift(ctx, OPC_SLLV, ry, rx, ry);
    976            break;
    977        case RR_SRLV:
    978            gen_shift(ctx, OPC_SRLV, ry, rx, ry);
    979            break;
    980        case RR_SRAV:
    981            gen_shift(ctx, OPC_SRAV, ry, rx, ry);
    982            break;
    983#if defined(TARGET_MIPS64)
    984        case RR_DSRL:
    985            check_insn(ctx, ISA_MIPS3);
    986            check_mips_64(ctx);
    987            gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
    988            break;
    989#endif
    990        case RR_CMP:
    991            gen_logic(ctx, OPC_XOR, 24, rx, ry);
    992            break;
    993        case RR_NEG:
    994            gen_arith(ctx, OPC_SUBU, rx, 0, ry);
    995            break;
    996        case RR_AND:
    997            gen_logic(ctx, OPC_AND, rx, rx, ry);
    998            break;
    999        case RR_OR:
   1000            gen_logic(ctx, OPC_OR, rx, rx, ry);
   1001            break;
   1002        case RR_XOR:
   1003            gen_logic(ctx, OPC_XOR, rx, rx, ry);
   1004            break;
   1005        case RR_NOT:
   1006            gen_logic(ctx, OPC_NOR, rx, ry, 0);
   1007            break;
   1008        case RR_MFHI:
   1009            gen_HILO(ctx, OPC_MFHI, 0, rx);
   1010            break;
   1011        case RR_CNVT:
   1012            check_insn(ctx, ISA_MIPS_R1);
   1013            switch (cnvt_op) {
   1014            case RR_RY_CNVT_ZEB:
   1015                tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
   1016                break;
   1017            case RR_RY_CNVT_ZEH:
   1018                tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
   1019                break;
   1020            case RR_RY_CNVT_SEB:
   1021                tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
   1022                break;
   1023            case RR_RY_CNVT_SEH:
   1024                tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
   1025                break;
   1026#if defined(TARGET_MIPS64)
   1027            case RR_RY_CNVT_ZEW:
   1028                check_insn(ctx, ISA_MIPS_R1);
   1029                check_mips_64(ctx);
   1030                tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
   1031                break;
   1032            case RR_RY_CNVT_SEW:
   1033                check_insn(ctx, ISA_MIPS_R1);
   1034                check_mips_64(ctx);
   1035                tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
   1036                break;
   1037#endif
   1038            default:
   1039                gen_reserved_instruction(ctx);
   1040                break;
   1041            }
   1042            break;
   1043        case RR_MFLO:
   1044            gen_HILO(ctx, OPC_MFLO, 0, rx);
   1045            break;
   1046#if defined(TARGET_MIPS64)
   1047        case RR_DSRA:
   1048            check_insn(ctx, ISA_MIPS3);
   1049            check_mips_64(ctx);
   1050            gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
   1051            break;
   1052        case RR_DSLLV:
   1053            check_insn(ctx, ISA_MIPS3);
   1054            check_mips_64(ctx);
   1055            gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
   1056            break;
   1057        case RR_DSRLV:
   1058            check_insn(ctx, ISA_MIPS3);
   1059            check_mips_64(ctx);
   1060            gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
   1061            break;
   1062        case RR_DSRAV:
   1063            check_insn(ctx, ISA_MIPS3);
   1064            check_mips_64(ctx);
   1065            gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
   1066            break;
   1067#endif
   1068        case RR_MULT:
   1069            gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
   1070            break;
   1071        case RR_MULTU:
   1072            gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
   1073            break;
   1074        case RR_DIV:
   1075            gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
   1076            break;
   1077        case RR_DIVU:
   1078            gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
   1079            break;
   1080#if defined(TARGET_MIPS64)
   1081        case RR_DMULT:
   1082            check_insn(ctx, ISA_MIPS3);
   1083            check_mips_64(ctx);
   1084            gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
   1085            break;
   1086        case RR_DMULTU:
   1087            check_insn(ctx, ISA_MIPS3);
   1088            check_mips_64(ctx);
   1089            gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
   1090            break;
   1091        case RR_DDIV:
   1092            check_insn(ctx, ISA_MIPS3);
   1093            check_mips_64(ctx);
   1094            gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
   1095            break;
   1096        case RR_DDIVU:
   1097            check_insn(ctx, ISA_MIPS3);
   1098            check_mips_64(ctx);
   1099            gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
   1100            break;
   1101#endif
   1102        default:
   1103            gen_reserved_instruction(ctx);
   1104            break;
   1105        }
   1106        break;
   1107    case M16_OPC_EXTEND:
   1108        decode_extended_mips16_opc(env, ctx);
   1109        n_bytes = 4;
   1110        break;
   1111#if defined(TARGET_MIPS64)
   1112    case M16_OPC_I64:
   1113        funct = (ctx->opcode >> 8) & 0x7;
   1114        decode_i64_mips16(ctx, ry, funct, offset, 0);
   1115        break;
   1116#endif
   1117    default:
   1118        gen_reserved_instruction(ctx);
   1119        break;
   1120    }
   1121
   1122    return n_bytes;
   1123}