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