static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)

{

    const char *opn = "loongson_cp2";

    uint32_t opc, shift_max;

    TCGv_i64 t0, t1;



    opc = MASK_LMI(ctx->opcode);

    switch (opc) {

    case OPC_ADD_CP2:

    case OPC_SUB_CP2:

    case OPC_DADD_CP2:

    case OPC_DSUB_CP2:

        t0 = tcg_temp_local_new_i64();

        t1 = tcg_temp_local_new_i64();

        break;

    default:

        t0 = tcg_temp_new_i64();

        t1 = tcg_temp_new_i64();

        break;

    }



    gen_load_fpr64(ctx, t0, rs);

    gen_load_fpr64(ctx, t1, rt);



#define LMI_HELPER(UP, LO) \

    case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break

#define LMI_HELPER_1(UP, LO) \

    case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break

#define LMI_DIRECT(UP, LO, OP) \

    case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break



    switch (opc) {

    LMI_HELPER(PADDSH, paddsh);

    LMI_HELPER(PADDUSH, paddush);

    LMI_HELPER(PADDH, paddh);

    LMI_HELPER(PADDW, paddw);

    LMI_HELPER(PADDSB, paddsb);

    LMI_HELPER(PADDUSB, paddusb);

    LMI_HELPER(PADDB, paddb);



    LMI_HELPER(PSUBSH, psubsh);

    LMI_HELPER(PSUBUSH, psubush);

    LMI_HELPER(PSUBH, psubh);

    LMI_HELPER(PSUBW, psubw);

    LMI_HELPER(PSUBSB, psubsb);

    LMI_HELPER(PSUBUSB, psubusb);

    LMI_HELPER(PSUBB, psubb);



    LMI_HELPER(PSHUFH, pshufh);

    LMI_HELPER(PACKSSWH, packsswh);

    LMI_HELPER(PACKSSHB, packsshb);

    LMI_HELPER(PACKUSHB, packushb);



    LMI_HELPER(PUNPCKLHW, punpcklhw);

    LMI_HELPER(PUNPCKHHW, punpckhhw);

    LMI_HELPER(PUNPCKLBH, punpcklbh);

    LMI_HELPER(PUNPCKHBH, punpckhbh);

    LMI_HELPER(PUNPCKLWD, punpcklwd);

    LMI_HELPER(PUNPCKHWD, punpckhwd);



    LMI_HELPER(PAVGH, pavgh);

    LMI_HELPER(PAVGB, pavgb);

    LMI_HELPER(PMAXSH, pmaxsh);

    LMI_HELPER(PMINSH, pminsh);

    LMI_HELPER(PMAXUB, pmaxub);

    LMI_HELPER(PMINUB, pminub);



    LMI_HELPER(PCMPEQW, pcmpeqw);

    LMI_HELPER(PCMPGTW, pcmpgtw);

    LMI_HELPER(PCMPEQH, pcmpeqh);

    LMI_HELPER(PCMPGTH, pcmpgth);

    LMI_HELPER(PCMPEQB, pcmpeqb);

    LMI_HELPER(PCMPGTB, pcmpgtb);



    LMI_HELPER(PSLLW, psllw);

    LMI_HELPER(PSLLH, psllh);

    LMI_HELPER(PSRLW, psrlw);

    LMI_HELPER(PSRLH, psrlh);

    LMI_HELPER(PSRAW, psraw);

    LMI_HELPER(PSRAH, psrah);



    LMI_HELPER(PMULLH, pmullh);

    LMI_HELPER(PMULHH, pmulhh);

    LMI_HELPER(PMULHUH, pmulhuh);

    LMI_HELPER(PMADDHW, pmaddhw);



    LMI_HELPER(PASUBUB, pasubub);

    LMI_HELPER_1(BIADD, biadd);

    LMI_HELPER_1(PMOVMSKB, pmovmskb);



    LMI_DIRECT(PADDD, paddd, add);

    LMI_DIRECT(PSUBD, psubd, sub);

    LMI_DIRECT(XOR_CP2, xor, xor);

    LMI_DIRECT(NOR_CP2, nor, nor);

    LMI_DIRECT(AND_CP2, and, and);

    LMI_DIRECT(PANDN, pandn, andc);

    LMI_DIRECT(OR, or, or);



    case OPC_PINSRH_0:

        tcg_gen_deposit_i64(t0, t0, t1, 0, 16);

        opn = "pinsrh_0";

        break;

    case OPC_PINSRH_1:

        tcg_gen_deposit_i64(t0, t0, t1, 16, 16);

        opn = "pinsrh_1";

        break;

    case OPC_PINSRH_2:

        tcg_gen_deposit_i64(t0, t0, t1, 32, 16);

        opn = "pinsrh_2";

        break;

    case OPC_PINSRH_3:

        tcg_gen_deposit_i64(t0, t0, t1, 48, 16);

        opn = "pinsrh_3";

        break;



    case OPC_PEXTRH:

        tcg_gen_andi_i64(t1, t1, 3);

        tcg_gen_shli_i64(t1, t1, 4);

        tcg_gen_shr_i64(t0, t0, t1);

        tcg_gen_ext16u_i64(t0, t0);

        opn = "pextrh";

        break;



    case OPC_ADDU_CP2:

        tcg_gen_add_i64(t0, t0, t1);

        tcg_gen_ext32s_i64(t0, t0);

        opn = "addu";

        break;

    case OPC_SUBU_CP2:

        tcg_gen_sub_i64(t0, t0, t1);

        tcg_gen_ext32s_i64(t0, t0);

        opn = "addu";

        break;



    case OPC_SLL_CP2:

        opn = "sll";

        shift_max = 32;

        goto do_shift;

    case OPC_SRL_CP2:

        opn = "srl";

        shift_max = 32;

        goto do_shift;

    case OPC_SRA_CP2:

        opn = "sra";

        shift_max = 32;

        goto do_shift;

    case OPC_DSLL_CP2:

        opn = "dsll";

        shift_max = 64;

        goto do_shift;

    case OPC_DSRL_CP2:

        opn = "dsrl";

        shift_max = 64;

        goto do_shift;

    case OPC_DSRA_CP2:

        opn = "dsra";

        shift_max = 64;

        goto do_shift;

    do_shift:

        /* Make sure shift count isn't TCG undefined behaviour.  */

        tcg_gen_andi_i64(t1, t1, shift_max - 1);



        switch (opc) {

        case OPC_SLL_CP2:

        case OPC_DSLL_CP2:

            tcg_gen_shl_i64(t0, t0, t1);

            break;

        case OPC_SRA_CP2:

        case OPC_DSRA_CP2:

            /* Since SRA is UndefinedResult without sign-extended inputs,

               we can treat SRA and DSRA the same.  */

            tcg_gen_sar_i64(t0, t0, t1);

            break;

        case OPC_SRL_CP2:

            /* We want to shift in zeros for SRL; zero-extend first.  */

            tcg_gen_ext32u_i64(t0, t0);

            /* FALLTHRU */

        case OPC_DSRL_CP2:

            tcg_gen_shr_i64(t0, t0, t1);

            break;

        }



        if (shift_max == 32) {

            tcg_gen_ext32s_i64(t0, t0);

        }



        /* Shifts larger than MAX produce zero.  */

        tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);

        tcg_gen_neg_i64(t1, t1);

        tcg_gen_and_i64(t0, t0, t1);

        break;



    case OPC_ADD_CP2:

    case OPC_DADD_CP2:

        {

            TCGv_i64 t2 = tcg_temp_new_i64();

            int lab = gen_new_label();



            tcg_gen_mov_i64(t2, t0);

            tcg_gen_add_i64(t0, t1, t2);

            if (opc == OPC_ADD_CP2) {

                tcg_gen_ext32s_i64(t0, t0);

            }

            tcg_gen_xor_i64(t1, t1, t2);

            tcg_gen_xor_i64(t2, t2, t0);

            tcg_gen_andc_i64(t1, t2, t1);

            tcg_temp_free_i64(t2);

            tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);

            generate_exception(ctx, EXCP_OVERFLOW);

            gen_set_label(lab);



            opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");

            break;

        }



    case OPC_SUB_CP2:

    case OPC_DSUB_CP2:

        {

            TCGv_i64 t2 = tcg_temp_new_i64();

            int lab = gen_new_label();



            tcg_gen_mov_i64(t2, t0);

            tcg_gen_sub_i64(t0, t1, t2);

            if (opc == OPC_SUB_CP2) {

                tcg_gen_ext32s_i64(t0, t0);

            }

            tcg_gen_xor_i64(t1, t1, t2);

            tcg_gen_xor_i64(t2, t2, t0);

            tcg_gen_and_i64(t1, t1, t2);

            tcg_temp_free_i64(t2);

            tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);

            generate_exception(ctx, EXCP_OVERFLOW);

            gen_set_label(lab);



            opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");

            break;

        }



    case OPC_PMULUW:

        tcg_gen_ext32u_i64(t0, t0);

        tcg_gen_ext32u_i64(t1, t1);

        tcg_gen_mul_i64(t0, t0, t1);

        opn = "pmuluw";

        break;



    case OPC_SEQU_CP2:

    case OPC_SEQ_CP2:

    case OPC_SLTU_CP2:

    case OPC_SLT_CP2:

    case OPC_SLEU_CP2:

    case OPC_SLE_CP2:

        /* ??? Document is unclear: Set FCC[CC].  Does that mean the

           FD field is the CC field?  */

    default:

        MIPS_INVAL(opn);

        generate_exception(ctx, EXCP_RI);

        return;

    }



