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é 118cab4157SRichard Henderson #include "cpu.h" 12f15f8935SRichard Henderson #include "tcg/tcg-op.h" 138cab4157SRichard Henderson #include "exec/translator.h" 148cab4157SRichard Henderson #include "exec/helper-gen.h" 158cab4157SRichard Henderson #include "qemu/log.h" 16e3130936SPhilippe Mathieu-Daudé 1746c9e2b3SPhilippe Mathieu-Daudé #define MIPS_DEBUG_DISAS 0 1846c9e2b3SPhilippe Mathieu-Daudé 19e3130936SPhilippe Mathieu-Daudé typedef struct DisasContext { 20e3130936SPhilippe Mathieu-Daudé DisasContextBase base; 21e3130936SPhilippe Mathieu-Daudé target_ulong saved_pc; 22e3130936SPhilippe Mathieu-Daudé target_ulong page_start; 23e3130936SPhilippe Mathieu-Daudé uint32_t opcode; 24e3130936SPhilippe Mathieu-Daudé uint64_t insn_flags; 250cfd392dSPhilippe Mathieu-Daudé int32_t CP0_Config0; 26e3130936SPhilippe Mathieu-Daudé int32_t CP0_Config1; 27e3130936SPhilippe Mathieu-Daudé int32_t CP0_Config2; 28e3130936SPhilippe Mathieu-Daudé int32_t CP0_Config3; 29e3130936SPhilippe Mathieu-Daudé int32_t CP0_Config5; 30e3130936SPhilippe Mathieu-Daudé /* Routine used to access memory */ 31e3130936SPhilippe Mathieu-Daudé int mem_idx; 32e3130936SPhilippe Mathieu-Daudé MemOp default_tcg_memop_mask; 33e3130936SPhilippe Mathieu-Daudé uint32_t hflags, saved_hflags; 34e3130936SPhilippe Mathieu-Daudé target_ulong btarget; 35e3130936SPhilippe Mathieu-Daudé bool ulri; 36e3130936SPhilippe Mathieu-Daudé int kscrexist; 37e3130936SPhilippe Mathieu-Daudé bool rxi; 38e3130936SPhilippe Mathieu-Daudé int ie; 39e3130936SPhilippe Mathieu-Daudé bool bi; 40e3130936SPhilippe Mathieu-Daudé bool bp; 41e3130936SPhilippe Mathieu-Daudé uint64_t PAMask; 42e3130936SPhilippe Mathieu-Daudé bool mvh; 43e3130936SPhilippe Mathieu-Daudé bool eva; 44e3130936SPhilippe Mathieu-Daudé bool sc; 45e3130936SPhilippe Mathieu-Daudé int CP0_LLAddr_shift; 46e3130936SPhilippe Mathieu-Daudé bool ps; 47e3130936SPhilippe Mathieu-Daudé bool vp; 48e3130936SPhilippe Mathieu-Daudé bool cmgcr; 49e3130936SPhilippe Mathieu-Daudé bool mrp; 50e3130936SPhilippe Mathieu-Daudé bool nan2008; 51e3130936SPhilippe Mathieu-Daudé bool abs2008; 52e3130936SPhilippe Mathieu-Daudé bool mi; 53e3130936SPhilippe Mathieu-Daudé int gi; 54e3130936SPhilippe Mathieu-Daudé } DisasContext; 55e3130936SPhilippe Mathieu-Daudé 56d44971e7SRichard Henderson #define DISAS_STOP DISAS_TARGET_0 57d44971e7SRichard Henderson #define DISAS_EXIT DISAS_TARGET_1 58d44971e7SRichard Henderson #define DISAS_SEMIHOST DISAS_TARGET_2 59d44971e7SRichard Henderson 6046c9e2b3SPhilippe Mathieu-Daudé /* MIPS major opcodes */ 6146c9e2b3SPhilippe Mathieu-Daudé #define MASK_OP_MAJOR(op) (op & (0x3F << 26)) 6246c9e2b3SPhilippe Mathieu-Daudé 6357eedcf7SPhilippe Mathieu-Daudé #define OPC_CP1 (0x11 << 26) 6457eedcf7SPhilippe Mathieu-Daudé 6557eedcf7SPhilippe Mathieu-Daudé /* Coprocessor 1 (rs field) */ 6657eedcf7SPhilippe Mathieu-Daudé #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21))) 6757eedcf7SPhilippe Mathieu-Daudé 6857eedcf7SPhilippe Mathieu-Daudé /* Values for the fmt field in FP instructions */ 6957eedcf7SPhilippe Mathieu-Daudé enum { 7057eedcf7SPhilippe Mathieu-Daudé /* 0 - 15 are reserved */ 7157eedcf7SPhilippe Mathieu-Daudé FMT_S = 16, /* single fp */ 7257eedcf7SPhilippe Mathieu-Daudé FMT_D = 17, /* double fp */ 7357eedcf7SPhilippe Mathieu-Daudé FMT_E = 18, /* extended fp */ 7457eedcf7SPhilippe Mathieu-Daudé FMT_Q = 19, /* quad fp */ 7557eedcf7SPhilippe Mathieu-Daudé FMT_W = 20, /* 32-bit fixed */ 7657eedcf7SPhilippe Mathieu-Daudé FMT_L = 21, /* 64-bit fixed */ 7757eedcf7SPhilippe Mathieu-Daudé FMT_PS = 22, /* paired single fp */ 7857eedcf7SPhilippe Mathieu-Daudé /* 23 - 31 are reserved */ 7957eedcf7SPhilippe Mathieu-Daudé }; 8057eedcf7SPhilippe Mathieu-Daudé 8157eedcf7SPhilippe Mathieu-Daudé enum { 8257eedcf7SPhilippe Mathieu-Daudé OPC_MFC1 = (0x00 << 21) | OPC_CP1, 8357eedcf7SPhilippe Mathieu-Daudé OPC_DMFC1 = (0x01 << 21) | OPC_CP1, 8457eedcf7SPhilippe Mathieu-Daudé OPC_CFC1 = (0x02 << 21) | OPC_CP1, 8557eedcf7SPhilippe Mathieu-Daudé OPC_MFHC1 = (0x03 << 21) | OPC_CP1, 8657eedcf7SPhilippe Mathieu-Daudé OPC_MTC1 = (0x04 << 21) | OPC_CP1, 8757eedcf7SPhilippe Mathieu-Daudé OPC_DMTC1 = (0x05 << 21) | OPC_CP1, 8857eedcf7SPhilippe Mathieu-Daudé OPC_CTC1 = (0x06 << 21) | OPC_CP1, 8957eedcf7SPhilippe Mathieu-Daudé OPC_MTHC1 = (0x07 << 21) | OPC_CP1, 9057eedcf7SPhilippe Mathieu-Daudé OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ 9157eedcf7SPhilippe Mathieu-Daudé OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1, 9257eedcf7SPhilippe Mathieu-Daudé OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1, 9357eedcf7SPhilippe Mathieu-Daudé OPC_S_FMT = (FMT_S << 21) | OPC_CP1, 9457eedcf7SPhilippe Mathieu-Daudé OPC_D_FMT = (FMT_D << 21) | OPC_CP1, 9557eedcf7SPhilippe Mathieu-Daudé OPC_E_FMT = (FMT_E << 21) | OPC_CP1, 9657eedcf7SPhilippe Mathieu-Daudé OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1, 9757eedcf7SPhilippe Mathieu-Daudé OPC_W_FMT = (FMT_W << 21) | OPC_CP1, 9857eedcf7SPhilippe Mathieu-Daudé OPC_L_FMT = (FMT_L << 21) | OPC_CP1, 9957eedcf7SPhilippe Mathieu-Daudé OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1, 10057eedcf7SPhilippe Mathieu-Daudé OPC_BC1EQZ = (0x09 << 21) | OPC_CP1, 10157eedcf7SPhilippe Mathieu-Daudé OPC_BC1NEZ = (0x0D << 21) | OPC_CP1, 10257eedcf7SPhilippe Mathieu-Daudé }; 10357eedcf7SPhilippe Mathieu-Daudé 10457eedcf7SPhilippe Mathieu-Daudé #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F)) 10557eedcf7SPhilippe Mathieu-Daudé #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16))) 10657eedcf7SPhilippe Mathieu-Daudé 10757eedcf7SPhilippe Mathieu-Daudé enum { 10857eedcf7SPhilippe Mathieu-Daudé OPC_BC1F = (0x00 << 16) | OPC_BC1, 10957eedcf7SPhilippe Mathieu-Daudé OPC_BC1T = (0x01 << 16) | OPC_BC1, 11057eedcf7SPhilippe Mathieu-Daudé OPC_BC1FL = (0x02 << 16) | OPC_BC1, 11157eedcf7SPhilippe Mathieu-Daudé OPC_BC1TL = (0x03 << 16) | OPC_BC1, 11257eedcf7SPhilippe Mathieu-Daudé }; 11357eedcf7SPhilippe Mathieu-Daudé 11457eedcf7SPhilippe Mathieu-Daudé enum { 11557eedcf7SPhilippe Mathieu-Daudé OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2, 11657eedcf7SPhilippe Mathieu-Daudé OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2, 11757eedcf7SPhilippe Mathieu-Daudé }; 11857eedcf7SPhilippe Mathieu-Daudé 11957eedcf7SPhilippe Mathieu-Daudé enum { 12057eedcf7SPhilippe Mathieu-Daudé OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4, 12157eedcf7SPhilippe Mathieu-Daudé OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4, 12257eedcf7SPhilippe Mathieu-Daudé }; 12357eedcf7SPhilippe Mathieu-Daudé 124761533fcSPhilippe Mathieu-Daudé #define gen_helper_0e1i(name, arg1, arg2) do { \ 125ad75a51eSRichard Henderson gen_helper_##name(tcg_env, arg1, tcg_constant_i32(arg2)); \ 126761533fcSPhilippe Mathieu-Daudé } while (0) 127761533fcSPhilippe Mathieu-Daudé 128761533fcSPhilippe Mathieu-Daudé #define gen_helper_1e0i(name, ret, arg1) do { \ 129ad75a51eSRichard Henderson gen_helper_##name(ret, tcg_env, tcg_constant_i32(arg1)); \ 130761533fcSPhilippe Mathieu-Daudé } while (0) 131761533fcSPhilippe Mathieu-Daudé 132761533fcSPhilippe Mathieu-Daudé #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \ 133ad75a51eSRichard Henderson gen_helper_##name(tcg_env, arg1, arg2, tcg_constant_i32(arg3));\ 134761533fcSPhilippe Mathieu-Daudé } while (0) 135761533fcSPhilippe Mathieu-Daudé 13646c9e2b3SPhilippe Mathieu-Daudé void generate_exception(DisasContext *ctx, int excp); 13746c9e2b3SPhilippe Mathieu-Daudé void generate_exception_err(DisasContext *ctx, int excp, int err); 13846c9e2b3SPhilippe Mathieu-Daudé void generate_exception_end(DisasContext *ctx, int excp); 1396f3533ddSRichard Henderson void generate_exception_break(DisasContext *ctx, int code); 1403a4ef3b7SPhilippe Mathieu-Daudé void gen_reserved_instruction(DisasContext *ctx); 14146c9e2b3SPhilippe Mathieu-Daudé 14246c9e2b3SPhilippe Mathieu-Daudé void check_insn(DisasContext *ctx, uint64_t flags); 14346c9e2b3SPhilippe Mathieu-Daudé void check_mips_64(DisasContext *ctx); 144905bdf72SPhilippe Mathieu-Daudé /** 145905bdf72SPhilippe Mathieu-Daudé * check_cp0_enabled: 146905bdf72SPhilippe Mathieu-Daudé * Return %true if CP0 is enabled, otherwise return %false 147905bdf72SPhilippe Mathieu-Daudé * and emit a 'coprocessor unusable' exception. 148905bdf72SPhilippe Mathieu-Daudé */ 149905bdf72SPhilippe Mathieu-Daudé bool check_cp0_enabled(DisasContext *ctx); 1508758d1b8SPhilippe Mathieu-Daudé void check_cp1_enabled(DisasContext *ctx); 1518758d1b8SPhilippe Mathieu-Daudé void check_cp1_64bitmode(DisasContext *ctx); 1528758d1b8SPhilippe Mathieu-Daudé void check_cp1_registers(DisasContext *ctx, int regs); 1538758d1b8SPhilippe Mathieu-Daudé void check_cop1x(DisasContext *ctx); 15446c9e2b3SPhilippe Mathieu-Daudé 15546c9e2b3SPhilippe Mathieu-Daudé void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset); 15646c9e2b3SPhilippe Mathieu-Daudé void gen_move_low32(TCGv ret, TCGv_i64 arg); 15746c9e2b3SPhilippe Mathieu-Daudé void gen_move_high32(TCGv ret, TCGv_i64 arg); 15846c9e2b3SPhilippe Mathieu-Daudé void gen_load_gpr(TCGv t, int reg); 15946c9e2b3SPhilippe Mathieu-Daudé void gen_store_gpr(TCGv t, int reg); 16061f4e0ecSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64) 16161f4e0ecSPhilippe Mathieu-Daudé void gen_load_gpr_hi(TCGv_i64 t, int reg); 16261f4e0ecSPhilippe Mathieu-Daudé void gen_store_gpr_hi(TCGv_i64 t, int reg); 16361f4e0ecSPhilippe Mathieu-Daudé #endif /* TARGET_MIPS64 */ 1648758d1b8SPhilippe Mathieu-Daudé void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg); 1658758d1b8SPhilippe Mathieu-Daudé void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg); 1668758d1b8SPhilippe Mathieu-Daudé void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg); 1678758d1b8SPhilippe Mathieu-Daudé void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg); 1688758d1b8SPhilippe Mathieu-Daudé int get_fp_bit(int cc); 16946c9e2b3SPhilippe Mathieu-Daudé 170d5076631SPhilippe Mathieu-Daudé void gen_ldxs(DisasContext *ctx, int base, int index, int rd); 171d5076631SPhilippe Mathieu-Daudé void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp); 172d5076631SPhilippe Mathieu-Daudé void gen_addiupc(DisasContext *ctx, int rx, int imm, 173d5076631SPhilippe Mathieu-Daudé int is_64_bit, int extended); 174d5076631SPhilippe Mathieu-Daudé 175a685f7d0SPhilippe Mathieu-Daudé /* 176a685f7d0SPhilippe Mathieu-Daudé * Address Computation and Large Constant Instructions 177a685f7d0SPhilippe Mathieu-Daudé */ 17846c9e2b3SPhilippe Mathieu-Daudé void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1); 179a685f7d0SPhilippe Mathieu-Daudé bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa); 180a685f7d0SPhilippe Mathieu-Daudé bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa); 18146c9e2b3SPhilippe Mathieu-Daudé 182f9fa53f1SPhilippe Mathieu-Daudé void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel); 183f9fa53f1SPhilippe Mathieu-Daudé 18446c9e2b3SPhilippe Mathieu-Daudé extern TCGv cpu_gpr[32], cpu_PC; 185cefd68f6SPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64) 186cefd68f6SPhilippe Mathieu-Daudé extern TCGv_i64 cpu_gpr_hi[32]; 187cefd68f6SPhilippe Mathieu-Daudé #endif 1889f5f7691SPhilippe Mathieu-Daudé extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; 1898758d1b8SPhilippe Mathieu-Daudé extern TCGv_i32 fpu_fcr0, fpu_fcr31; 1908758d1b8SPhilippe Mathieu-Daudé extern TCGv_i64 fpu_f64[32]; 19146c9e2b3SPhilippe Mathieu-Daudé extern TCGv bcond; 19246c9e2b3SPhilippe Mathieu-Daudé 19346c9e2b3SPhilippe Mathieu-Daudé #define LOG_DISAS(...) \ 19446c9e2b3SPhilippe Mathieu-Daudé do { \ 19546c9e2b3SPhilippe Mathieu-Daudé if (MIPS_DEBUG_DISAS) { \ 19646c9e2b3SPhilippe Mathieu-Daudé qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ 19746c9e2b3SPhilippe Mathieu-Daudé } \ 19846c9e2b3SPhilippe Mathieu-Daudé } while (0) 19946c9e2b3SPhilippe Mathieu-Daudé 20046c9e2b3SPhilippe Mathieu-Daudé #define MIPS_INVAL(op) \ 20146c9e2b3SPhilippe Mathieu-Daudé do { \ 20246c9e2b3SPhilippe Mathieu-Daudé if (MIPS_DEBUG_DISAS) { \ 20346c9e2b3SPhilippe Mathieu-Daudé qemu_log_mask(CPU_LOG_TB_IN_ASM, \ 20485c19af6SAnton Johansson "%016" VADDR_PRIx \ 20585c19af6SAnton Johansson ": %08x Invalid %s %03x %03x %03x\n", \ 20646c9e2b3SPhilippe Mathieu-Daudé ctx->base.pc_next, ctx->opcode, op, \ 20746c9e2b3SPhilippe Mathieu-Daudé ctx->opcode >> 26, ctx->opcode & 0x3F, \ 20846c9e2b3SPhilippe Mathieu-Daudé ((ctx->opcode >> 16) & 0x1F)); \ 20946c9e2b3SPhilippe Mathieu-Daudé } \ 21046c9e2b3SPhilippe Mathieu-Daudé } while (0) 21146c9e2b3SPhilippe Mathieu-Daudé 212959c5da2SPhilippe Mathieu-Daudé /* MSA */ 213959c5da2SPhilippe Mathieu-Daudé void msa_translate_init(void); 214959c5da2SPhilippe Mathieu-Daudé 215c7abe00aSPhilippe Mathieu-Daudé /* MXU */ 216fe35ea94SPhilippe Mathieu-Daudé void mxu_translate_init(void); 217c7abe00aSPhilippe Mathieu-Daudé bool decode_ase_mxu(DisasContext *ctx, uint32_t insn); 218c7abe00aSPhilippe Mathieu-Daudé 219c7a9ef75SPhilippe Mathieu-Daudé /* decodetree generated */ 2203f7a9278SPhilippe Mathieu-Daudé bool decode_isa_rel6(DisasContext *ctx, uint32_t insn); 221c7a9ef75SPhilippe Mathieu-Daudé bool decode_ase_msa(DisasContext *ctx, uint32_t insn); 222ffc672aaSPhilippe Mathieu-Daudé bool decode_ext_txx9(DisasContext *ctx, uint32_t insn); 223ffc672aaSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64) 22403afdc28SJiaxun Yang bool decode_ase_lcsr(DisasContext *ctx, uint32_t insn); 225ffc672aaSPhilippe Mathieu-Daudé bool decode_ext_tx79(DisasContext *ctx, uint32_t insn); 22672d680e4SPavel Dovgalyuk bool decode_ext_octeon(DisasContext *ctx, uint32_t insn); 227ffc672aaSPhilippe Mathieu-Daudé #endif 2289d005392SPhilippe Mathieu-Daudé bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn); 229c7a9ef75SPhilippe Mathieu-Daudé 230fb3164e4SPhilippe Mathieu-Daudé /* 231fb3164e4SPhilippe Mathieu-Daudé * Helpers for implementing sets of trans_* functions. 232fb3164e4SPhilippe Mathieu-Daudé * Defer the implementation of NAME to FUNC, with optional extra arguments. 233fb3164e4SPhilippe Mathieu-Daudé */ 234fb3164e4SPhilippe Mathieu-Daudé #define TRANS(NAME, FUNC, ...) \ 235fb3164e4SPhilippe Mathieu-Daudé static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \ 236fb3164e4SPhilippe Mathieu-Daudé { return FUNC(ctx, a, __VA_ARGS__); } 237fb3164e4SPhilippe Mathieu-Daudé 238*e99072b6SPhilippe Mathieu-Daudé static inline bool disas_is_bigendian(DisasContext *ctx) 239bf78469cSPhilippe Mathieu-Daudé { 240bf78469cSPhilippe Mathieu-Daudé return extract32(ctx->CP0_Config0, CP0C0_BE, 1); 241bf78469cSPhilippe Mathieu-Daudé } 242bf78469cSPhilippe Mathieu-Daudé 243e3130936SPhilippe Mathieu-Daudé #endif 244