qemu

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

translate.h (7929B)


      1 /*
      2  *  MIPS translation routines.
      3  *
      4  *  Copyright (c) 2004-2005 Jocelyn Mayer
      5  *
      6  * SPDX-License-Identifier: LGPL-2.1-or-later
      7  */
      8 #ifndef TARGET_MIPS_TRANSLATE_H
      9 #define TARGET_MIPS_TRANSLATE_H
     10 
     11 #include "qemu/log.h"
     12 #include "exec/translator.h"
     13 
     14 #define MIPS_DEBUG_DISAS 0
     15 
     16 typedef struct DisasContext {
     17     DisasContextBase base;
     18     target_ulong saved_pc;
     19     target_ulong page_start;
     20     uint32_t opcode;
     21     uint64_t insn_flags;
     22     int32_t CP0_Config0;
     23     int32_t CP0_Config1;
     24     int32_t CP0_Config2;
     25     int32_t CP0_Config3;
     26     int32_t CP0_Config5;
     27     /* Routine used to access memory */
     28     int mem_idx;
     29     MemOp default_tcg_memop_mask;
     30     uint32_t hflags, saved_hflags;
     31     target_ulong btarget;
     32     bool ulri;
     33     int kscrexist;
     34     bool rxi;
     35     int ie;
     36     bool bi;
     37     bool bp;
     38     uint64_t PAMask;
     39     bool mvh;
     40     bool eva;
     41     bool sc;
     42     int CP0_LLAddr_shift;
     43     bool ps;
     44     bool vp;
     45     bool cmgcr;
     46     bool mrp;
     47     bool nan2008;
     48     bool abs2008;
     49     bool saar;
     50     bool mi;
     51     int gi;
     52 } DisasContext;
     53 
     54 #define DISAS_STOP       DISAS_TARGET_0
     55 #define DISAS_EXIT       DISAS_TARGET_1
     56 #define DISAS_SEMIHOST   DISAS_TARGET_2
     57 
     58 /* MIPS major opcodes */
     59 #define MASK_OP_MAJOR(op)   (op & (0x3F << 26))
     60 
     61 #define OPC_CP1 (0x11 << 26)
     62 
     63 /* Coprocessor 1 (rs field) */
     64 #define MASK_CP1(op)                (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
     65 
     66 /* Values for the fmt field in FP instructions */
     67 enum {
     68     /* 0 - 15 are reserved */
     69     FMT_S = 16,          /* single fp */
     70     FMT_D = 17,          /* double fp */
     71     FMT_E = 18,          /* extended fp */
     72     FMT_Q = 19,          /* quad fp */
     73     FMT_W = 20,          /* 32-bit fixed */
     74     FMT_L = 21,          /* 64-bit fixed */
     75     FMT_PS = 22,         /* paired single fp */
     76     /* 23 - 31 are reserved */
     77 };
     78 
     79 enum {
     80     OPC_MFC1     = (0x00 << 21) | OPC_CP1,
     81     OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
     82     OPC_CFC1     = (0x02 << 21) | OPC_CP1,
     83     OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
     84     OPC_MTC1     = (0x04 << 21) | OPC_CP1,
     85     OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
     86     OPC_CTC1     = (0x06 << 21) | OPC_CP1,
     87     OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
     88     OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
     89     OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
     90     OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
     91     OPC_S_FMT    = (FMT_S << 21) | OPC_CP1,
     92     OPC_D_FMT    = (FMT_D << 21) | OPC_CP1,
     93     OPC_E_FMT    = (FMT_E << 21) | OPC_CP1,
     94     OPC_Q_FMT    = (FMT_Q << 21) | OPC_CP1,
     95     OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,
     96     OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,
     97     OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1,
     98     OPC_BC1EQZ   = (0x09 << 21) | OPC_CP1,
     99     OPC_BC1NEZ   = (0x0D << 21) | OPC_CP1,
    100 };
    101 
    102 #define MASK_CP1_FUNC(op)           (MASK_CP1(op) | (op & 0x3F))
    103 #define MASK_BC1(op)                (MASK_CP1(op) | (op & (0x3 << 16)))
    104 
    105 enum {
    106     OPC_BC1F     = (0x00 << 16) | OPC_BC1,
    107     OPC_BC1T     = (0x01 << 16) | OPC_BC1,
    108     OPC_BC1FL    = (0x02 << 16) | OPC_BC1,
    109     OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
    110 };
    111 
    112 enum {
    113     OPC_BC1FANY2     = (0x00 << 16) | OPC_BC1ANY2,
    114     OPC_BC1TANY2     = (0x01 << 16) | OPC_BC1ANY2,
    115 };
    116 
    117 enum {
    118     OPC_BC1FANY4     = (0x00 << 16) | OPC_BC1ANY4,
    119     OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
    120 };
    121 
    122 #define gen_helper_0e1i(name, arg1, arg2) do { \
    123     gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \
    124     } while (0)
    125 
    126 #define gen_helper_1e0i(name, ret, arg1) do { \
    127     gen_helper_##name(ret, cpu_env, tcg_constant_i32(arg1)); \
    128     } while (0)
    129 
    130 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
    131     gen_helper_##name(cpu_env, arg1, arg2, tcg_constant_i32(arg3));\
    132     } while (0)
    133 
    134 void generate_exception(DisasContext *ctx, int excp);
    135 void generate_exception_err(DisasContext *ctx, int excp, int err);
    136 void generate_exception_end(DisasContext *ctx, int excp);
    137 void generate_exception_break(DisasContext *ctx, int code);
    138 void gen_reserved_instruction(DisasContext *ctx);
    139 
    140 void check_insn(DisasContext *ctx, uint64_t flags);
    141 void check_mips_64(DisasContext *ctx);
    142 /**
    143  * check_cp0_enabled:
    144  * Return %true if CP0 is enabled, otherwise return %false
    145  * and emit a 'coprocessor unusable' exception.
    146  */
    147 bool check_cp0_enabled(DisasContext *ctx);
    148 void check_cp1_enabled(DisasContext *ctx);
    149 void check_cp1_64bitmode(DisasContext *ctx);
    150 void check_cp1_registers(DisasContext *ctx, int regs);
    151 void check_cop1x(DisasContext *ctx);
    152 
    153 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset);
    154 void gen_move_low32(TCGv ret, TCGv_i64 arg);
    155 void gen_move_high32(TCGv ret, TCGv_i64 arg);
    156 void gen_load_gpr(TCGv t, int reg);
    157 void gen_store_gpr(TCGv t, int reg);
    158 #if defined(TARGET_MIPS64)
    159 void gen_load_gpr_hi(TCGv_i64 t, int reg);
    160 void gen_store_gpr_hi(TCGv_i64 t, int reg);
    161 #endif /* TARGET_MIPS64 */
    162 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
    163 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
    164 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
    165 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
    166 int get_fp_bit(int cc);
    167 
    168 void gen_ldxs(DisasContext *ctx, int base, int index, int rd);
    169 void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp);
    170 void gen_addiupc(DisasContext *ctx, int rx, int imm,
    171                  int is_64_bit, int extended);
    172 
    173 /*
    174  * Address Computation and Large Constant Instructions
    175  */
    176 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1);
    177 bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
    178 bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
    179 
    180 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel);
    181 
    182 extern TCGv cpu_gpr[32], cpu_PC;
    183 #if defined(TARGET_MIPS64)
    184 extern TCGv_i64 cpu_gpr_hi[32];
    185 #endif
    186 extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
    187 extern TCGv_i32 fpu_fcr0, fpu_fcr31;
    188 extern TCGv_i64 fpu_f64[32];
    189 extern TCGv bcond;
    190 
    191 #define LOG_DISAS(...)                                                        \
    192     do {                                                                      \
    193         if (MIPS_DEBUG_DISAS) {                                               \
    194             qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__);                 \
    195         }                                                                     \
    196     } while (0)
    197 
    198 #define MIPS_INVAL(op)                                                        \
    199     do {                                                                      \
    200         if (MIPS_DEBUG_DISAS) {                                               \
    201             qemu_log_mask(CPU_LOG_TB_IN_ASM,                                  \
    202                           TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
    203                           ctx->base.pc_next, ctx->opcode, op,                 \
    204                           ctx->opcode >> 26, ctx->opcode & 0x3F,              \
    205                           ((ctx->opcode >> 16) & 0x1F));                      \
    206         }                                                                     \
    207     } while (0)
    208 
    209 /* MSA */
    210 void msa_translate_init(void);
    211 
    212 /* MXU */
    213 void mxu_translate_init(void);
    214 bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
    215 
    216 /* decodetree generated */
    217 bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
    218 bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
    219 bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
    220 #if defined(TARGET_MIPS64)
    221 bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
    222 bool decode_ext_octeon(DisasContext *ctx, uint32_t insn);
    223 #endif
    224 bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
    225 
    226 /*
    227  * Helpers for implementing sets of trans_* functions.
    228  * Defer the implementation of NAME to FUNC, with optional extra arguments.
    229  */
    230 #define TRANS(NAME, FUNC, ...) \
    231     static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
    232     { return FUNC(ctx, a, __VA_ARGS__); }
    233 
    234 static inline bool cpu_is_bigendian(DisasContext *ctx)
    235 {
    236     return extract32(ctx->CP0_Config0, CP0C0_BE, 1);
    237 }
    238 
    239 #endif