xref: /qemu/target/mips/tcg/translate.h (revision 905bdf72a6373bcb46fbdc8b9d7d9f83d134a266)
1e3130936SPhilippe Mathieu-Daudé /*
2e3130936SPhilippe Mathieu-Daudé  *  MIPS translation routines.
3e3130936SPhilippe Mathieu-Daudé  *
4e3130936SPhilippe Mathieu-Daudé  *  Copyright (c) 2004-2005 Jocelyn Mayer
5e3130936SPhilippe Mathieu-Daudé  *
6e3130936SPhilippe Mathieu-Daudé  * SPDX-License-Identifier: LGPL-2.1-or-later
7e3130936SPhilippe Mathieu-Daudé  */
8e3130936SPhilippe Mathieu-Daudé #ifndef TARGET_MIPS_TRANSLATE_H
9e3130936SPhilippe Mathieu-Daudé #define TARGET_MIPS_TRANSLATE_H
10e3130936SPhilippe Mathieu-Daudé 
11e3130936SPhilippe Mathieu-Daudé #include "exec/translator.h"
12e3130936SPhilippe Mathieu-Daudé 
1346c9e2b3SPhilippe Mathieu-Daudé #define MIPS_DEBUG_DISAS 0
1446c9e2b3SPhilippe Mathieu-Daudé 
15e3130936SPhilippe Mathieu-Daudé typedef struct DisasContext {
16e3130936SPhilippe Mathieu-Daudé     DisasContextBase base;
17e3130936SPhilippe Mathieu-Daudé     target_ulong saved_pc;
18e3130936SPhilippe Mathieu-Daudé     target_ulong page_start;
19e3130936SPhilippe Mathieu-Daudé     uint32_t opcode;
20e3130936SPhilippe Mathieu-Daudé     uint64_t insn_flags;
21e3130936SPhilippe Mathieu-Daudé     int32_t CP0_Config1;
22e3130936SPhilippe Mathieu-Daudé     int32_t CP0_Config2;
23e3130936SPhilippe Mathieu-Daudé     int32_t CP0_Config3;
24e3130936SPhilippe Mathieu-Daudé     int32_t CP0_Config5;
25e3130936SPhilippe Mathieu-Daudé     /* Routine used to access memory */
26e3130936SPhilippe Mathieu-Daudé     int mem_idx;
27e3130936SPhilippe Mathieu-Daudé     MemOp default_tcg_memop_mask;
28e3130936SPhilippe Mathieu-Daudé     uint32_t hflags, saved_hflags;
29e3130936SPhilippe Mathieu-Daudé     target_ulong btarget;
30e3130936SPhilippe Mathieu-Daudé     bool ulri;
31e3130936SPhilippe Mathieu-Daudé     int kscrexist;
32e3130936SPhilippe Mathieu-Daudé     bool rxi;
33e3130936SPhilippe Mathieu-Daudé     int ie;
34e3130936SPhilippe Mathieu-Daudé     bool bi;
35e3130936SPhilippe Mathieu-Daudé     bool bp;
36e3130936SPhilippe Mathieu-Daudé     uint64_t PAMask;
37e3130936SPhilippe Mathieu-Daudé     bool mvh;
38e3130936SPhilippe Mathieu-Daudé     bool eva;
39e3130936SPhilippe Mathieu-Daudé     bool sc;
40e3130936SPhilippe Mathieu-Daudé     int CP0_LLAddr_shift;
41e3130936SPhilippe Mathieu-Daudé     bool ps;
42e3130936SPhilippe Mathieu-Daudé     bool vp;
43e3130936SPhilippe Mathieu-Daudé     bool cmgcr;
44e3130936SPhilippe Mathieu-Daudé     bool mrp;
45e3130936SPhilippe Mathieu-Daudé     bool nan2008;
46e3130936SPhilippe Mathieu-Daudé     bool abs2008;
47e3130936SPhilippe Mathieu-Daudé     bool saar;
48e3130936SPhilippe Mathieu-Daudé     bool mi;
49e3130936SPhilippe Mathieu-Daudé     int gi;
50e3130936SPhilippe Mathieu-Daudé } DisasContext;
51e3130936SPhilippe Mathieu-Daudé 
5246c9e2b3SPhilippe Mathieu-Daudé /* MIPS major opcodes */
5346c9e2b3SPhilippe Mathieu-Daudé #define MASK_OP_MAJOR(op)   (op & (0x3F << 26))
5446c9e2b3SPhilippe Mathieu-Daudé 
5557eedcf7SPhilippe Mathieu-Daudé #define OPC_CP1 (0x11 << 26)
5657eedcf7SPhilippe Mathieu-Daudé 
5757eedcf7SPhilippe Mathieu-Daudé /* Coprocessor 1 (rs field) */
5857eedcf7SPhilippe Mathieu-Daudé #define MASK_CP1(op)                (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
5957eedcf7SPhilippe Mathieu-Daudé 
6057eedcf7SPhilippe Mathieu-Daudé /* Values for the fmt field in FP instructions */
6157eedcf7SPhilippe Mathieu-Daudé enum {
6257eedcf7SPhilippe Mathieu-Daudé     /* 0 - 15 are reserved */
6357eedcf7SPhilippe Mathieu-Daudé     FMT_S = 16,          /* single fp */
6457eedcf7SPhilippe Mathieu-Daudé     FMT_D = 17,          /* double fp */
6557eedcf7SPhilippe Mathieu-Daudé     FMT_E = 18,          /* extended fp */
6657eedcf7SPhilippe Mathieu-Daudé     FMT_Q = 19,          /* quad fp */
6757eedcf7SPhilippe Mathieu-Daudé     FMT_W = 20,          /* 32-bit fixed */
6857eedcf7SPhilippe Mathieu-Daudé     FMT_L = 21,          /* 64-bit fixed */
6957eedcf7SPhilippe Mathieu-Daudé     FMT_PS = 22,         /* paired single fp */
7057eedcf7SPhilippe Mathieu-Daudé     /* 23 - 31 are reserved */
7157eedcf7SPhilippe Mathieu-Daudé };
7257eedcf7SPhilippe Mathieu-Daudé 
7357eedcf7SPhilippe Mathieu-Daudé enum {
7457eedcf7SPhilippe Mathieu-Daudé     OPC_MFC1     = (0x00 << 21) | OPC_CP1,
7557eedcf7SPhilippe Mathieu-Daudé     OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
7657eedcf7SPhilippe Mathieu-Daudé     OPC_CFC1     = (0x02 << 21) | OPC_CP1,
7757eedcf7SPhilippe Mathieu-Daudé     OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
7857eedcf7SPhilippe Mathieu-Daudé     OPC_MTC1     = (0x04 << 21) | OPC_CP1,
7957eedcf7SPhilippe Mathieu-Daudé     OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
8057eedcf7SPhilippe Mathieu-Daudé     OPC_CTC1     = (0x06 << 21) | OPC_CP1,
8157eedcf7SPhilippe Mathieu-Daudé     OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
8257eedcf7SPhilippe Mathieu-Daudé     OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
8357eedcf7SPhilippe Mathieu-Daudé     OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
8457eedcf7SPhilippe Mathieu-Daudé     OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
8557eedcf7SPhilippe Mathieu-Daudé     OPC_S_FMT    = (FMT_S << 21) | OPC_CP1,
8657eedcf7SPhilippe Mathieu-Daudé     OPC_D_FMT    = (FMT_D << 21) | OPC_CP1,
8757eedcf7SPhilippe Mathieu-Daudé     OPC_E_FMT    = (FMT_E << 21) | OPC_CP1,
8857eedcf7SPhilippe Mathieu-Daudé     OPC_Q_FMT    = (FMT_Q << 21) | OPC_CP1,
8957eedcf7SPhilippe Mathieu-Daudé     OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,
9057eedcf7SPhilippe Mathieu-Daudé     OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,
9157eedcf7SPhilippe Mathieu-Daudé     OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1,
9257eedcf7SPhilippe Mathieu-Daudé     OPC_BC1EQZ   = (0x09 << 21) | OPC_CP1,
9357eedcf7SPhilippe Mathieu-Daudé     OPC_BC1NEZ   = (0x0D << 21) | OPC_CP1,
9457eedcf7SPhilippe Mathieu-Daudé };
9557eedcf7SPhilippe Mathieu-Daudé 
9657eedcf7SPhilippe Mathieu-Daudé #define MASK_CP1_FUNC(op)           (MASK_CP1(op) | (op & 0x3F))
9757eedcf7SPhilippe Mathieu-Daudé #define MASK_BC1(op)                (MASK_CP1(op) | (op & (0x3 << 16)))
9857eedcf7SPhilippe Mathieu-Daudé 
9957eedcf7SPhilippe Mathieu-Daudé enum {
10057eedcf7SPhilippe Mathieu-Daudé     OPC_BC1F     = (0x00 << 16) | OPC_BC1,
10157eedcf7SPhilippe Mathieu-Daudé     OPC_BC1T     = (0x01 << 16) | OPC_BC1,
10257eedcf7SPhilippe Mathieu-Daudé     OPC_BC1FL    = (0x02 << 16) | OPC_BC1,
10357eedcf7SPhilippe Mathieu-Daudé     OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
10457eedcf7SPhilippe Mathieu-Daudé };
10557eedcf7SPhilippe Mathieu-Daudé 
10657eedcf7SPhilippe Mathieu-Daudé enum {
10757eedcf7SPhilippe Mathieu-Daudé     OPC_BC1FANY2     = (0x00 << 16) | OPC_BC1ANY2,
10857eedcf7SPhilippe Mathieu-Daudé     OPC_BC1TANY2     = (0x01 << 16) | OPC_BC1ANY2,
10957eedcf7SPhilippe Mathieu-Daudé };
11057eedcf7SPhilippe Mathieu-Daudé 
11157eedcf7SPhilippe Mathieu-Daudé enum {
11257eedcf7SPhilippe Mathieu-Daudé     OPC_BC1FANY4     = (0x00 << 16) | OPC_BC1ANY4,
11357eedcf7SPhilippe Mathieu-Daudé     OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
11457eedcf7SPhilippe Mathieu-Daudé };
11557eedcf7SPhilippe Mathieu-Daudé 
11646c9e2b3SPhilippe Mathieu-Daudé void generate_exception(DisasContext *ctx, int excp);
11746c9e2b3SPhilippe Mathieu-Daudé void generate_exception_err(DisasContext *ctx, int excp, int err);
11846c9e2b3SPhilippe Mathieu-Daudé void generate_exception_end(DisasContext *ctx, int excp);
1193a4ef3b7SPhilippe Mathieu-Daudé void gen_reserved_instruction(DisasContext *ctx);
12046c9e2b3SPhilippe Mathieu-Daudé 
12146c9e2b3SPhilippe Mathieu-Daudé void check_insn(DisasContext *ctx, uint64_t flags);
12246c9e2b3SPhilippe Mathieu-Daudé void check_mips_64(DisasContext *ctx);
123*905bdf72SPhilippe Mathieu-Daudé /**
124*905bdf72SPhilippe Mathieu-Daudé  * check_cp0_enabled:
125*905bdf72SPhilippe Mathieu-Daudé  * Return %true if CP0 is enabled, otherwise return %false
126*905bdf72SPhilippe Mathieu-Daudé  * and emit a 'coprocessor unusable' exception.
127*905bdf72SPhilippe Mathieu-Daudé  */
128*905bdf72SPhilippe Mathieu-Daudé bool check_cp0_enabled(DisasContext *ctx);
1298758d1b8SPhilippe Mathieu-Daudé void check_cp1_enabled(DisasContext *ctx);
1308758d1b8SPhilippe Mathieu-Daudé void check_cp1_64bitmode(DisasContext *ctx);
1318758d1b8SPhilippe Mathieu-Daudé void check_cp1_registers(DisasContext *ctx, int regs);
1328758d1b8SPhilippe Mathieu-Daudé void check_cop1x(DisasContext *ctx);
13346c9e2b3SPhilippe Mathieu-Daudé 
13446c9e2b3SPhilippe Mathieu-Daudé void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset);
13546c9e2b3SPhilippe Mathieu-Daudé void gen_move_low32(TCGv ret, TCGv_i64 arg);
13646c9e2b3SPhilippe Mathieu-Daudé void gen_move_high32(TCGv ret, TCGv_i64 arg);
13746c9e2b3SPhilippe Mathieu-Daudé void gen_load_gpr(TCGv t, int reg);
13846c9e2b3SPhilippe Mathieu-Daudé void gen_store_gpr(TCGv t, int reg);
13961f4e0ecSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
14061f4e0ecSPhilippe Mathieu-Daudé void gen_load_gpr_hi(TCGv_i64 t, int reg);
14161f4e0ecSPhilippe Mathieu-Daudé void gen_store_gpr_hi(TCGv_i64 t, int reg);
14261f4e0ecSPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */
1438758d1b8SPhilippe Mathieu-Daudé void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
1448758d1b8SPhilippe Mathieu-Daudé void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
1458758d1b8SPhilippe Mathieu-Daudé void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
1468758d1b8SPhilippe Mathieu-Daudé void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
1478758d1b8SPhilippe Mathieu-Daudé int get_fp_bit(int cc);
14846c9e2b3SPhilippe Mathieu-Daudé 
149a685f7d0SPhilippe Mathieu-Daudé /*
150a685f7d0SPhilippe Mathieu-Daudé  * Address Computation and Large Constant Instructions
151a685f7d0SPhilippe Mathieu-Daudé  */
15246c9e2b3SPhilippe Mathieu-Daudé void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1);
153a685f7d0SPhilippe Mathieu-Daudé bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
154a685f7d0SPhilippe Mathieu-Daudé bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
15546c9e2b3SPhilippe Mathieu-Daudé 
156f9fa53f1SPhilippe Mathieu-Daudé void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel);
157f9fa53f1SPhilippe Mathieu-Daudé 
15846c9e2b3SPhilippe Mathieu-Daudé extern TCGv cpu_gpr[32], cpu_PC;
159cefd68f6SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
160cefd68f6SPhilippe Mathieu-Daudé extern TCGv_i64 cpu_gpr_hi[32];
161cefd68f6SPhilippe Mathieu-Daudé #endif
1629f5f7691SPhilippe Mathieu-Daudé extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1638758d1b8SPhilippe Mathieu-Daudé extern TCGv_i32 fpu_fcr0, fpu_fcr31;
1648758d1b8SPhilippe Mathieu-Daudé extern TCGv_i64 fpu_f64[32];
16546c9e2b3SPhilippe Mathieu-Daudé extern TCGv bcond;
16646c9e2b3SPhilippe Mathieu-Daudé 
16746c9e2b3SPhilippe Mathieu-Daudé #define LOG_DISAS(...)                                                        \
16846c9e2b3SPhilippe Mathieu-Daudé     do {                                                                      \
16946c9e2b3SPhilippe Mathieu-Daudé         if (MIPS_DEBUG_DISAS) {                                               \
17046c9e2b3SPhilippe Mathieu-Daudé             qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__);                 \
17146c9e2b3SPhilippe Mathieu-Daudé         }                                                                     \
17246c9e2b3SPhilippe Mathieu-Daudé     } while (0)
17346c9e2b3SPhilippe Mathieu-Daudé 
17446c9e2b3SPhilippe Mathieu-Daudé #define MIPS_INVAL(op)                                                        \
17546c9e2b3SPhilippe Mathieu-Daudé     do {                                                                      \
17646c9e2b3SPhilippe Mathieu-Daudé         if (MIPS_DEBUG_DISAS) {                                               \
17746c9e2b3SPhilippe Mathieu-Daudé             qemu_log_mask(CPU_LOG_TB_IN_ASM,                                  \
17846c9e2b3SPhilippe Mathieu-Daudé                           TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
17946c9e2b3SPhilippe Mathieu-Daudé                           ctx->base.pc_next, ctx->opcode, op,                 \
18046c9e2b3SPhilippe Mathieu-Daudé                           ctx->opcode >> 26, ctx->opcode & 0x3F,              \
18146c9e2b3SPhilippe Mathieu-Daudé                           ((ctx->opcode >> 16) & 0x1F));                      \
18246c9e2b3SPhilippe Mathieu-Daudé         }                                                                     \
18346c9e2b3SPhilippe Mathieu-Daudé     } while (0)
18446c9e2b3SPhilippe Mathieu-Daudé 
185959c5da2SPhilippe Mathieu-Daudé /* MSA */
186959c5da2SPhilippe Mathieu-Daudé void msa_translate_init(void);
187959c5da2SPhilippe Mathieu-Daudé 
188c7abe00aSPhilippe Mathieu-Daudé /* MXU */
189fe35ea94SPhilippe Mathieu-Daudé void mxu_translate_init(void);
190c7abe00aSPhilippe Mathieu-Daudé bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
191c7abe00aSPhilippe Mathieu-Daudé 
192c7a9ef75SPhilippe Mathieu-Daudé /* decodetree generated */
1933f7a9278SPhilippe Mathieu-Daudé bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
194c7a9ef75SPhilippe Mathieu-Daudé bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
195ffc672aaSPhilippe Mathieu-Daudé bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
196ffc672aaSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
197ffc672aaSPhilippe Mathieu-Daudé bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
198ffc672aaSPhilippe Mathieu-Daudé #endif
199c7a9ef75SPhilippe Mathieu-Daudé 
200e3130936SPhilippe Mathieu-Daudé #endif
201