]> git.proxmox.com Git - mirror_qemu.git/blob - target/mips/tcg/translate.h
Merge tag 'linux-user-for-7.1-pull-request' of https://gitlab.com/laurent_vivier...
[mirror_qemu.git] / target / mips / tcg / translate.h
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 "qemu/log.h"
12 #include "exec/translator.h"
13
14 #define MIPS_DEBUG_DISAS 0
15
16 typedef struct DisasContext {
17 DisasContextBase base;
18 target_ulong saved_pc;
19 target_ulong page_start;
20 uint32_t opcode;
21 uint64_t insn_flags;
22 int32_t CP0_Config0;
23 int32_t CP0_Config1;
24 int32_t CP0_Config2;
25 int32_t CP0_Config3;
26 int32_t CP0_Config5;
27 /* Routine used to access memory */
28 int mem_idx;
29 MemOp default_tcg_memop_mask;
30 uint32_t hflags, saved_hflags;
31 target_ulong btarget;
32 bool ulri;
33 int kscrexist;
34 bool rxi;
35 int ie;
36 bool bi;
37 bool bp;
38 uint64_t PAMask;
39 bool mvh;
40 bool eva;
41 bool sc;
42 int CP0_LLAddr_shift;
43 bool ps;
44 bool vp;
45 bool cmgcr;
46 bool mrp;
47 bool nan2008;
48 bool abs2008;
49 bool saar;
50 bool mi;
51 int gi;
52 } DisasContext;
53
54 #define DISAS_STOP DISAS_TARGET_0
55 #define DISAS_EXIT DISAS_TARGET_1
56 #define DISAS_SEMIHOST DISAS_TARGET_2
57
58 /* MIPS major opcodes */
59 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
60
61 #define OPC_CP1 (0x11 << 26)
62
63 /* Coprocessor 1 (rs field) */
64 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
65
66 /* Values for the fmt field in FP instructions */
67 enum {
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 */
77 };
78
79 enum {
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,
100 };
101
102 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
103 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
104
105 enum {
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,
110 };
111
112 enum {
113 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
114 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
115 };
116
117 enum {
118 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
119 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
120 };
121
122 #define gen_helper_0e1i(name, arg1, arg2) do { \
123 gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \
124 } while (0)
125
126 #define gen_helper_1e0i(name, ret, arg1) do { \
127 gen_helper_##name(ret, cpu_env, tcg_constant_i32(arg1)); \
128 } while (0)
129
130 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
131 gen_helper_##name(cpu_env, arg1, arg2, tcg_constant_i32(arg3));\
132 } while (0)
133
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);
139
140 void check_insn(DisasContext *ctx, uint64_t flags);
141 void check_mips_64(DisasContext *ctx);
142 /**
143 * check_cp0_enabled:
144 * Return %true if CP0 is enabled, otherwise return %false
145 * and emit a 'coprocessor unusable' exception.
146 */
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);
152
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);
167
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);
172
173 /*
174 * Address Computation and Large Constant Instructions
175 */
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);
179
180 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel);
181
182 extern TCGv cpu_gpr[32], cpu_PC;
183 #if defined(TARGET_MIPS64)
184 extern TCGv_i64 cpu_gpr_hi[32];
185 #endif
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];
189 extern TCGv bcond;
190
191 #define LOG_DISAS(...) \
192 do { \
193 if (MIPS_DEBUG_DISAS) { \
194 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
195 } \
196 } while (0)
197
198 #define MIPS_INVAL(op) \
199 do { \
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)); \
206 } \
207 } while (0)
208
209 /* MSA */
210 void msa_translate_init(void);
211
212 /* MXU */
213 void mxu_translate_init(void);
214 bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
215
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);
223 #endif
224 bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn);
225
226 /*
227 * Helpers for implementing sets of trans_* functions.
228 * Defer the implementation of NAME to FUNC, with optional extra arguments.
229 */
230 #define TRANS(NAME, FUNC, ...) \
231 static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
232 { return FUNC(ctx, a, __VA_ARGS__); }
233
234 static inline bool cpu_is_bigendian(DisasContext *ctx)
235 {
236 return extract32(ctx->CP0_Config0, CP0C0_BE, 1);
237 }
238
239 #endif