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