qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

octeon_translate.c (3824B)


      1 /*
      2  * Octeon-specific instructions translation routines
      3  *
      4  *  Copyright (c) 2022 Pavel Dovgalyuk
      5  *
      6  * SPDX-License-Identifier: GPL-2.0-or-later
      7  */
      8 
      9 #include "qemu/osdep.h"
     10 #include "tcg/tcg-op.h"
     11 #include "tcg/tcg-op-gvec.h"
     12 #include "exec/helper-gen.h"
     13 #include "translate.h"
     14 
     15 /* Include the auto-generated decoder.  */
     16 #include "decode-octeon.c.inc"
     17 
     18 static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
     19 {
     20     TCGv p;
     21 
     22     if (ctx->hflags & MIPS_HFLAG_BMASK) {
     23         LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
     24                   TARGET_FMT_lx "\n", ctx->base.pc_next);
     25         generate_exception_end(ctx, EXCP_RI);
     26         return true;
     27     }
     28 
     29     /* Load needed operands */
     30     TCGv t0 = tcg_temp_new();
     31     gen_load_gpr(t0, a->rs);
     32 
     33     p = tcg_constant_tl(1ULL << a->p);
     34     if (a->set) {
     35         tcg_gen_and_tl(bcond, p, t0);
     36     } else {
     37         tcg_gen_andc_tl(bcond, p, t0);
     38     }
     39 
     40     ctx->hflags |= MIPS_HFLAG_BC;
     41     ctx->btarget = ctx->base.pc_next + 4 + a->offset * 4;
     42     ctx->hflags |= MIPS_HFLAG_BDS32;
     43 
     44     tcg_temp_free(t0);
     45     return true;
     46 }
     47 
     48 static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a)
     49 {
     50     TCGv t0, t1;
     51 
     52     if (a->rt == 0) {
     53         /* nop */
     54         return true;
     55     }
     56 
     57     t0 = tcg_temp_new();
     58     t1 = tcg_temp_new();
     59     gen_load_gpr(t0, a->rs);
     60     gen_load_gpr(t1, a->rt);
     61 
     62     tcg_gen_add_tl(t0, t0, t1);
     63     tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff);
     64 
     65     tcg_temp_free(t0);
     66     tcg_temp_free(t1);
     67 
     68     return true;
     69 }
     70 
     71 static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a)
     72 {
     73     TCGv t0, t1;
     74 
     75     if (a->rt == 0) {
     76         /* nop */
     77         return true;
     78     }
     79 
     80     t0 = tcg_temp_new();
     81     t1 = tcg_temp_new();
     82     gen_load_gpr(t0, a->rs);
     83     gen_load_gpr(t1, a->rt);
     84 
     85     tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1);
     86 
     87     tcg_temp_free(t0);
     88     tcg_temp_free(t1);
     89 
     90     return true;
     91 }
     92 
     93 static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a)
     94 {
     95     TCGv t0;
     96 
     97     if (a->rt == 0) {
     98         /* nop */
     99         return true;
    100     }
    101 
    102     t0 = tcg_temp_new();
    103     gen_load_gpr(t0, a->rs);
    104     tcg_gen_sextract_tl(t0, t0, a->p, a->lenm1 + 1);
    105     gen_store_gpr(t0, a->rt);
    106     tcg_temp_free(t0);
    107 
    108     return true;
    109 }
    110 
    111 static bool trans_CINS(DisasContext *ctx, arg_CINS *a)
    112 {
    113     TCGv t0;
    114 
    115     if (a->rt == 0) {
    116         /* nop */
    117         return true;
    118     }
    119 
    120     t0 = tcg_temp_new();
    121     gen_load_gpr(t0, a->rs);
    122     tcg_gen_deposit_z_tl(t0, t0, a->p, a->lenm1 + 1);
    123     gen_store_gpr(t0, a->rt);
    124     tcg_temp_free(t0);
    125 
    126     return true;
    127 }
    128 
    129 static bool trans_POP(DisasContext *ctx, arg_POP *a)
    130 {
    131     TCGv t0;
    132 
    133     if (a->rd == 0) {
    134         /* nop */
    135         return true;
    136     }
    137 
    138     t0 = tcg_temp_new();
    139     gen_load_gpr(t0, a->rs);
    140     if (!a->dw) {
    141         tcg_gen_andi_i64(t0, t0, 0xffffffff);
    142     }
    143     tcg_gen_ctpop_tl(t0, t0);
    144     gen_store_gpr(t0, a->rd);
    145     tcg_temp_free(t0);
    146 
    147     return true;
    148 }
    149 
    150 static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a)
    151 {
    152     TCGv t0, t1;
    153 
    154     if (a->rd == 0) {
    155         /* nop */
    156         return true;
    157     }
    158 
    159     t0 = tcg_temp_new();
    160     t1 = tcg_temp_new();
    161 
    162     gen_load_gpr(t0, a->rs);
    163     gen_load_gpr(t1, a->rt);
    164 
    165     if (a->ne) {
    166         tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[a->rd], t1, t0);
    167     } else {
    168         tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0);
    169     }
    170 
    171     tcg_temp_free(t0);
    172     tcg_temp_free(t1);
    173 
    174     return true;
    175 }
    176 
    177 static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a)
    178 {
    179     TCGv t0;
    180 
    181     if (a->rt == 0) {
    182         /* nop */
    183         return true;
    184     }
    185 
    186     t0 = tcg_temp_new();
    187 
    188     gen_load_gpr(t0, a->rs);
    189 
    190     /* Sign-extend to 64 bit value */
    191     target_ulong imm = a->imm;
    192     if (a->ne) {
    193         tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm);
    194     } else {
    195         tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm);
    196     }
    197 
    198     tcg_temp_free(t0);
    199 
    200     return true;
    201 }