2 * MIPS translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
6 * SPDX-License-Identifier: LGPL-2.1-or-later
8 #ifndef TARGET_MIPS_TRANSLATE_H
9 #define TARGET_MIPS_TRANSLATE_H
12 #include "tcg/tcg-op.h"
13 #include "exec/translator.h"
14 #include "exec/helper-gen.h"
17 #define MIPS_DEBUG_DISAS 0
19 typedef struct DisasContext
{
20 DisasContextBase base
;
21 target_ulong saved_pc
;
22 target_ulong page_start
;
30 /* Routine used to access memory */
32 MemOp default_tcg_memop_mask
;
33 uint32_t hflags
, saved_hflags
;
56 #define DISAS_STOP DISAS_TARGET_0
57 #define DISAS_EXIT DISAS_TARGET_1
58 #define DISAS_SEMIHOST DISAS_TARGET_2
60 /* MIPS major opcodes */
61 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
63 #define OPC_CP1 (0x11 << 26)
65 /* Coprocessor 1 (rs field) */
66 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
68 /* Values for the fmt field in FP instructions */
70 /* 0 - 15 are reserved */
71 FMT_S
= 16, /* single fp */
72 FMT_D
= 17, /* double fp */
73 FMT_E
= 18, /* extended fp */
74 FMT_Q
= 19, /* quad fp */
75 FMT_W
= 20, /* 32-bit fixed */
76 FMT_L
= 21, /* 64-bit fixed */
77 FMT_PS
= 22, /* paired single fp */
78 /* 23 - 31 are reserved */
82 OPC_MFC1
= (0x00 << 21) | OPC_CP1
,
83 OPC_DMFC1
= (0x01 << 21) | OPC_CP1
,
84 OPC_CFC1
= (0x02 << 21) | OPC_CP1
,
85 OPC_MFHC1
= (0x03 << 21) | OPC_CP1
,
86 OPC_MTC1
= (0x04 << 21) | OPC_CP1
,
87 OPC_DMTC1
= (0x05 << 21) | OPC_CP1
,
88 OPC_CTC1
= (0x06 << 21) | OPC_CP1
,
89 OPC_MTHC1
= (0x07 << 21) | OPC_CP1
,
90 OPC_BC1
= (0x08 << 21) | OPC_CP1
, /* bc */
91 OPC_BC1ANY2
= (0x09 << 21) | OPC_CP1
,
92 OPC_BC1ANY4
= (0x0A << 21) | OPC_CP1
,
93 OPC_S_FMT
= (FMT_S
<< 21) | OPC_CP1
,
94 OPC_D_FMT
= (FMT_D
<< 21) | OPC_CP1
,
95 OPC_E_FMT
= (FMT_E
<< 21) | OPC_CP1
,
96 OPC_Q_FMT
= (FMT_Q
<< 21) | OPC_CP1
,
97 OPC_W_FMT
= (FMT_W
<< 21) | OPC_CP1
,
98 OPC_L_FMT
= (FMT_L
<< 21) | OPC_CP1
,
99 OPC_PS_FMT
= (FMT_PS
<< 21) | OPC_CP1
,
100 OPC_BC1EQZ
= (0x09 << 21) | OPC_CP1
,
101 OPC_BC1NEZ
= (0x0D << 21) | OPC_CP1
,
104 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
105 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
108 OPC_BC1F
= (0x00 << 16) | OPC_BC1
,
109 OPC_BC1T
= (0x01 << 16) | OPC_BC1
,
110 OPC_BC1FL
= (0x02 << 16) | OPC_BC1
,
111 OPC_BC1TL
= (0x03 << 16) | OPC_BC1
,
115 OPC_BC1FANY2
= (0x00 << 16) | OPC_BC1ANY2
,
116 OPC_BC1TANY2
= (0x01 << 16) | OPC_BC1ANY2
,
120 OPC_BC1FANY4
= (0x00 << 16) | OPC_BC1ANY4
,
121 OPC_BC1TANY4
= (0x01 << 16) | OPC_BC1ANY4
,
124 #define gen_helper_0e1i(name, arg1, arg2) do { \
125 gen_helper_##name(tcg_env, arg1, tcg_constant_i32(arg2)); \
128 #define gen_helper_1e0i(name, ret, arg1) do { \
129 gen_helper_##name(ret, tcg_env, tcg_constant_i32(arg1)); \
132 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
133 gen_helper_##name(tcg_env, arg1, arg2, tcg_constant_i32(arg3));\
136 void generate_exception(DisasContext
*ctx
, int excp
);
137 void generate_exception_err(DisasContext
*ctx
, int excp
, int err
);
138 void generate_exception_end(DisasContext
*ctx
, int excp
);
139 void generate_exception_break(DisasContext
*ctx
, int code
);
140 void gen_reserved_instruction(DisasContext
*ctx
);
142 void check_insn(DisasContext
*ctx
, uint64_t flags
);
143 void check_mips_64(DisasContext
*ctx
);
146 * Return %true if CP0 is enabled, otherwise return %false
147 * and emit a 'coprocessor unusable' exception.
149 bool check_cp0_enabled(DisasContext
*ctx
);
150 void check_cp1_enabled(DisasContext
*ctx
);
151 void check_cp1_64bitmode(DisasContext
*ctx
);
152 void check_cp1_registers(DisasContext
*ctx
, int regs
);
153 void check_cop1x(DisasContext
*ctx
);
155 void gen_base_offset_addr(DisasContext
*ctx
, TCGv addr
, int base
, int offset
);
156 void gen_move_low32(TCGv ret
, TCGv_i64 arg
);
157 void gen_move_high32(TCGv ret
, TCGv_i64 arg
);
158 void gen_load_gpr(TCGv t
, int reg
);
159 void gen_store_gpr(TCGv t
, int reg
);
160 #if defined(TARGET_MIPS64)
161 void gen_load_gpr_hi(TCGv_i64 t
, int reg
);
162 void gen_store_gpr_hi(TCGv_i64 t
, int reg
);
163 #endif /* TARGET_MIPS64 */
164 void gen_load_fpr32(DisasContext
*ctx
, TCGv_i32 t
, int reg
);
165 void gen_load_fpr64(DisasContext
*ctx
, TCGv_i64 t
, int reg
);
166 void gen_store_fpr32(DisasContext
*ctx
, TCGv_i32 t
, int reg
);
167 void gen_store_fpr64(DisasContext
*ctx
, TCGv_i64 t
, int reg
);
168 int get_fp_bit(int cc
);
170 void gen_ldxs(DisasContext
*ctx
, int base
, int index
, int rd
);
171 void gen_align(DisasContext
*ctx
, int wordsz
, int rd
, int rs
, int rt
, int bp
);
172 void gen_addiupc(DisasContext
*ctx
, int rx
, int imm
,
173 int is_64_bit
, int extended
);
176 * Address Computation and Large Constant Instructions
178 void gen_op_addr_add(DisasContext
*ctx
, TCGv ret
, TCGv arg0
, TCGv arg1
);
179 void gen_op_addr_addi(DisasContext
*ctx
, TCGv ret
, TCGv base
, target_long ofs
);
180 bool gen_lsa(DisasContext
*ctx
, int rd
, int rt
, int rs
, int sa
);
181 bool gen_dlsa(DisasContext
*ctx
, int rd
, int rt
, int rs
, int sa
);
183 void gen_rdhwr(DisasContext
*ctx
, int rt
, int rd
, int sel
);
185 extern TCGv cpu_gpr
[32], cpu_PC
;
186 #if defined(TARGET_MIPS64)
187 extern TCGv_i64 cpu_gpr_hi
[32];
189 extern TCGv cpu_HI
[MIPS_DSP_ACC
], cpu_LO
[MIPS_DSP_ACC
];
190 extern TCGv_i32 fpu_fcr0
, fpu_fcr31
;
191 extern TCGv_i64 fpu_f64
[32];
194 #define LOG_DISAS(...) \
196 if (MIPS_DEBUG_DISAS) { \
197 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
201 #define MIPS_INVAL(op) \
203 if (MIPS_DEBUG_DISAS) { \
204 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
206 ": %08x Invalid %s %03x %03x %03x\n", \
207 ctx->base.pc_next, ctx->opcode, op, \
208 ctx->opcode >> 26, ctx->opcode & 0x3F, \
209 ((ctx->opcode >> 16) & 0x1F)); \
214 void msa_translate_init(void);
217 void mxu_translate_init(void);
218 bool decode_ase_mxu(DisasContext
*ctx
, uint32_t insn
);
220 /* decodetree generated */
221 bool decode_isa_rel6(DisasContext
*ctx
, uint32_t insn
);
222 bool decode_ase_msa(DisasContext
*ctx
, uint32_t insn
);
223 bool decode_ext_txx9(DisasContext
*ctx
, uint32_t insn
);
224 #if defined(TARGET_MIPS64)
225 bool decode_ase_lcsr(DisasContext
*ctx
, uint32_t insn
);
226 bool decode_ext_tx79(DisasContext
*ctx
, uint32_t insn
);
227 bool decode_ext_octeon(DisasContext
*ctx
, uint32_t insn
);
229 bool decode_ext_vr54xx(DisasContext
*ctx
, uint32_t insn
);
232 * Helpers for implementing sets of trans_* functions.
233 * Defer the implementation of NAME to FUNC, with optional extra arguments.
235 #define TRANS(NAME, FUNC, ...) \
236 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
237 { return FUNC(ctx, a, __VA_ARGS__); }
239 static inline bool disas_is_bigendian(DisasContext
*ctx
)
241 return extract32(ctx
->CP0_Config0
, CP0C0_BE
, 1);
244 static inline MemOp
mo_endian(DisasContext
*dc
)
246 return disas_is_bigendian(dc
) ? MO_BE
: MO_LE
;
249 static inline MemOp
mo_endian_rev(DisasContext
*dc
, bool reversed
)
251 return disas_is_bigendian(dc
) ^ reversed
? MO_BE
: MO_LE
;