#undef LMI_HELPER

#undef LMI_DIRECT



    gen_store_fpr64(ctx, t0, rd);



    (void)opn; /* avoid a compiler warning */

    MIPS_DEBUG("%s %s, %s, %s", opn,

               fregnames[rd], fregnames[rs], fregnames[rt]);

    tcg_temp_free_i64(t0);

    tcg_temp_free_i64(t1);

}

static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)

{

    const char *opn = "loongson_cp2";

    uint32_t opc, shift_max;

    TCGv_i64 t0, t1;



    opc = MASK_LMI(ctx->opcode);

    switch (opc) {

    case OPC_ADD_CP2:

    case OPC_SUB_CP2:

    case OPC_DADD_CP2:

    case OPC_DSUB_CP2:

        t0 = tcg_temp_local_new_i64();

        t1 = tcg_temp_local_new_i64();

        break;

    default:

        t0 = tcg_temp_new_i64();

        t1 = tcg_temp_new_i64();

        break;

    }



    gen_load_fpr64(ctx, t0, rs);

    gen_load_fpr64(ctx, t1, rt);



#define LMI_HELPER(UP, LO) \

    case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break

#define LMI_HELPER_1(UP, LO) \

    case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break

#define LMI_DIRECT(UP, LO, OP) \

    case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break



    switch (opc) {

    LMI_HELPER(PADDSH, paddsh);

    LMI_HELPER(PADDUSH, paddush);

    LMI_HELPER(PADDH, paddh);

    LMI_HELPER(PADDW, paddw);

    LMI_HELPER(PADDSB, paddsb);

    LMI_HELPER(PADDUSB, paddusb);

    LMI_HELPER(PADDB, paddb);



    LMI_HELPER(PSUBSH, psubsh);

    LMI_HELPER(PSUBUSH, psubush);

    LMI_HELPER(PSUBH, psubh);

    LMI_HELPER(PSUBW, psubw);

    LMI_HELPER(PSUBSB, psubsb);

    LMI_HELPER(PSUBUSB, psubusb);

    LMI_HELPER(PSUBB, psubb);



    LMI_HELPER(PSHUFH, pshufh);

    LMI_HELPER(PACKSSWH, packsswh);

    LMI_HELPER(PACKSSHB, packsshb);

    LMI_HELPER(PACKUSHB, packushb);



    LMI_HELPER(PUNPCKLHW, punpcklhw);

    LMI_HELPER(PUNPCKHHW, punpckhhw);

    LMI_HELPER(PUNPCKLBH, punpcklbh);

    LMI_HELPER(PUNPCKHBH, punpckhbh);

    LMI_HELPER(PUNPCKLWD, punpcklwd);

    LMI_HELPER(PUNPCKHWD, punpckhwd);



    LMI_HELPER(PAVGH, pavgh);

    LMI_HELPER(PAVGB, pavgb);

    LMI_HELPER(PMAXSH, pmaxsh);

    LMI_HELPER(PMINSH, pminsh);

    LMI_HELPER(PMAXUB, pmaxub);

    LMI_HELPER(PMINUB, pminub);



    LMI_HELPER(PCMPEQW, pcmpeqw);

    LMI_HELPER(PCMPGTW, pcmpgtw);

    LMI_HELPER(PCMPEQH, pcmpeqh);

    LMI_HELPER(PCMPGTH, pcmpgth);

    LMI_HELPER(PCMPEQB, pcmpeqb);

    LMI_HELPER(PCMPGTB, pcmpgtb);



    LMI_HELPER(PSLLW, psllw);

    LMI_HELPER(PSLLH, psllh);

    LMI_HELPER(PSRLW, psrlw);

    LMI_HELPER(PSRLH, psrlh);

    LMI_HELPER(PSRAW, psraw);

    LMI_HELPER(PSRAH, psrah);



    LMI_HELPER(PMULLH, pmullh);

    LMI_HELPER(PMULHH, pmulhh);

    LMI_HELPER(PMULHUH, pmulhuh);

    LMI_HELPER(PMADDHW, pmaddhw);



    LMI_HELPER(PASUBUB, pasubub);

    LMI_HELPER_1(BIADD, biadd);

    LMI_HELPER_1(PMOVMSKB, pmovmskb);



    LMI_DIRECT(PADDD, paddd, add);

    LMI_DIRECT(PSUBD, psubd, sub);

    LMI_DIRECT(XOR_CP2, xor, xor);

    LMI_DIRECT(NOR_CP2, nor, nor);

    LMI_DIRECT(AND_CP2, and, and);

    LMI_DIRECT(PANDN, pandn, andc);

    LMI_DIRECT(OR, or, or);



    case OPC_PINSRH_0:

        tcg_gen_deposit_i64(t0, t0, t1, 0, 16);

        opn = "pinsrh_0";

        break;

    case OPC_PINSRH_1:

        tcg_gen_deposit_i64(t0, t0, t1, 16, 16);

        opn = "pinsrh_1";

        break;

    case OPC_PINSRH_2:

        tcg_gen_deposit_i64(t0, t0, t1, 32, 16);

        opn = "pinsrh_2";

        break;

    case OPC_PINSRH_3:

        tcg_gen_deposit_i64(t0, t0, t1, 48, 16);

        opn = "pinsrh_3";

        break;



    case OPC_PEXTRH:

        tcg_gen_andi_i64(t1, t1, 3);

        tcg_gen_shli_i64(t1, t1, 4);

        tcg_gen_shr_i64(t0, t0, t1);

        tcg_gen_ext16u_i64(t0, t0);

        opn = "pextrh";

        break;



    case OPC_ADDU_CP2:

        tcg_gen_add_i64(t0, t0, t1);

        tcg_gen_ext32s_i64(t0, t0);

        opn = "addu";

        break;

    case OPC_SUBU_CP2:

        tcg_gen_sub_i64(t0, t0, t1);

        tcg_gen_ext32s_i64(t0, t0);

        opn = "addu";

        break;



    case OPC_SLL_CP2:

        opn = "sll";

        shift_max = 32;

        goto do_shift;

    case OPC_SRL_CP2:

        opn = "srl";

        shift_max = 32;

        goto do_shift;

    case OPC_SRA_CP2:

        opn = "sra";

        shift_max = 32;

        goto do_shift;

    case OPC_DSLL_CP2:

        opn = "dsll";

        shift_max = 64;

        goto do_shift;

    case OPC_DSRL_CP2:

        opn = "dsrl";

        shift_max = 64;

        goto do_shift;

    case OPC_DSRA_CP2:

        opn = "dsra";

        shift_max = 64;

        goto do_shift;

    do_shift:

        

        tcg_gen_andi_i64(t1, t1, shift_max - 1);



        switch (opc) {

        case OPC_SLL_CP2:

        case OPC_DSLL_CP2:

            tcg_gen_shl_i64(t0, t0, t1);

            break;

        case OPC_SRA_CP2:

        case OPC_DSRA_CP2:

            



            tcg_gen_sar_i64(t0, t0, t1);

            break;

        case OPC_SRL_CP2:

            

            tcg_gen_ext32u_i64(t0, t0);

            

        case OPC_DSRL_CP2:

            tcg_gen_shr_i64(t0, t0, t1);

            break;

        }



        if (shift_max == 32) {

            tcg_gen_ext32s_i64(t0, t0);

        }



        

        tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);

        tcg_gen_neg_i64(t1, t1);

        tcg_gen_and_i64(t0, t0, t1);

        break;



    case OPC_ADD_CP2:

    case OPC_DADD_CP2:

        {

            TCGv_i64 t2 = tcg_temp_new_i64();

            int lab = gen_new_label();



            tcg_gen_mov_i64(t2, t0);

            tcg_gen_add_i64(t0, t1, t2);

            if (opc == OPC_ADD_CP2) {

                tcg_gen_ext32s_i64(t0, t0);

            }

            tcg_gen_xor_i64(t1, t1, t2);

            tcg_gen_xor_i64(t2, t2, t0);

            tcg_gen_andc_i64(t1, t2, t1);

            tcg_temp_free_i64(t2);

            tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);

            generate_exception(ctx, EXCP_OVERFLOW);

            gen_set_label(lab);



            opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");

            break;

        }



    case OPC_SUB_CP2:

    case OPC_DSUB_CP2:

        {

            TCGv_i64 t2 = tcg_temp_new_i64();

            int lab = gen_new_label();



            tcg_gen_mov_i64(t2, t0);

            tcg_gen_sub_i64(t0, t1, t2);

            if (opc == OPC_SUB_CP2) {

                tcg_gen_ext32s_i64(t0, t0);

            }

            tcg_gen_xor_i64(t1, t1, t2);

            tcg_gen_xor_i64(t2, t2, t0);

            tcg_gen_and_i64(t1, t1, t2);

            tcg_temp_free_i64(t2);

            tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);

            generate_exception(ctx, EXCP_OVERFLOW);

            gen_set_label(lab);



            opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");

            break;

        }



    case OPC_PMULUW:

        tcg_gen_ext32u_i64(t0, t0);

        tcg_gen_ext32u_i64(t1, t1);

        tcg_gen_mul_i64(t0, t0, t1);

        opn = "pmuluw";

        break;



    case OPC_SEQU_CP2:

    case OPC_SEQ_CP2:

    case OPC_SLTU_CP2:

    case OPC_SLT_CP2:

    case OPC_SLEU_CP2:

    case OPC_SLE_CP2:

        



    default:

        MIPS_INVAL(opn);

        generate_exception(ctx, EXCP_RI);

        return;

    }



