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 "exec/translator.h"
14 #define MIPS_DEBUG_DISAS 0
16 typedef struct DisasContext
{
17 DisasContextBase base
;
18 target_ulong saved_pc
;
19 target_ulong page_start
;
27 /* Routine used to access memory */
29 MemOp default_tcg_memop_mask
;
30 uint32_t hflags
, saved_hflags
;
54 #define DISAS_STOP DISAS_TARGET_0
55 #define DISAS_EXIT DISAS_TARGET_1
56 #define DISAS_SEMIHOST DISAS_TARGET_2
58 /* MIPS major opcodes */
59 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
61 #define OPC_CP1 (0x11 << 26)
63 /* Coprocessor 1 (rs field) */
64 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
66 /* Values for the fmt field in FP instructions */
68 /* 0 - 15 are reserved */
69 FMT_S
= 16, /* single fp */
70 FMT_D
= 17, /* double fp */
71 FMT_E
= 18, /* extended fp */
72 FMT_Q
= 19, /* quad fp */
73 FMT_W
= 20, /* 32-bit fixed */
74 FMT_L
= 21, /* 64-bit fixed */
75 FMT_PS
= 22, /* paired single fp */
76 /* 23 - 31 are reserved */
80 OPC_MFC1
= (0x00 << 21) | OPC_CP1
,
81 OPC_DMFC1
= (0x01 << 21) | OPC_CP1
,
82 OPC_CFC1
= (0x02 << 21) | OPC_CP1
,
83 OPC_MFHC1
= (0x03 << 21) | OPC_CP1
,
84 OPC_MTC1
= (0x04 << 21) | OPC_CP1
,
85 OPC_DMTC1
= (0x05 << 21) | OPC_CP1
,
86 OPC_CTC1
= (0x06 << 21) | OPC_CP1
,
87 OPC_MTHC1
= (0x07 << 21) | OPC_CP1
,
88 OPC_BC1
= (0x08 << 21) | OPC_CP1
, /* bc */
89 OPC_BC1ANY2
= (0x09 << 21) | OPC_CP1
,
90 OPC_BC1ANY4
= (0x0A << 21) | OPC_CP1
,
91 OPC_S_FMT
= (FMT_S
<< 21) | OPC_CP1
,
92 OPC_D_FMT
= (FMT_D
<< 21) | OPC_CP1
,
93 OPC_E_FMT
= (FMT_E
<< 21) | OPC_CP1
,
94 OPC_Q_FMT
= (FMT_Q
<< 21) | OPC_CP1
,
95 OPC_W_FMT
= (FMT_W
<< 21) | OPC_CP1
,
96 OPC_L_FMT
= (FMT_L
<< 21) | OPC_CP1
,
97 OPC_PS_FMT
= (FMT_PS
<< 21) | OPC_CP1
,
98 OPC_BC1EQZ
= (0x09 << 21) | OPC_CP1
,
99 OPC_BC1NEZ
= (0x0D << 21) | OPC_CP1
,
102 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
103 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
106 OPC_BC1F
= (0x00 << 16) | OPC_BC1
,
107 OPC_BC1T
= (0x01 << 16) | OPC_BC1
,
108 OPC_BC1FL
= (0x02 << 16) | OPC_BC1
,
109 OPC_BC1TL
= (0x03 << 16) | OPC_BC1
,
113 OPC_BC1FANY2
= (0x00 << 16) | OPC_BC1ANY2
,
114 OPC_BC1TANY2
= (0x01 << 16) | OPC_BC1ANY2
,
118 OPC_BC1FANY4
= (0x00 << 16) | OPC_BC1ANY4
,
119 OPC_BC1TANY4
= (0x01 << 16) | OPC_BC1ANY4
,
122 #define gen_helper_0e1i(name, arg1, arg2) do { \
123 gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \
126 #define gen_helper_1e0i(name, ret, arg1) do { \
127 gen_helper_##name(ret, cpu_env, tcg_constant_i32(arg1)); \
130 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
131 gen_helper_##name(cpu_env, arg1, arg2, tcg_constant_i32(arg3));\
134 void generate_exception(DisasContext
*ctx
, int excp
);
135 void generate_exception_err(DisasContext
*ctx
, int excp
, int err
);
136 void generate_exception_end(DisasContext
*ctx
, int excp
);
137 void generate_exception_break(DisasContext
*ctx
, int code
);
138 void gen_reserved_instruction(DisasContext
*ctx
);
140 void check_insn(DisasContext
*ctx
, uint64_t flags
);
141 void check_mips_64(DisasContext
*ctx
);
144 * Return %true if CP0 is enabled, otherwise return %false
145 * and emit a 'coprocessor unusable' exception.
147 bool check_cp0_enabled(DisasContext
*ctx
);
148 void check_cp1_enabled(DisasContext
*ctx
);
149 void check_cp1_64bitmode(DisasContext
*ctx
);
150 void check_cp1_registers(DisasContext
*ctx
, int regs
);
151 void check_cop1x(DisasContext
*ctx
);
153 void gen_base_offset_addr(DisasContext
*ctx
, TCGv addr
, int base
, int offset
);
154 void gen_move_low32(TCGv ret
, TCGv_i64 arg
);
155 void gen_move_high32(TCGv ret
, TCGv_i64 arg
);
156 void gen_load_gpr(TCGv t
, int reg
);
157 void gen_store_gpr(TCGv t
, int reg
);
158 #if defined(TARGET_MIPS64)
159 void gen_load_gpr_hi(TCGv_i64 t
, int reg
);
160 void gen_store_gpr_hi(TCGv_i64 t
, int reg
);
161 #endif /* TARGET_MIPS64 */
162 void gen_load_fpr32(DisasContext
*ctx
, TCGv_i32 t
, int reg
);
163 void gen_load_fpr64(DisasContext
*ctx
, TCGv_i64 t
, int reg
);
164 void gen_store_fpr32(DisasContext
*ctx
, TCGv_i32 t
, int reg
);
165 void gen_store_fpr64(DisasContext
*ctx
, TCGv_i64 t
, int reg
);
166 int get_fp_bit(int cc
);
168 void gen_ldxs(DisasContext
*ctx
, int base
, int index
, int rd
);
169 void gen_align(DisasContext
*ctx
, int wordsz
, int rd
, int rs
, int rt
, int bp
);
170 void gen_addiupc(DisasContext
*ctx
, int rx
, int imm
,
171 int is_64_bit
, int extended
);
174 * Address Computation and Large Constant Instructions
176 void gen_op_addr_add(DisasContext
*ctx
, TCGv ret
, TCGv arg0
, TCGv arg1
);
177 bool gen_lsa(DisasContext
*ctx
, int rd
, int rt
, int rs
, int sa
);
178 bool gen_dlsa(DisasContext
*ctx
, int rd
, int rt
, int rs
, int sa
);
180 void gen_rdhwr(DisasContext
*ctx
, int rt
, int rd
, int sel
);
182 extern TCGv cpu_gpr
[32], cpu_PC
;
183 #if defined(TARGET_MIPS64)
184 extern TCGv_i64 cpu_gpr_hi
[32];
186 extern TCGv cpu_HI
[MIPS_DSP_ACC
], cpu_LO
[MIPS_DSP_ACC
];
187 extern TCGv_i32 fpu_fcr0
, fpu_fcr31
;
188 extern TCGv_i64 fpu_f64
[32];
191 #define LOG_DISAS(...) \
193 if (MIPS_DEBUG_DISAS) { \
194 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
198 #define MIPS_INVAL(op) \
200 if (MIPS_DEBUG_DISAS) { \
201 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
202 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
203 ctx->base.pc_next, ctx->opcode, op, \
204 ctx->opcode >> 26, ctx->opcode & 0x3F, \
205 ((ctx->opcode >> 16) & 0x1F)); \
210 void msa_translate_init(void);
213 void mxu_translate_init(void);
214 bool decode_ase_mxu(DisasContext
*ctx
, uint32_t insn
);
216 /* decodetree generated */
217 bool decode_isa_rel6(DisasContext
*ctx
, uint32_t insn
);
218 bool decode_ase_msa(DisasContext
*ctx
, uint32_t insn
);
219 bool decode_ext_txx9(DisasContext
*ctx
, uint32_t insn
);
220 #if defined(TARGET_MIPS64)
221 bool decode_ext_tx79(DisasContext
*ctx
, uint32_t insn
);
222 bool decode_ext_octeon(DisasContext
*ctx
, uint32_t insn
);
224 bool decode_ext_vr54xx(DisasContext
*ctx
, uint32_t insn
);
227 * Helpers for implementing sets of trans_* functions.
228 * Defer the implementation of NAME to FUNC, with optional extra arguments.
230 #define TRANS(NAME, FUNC, ...) \
231 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
232 { return FUNC(ctx, a, __VA_ARGS__); }
234 static inline bool cpu_is_bigendian(DisasContext
*ctx
)
236 return extract32(ctx
->CP0_Config0
, CP0C0_BE
, 1);