xref: /qemu/target/mips/tcg/translate.h (revision bf78469cc8ddb117b6db4a353e59fb4664a96de4)
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;
210cfd392dSPhilippe Mathieu-Daudé     int32_t CP0_Config0;
22e3130936SPhilippe Mathieu-Daudé     int32_t CP0_Config1;
23e3130936SPhilippe Mathieu-Daudé     int32_t CP0_Config2;
24e3130936SPhilippe Mathieu-Daudé     int32_t CP0_Config3;
25e3130936SPhilippe Mathieu-Daudé     int32_t CP0_Config5;
26e3130936SPhilippe Mathieu-Daudé     /* Routine used to access memory */
27e3130936SPhilippe Mathieu-Daudé     int mem_idx;
28e3130936SPhilippe Mathieu-Daudé     MemOp default_tcg_memop_mask;
29e3130936SPhilippe Mathieu-Daudé     uint32_t hflags, saved_hflags;
30e3130936SPhilippe Mathieu-Daudé     target_ulong btarget;
31e3130936SPhilippe Mathieu-Daudé     bool ulri;
32e3130936SPhilippe Mathieu-Daudé     int kscrexist;
33e3130936SPhilippe Mathieu-Daudé     bool rxi;
34e3130936SPhilippe Mathieu-Daudé     int ie;
35e3130936SPhilippe Mathieu-Daudé     bool bi;
36e3130936SPhilippe Mathieu-Daudé     bool bp;
37e3130936SPhilippe Mathieu-Daudé     uint64_t PAMask;
38e3130936SPhilippe Mathieu-Daudé     bool mvh;
39e3130936SPhilippe Mathieu-Daudé     bool eva;
40e3130936SPhilippe Mathieu-Daudé     bool sc;
41e3130936SPhilippe Mathieu-Daudé     int CP0_LLAddr_shift;
42e3130936SPhilippe Mathieu-Daudé     bool ps;
43e3130936SPhilippe Mathieu-Daudé     bool vp;
44e3130936SPhilippe Mathieu-Daudé     bool cmgcr;
45e3130936SPhilippe Mathieu-Daudé     bool mrp;
46e3130936SPhilippe Mathieu-Daudé     bool nan2008;
47e3130936SPhilippe Mathieu-Daudé     bool abs2008;
48e3130936SPhilippe Mathieu-Daudé     bool saar;
49e3130936SPhilippe Mathieu-Daudé     bool mi;
50e3130936SPhilippe Mathieu-Daudé     int gi;
51e3130936SPhilippe Mathieu-Daudé } DisasContext;
52e3130936SPhilippe Mathieu-Daudé 
5346c9e2b3SPhilippe Mathieu-Daudé /* MIPS major opcodes */
5446c9e2b3SPhilippe Mathieu-Daudé #define MASK_OP_MAJOR(op)   (op & (0x3F << 26))
5546c9e2b3SPhilippe Mathieu-Daudé 
5657eedcf7SPhilippe Mathieu-Daudé #define OPC_CP1 (0x11 << 26)
5757eedcf7SPhilippe Mathieu-Daudé 
5857eedcf7SPhilippe Mathieu-Daudé /* Coprocessor 1 (rs field) */
5957eedcf7SPhilippe Mathieu-Daudé #define MASK_CP1(op)                (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
6057eedcf7SPhilippe Mathieu-Daudé 
6157eedcf7SPhilippe Mathieu-Daudé /* Values for the fmt field in FP instructions */
6257eedcf7SPhilippe Mathieu-Daudé enum {
6357eedcf7SPhilippe Mathieu-Daudé     /* 0 - 15 are reserved */
6457eedcf7SPhilippe Mathieu-Daudé     FMT_S = 16,          /* single fp */
6557eedcf7SPhilippe Mathieu-Daudé     FMT_D = 17,          /* double fp */
6657eedcf7SPhilippe Mathieu-Daudé     FMT_E = 18,          /* extended fp */
6757eedcf7SPhilippe Mathieu-Daudé     FMT_Q = 19,          /* quad fp */
6857eedcf7SPhilippe Mathieu-Daudé     FMT_W = 20,          /* 32-bit fixed */
6957eedcf7SPhilippe Mathieu-Daudé     FMT_L = 21,          /* 64-bit fixed */
7057eedcf7SPhilippe Mathieu-Daudé     FMT_PS = 22,         /* paired single fp */
7157eedcf7SPhilippe Mathieu-Daudé     /* 23 - 31 are reserved */
7257eedcf7SPhilippe Mathieu-Daudé };
7357eedcf7SPhilippe Mathieu-Daudé 
7457eedcf7SPhilippe Mathieu-Daudé enum {
7557eedcf7SPhilippe Mathieu-Daudé     OPC_MFC1     = (0x00 << 21) | OPC_CP1,
7657eedcf7SPhilippe Mathieu-Daudé     OPC_DMFC1    = (0x01 << 21) | OPC_CP1,
7757eedcf7SPhilippe Mathieu-Daudé     OPC_CFC1     = (0x02 << 21) | OPC_CP1,
7857eedcf7SPhilippe Mathieu-Daudé     OPC_MFHC1    = (0x03 << 21) | OPC_CP1,
7957eedcf7SPhilippe Mathieu-Daudé     OPC_MTC1     = (0x04 << 21) | OPC_CP1,
8057eedcf7SPhilippe Mathieu-Daudé     OPC_DMTC1    = (0x05 << 21) | OPC_CP1,
8157eedcf7SPhilippe Mathieu-Daudé     OPC_CTC1     = (0x06 << 21) | OPC_CP1,
8257eedcf7SPhilippe Mathieu-Daudé     OPC_MTHC1    = (0x07 << 21) | OPC_CP1,
8357eedcf7SPhilippe Mathieu-Daudé     OPC_BC1      = (0x08 << 21) | OPC_CP1, /* bc */
8457eedcf7SPhilippe Mathieu-Daudé     OPC_BC1ANY2  = (0x09 << 21) | OPC_CP1,
8557eedcf7SPhilippe Mathieu-Daudé     OPC_BC1ANY4  = (0x0A << 21) | OPC_CP1,
8657eedcf7SPhilippe Mathieu-Daudé     OPC_S_FMT    = (FMT_S << 21) | OPC_CP1,
8757eedcf7SPhilippe Mathieu-Daudé     OPC_D_FMT    = (FMT_D << 21) | OPC_CP1,
8857eedcf7SPhilippe Mathieu-Daudé     OPC_E_FMT    = (FMT_E << 21) | OPC_CP1,
8957eedcf7SPhilippe Mathieu-Daudé     OPC_Q_FMT    = (FMT_Q << 21) | OPC_CP1,
9057eedcf7SPhilippe Mathieu-Daudé     OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,
9157eedcf7SPhilippe Mathieu-Daudé     OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,
9257eedcf7SPhilippe Mathieu-Daudé     OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1,
9357eedcf7SPhilippe Mathieu-Daudé     OPC_BC1EQZ   = (0x09 << 21) | OPC_CP1,
9457eedcf7SPhilippe Mathieu-Daudé     OPC_BC1NEZ   = (0x0D << 21) | OPC_CP1,
9557eedcf7SPhilippe Mathieu-Daudé };
9657eedcf7SPhilippe Mathieu-Daudé 
9757eedcf7SPhilippe Mathieu-Daudé #define MASK_CP1_FUNC(op)           (MASK_CP1(op) | (op & 0x3F))
9857eedcf7SPhilippe Mathieu-Daudé #define MASK_BC1(op)                (MASK_CP1(op) | (op & (0x3 << 16)))
9957eedcf7SPhilippe Mathieu-Daudé 
10057eedcf7SPhilippe Mathieu-Daudé enum {
10157eedcf7SPhilippe Mathieu-Daudé     OPC_BC1F     = (0x00 << 16) | OPC_BC1,
10257eedcf7SPhilippe Mathieu-Daudé     OPC_BC1T     = (0x01 << 16) | OPC_BC1,
10357eedcf7SPhilippe Mathieu-Daudé     OPC_BC1FL    = (0x02 << 16) | OPC_BC1,
10457eedcf7SPhilippe Mathieu-Daudé     OPC_BC1TL    = (0x03 << 16) | OPC_BC1,
10557eedcf7SPhilippe Mathieu-Daudé };
10657eedcf7SPhilippe Mathieu-Daudé 
10757eedcf7SPhilippe Mathieu-Daudé enum {
10857eedcf7SPhilippe Mathieu-Daudé     OPC_BC1FANY2     = (0x00 << 16) | OPC_BC1ANY2,
10957eedcf7SPhilippe Mathieu-Daudé     OPC_BC1TANY2     = (0x01 << 16) | OPC_BC1ANY2,
11057eedcf7SPhilippe Mathieu-Daudé };
11157eedcf7SPhilippe Mathieu-Daudé 
11257eedcf7SPhilippe Mathieu-Daudé enum {
11357eedcf7SPhilippe Mathieu-Daudé     OPC_BC1FANY4     = (0x00 << 16) | OPC_BC1ANY4,
11457eedcf7SPhilippe Mathieu-Daudé     OPC_BC1TANY4     = (0x01 << 16) | OPC_BC1ANY4,
11557eedcf7SPhilippe Mathieu-Daudé };
11657eedcf7SPhilippe Mathieu-Daudé 
117761533fcSPhilippe Mathieu-Daudé #define gen_helper_0e1i(name, arg1, arg2) do { \
118761533fcSPhilippe Mathieu-Daudé     gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \
119761533fcSPhilippe Mathieu-Daudé     } while (0)
120761533fcSPhilippe Mathieu-Daudé 
121761533fcSPhilippe Mathieu-Daudé #define gen_helper_1e0i(name, ret, arg1) do { \
122761533fcSPhilippe Mathieu-Daudé     gen_helper_##name(ret, cpu_env, tcg_constant_i32(arg1)); \
123761533fcSPhilippe Mathieu-Daudé     } while (0)
124761533fcSPhilippe Mathieu-Daudé 
125761533fcSPhilippe Mathieu-Daudé #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
126761533fcSPhilippe Mathieu-Daudé     gen_helper_##name(cpu_env, arg1, arg2, tcg_constant_i32(arg3));\
127761533fcSPhilippe Mathieu-Daudé     } while (0)
128761533fcSPhilippe Mathieu-Daudé 
12946c9e2b3SPhilippe Mathieu-Daudé void generate_exception(DisasContext *ctx, int excp);
13046c9e2b3SPhilippe Mathieu-Daudé void generate_exception_err(DisasContext *ctx, int excp, int err);
13146c9e2b3SPhilippe Mathieu-Daudé void generate_exception_end(DisasContext *ctx, int excp);
1323a4ef3b7SPhilippe Mathieu-Daudé void gen_reserved_instruction(DisasContext *ctx);
13346c9e2b3SPhilippe Mathieu-Daudé 
13446c9e2b3SPhilippe Mathieu-Daudé void check_insn(DisasContext *ctx, uint64_t flags);
13546c9e2b3SPhilippe Mathieu-Daudé void check_mips_64(DisasContext *ctx);
136905bdf72SPhilippe Mathieu-Daudé /**
137905bdf72SPhilippe Mathieu-Daudé  * check_cp0_enabled:
138905bdf72SPhilippe Mathieu-Daudé  * Return %true if CP0 is enabled, otherwise return %false
139905bdf72SPhilippe Mathieu-Daudé  * and emit a 'coprocessor unusable' exception.
140905bdf72SPhilippe Mathieu-Daudé  */
141905bdf72SPhilippe Mathieu-Daudé bool check_cp0_enabled(DisasContext *ctx);
1428758d1b8SPhilippe Mathieu-Daudé void check_cp1_enabled(DisasContext *ctx);
1438758d1b8SPhilippe Mathieu-Daudé void check_cp1_64bitmode(DisasContext *ctx);
1448758d1b8SPhilippe Mathieu-Daudé void check_cp1_registers(DisasContext *ctx, int regs);
1458758d1b8SPhilippe Mathieu-Daudé void check_cop1x(DisasContext *ctx);
14646c9e2b3SPhilippe Mathieu-Daudé 
14746c9e2b3SPhilippe Mathieu-Daudé void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset);
14846c9e2b3SPhilippe Mathieu-Daudé void gen_move_low32(TCGv ret, TCGv_i64 arg);
14946c9e2b3SPhilippe Mathieu-Daudé void gen_move_high32(TCGv ret, TCGv_i64 arg);
15046c9e2b3SPhilippe Mathieu-Daudé void gen_load_gpr(TCGv t, int reg);
15146c9e2b3SPhilippe Mathieu-Daudé void gen_store_gpr(TCGv t, int reg);
15261f4e0ecSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
15361f4e0ecSPhilippe Mathieu-Daudé void gen_load_gpr_hi(TCGv_i64 t, int reg);
15461f4e0ecSPhilippe Mathieu-Daudé void gen_store_gpr_hi(TCGv_i64 t, int reg);
15561f4e0ecSPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */
1568758d1b8SPhilippe Mathieu-Daudé void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
1578758d1b8SPhilippe Mathieu-Daudé void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
1588758d1b8SPhilippe Mathieu-Daudé void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
1598758d1b8SPhilippe Mathieu-Daudé void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
1608758d1b8SPhilippe Mathieu-Daudé int get_fp_bit(int cc);
16146c9e2b3SPhilippe Mathieu-Daudé 
162d5076631SPhilippe Mathieu-Daudé void gen_ldxs(DisasContext *ctx, int base, int index, int rd);
163d5076631SPhilippe Mathieu-Daudé void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp);
164d5076631SPhilippe Mathieu-Daudé void gen_addiupc(DisasContext *ctx, int rx, int imm,
165d5076631SPhilippe Mathieu-Daudé                  int is_64_bit, int extended);
166d5076631SPhilippe Mathieu-Daudé 
167a685f7d0SPhilippe Mathieu-Daudé /*
168a685f7d0SPhilippe Mathieu-Daudé  * Address Computation and Large Constant Instructions
169a685f7d0SPhilippe Mathieu-Daudé  */
17046c9e2b3SPhilippe Mathieu-Daudé void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1);
171a685f7d0SPhilippe Mathieu-Daudé bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
172a685f7d0SPhilippe Mathieu-Daudé bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
17346c9e2b3SPhilippe Mathieu-Daudé 
174f9fa53f1SPhilippe Mathieu-Daudé void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel);
175f9fa53f1SPhilippe Mathieu-Daudé 
17646c9e2b3SPhilippe Mathieu-Daudé extern TCGv cpu_gpr[32], cpu_PC;
177cefd68f6SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
178cefd68f6SPhilippe Mathieu-Daudé extern TCGv_i64 cpu_gpr_hi[32];
179cefd68f6SPhilippe Mathieu-Daudé #endif
1809f5f7691SPhilippe Mathieu-Daudé extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1818758d1b8SPhilippe Mathieu-Daudé extern TCGv_i32 fpu_fcr0, fpu_fcr31;
1828758d1b8SPhilippe Mathieu-Daudé extern TCGv_i64 fpu_f64[32];
18346c9e2b3SPhilippe Mathieu-Daudé extern TCGv bcond;
18446c9e2b3SPhilippe Mathieu-Daudé 
18546c9e2b3SPhilippe Mathieu-Daudé #define LOG_DISAS(...)                                                        \
18646c9e2b3SPhilippe Mathieu-Daudé     do {                                                                      \
18746c9e2b3SPhilippe Mathieu-Daudé         if (MIPS_DEBUG_DISAS) {                                               \
18846c9e2b3SPhilippe Mathieu-Daudé             qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__);                 \
18946c9e2b3SPhilippe Mathieu-Daudé         }                                                                     \
19046c9e2b3SPhilippe Mathieu-Daudé     } while (0)
19146c9e2b3SPhilippe Mathieu-Daudé 
19246c9e2b3SPhilippe Mathieu-Daudé #define MIPS_INVAL(op)                                                        \
19346c9e2b3SPhilippe Mathieu-Daudé     do {                                                                      \
19446c9e2b3SPhilippe Mathieu-Daudé         if (MIPS_DEBUG_DISAS) {                                               \
19546c9e2b3SPhilippe Mathieu-Daudé             qemu_log_mask(CPU_LOG_TB_IN_ASM,                                  \
19646c9e2b3SPhilippe Mathieu-Daudé                           TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
19746c9e2b3SPhilippe Mathieu-Daudé                           ctx->base.pc_next, ctx->opcode, op,                 \
19846c9e2b3SPhilippe Mathieu-Daudé                           ctx->opcode >> 26, ctx->opcode & 0x3F,              \
19946c9e2b3SPhilippe Mathieu-Daudé                           ((ctx->opcode >> 16) & 0x1F));                      \
20046c9e2b3SPhilippe Mathieu-Daudé         }                                                                     \
20146c9e2b3SPhilippe Mathieu-Daudé     } while (0)
20246c9e2b3SPhilippe Mathieu-Daudé 
203959c5da2SPhilippe Mathieu-Daudé /* MSA */
204959c5da2SPhilippe Mathieu-Daudé void msa_translate_init(void);
205959c5da2SPhilippe Mathieu-Daudé 
206c7abe00aSPhilippe Mathieu-Daudé /* MXU */
207fe35ea94SPhilippe Mathieu-Daudé void mxu_translate_init(void);
208c7abe00aSPhilippe Mathieu-Daudé bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
209c7abe00aSPhilippe Mathieu-Daudé 
210c7a9ef75SPhilippe Mathieu-Daudé /* decodetree generated */
2113f7a9278SPhilippe Mathieu-Daudé bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
212c7a9ef75SPhilippe Mathieu-Daudé bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
213ffc672aaSPhilippe Mathieu-Daudé bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
214ffc672aaSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64)
215ffc672aaSPhilippe Mathieu-Daudé bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
216ffc672aaSPhilippe Mathieu-Daudé #endif
2179d005392SPhilippe Mathieu-Daudé bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
218c7a9ef75SPhilippe Mathieu-Daudé 
219fb3164e4SPhilippe Mathieu-Daudé /*
220fb3164e4SPhilippe Mathieu-Daudé  * Helpers for implementing sets of trans_* functions.
221fb3164e4SPhilippe Mathieu-Daudé  * Defer the implementation of NAME to FUNC, with optional extra arguments.
222fb3164e4SPhilippe Mathieu-Daudé  */
223fb3164e4SPhilippe Mathieu-Daudé #define TRANS(NAME, FUNC, ...) \
224fb3164e4SPhilippe Mathieu-Daudé     static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
225fb3164e4SPhilippe Mathieu-Daudé     { return FUNC(ctx, a, __VA_ARGS__); }
226fb3164e4SPhilippe Mathieu-Daudé 
227*bf78469cSPhilippe Mathieu-Daudé static inline bool cpu_is_bigendian(DisasContext *ctx)
228*bf78469cSPhilippe Mathieu-Daudé {
229*bf78469cSPhilippe Mathieu-Daudé     return extract32(ctx->CP0_Config0, CP0C0_BE, 1);
230*bf78469cSPhilippe Mathieu-Daudé }
231*bf78469cSPhilippe Mathieu-Daudé 
232e3130936SPhilippe Mathieu-Daudé #endif
233