#undef LMI_HELPER

#undef LMI_DIRECT



    gen_store_fpr64(ctx, t0, rd);



    (void)opn; 

    MIPS_DEBUG("%s %s, %s, %s", opn,

               fregnames[rd], fregnames[rs], fregnames[rt]);

    tcg_temp_free_i64(t0);

    tcg_temp_free_i64(t1);

}

static void FUNC_0(DisasContext *VAR_0, int VAR_1, int VAR_2, int VAR_3)

{

    const char *VAR_4 = "loongson_cp2";

    uint32_t opc, shift_max;

    TCGv_i64 t0, t1;



    opc = MASK_LMI(VAR_0->opcode);

    switch (opc) {

    case OPC_ADD_CP2:

    case OPC_SUB_CP2:

    case OPC_DADD_CP2:

    case OPC_DSUB_CP2:

        t0 = tcg_temp_local_new_i64();

        t1 = tcg_temp_local_new_i64();

        break;

    default:

        t0 = tcg_temp_new_i64();

        t1 = tcg_temp_new_i64();

        break;

    }



    gen_load_fpr64(VAR_0, t0, VAR_2);

    gen_load_fpr64(VAR_0, t1, VAR_3);



#define LMI_HELPER(UP, LO) \

    case OPC_##UP: gen_helper_##LO(t0, t0, t1); VAR_4 = #LO; break

#define LMI_HELPER_1(UP, LO) \

    case OPC_##UP: gen_helper_##LO(t0, t0); VAR_4 = #LO; break

#define LMI_DIRECT(UP, LO, OP) \

    case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); VAR_4 = #LO; break



    switch (opc) {

    LMI_HELPER(PADDSH, paddsh);

    LMI_HELPER(PADDUSH, paddush);

    LMI_HELPER(PADDH, paddh);

    LMI_HELPER(PADDW, paddw);

    LMI_HELPER(PADDSB, paddsb);

    LMI_HELPER(PADDUSB, paddusb);

    LMI_HELPER(PADDB, paddb);



    LMI_HELPER(PSUBSH, psubsh);

    LMI_HELPER(PSUBUSH, psubush);

    LMI_HELPER(PSUBH, psubh);

    LMI_HELPER(PSUBW, psubw);

    LMI_HELPER(PSUBSB, psubsb);

    LMI_HELPER(PSUBUSB, psubusb);

    LMI_HELPER(PSUBB, psubb);



    LMI_HELPER(PSHUFH, pshufh);

    LMI_HELPER(PACKSSWH, packsswh);

    LMI_HELPER(PACKSSHB, packsshb);

    LMI_HELPER(PACKUSHB, packushb);



    LMI_HELPER(PUNPCKLHW, punpcklhw);

    LMI_HELPER(PUNPCKHHW, punpckhhw);

    LMI_HELPER(PUNPCKLBH, punpcklbh);

    LMI_HELPER(PUNPCKHBH, punpckhbh);

    LMI_HELPER(PUNPCKLWD, punpcklwd);

    LMI_HELPER(PUNPCKHWD, punpckhwd);



    LMI_HELPER(PAVGH, pavgh);

    LMI_HELPER(PAVGB, pavgb);

    LMI_HELPER(PMAXSH, pmaxsh);

    LMI_HELPER(PMINSH, pminsh);

    LMI_HELPER(PMAXUB, pmaxub);

    LMI_HELPER(PMINUB, pminub);



    LMI_HELPER(PCMPEQW, pcmpeqw);

    LMI_HELPER(PCMPGTW, pcmpgtw);

    LMI_HELPER(PCMPEQH, pcmpeqh);

    LMI_HELPER(PCMPGTH, pcmpgth);

    LMI_HELPER(PCMPEQB, pcmpeqb);

    LMI_HELPER(PCMPGTB, pcmpgtb);



    LMI_HELPER(PSLLW, psllw);

    LMI_HELPER(PSLLH, psllh);

    LMI_HELPER(PSRLW, psrlw);

    LMI_HELPER(PSRLH, psrlh);

    LMI_HELPER(PSRAW, psraw);

    LMI_HELPER(PSRAH, psrah);



    LMI_HELPER(PMULLH, pmullh);

    LMI_HELPER(PMULHH, pmulhh);

    LMI_HELPER(PMULHUH, pmulhuh);

    LMI_HELPER(PMADDHW, pmaddhw);



    LMI_HELPER(PASUBUB, pasubub);

    LMI_HELPER_1(BIADD, biadd);

    LMI_HELPER_1(PMOVMSKB, pmovmskb);



    LMI_DIRECT(PADDD, paddd, add);

    LMI_DIRECT(PSUBD, psubd, sub);

    LMI_DIRECT(XOR_CP2, xor, xor);

    LMI_DIRECT(NOR_CP2, nor, nor);

    LMI_DIRECT(AND_CP2, and, and);

    LMI_DIRECT(PANDN, pandn, andc);

    LMI_DIRECT(OR, or, or);



    case OPC_PINSRH_0:

        tcg_gen_deposit_i64(t0, t0, t1, 0, 16);

        VAR_4 = "pinsrh_0";

        break;

    case OPC_PINSRH_1:

        tcg_gen_deposit_i64(t0, t0, t1, 16, 16);

        VAR_4 = "pinsrh_1";

        break;

    case OPC_PINSRH_2:

        tcg_gen_deposit_i64(t0, t0, t1, 32, 16);

        VAR_4 = "pinsrh_2";

        break;

    case OPC_PINSRH_3:

        tcg_gen_deposit_i64(t0, t0, t1, 48, 16);

        VAR_4 = "pinsrh_3";

        break;



    case OPC_PEXTRH:

        tcg_gen_andi_i64(t1, t1, 3);

        tcg_gen_shli_i64(t1, t1, 4);

        tcg_gen_shr_i64(t0, t0, t1);

        tcg_gen_ext16u_i64(t0, t0);

        VAR_4 = "pextrh";

        break;



    case OPC_ADDU_CP2:

        tcg_gen_add_i64(t0, t0, t1);

        tcg_gen_ext32s_i64(t0, t0);

        VAR_4 = "addu";

        break;

    case OPC_SUBU_CP2:

        tcg_gen_sub_i64(t0, t0, t1);

        tcg_gen_ext32s_i64(t0, t0);

        VAR_4 = "addu";

        break;



    case OPC_SLL_CP2:

        VAR_4 = "sll";

        shift_max = 32;

        goto do_shift;

    case OPC_SRL_CP2:

        VAR_4 = "srl";

        shift_max = 32;

        goto do_shift;

    case OPC_SRA_CP2:

        VAR_4 = "sra";

        shift_max = 32;

        goto do_shift;

    case OPC_DSLL_CP2:

        VAR_4 = "dsll";

        shift_max = 64;

        goto do_shift;

    case OPC_DSRL_CP2:

        VAR_4 = "dsrl";

        shift_max = 64;

        goto do_shift;

    case OPC_DSRA_CP2:

        VAR_4 = "dsra";

        shift_max = 64;

        goto do_shift;

    do_shift:

        

        tcg_gen_andi_i64(t1, t1, shift_max - 1);



        switch (opc) {

        case OPC_SLL_CP2:

        case OPC_DSLL_CP2:

            tcg_gen_shl_i64(t0, t0, t1);

            break;

        case OPC_SRA_CP2:

        case OPC_DSRA_CP2:

            



            tcg_gen_sar_i64(t0, t0, t1);

            break;

        case OPC_SRL_CP2:

            

            tcg_gen_ext32u_i64(t0, t0);

            

        case OPC_DSRL_CP2:

            tcg_gen_shr_i64(t0, t0, t1);

            break;

        }



        if (shift_max == 32) {

            tcg_gen_ext32s_i64(t0, t0);

        }



        

        tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);

        tcg_gen_neg_i64(t1, t1);

        tcg_gen_and_i64(t0, t0, t1);

        break;



    case OPC_ADD_CP2:

    case OPC_DADD_CP2:

        {

            TCGv_i64 t2 = tcg_temp_new_i64();

            int VAR_6 = gen_new_label();



            tcg_gen_mov_i64(t2, t0);

            tcg_gen_add_i64(t0, t1, t2);

            if (opc == OPC_ADD_CP2) {

                tcg_gen_ext32s_i64(t0, t0);

            }

            tcg_gen_xor_i64(t1, t1, t2);

            tcg_gen_xor_i64(t2, t2, t0);

            tcg_gen_andc_i64(t1, t2, t1);

            tcg_temp_free_i64(t2);

            tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, VAR_6);

            generate_exception(VAR_0, EXCP_OVERFLOW);

            gen_set_label(VAR_6);



            VAR_4 = (opc == OPC_ADD_CP2 ? "add" : "dadd");

            break;

        }



    case OPC_SUB_CP2:

    case OPC_DSUB_CP2:

        {

            TCGv_i64 t2 = tcg_temp_new_i64();

            int VAR_6 = gen_new_label();



            tcg_gen_mov_i64(t2, t0);

            tcg_gen_sub_i64(t0, t1, t2);

            if (opc == OPC_SUB_CP2) {

                tcg_gen_ext32s_i64(t0, t0);

            }

            tcg_gen_xor_i64(t1, t1, t2);

            tcg_gen_xor_i64(t2, t2, t0);

            tcg_gen_and_i64(t1, t1, t2);

            tcg_temp_free_i64(t2);

            tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, VAR_6);

            generate_exception(VAR_0, EXCP_OVERFLOW);

            gen_set_label(VAR_6);



            VAR_4 = (opc == OPC_SUB_CP2 ? "sub" : "dsub");

            break;

        }



    case OPC_PMULUW:

        tcg_gen_ext32u_i64(t0, t0);

        tcg_gen_ext32u_i64(t1, t1);

        tcg_gen_mul_i64(t0, t0, t1);

        VAR_4 = "pmuluw";

        break;



    case OPC_SEQU_CP2:

    case OPC_SEQ_CP2:

    case OPC_SLTU_CP2:

    case OPC_SLT_CP2:

    case OPC_SLEU_CP2:

    case OPC_SLE_CP2:

        



    default:

        MIPS_INVAL(VAR_4);

        generate_exception(VAR_0, EXCP_RI);

        return;

    }



