]>
Commit | Line | Data |
---|---|---|
e3130936 PMD |
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 | ||
8cab4157 | 11 | #include "cpu.h" |
f15f8935 | 12 | #include "tcg/tcg-op.h" |
8cab4157 RH |
13 | #include "exec/translator.h" |
14 | #include "exec/helper-gen.h" | |
15 | #include "qemu/log.h" | |
e3130936 | 16 | |
46c9e2b3 PMD |
17 | #define MIPS_DEBUG_DISAS 0 |
18 | ||
e3130936 PMD |
19 | typedef struct DisasContext { |
20 | DisasContextBase base; | |
21 | target_ulong saved_pc; | |
22 | target_ulong page_start; | |
23 | uint32_t opcode; | |
24 | uint64_t insn_flags; | |
0cfd392d | 25 | int32_t CP0_Config0; |
e3130936 PMD |
26 | int32_t CP0_Config1; |
27 | int32_t CP0_Config2; | |
28 | int32_t CP0_Config3; | |
29 | int32_t CP0_Config5; | |
30 | /* Routine used to access memory */ | |
31 | int mem_idx; | |
32 | MemOp default_tcg_memop_mask; | |
33 | uint32_t hflags, saved_hflags; | |
34 | target_ulong btarget; | |
35 | bool ulri; | |
36 | int kscrexist; | |
37 | bool rxi; | |
38 | int ie; | |
39 | bool bi; | |
40 | bool bp; | |
41 | uint64_t PAMask; | |
42 | bool mvh; | |
43 | bool eva; | |
44 | bool sc; | |
45 | int CP0_LLAddr_shift; | |
46 | bool ps; | |
47 | bool vp; | |
48 | bool cmgcr; | |
49 | bool mrp; | |
50 | bool nan2008; | |
51 | bool abs2008; | |
52 | bool saar; | |
53 | bool mi; | |
54 | int gi; | |
55 | } DisasContext; | |
56 | ||
d44971e7 RH |
57 | #define DISAS_STOP DISAS_TARGET_0 |
58 | #define DISAS_EXIT DISAS_TARGET_1 | |
59 | #define DISAS_SEMIHOST DISAS_TARGET_2 | |
60 | ||
46c9e2b3 PMD |
61 | /* MIPS major opcodes */ |
62 | #define MASK_OP_MAJOR(op) (op & (0x3F << 26)) | |
63 | ||
57eedcf7 PMD |
64 | #define OPC_CP1 (0x11 << 26) |
65 | ||
66 | /* Coprocessor 1 (rs field) */ | |
67 | #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21))) | |
68 | ||
69 | /* Values for the fmt field in FP instructions */ | |
70 | enum { | |
71 | /* 0 - 15 are reserved */ | |
72 | FMT_S = 16, /* single fp */ | |
73 | FMT_D = 17, /* double fp */ | |
74 | FMT_E = 18, /* extended fp */ | |
75 | FMT_Q = 19, /* quad fp */ | |
76 | FMT_W = 20, /* 32-bit fixed */ | |
77 | FMT_L = 21, /* 64-bit fixed */ | |
78 | FMT_PS = 22, /* paired single fp */ | |
79 | /* 23 - 31 are reserved */ | |
80 | }; | |
81 | ||
82 | enum { | |
83 | OPC_MFC1 = (0x00 << 21) | OPC_CP1, | |
84 | OPC_DMFC1 = (0x01 << 21) | OPC_CP1, | |
85 | OPC_CFC1 = (0x02 << 21) | OPC_CP1, | |
86 | OPC_MFHC1 = (0x03 << 21) | OPC_CP1, | |
87 | OPC_MTC1 = (0x04 << 21) | OPC_CP1, | |
88 | OPC_DMTC1 = (0x05 << 21) | OPC_CP1, | |
89 | OPC_CTC1 = (0x06 << 21) | OPC_CP1, | |
90 | OPC_MTHC1 = (0x07 << 21) | OPC_CP1, | |
91 | OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */ | |
92 | OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1, | |
93 | OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1, | |
57eedcf7 PMD |
94 | OPC_S_FMT = (FMT_S << 21) | OPC_CP1, |
95 | OPC_D_FMT = (FMT_D << 21) | OPC_CP1, | |
96 | OPC_E_FMT = (FMT_E << 21) | OPC_CP1, | |
97 | OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1, | |
98 | OPC_W_FMT = (FMT_W << 21) | OPC_CP1, | |
99 | OPC_L_FMT = (FMT_L << 21) | OPC_CP1, | |
100 | OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1, | |
101 | OPC_BC1EQZ = (0x09 << 21) | OPC_CP1, | |
102 | OPC_BC1NEZ = (0x0D << 21) | OPC_CP1, | |
57eedcf7 PMD |
103 | }; |
104 | ||
105 | #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F)) | |
106 | #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16))) | |
107 | ||
108 | enum { | |
109 | OPC_BC1F = (0x00 << 16) | OPC_BC1, | |
110 | OPC_BC1T = (0x01 << 16) | OPC_BC1, | |
111 | OPC_BC1FL = (0x02 << 16) | OPC_BC1, | |
112 | OPC_BC1TL = (0x03 << 16) | OPC_BC1, | |
113 | }; | |
114 | ||
115 | enum { | |
116 | OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2, | |
117 | OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2, | |
118 | }; | |
119 | ||
120 | enum { | |
121 | OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4, | |
122 | OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4, | |
123 | }; | |
124 | ||
761533fc | 125 | #define gen_helper_0e1i(name, arg1, arg2) do { \ |
ad75a51e | 126 | gen_helper_##name(tcg_env, arg1, tcg_constant_i32(arg2)); \ |
761533fc PMD |
127 | } while (0) |
128 | ||
129 | #define gen_helper_1e0i(name, ret, arg1) do { \ | |
ad75a51e | 130 | gen_helper_##name(ret, tcg_env, tcg_constant_i32(arg1)); \ |
761533fc PMD |
131 | } while (0) |
132 | ||
133 | #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \ | |
ad75a51e | 134 | gen_helper_##name(tcg_env, arg1, arg2, tcg_constant_i32(arg3));\ |
761533fc PMD |
135 | } while (0) |
136 | ||
46c9e2b3 PMD |
137 | void generate_exception(DisasContext *ctx, int excp); |
138 | void generate_exception_err(DisasContext *ctx, int excp, int err); | |
139 | void generate_exception_end(DisasContext *ctx, int excp); | |
6f3533dd | 140 | void generate_exception_break(DisasContext *ctx, int code); |
3a4ef3b7 | 141 | void gen_reserved_instruction(DisasContext *ctx); |
46c9e2b3 PMD |
142 | |
143 | void check_insn(DisasContext *ctx, uint64_t flags); | |
46c9e2b3 | 144 | void check_mips_64(DisasContext *ctx); |
905bdf72 PMD |
145 | /** |
146 | * check_cp0_enabled: | |
147 | * Return %true if CP0 is enabled, otherwise return %false | |
148 | * and emit a 'coprocessor unusable' exception. | |
149 | */ | |
150 | bool check_cp0_enabled(DisasContext *ctx); | |
8758d1b8 PMD |
151 | void check_cp1_enabled(DisasContext *ctx); |
152 | void check_cp1_64bitmode(DisasContext *ctx); | |
153 | void check_cp1_registers(DisasContext *ctx, int regs); | |
154 | void check_cop1x(DisasContext *ctx); | |
46c9e2b3 PMD |
155 | |
156 | void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset); | |
157 | void gen_move_low32(TCGv ret, TCGv_i64 arg); | |
158 | void gen_move_high32(TCGv ret, TCGv_i64 arg); | |
159 | void gen_load_gpr(TCGv t, int reg); | |
160 | void gen_store_gpr(TCGv t, int reg); | |
61f4e0ec PMD |
161 | #if defined(TARGET_MIPS64) |
162 | void gen_load_gpr_hi(TCGv_i64 t, int reg); | |
163 | void gen_store_gpr_hi(TCGv_i64 t, int reg); | |
164 | #endif /* TARGET_MIPS64 */ | |
8758d1b8 PMD |
165 | void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg); |
166 | void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg); | |
167 | void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg); | |
168 | void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg); | |
169 | int get_fp_bit(int cc); | |
46c9e2b3 | 170 | |
d5076631 PMD |
171 | void gen_ldxs(DisasContext *ctx, int base, int index, int rd); |
172 | void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp); | |
173 | void gen_addiupc(DisasContext *ctx, int rx, int imm, | |
174 | int is_64_bit, int extended); | |
175 | ||
a685f7d0 PMD |
176 | /* |
177 | * Address Computation and Large Constant Instructions | |
178 | */ | |
46c9e2b3 | 179 | void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1); |
a685f7d0 PMD |
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); | |
46c9e2b3 | 182 | |
f9fa53f1 PMD |
183 | void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel); |
184 | ||
46c9e2b3 | 185 | extern TCGv cpu_gpr[32], cpu_PC; |
cefd68f6 PMD |
186 | #if defined(TARGET_MIPS64) |
187 | extern TCGv_i64 cpu_gpr_hi[32]; | |
188 | #endif | |
9f5f7691 | 189 | extern TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC]; |
8758d1b8 PMD |
190 | extern TCGv_i32 fpu_fcr0, fpu_fcr31; |
191 | extern TCGv_i64 fpu_f64[32]; | |
46c9e2b3 PMD |
192 | extern TCGv bcond; |
193 | ||
194 | #define LOG_DISAS(...) \ | |
195 | do { \ | |
196 | if (MIPS_DEBUG_DISAS) { \ | |
197 | qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \ | |
198 | } \ | |
199 | } while (0) | |
200 | ||
201 | #define MIPS_INVAL(op) \ | |
202 | do { \ | |
203 | if (MIPS_DEBUG_DISAS) { \ | |
204 | qemu_log_mask(CPU_LOG_TB_IN_ASM, \ | |
85c19af6 AJ |
205 | "%016" VADDR_PRIx \ |
206 | ": %08x Invalid %s %03x %03x %03x\n", \ | |
46c9e2b3 PMD |
207 | ctx->base.pc_next, ctx->opcode, op, \ |
208 | ctx->opcode >> 26, ctx->opcode & 0x3F, \ | |
209 | ((ctx->opcode >> 16) & 0x1F)); \ | |
210 | } \ | |
211 | } while (0) | |
212 | ||
959c5da2 PMD |
213 | /* MSA */ |
214 | void msa_translate_init(void); | |
215 | ||
c7abe00a | 216 | /* MXU */ |
fe35ea94 | 217 | void mxu_translate_init(void); |
c7abe00a PMD |
218 | bool decode_ase_mxu(DisasContext *ctx, uint32_t insn); |
219 | ||
c7a9ef75 | 220 | /* decodetree generated */ |
3f7a9278 | 221 | bool decode_isa_rel6(DisasContext *ctx, uint32_t insn); |
c7a9ef75 | 222 | bool decode_ase_msa(DisasContext *ctx, uint32_t insn); |
ffc672aa PMD |
223 | bool decode_ext_txx9(DisasContext *ctx, uint32_t insn); |
224 | #if defined(TARGET_MIPS64) | |
03afdc28 | 225 | bool decode_ase_lcsr(DisasContext *ctx, uint32_t insn); |
ffc672aa | 226 | bool decode_ext_tx79(DisasContext *ctx, uint32_t insn); |
72d680e4 | 227 | bool decode_ext_octeon(DisasContext *ctx, uint32_t insn); |
ffc672aa | 228 | #endif |
9d005392 | 229 | bool decode_ext_vr54xx(DisasContext *ctx, uint32_t insn); |
c7a9ef75 | 230 | |
fb3164e4 PMD |
231 | /* |
232 | * Helpers for implementing sets of trans_* functions. | |
233 | * Defer the implementation of NAME to FUNC, with optional extra arguments. | |
234 | */ | |
235 | #define TRANS(NAME, FUNC, ...) \ | |
236 | static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \ | |
237 | { return FUNC(ctx, a, __VA_ARGS__); } | |
238 | ||
bf78469c PMD |
239 | static inline bool cpu_is_bigendian(DisasContext *ctx) |
240 | { | |
241 | return extract32(ctx->CP0_Config0, CP0C0_BE, 1); | |
242 | } | |
243 | ||
e3130936 | 244 | #endif |