#undef LMI_HELPER

#undef LMI_DIRECT



    gen_store_fpr64(VAR_0, t0, VAR_1);



    (void)VAR_4; 

    MIPS_DEBUG("%s %s, %s, %s", VAR_4,

               fregnames[VAR_1], fregnames[VAR_2], fregnames[VAR_3]);

    tcg_temp_free_i64(t0);

    tcg_temp_free_i64(t1);

}

static void FUNC_0(DisasContext *VAR_0, int VAR_1, int VAR_2, int VAR_3)
{ const char *VAR_4 = "loongson_cp2"; uint32_t opc, shift_max; TCGv_i64 t0, t1; opc = MASK_LMI(VAR_0->opcode); switch (opc) { case OPC_ADD_CP2:
case OPC_SUB_CP2:
case OPC_DADD_CP2:
case OPC_DSUB_CP2:
t0 = tcg_temp_local_new_i64(); t1 = tcg_temp_local_new_i64(); break; default:
t0 = tcg_temp_new_i64(); t1 = tcg_temp_new_i64(); break; } gen_load_fpr64(VAR_0, t0, VAR_2); gen_load_fpr64(VAR_0, t1, VAR_3); #define LMI_HELPER(UP, LO) \
case OPC_##UP: gen_helper_##LO(t0, t0, t1); VAR_4 = #LO; break #define LMI_HELPER_1(UP, LO) \
case OPC_##UP: gen_helper_##LO(t0, t0); VAR_4 = #LO; break #define LMI_DIRECT(UP, LO, OP) \
case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); VAR_4 = #LO; break switch (opc) { LMI_HELPER(PADDSH, paddsh); LMI_HELPER(PADDUSH, paddush); LMI_HELPER(PADDH, paddh); LMI_HELPER(PADDW, paddw); LMI_HELPER(PADDSB, paddsb); LMI_HELPER(PADDUSB, paddusb); LMI_HELPER(PADDB, paddb); LMI_HELPER(PSUBSH, psubsh); LMI_HELPER(PSUBUSH, psubush); LMI_HELPER(PSUBH, psubh); LMI_HELPER(PSUBW, psubw); LMI_HELPER(PSUBSB, psubsb); LMI_HELPER(PSUBUSB, psubusb); LMI_HELPER(PSUBB, psubb); LMI_HELPER(PSHUFH, pshufh); LMI_HELPER(PACKSSWH, packsswh); LMI_HELPER(PACKSSHB, packsshb); LMI_HELPER(PACKUSHB, packushb); LMI_HELPER(PUNPCKLHW, punpcklhw); LMI_HELPER(PUNPCKHHW, punpckhhw); LMI_HELPER(PUNPCKLBH, punpcklbh); LMI_HELPER(PUNPCKHBH, punpckhbh); LMI_HELPER(PUNPCKLWD, punpcklwd); LMI_HELPER(PUNPCKHWD, punpckhwd); LMI_HELPER(PAVGH, pavgh); LMI_HELPER(PAVGB, pavgb); LMI_HELPER(PMAXSH, pmaxsh); LMI_HELPER(PMINSH, pminsh); LMI_HELPER(PMAXUB, pmaxub); LMI_HELPER(PMINUB, pminub); LMI_HELPER(PCMPEQW, pcmpeqw); LMI_HELPER(PCMPGTW, pcmpgtw); LMI_HELPER(PCMPEQH, pcmpeqh); LMI_HELPER(PCMPGTH, pcmpgth); LMI_HELPER(PCMPEQB, pcmpeqb); LMI_HELPER(PCMPGTB, pcmpgtb); LMI_HELPER(PSLLW, psllw); LMI_HELPER(PSLLH, psllh); LMI_HELPER(PSRLW, psrlw); LMI_HELPER(PSRLH, psrlh); LMI_HELPER(PSRAW, psraw); LMI_HELPER(PSRAH, psrah); LMI_HELPER(PMULLH, pmullh); LMI_HELPER(PMULHH, pmulhh); LMI_HELPER(PMULHUH, pmulhuh); LMI_HELPER(PMADDHW, pmaddhw); LMI_HELPER(PASUBUB, pasubub); LMI_HELPER_1(BIADD, biadd); LMI_HELPER_1(PMOVMSKB, pmovmskb); LMI_DIRECT(PADDD, paddd, add); LMI_DIRECT(PSUBD, psubd, sub); LMI_DIRECT(XOR_CP2, xor, xor); LMI_DIRECT(NOR_CP2, nor, nor); LMI_DIRECT(AND_CP2, and, and); LMI_DIRECT(PANDN, pandn, andc); LMI_DIRECT(OR, or, or); case OPC_PINSRH_0:
tcg_gen_deposit_i64(t0, t0, t1, 0, 16); VAR_4 = "pinsrh_0"; break; case OPC_PINSRH_1:
tcg_gen_deposit_i64(t0, t0, t1, 16, 16); VAR_4 = "pinsrh_1"; break; case OPC_PINSRH_2:
tcg_gen_deposit_i64(t0, t0, t1, 32, 16); VAR_4 = "pinsrh_2"; break; case OPC_PINSRH_3:
tcg_gen_deposit_i64(t0, t0, t1, 48, 16); VAR_4 = "pinsrh_3"; break; case OPC_PEXTRH:
tcg_gen_andi_i64(t1, t1, 3); tcg_gen_shli_i64(t1, t1, 4); tcg_gen_shr_i64(t0, t0, t1); tcg_gen_ext16u_i64(t0, t0); VAR_4 = "pextrh"; break; case OPC_ADDU_CP2:
tcg_gen_add_i64(t0, t0, t1); tcg_gen_ext32s_i64(t0, t0); VAR_4 = "addu"; break; case OPC_SUBU_CP2:
tcg_gen_sub_i64(t0, t0, t1); tcg_gen_ext32s_i64(t0, t0); VAR_4 = "addu"; break; case OPC_SLL_CP2:
VAR_4 = "sll"; shift_max = 32; goto do_shift; case OPC_SRL_CP2:
VAR_4 = "srl"; shift_max = 32; goto do_shift; case OPC_SRA_CP2:
VAR_4 = "sra"; shift_max = 32; goto do_shift; case OPC_DSLL_CP2:
VAR_4 = "dsll"; shift_max = 64; goto do_shift; case OPC_DSRL_CP2:
VAR_4 = "dsrl"; shift_max = 64; goto do_shift; case OPC_DSRA_CP2:
VAR_4 = "dsra"; shift_max = 64; goto do_shift; do_shift:
tcg_gen_andi_i64(t1, t1, shift_max - 1); switch (opc) { case OPC_SLL_CP2:
case OPC_DSLL_CP2:
tcg_gen_shl_i64(t0, t0, t1); break; case OPC_SRA_CP2:
case OPC_DSRA_CP2:
tcg_gen_sar_i64(t0, t0, t1); break; case OPC_SRL_CP2:
tcg_gen_ext32u_i64(t0, t0); case OPC_DSRL_CP2:
tcg_gen_shr_i64(t0, t0, t1); break; } if (shift_max == 32) { tcg_gen_ext32s_i64(t0, t0); } tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max); tcg_gen_neg_i64(t1, t1); tcg_gen_and_i64(t0, t0, t1); break; case OPC_ADD_CP2:
case OPC_DADD_CP2:
{ TCGv_i64 t2 = tcg_temp_new_i64(); int VAR_6 = gen_new_label(); tcg_gen_mov_i64(t2, t0); tcg_gen_add_i64(t0, t1, t2); if (opc == OPC_ADD_CP2) { tcg_gen_ext32s_i64(t0, t0); } tcg_gen_xor_i64(t1, t1, t2); tcg_gen_xor_i64(t2, t2, t0); tcg_gen_andc_i64(t1, t2, t1); tcg_temp_free_i64(t2); tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, VAR_6); generate_exception(VAR_0, EXCP_OVERFLOW); gen_set_label(VAR_6); VAR_4 = (opc == OPC_ADD_CP2 ? "add" : "dadd"); break; } case OPC_SUB_CP2:
case OPC_DSUB_CP2:
{ TCGv_i64 t2 = tcg_temp_new_i64(); int VAR_6 = gen_new_label(); tcg_gen_mov_i64(t2, t0); tcg_gen_sub_i64(t0, t1, t2); if (opc == OPC_SUB_CP2) { tcg_gen_ext32s_i64(t0, t0); } tcg_gen_xor_i64(t1, t1, t2); tcg_gen_xor_i64(t2, t2, t0); tcg_gen_and_i64(t1, t1, t2); tcg_temp_free_i64(t2); tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, VAR_6); generate_exception(VAR_0, EXCP_OVERFLOW); gen_set_label(VAR_6); VAR_4 = (opc == OPC_SUB_CP2 ? "sub" : "dsub"); break; } case OPC_PMULUW:
tcg_gen_ext32u_i64(t0, t0); tcg_gen_ext32u_i64(t1, t1); tcg_gen_mul_i64(t0, t0, t1); VAR_4 = "pmuluw"; break; case OPC_SEQU_CP2:
case OPC_SEQ_CP2:
case OPC_SLTU_CP2:
case OPC_SLT_CP2:
case OPC_SLEU_CP2:
case OPC_SLE_CP2:
default:
MIPS_INVAL(VAR_4); generate_exception(VAR_0, EXCP_RI); return; } #undef LMI_HELPER
#undef LMI_DIRECT
gen_store_fpr64(VAR_0, t0, VAR_1); (void)VAR_4; MIPS_DEBUG("%s %s, %s, %s", VAR_4,
fregnames[VAR_1], fregnames[VAR_2], fregnames[VAR_3]); tcg_temp_free_i64(t0); tcg_temp_free_i64(t1); }