target/mips: Inline gen_helper_0e0i()
[qemu/ar7.git] / target / mips / tcg / translate.c
blobc515a337ebc14b92bc302a1da7244f80bdf25859
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
9 * Copyright (c) 2020 Philippe Mathieu-Daudé
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "qemu/osdep.h"
26 #include "cpu.h"
27 #include "internal.h"
28 #include "tcg/tcg-op.h"
29 #include "exec/translator.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "semihosting/semihost.h"
34 #include "trace.h"
35 #include "exec/translator.h"
36 #include "exec/log.h"
37 #include "qemu/qemu-print.h"
38 #include "fpu_helper.h"
39 #include "translate.h"
42 * Many sysemu-only helpers are not reachable for user-only.
43 * Define stub generators here, so that we need not either sprinkle
44 * ifdefs through the translator, nor provide the helper function.
46 #define STUB_HELPER(NAME, ...) \
47 static inline void gen_helper_##NAME(__VA_ARGS__) \
48 { g_assert_not_reached(); }
50 #ifdef CONFIG_USER_ONLY
51 STUB_HELPER(cache, TCGv_env env, TCGv val, TCGv_i32 reg)
52 #endif
54 enum {
55 /* indirect opcode tables */
56 OPC_SPECIAL = (0x00 << 26),
57 OPC_REGIMM = (0x01 << 26),
58 OPC_CP0 = (0x10 << 26),
59 OPC_CP2 = (0x12 << 26),
60 OPC_CP3 = (0x13 << 26),
61 OPC_SPECIAL2 = (0x1C << 26),
62 OPC_SPECIAL3 = (0x1F << 26),
63 /* arithmetic with immediate */
64 OPC_ADDI = (0x08 << 26),
65 OPC_ADDIU = (0x09 << 26),
66 OPC_SLTI = (0x0A << 26),
67 OPC_SLTIU = (0x0B << 26),
68 /* logic with immediate */
69 OPC_ANDI = (0x0C << 26),
70 OPC_ORI = (0x0D << 26),
71 OPC_XORI = (0x0E << 26),
72 OPC_LUI = (0x0F << 26),
73 /* arithmetic with immediate */
74 OPC_DADDI = (0x18 << 26),
75 OPC_DADDIU = (0x19 << 26),
76 /* Jump and branches */
77 OPC_J = (0x02 << 26),
78 OPC_JAL = (0x03 << 26),
79 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
80 OPC_BEQL = (0x14 << 26),
81 OPC_BNE = (0x05 << 26),
82 OPC_BNEL = (0x15 << 26),
83 OPC_BLEZ = (0x06 << 26),
84 OPC_BLEZL = (0x16 << 26),
85 OPC_BGTZ = (0x07 << 26),
86 OPC_BGTZL = (0x17 << 26),
87 OPC_JALX = (0x1D << 26),
88 OPC_DAUI = (0x1D << 26),
89 /* Load and stores */
90 OPC_LDL = (0x1A << 26),
91 OPC_LDR = (0x1B << 26),
92 OPC_LB = (0x20 << 26),
93 OPC_LH = (0x21 << 26),
94 OPC_LWL = (0x22 << 26),
95 OPC_LW = (0x23 << 26),
96 OPC_LWPC = OPC_LW | 0x5,
97 OPC_LBU = (0x24 << 26),
98 OPC_LHU = (0x25 << 26),
99 OPC_LWR = (0x26 << 26),
100 OPC_LWU = (0x27 << 26),
101 OPC_SB = (0x28 << 26),
102 OPC_SH = (0x29 << 26),
103 OPC_SWL = (0x2A << 26),
104 OPC_SW = (0x2B << 26),
105 OPC_SDL = (0x2C << 26),
106 OPC_SDR = (0x2D << 26),
107 OPC_SWR = (0x2E << 26),
108 OPC_LL = (0x30 << 26),
109 OPC_LLD = (0x34 << 26),
110 OPC_LD = (0x37 << 26),
111 OPC_LDPC = OPC_LD | 0x5,
112 OPC_SC = (0x38 << 26),
113 OPC_SCD = (0x3C << 26),
114 OPC_SD = (0x3F << 26),
115 /* Floating point load/store */
116 OPC_LWC1 = (0x31 << 26),
117 OPC_LWC2 = (0x32 << 26),
118 OPC_LDC1 = (0x35 << 26),
119 OPC_LDC2 = (0x36 << 26),
120 OPC_SWC1 = (0x39 << 26),
121 OPC_SWC2 = (0x3A << 26),
122 OPC_SDC1 = (0x3D << 26),
123 OPC_SDC2 = (0x3E << 26),
124 /* Compact Branches */
125 OPC_BLEZALC = (0x06 << 26),
126 OPC_BGEZALC = (0x06 << 26),
127 OPC_BGEUC = (0x06 << 26),
128 OPC_BGTZALC = (0x07 << 26),
129 OPC_BLTZALC = (0x07 << 26),
130 OPC_BLTUC = (0x07 << 26),
131 OPC_BOVC = (0x08 << 26),
132 OPC_BEQZALC = (0x08 << 26),
133 OPC_BEQC = (0x08 << 26),
134 OPC_BLEZC = (0x16 << 26),
135 OPC_BGEZC = (0x16 << 26),
136 OPC_BGEC = (0x16 << 26),
137 OPC_BGTZC = (0x17 << 26),
138 OPC_BLTZC = (0x17 << 26),
139 OPC_BLTC = (0x17 << 26),
140 OPC_BNVC = (0x18 << 26),
141 OPC_BNEZALC = (0x18 << 26),
142 OPC_BNEC = (0x18 << 26),
143 OPC_BC = (0x32 << 26),
144 OPC_BEQZC = (0x36 << 26),
145 OPC_JIC = (0x36 << 26),
146 OPC_BALC = (0x3A << 26),
147 OPC_BNEZC = (0x3E << 26),
148 OPC_JIALC = (0x3E << 26),
149 /* MDMX ASE specific */
150 OPC_MDMX = (0x1E << 26),
151 /* Cache and prefetch */
152 OPC_CACHE = (0x2F << 26),
153 OPC_PREF = (0x33 << 26),
154 /* PC-relative address computation / loads */
155 OPC_PCREL = (0x3B << 26),
158 /* PC-relative address computation / loads */
159 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
160 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
161 enum {
162 /* Instructions determined by bits 19 and 20 */
163 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
164 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
165 OPC_LWUPC = OPC_PCREL | (2 << 19),
167 /* Instructions determined by bits 16 ... 20 */
168 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
169 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
171 /* Other */
172 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
175 /* MIPS special opcodes */
176 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
178 enum {
179 /* Shifts */
180 OPC_SLL = 0x00 | OPC_SPECIAL,
181 /* NOP is SLL r0, r0, 0 */
182 /* SSNOP is SLL r0, r0, 1 */
183 /* EHB is SLL r0, r0, 3 */
184 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
185 OPC_ROTR = OPC_SRL | (1 << 21),
186 OPC_SRA = 0x03 | OPC_SPECIAL,
187 OPC_SLLV = 0x04 | OPC_SPECIAL,
188 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
189 OPC_ROTRV = OPC_SRLV | (1 << 6),
190 OPC_SRAV = 0x07 | OPC_SPECIAL,
191 OPC_DSLLV = 0x14 | OPC_SPECIAL,
192 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
193 OPC_DROTRV = OPC_DSRLV | (1 << 6),
194 OPC_DSRAV = 0x17 | OPC_SPECIAL,
195 OPC_DSLL = 0x38 | OPC_SPECIAL,
196 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
197 OPC_DROTR = OPC_DSRL | (1 << 21),
198 OPC_DSRA = 0x3B | OPC_SPECIAL,
199 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
200 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
201 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
202 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
203 /* Multiplication / division */
204 OPC_MULT = 0x18 | OPC_SPECIAL,
205 OPC_MULTU = 0x19 | OPC_SPECIAL,
206 OPC_DIV = 0x1A | OPC_SPECIAL,
207 OPC_DIVU = 0x1B | OPC_SPECIAL,
208 OPC_DMULT = 0x1C | OPC_SPECIAL,
209 OPC_DMULTU = 0x1D | OPC_SPECIAL,
210 OPC_DDIV = 0x1E | OPC_SPECIAL,
211 OPC_DDIVU = 0x1F | OPC_SPECIAL,
213 /* 2 registers arithmetic / logic */
214 OPC_ADD = 0x20 | OPC_SPECIAL,
215 OPC_ADDU = 0x21 | OPC_SPECIAL,
216 OPC_SUB = 0x22 | OPC_SPECIAL,
217 OPC_SUBU = 0x23 | OPC_SPECIAL,
218 OPC_AND = 0x24 | OPC_SPECIAL,
219 OPC_OR = 0x25 | OPC_SPECIAL,
220 OPC_XOR = 0x26 | OPC_SPECIAL,
221 OPC_NOR = 0x27 | OPC_SPECIAL,
222 OPC_SLT = 0x2A | OPC_SPECIAL,
223 OPC_SLTU = 0x2B | OPC_SPECIAL,
224 OPC_DADD = 0x2C | OPC_SPECIAL,
225 OPC_DADDU = 0x2D | OPC_SPECIAL,
226 OPC_DSUB = 0x2E | OPC_SPECIAL,
227 OPC_DSUBU = 0x2F | OPC_SPECIAL,
228 /* Jumps */
229 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
230 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
231 /* Traps */
232 OPC_TGE = 0x30 | OPC_SPECIAL,
233 OPC_TGEU = 0x31 | OPC_SPECIAL,
234 OPC_TLT = 0x32 | OPC_SPECIAL,
235 OPC_TLTU = 0x33 | OPC_SPECIAL,
236 OPC_TEQ = 0x34 | OPC_SPECIAL,
237 OPC_TNE = 0x36 | OPC_SPECIAL,
238 /* HI / LO registers load & stores */
239 OPC_MFHI = 0x10 | OPC_SPECIAL,
240 OPC_MTHI = 0x11 | OPC_SPECIAL,
241 OPC_MFLO = 0x12 | OPC_SPECIAL,
242 OPC_MTLO = 0x13 | OPC_SPECIAL,
243 /* Conditional moves */
244 OPC_MOVZ = 0x0A | OPC_SPECIAL,
245 OPC_MOVN = 0x0B | OPC_SPECIAL,
247 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
248 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
250 OPC_MOVCI = 0x01 | OPC_SPECIAL,
252 /* Special */
253 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
254 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
255 OPC_BREAK = 0x0D | OPC_SPECIAL,
256 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
257 OPC_SYNC = 0x0F | OPC_SPECIAL,
259 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
260 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
261 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
262 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
266 * R6 Multiply and Divide instructions have the same opcode
267 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
269 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
271 enum {
272 R6_OPC_MUL = OPC_MULT | (2 << 6),
273 R6_OPC_MUH = OPC_MULT | (3 << 6),
274 R6_OPC_MULU = OPC_MULTU | (2 << 6),
275 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
276 R6_OPC_DIV = OPC_DIV | (2 << 6),
277 R6_OPC_MOD = OPC_DIV | (3 << 6),
278 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
279 R6_OPC_MODU = OPC_DIVU | (3 << 6),
281 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
282 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
283 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
284 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
285 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
286 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
287 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
288 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
290 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
291 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
292 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
293 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
294 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
297 /* REGIMM (rt field) opcodes */
298 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
300 enum {
301 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
302 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
303 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
304 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
305 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
306 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
307 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
308 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
309 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
310 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
311 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
312 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
313 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
314 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
315 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
316 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
318 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
319 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
322 /* Special2 opcodes */
323 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
325 enum {
326 /* Multiply & xxx operations */
327 OPC_MADD = 0x00 | OPC_SPECIAL2,
328 OPC_MADDU = 0x01 | OPC_SPECIAL2,
329 OPC_MUL = 0x02 | OPC_SPECIAL2,
330 OPC_MSUB = 0x04 | OPC_SPECIAL2,
331 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
332 /* Loongson 2F */
333 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
334 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
335 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
336 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
337 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
338 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
339 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
340 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
341 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
342 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
343 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
344 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
345 /* Misc */
346 OPC_CLZ = 0x20 | OPC_SPECIAL2,
347 OPC_CLO = 0x21 | OPC_SPECIAL2,
348 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
349 OPC_DCLO = 0x25 | OPC_SPECIAL2,
350 /* Special */
351 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
354 /* Special3 opcodes */
355 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
357 enum {
358 OPC_EXT = 0x00 | OPC_SPECIAL3,
359 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
360 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
361 OPC_DEXT = 0x03 | OPC_SPECIAL3,
362 OPC_INS = 0x04 | OPC_SPECIAL3,
363 OPC_DINSM = 0x05 | OPC_SPECIAL3,
364 OPC_DINSU = 0x06 | OPC_SPECIAL3,
365 OPC_DINS = 0x07 | OPC_SPECIAL3,
366 OPC_FORK = 0x08 | OPC_SPECIAL3,
367 OPC_YIELD = 0x09 | OPC_SPECIAL3,
368 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
369 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
370 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
371 OPC_GINV = 0x3D | OPC_SPECIAL3,
373 /* Loongson 2E */
374 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
375 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
376 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
377 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
378 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
379 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
380 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
381 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
382 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
383 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
384 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
385 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
387 /* MIPS DSP Load */
388 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
389 /* MIPS DSP Arithmetic */
390 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
391 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
392 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
393 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
394 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
395 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
396 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
397 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
398 /* MIPS DSP GPR-Based Shift Sub-class */
399 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
400 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
401 /* MIPS DSP Multiply Sub-class insns */
402 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
403 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
404 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
405 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
406 /* DSP Bit/Manipulation Sub-class */
407 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
408 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
409 /* MIPS DSP Append Sub-class */
410 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
411 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
412 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
413 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
414 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
416 /* EVA */
417 OPC_LWLE = 0x19 | OPC_SPECIAL3,
418 OPC_LWRE = 0x1A | OPC_SPECIAL3,
419 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
420 OPC_SBE = 0x1C | OPC_SPECIAL3,
421 OPC_SHE = 0x1D | OPC_SPECIAL3,
422 OPC_SCE = 0x1E | OPC_SPECIAL3,
423 OPC_SWE = 0x1F | OPC_SPECIAL3,
424 OPC_SWLE = 0x21 | OPC_SPECIAL3,
425 OPC_SWRE = 0x22 | OPC_SPECIAL3,
426 OPC_PREFE = 0x23 | OPC_SPECIAL3,
427 OPC_LBUE = 0x28 | OPC_SPECIAL3,
428 OPC_LHUE = 0x29 | OPC_SPECIAL3,
429 OPC_LBE = 0x2C | OPC_SPECIAL3,
430 OPC_LHE = 0x2D | OPC_SPECIAL3,
431 OPC_LLE = 0x2E | OPC_SPECIAL3,
432 OPC_LWE = 0x2F | OPC_SPECIAL3,
434 /* R6 */
435 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
436 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
437 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
438 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
439 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
440 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
443 /* Loongson EXT load/store quad word opcodes */
444 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
445 enum {
446 OPC_GSLQ = 0x0020 | OPC_LWC2,
447 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
448 OPC_GSSHFL = OPC_LWC2,
449 OPC_GSSQ = 0x0020 | OPC_SWC2,
450 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
451 OPC_GSSHFS = OPC_SWC2,
454 /* Loongson EXT shifted load/store opcodes */
455 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
456 enum {
457 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
458 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
459 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
460 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
461 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
462 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
463 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
464 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
467 /* Loongson EXT LDC2/SDC2 opcodes */
468 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
470 enum {
471 OPC_GSLBX = 0x0 | OPC_LDC2,
472 OPC_GSLHX = 0x1 | OPC_LDC2,
473 OPC_GSLWX = 0x2 | OPC_LDC2,
474 OPC_GSLDX = 0x3 | OPC_LDC2,
475 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
476 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
477 OPC_GSSBX = 0x0 | OPC_SDC2,
478 OPC_GSSHX = 0x1 | OPC_SDC2,
479 OPC_GSSWX = 0x2 | OPC_SDC2,
480 OPC_GSSDX = 0x3 | OPC_SDC2,
481 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
482 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
485 /* BSHFL opcodes */
486 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
488 enum {
489 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
490 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
491 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
492 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
493 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
494 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
495 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
496 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
499 /* DBSHFL opcodes */
500 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
502 enum {
503 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
504 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
505 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
506 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
507 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
508 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
509 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
510 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
511 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
512 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
513 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
516 /* MIPS DSP REGIMM opcodes */
517 enum {
518 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
519 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
522 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
523 /* MIPS DSP Load */
524 enum {
525 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
526 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
527 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
528 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
531 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
532 enum {
533 /* MIPS DSP Arithmetic Sub-class */
534 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
535 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
536 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
537 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
538 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
539 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
540 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
541 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
542 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
543 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
544 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
545 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
546 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
547 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
549 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
550 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
551 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
552 /* MIPS DSP Multiply Sub-class insns */
553 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
554 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
555 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
556 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
557 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
558 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
561 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
562 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
563 enum {
564 /* MIPS DSP Arithmetic Sub-class */
565 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
566 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
567 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
568 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
569 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
570 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
571 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
572 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
573 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
574 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
575 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
576 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
577 /* MIPS DSP Multiply Sub-class insns */
578 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
579 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
580 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
581 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
584 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
585 enum {
586 /* MIPS DSP Arithmetic Sub-class */
587 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
588 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
589 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
590 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
591 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
592 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
593 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
594 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
595 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
596 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
597 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
598 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
599 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
600 /* DSP Bit/Manipulation Sub-class */
601 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
608 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
609 enum {
610 /* MIPS DSP Arithmetic Sub-class */
611 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
612 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
613 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
614 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
615 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
616 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
617 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
618 /* DSP Compare-Pick Sub-class */
619 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
620 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
621 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
622 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
623 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
626 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
627 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
636 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
637 enum {
638 /* MIPS DSP GPR-Based Shift Sub-class */
639 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
640 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
641 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
642 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
643 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
644 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
645 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
646 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
647 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
648 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
649 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
650 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
651 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
663 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
664 enum {
665 /* MIPS DSP Multiply Sub-class insns */
666 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
667 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
668 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
669 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
670 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
671 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
672 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
673 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
674 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
675 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
676 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
677 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
678 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
679 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
680 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
683 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
690 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
691 enum {
692 /* DSP Bit/Manipulation Sub-class */
693 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
696 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
697 enum {
698 /* MIPS DSP Append Sub-class */
699 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
700 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
701 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
704 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
707 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
708 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
709 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
710 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
711 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
712 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
713 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
714 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
715 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
716 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
717 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
718 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
719 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
720 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
721 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
722 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
723 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
726 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
727 enum {
728 /* MIPS DSP Arithmetic Sub-class */
729 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
730 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
731 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
732 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
733 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
734 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
735 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
736 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
737 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
738 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
739 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
740 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
741 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
746 /* DSP Bit/Manipulation Sub-class */
747 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
755 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
756 enum {
757 /* MIPS DSP Multiply Sub-class insns */
758 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
759 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
760 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
761 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
762 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
763 /* MIPS DSP Arithmetic Sub-class */
764 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
765 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
766 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
767 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
768 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
769 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
770 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
771 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
772 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
773 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
774 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
775 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
776 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
777 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
778 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
779 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
780 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
781 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
782 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
783 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
784 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
787 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
788 enum {
789 /* DSP Compare-Pick Sub-class */
790 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
795 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
796 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
797 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
798 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
799 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
800 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
801 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
802 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
809 /* MIPS DSP Arithmetic Sub-class */
810 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
820 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
821 enum {
822 /* DSP Append Sub-class */
823 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
824 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
825 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
826 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
829 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
830 enum {
831 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
832 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
833 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
834 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
835 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
836 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
837 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
838 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
839 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
840 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
841 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
842 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
843 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
844 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
845 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
855 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
856 enum {
857 /* DSP Bit/Manipulation Sub-class */
858 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
861 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
862 enum {
863 /* MIPS DSP Multiply Sub-class insns */
864 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
867 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
868 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
869 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
870 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
871 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
872 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
873 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
874 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
875 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
876 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
892 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
893 enum {
894 /* MIPS DSP GPR-Based Shift Sub-class */
895 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
898 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
899 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
900 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
901 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
902 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
903 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
904 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
905 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
906 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
907 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
923 /* Coprocessor 0 (rs field) */
924 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
926 enum {
927 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
928 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
929 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
930 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
931 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
932 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
933 OPC_MFTR = (0x08 << 21) | OPC_CP0,
934 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
935 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
936 OPC_MTTR = (0x0C << 21) | OPC_CP0,
937 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
938 OPC_C0 = (0x10 << 21) | OPC_CP0,
939 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
940 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
941 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
942 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
943 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
944 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
945 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
946 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
947 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
948 OPC_C0_A = (0x1A << 21) | OPC_CP0,
949 OPC_C0_B = (0x1B << 21) | OPC_CP0,
950 OPC_C0_C = (0x1C << 21) | OPC_CP0,
951 OPC_C0_D = (0x1D << 21) | OPC_CP0,
952 OPC_C0_E = (0x1E << 21) | OPC_CP0,
953 OPC_C0_F = (0x1F << 21) | OPC_CP0,
956 /* MFMC0 opcodes */
957 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
959 enum {
960 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
961 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
962 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
963 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
964 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
965 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
966 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
967 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
970 /* Coprocessor 0 (with rs == C0) */
971 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
973 enum {
974 OPC_TLBR = 0x01 | OPC_C0,
975 OPC_TLBWI = 0x02 | OPC_C0,
976 OPC_TLBINV = 0x03 | OPC_C0,
977 OPC_TLBINVF = 0x04 | OPC_C0,
978 OPC_TLBWR = 0x06 | OPC_C0,
979 OPC_TLBP = 0x08 | OPC_C0,
980 OPC_RFE = 0x10 | OPC_C0,
981 OPC_ERET = 0x18 | OPC_C0,
982 OPC_DERET = 0x1F | OPC_C0,
983 OPC_WAIT = 0x20 | OPC_C0,
986 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
988 enum {
989 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
990 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
991 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
992 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
993 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
994 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
995 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
996 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
997 OPC_BC2 = (0x08 << 21) | OPC_CP2,
998 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
999 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1002 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1004 enum {
1005 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1006 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1007 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1008 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1009 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1010 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1011 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1012 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1014 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1015 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1016 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1017 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1018 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1019 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1020 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1021 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1023 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1024 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1025 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1026 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1027 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1028 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1029 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1030 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1032 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1033 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1034 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1035 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1036 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1037 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1038 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1039 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1041 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1042 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1043 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1044 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1045 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1046 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1048 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1049 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1050 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1051 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1052 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1053 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1055 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1056 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1057 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1058 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1059 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1060 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1062 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1063 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1064 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1065 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1066 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1067 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1069 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1070 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1071 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1072 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1073 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1074 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1076 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1077 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1078 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1079 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1080 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1081 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1083 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1084 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1085 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1086 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1087 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1088 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1090 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1091 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1092 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1093 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1094 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1095 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1099 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1101 enum {
1102 OPC_LWXC1 = 0x00 | OPC_CP3,
1103 OPC_LDXC1 = 0x01 | OPC_CP3,
1104 OPC_LUXC1 = 0x05 | OPC_CP3,
1105 OPC_SWXC1 = 0x08 | OPC_CP3,
1106 OPC_SDXC1 = 0x09 | OPC_CP3,
1107 OPC_SUXC1 = 0x0D | OPC_CP3,
1108 OPC_PREFX = 0x0F | OPC_CP3,
1109 OPC_ALNV_PS = 0x1E | OPC_CP3,
1110 OPC_MADD_S = 0x20 | OPC_CP3,
1111 OPC_MADD_D = 0x21 | OPC_CP3,
1112 OPC_MADD_PS = 0x26 | OPC_CP3,
1113 OPC_MSUB_S = 0x28 | OPC_CP3,
1114 OPC_MSUB_D = 0x29 | OPC_CP3,
1115 OPC_MSUB_PS = 0x2E | OPC_CP3,
1116 OPC_NMADD_S = 0x30 | OPC_CP3,
1117 OPC_NMADD_D = 0x31 | OPC_CP3,
1118 OPC_NMADD_PS = 0x36 | OPC_CP3,
1119 OPC_NMSUB_S = 0x38 | OPC_CP3,
1120 OPC_NMSUB_D = 0x39 | OPC_CP3,
1121 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1125 * MMI (MultiMedia Instruction) encodings
1126 * ======================================
1128 * MMI instructions encoding table keys:
1130 * * This code is reserved for future use. An attempt to execute it
1131 * causes a Reserved Instruction exception.
1132 * % This code indicates an instruction class. The instruction word
1133 * must be further decoded by examining additional tables that show
1134 * the values for other instruction fields.
1135 * # This code is reserved for the unsupported instructions DMULT,
1136 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1137 * to execute it causes a Reserved Instruction exception.
1139 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1141 * 31 26 0
1142 * +--------+----------------------------------------+
1143 * | opcode | |
1144 * +--------+----------------------------------------+
1146 * opcode bits 28..26
1147 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1148 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1149 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1150 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1151 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1152 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1153 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1154 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1155 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1156 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1157 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1160 enum {
1161 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1162 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1166 * MMI instructions with opcode field = MMI:
1168 * 31 26 5 0
1169 * +--------+-------------------------------+--------+
1170 * | MMI | |function|
1171 * +--------+-------------------------------+--------+
1173 * function bits 2..0
1174 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1175 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1176 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1177 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1178 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1179 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1180 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1181 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1182 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1183 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1184 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1187 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1188 enum {
1189 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1190 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1191 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1192 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1193 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1194 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1195 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1196 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1199 /* global register indices */
1200 TCGv cpu_gpr[32], cpu_PC;
1202 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1203 * and the upper halves in cpu_gpr_hi[].
1205 TCGv_i64 cpu_gpr_hi[32];
1206 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1207 static TCGv cpu_dspctrl, btarget;
1208 TCGv bcond;
1209 static TCGv cpu_lladdr, cpu_llval;
1210 static TCGv_i32 hflags;
1211 TCGv_i32 fpu_fcr0, fpu_fcr31;
1212 TCGv_i64 fpu_f64[32];
1214 #include "exec/gen-icount.h"
1216 #define gen_helper_0e1i(name, arg1, arg2) do { \
1217 gen_helper_##name(cpu_env, arg1, tcg_constant_i32(arg2)); \
1218 } while (0)
1220 #define gen_helper_1e0i(name, ret, arg1) do { \
1221 gen_helper_##name(ret, cpu_env, tcg_constant_i32(arg1)); \
1222 } while (0)
1224 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1225 gen_helper_##name(cpu_env, arg1, arg2, tcg_constant_i32(arg3));\
1226 } while (0)
1228 #define DISAS_STOP DISAS_TARGET_0
1229 #define DISAS_EXIT DISAS_TARGET_1
1231 static const char regnames_HI[][4] = {
1232 "HI0", "HI1", "HI2", "HI3",
1235 static const char regnames_LO[][4] = {
1236 "LO0", "LO1", "LO2", "LO3",
1239 /* General purpose registers moves. */
1240 void gen_load_gpr(TCGv t, int reg)
1242 if (reg == 0) {
1243 tcg_gen_movi_tl(t, 0);
1244 } else {
1245 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1249 void gen_store_gpr(TCGv t, int reg)
1251 if (reg != 0) {
1252 tcg_gen_mov_tl(cpu_gpr[reg], t);
1256 #if defined(TARGET_MIPS64)
1257 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1259 if (reg == 0) {
1260 tcg_gen_movi_i64(t, 0);
1261 } else {
1262 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1266 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1268 if (reg != 0) {
1269 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1272 #endif /* TARGET_MIPS64 */
1274 /* Moves to/from shadow registers. */
1275 static inline void gen_load_srsgpr(int from, int to)
1277 TCGv t0 = tcg_temp_new();
1279 if (from == 0) {
1280 tcg_gen_movi_tl(t0, 0);
1281 } else {
1282 TCGv_i32 t2 = tcg_temp_new_i32();
1283 TCGv_ptr addr = tcg_temp_new_ptr();
1285 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1286 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1287 tcg_gen_andi_i32(t2, t2, 0xf);
1288 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1289 tcg_gen_ext_i32_ptr(addr, t2);
1290 tcg_gen_add_ptr(addr, cpu_env, addr);
1292 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1293 tcg_temp_free_ptr(addr);
1294 tcg_temp_free_i32(t2);
1296 gen_store_gpr(t0, to);
1297 tcg_temp_free(t0);
1300 static inline void gen_store_srsgpr(int from, int to)
1302 if (to != 0) {
1303 TCGv t0 = tcg_temp_new();
1304 TCGv_i32 t2 = tcg_temp_new_i32();
1305 TCGv_ptr addr = tcg_temp_new_ptr();
1307 gen_load_gpr(t0, from);
1308 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1309 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1310 tcg_gen_andi_i32(t2, t2, 0xf);
1311 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1312 tcg_gen_ext_i32_ptr(addr, t2);
1313 tcg_gen_add_ptr(addr, cpu_env, addr);
1315 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1316 tcg_temp_free_ptr(addr);
1317 tcg_temp_free_i32(t2);
1318 tcg_temp_free(t0);
1322 /* Tests */
1323 static inline void gen_save_pc(target_ulong pc)
1325 tcg_gen_movi_tl(cpu_PC, pc);
1328 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1330 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1331 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1332 gen_save_pc(ctx->base.pc_next);
1333 ctx->saved_pc = ctx->base.pc_next;
1335 if (ctx->hflags != ctx->saved_hflags) {
1336 tcg_gen_movi_i32(hflags, ctx->hflags);
1337 ctx->saved_hflags = ctx->hflags;
1338 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1339 case MIPS_HFLAG_BR:
1340 break;
1341 case MIPS_HFLAG_BC:
1342 case MIPS_HFLAG_BL:
1343 case MIPS_HFLAG_B:
1344 tcg_gen_movi_tl(btarget, ctx->btarget);
1345 break;
1350 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1352 ctx->saved_hflags = ctx->hflags;
1353 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1354 case MIPS_HFLAG_BR:
1355 break;
1356 case MIPS_HFLAG_BC:
1357 case MIPS_HFLAG_BL:
1358 case MIPS_HFLAG_B:
1359 ctx->btarget = env->btarget;
1360 break;
1364 void generate_exception_err(DisasContext *ctx, int excp, int err)
1366 TCGv_i32 texcp = tcg_const_i32(excp);
1367 TCGv_i32 terr = tcg_const_i32(err);
1368 save_cpu_state(ctx, 1);
1369 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1370 tcg_temp_free_i32(terr);
1371 tcg_temp_free_i32(texcp);
1372 ctx->base.is_jmp = DISAS_NORETURN;
1375 void generate_exception(DisasContext *ctx, int excp)
1377 gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
1380 void generate_exception_end(DisasContext *ctx, int excp)
1382 generate_exception_err(ctx, excp, 0);
1385 void gen_reserved_instruction(DisasContext *ctx)
1387 generate_exception_end(ctx, EXCP_RI);
1390 /* Floating point register moves. */
1391 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1393 if (ctx->hflags & MIPS_HFLAG_FRE) {
1394 generate_exception(ctx, EXCP_RI);
1396 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1399 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1401 TCGv_i64 t64;
1402 if (ctx->hflags & MIPS_HFLAG_FRE) {
1403 generate_exception(ctx, EXCP_RI);
1405 t64 = tcg_temp_new_i64();
1406 tcg_gen_extu_i32_i64(t64, t);
1407 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1408 tcg_temp_free_i64(t64);
1411 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1413 if (ctx->hflags & MIPS_HFLAG_F64) {
1414 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1415 } else {
1416 gen_load_fpr32(ctx, t, reg | 1);
1420 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1422 if (ctx->hflags & MIPS_HFLAG_F64) {
1423 TCGv_i64 t64 = tcg_temp_new_i64();
1424 tcg_gen_extu_i32_i64(t64, t);
1425 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1426 tcg_temp_free_i64(t64);
1427 } else {
1428 gen_store_fpr32(ctx, t, reg | 1);
1432 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1434 if (ctx->hflags & MIPS_HFLAG_F64) {
1435 tcg_gen_mov_i64(t, fpu_f64[reg]);
1436 } else {
1437 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1441 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1443 if (ctx->hflags & MIPS_HFLAG_F64) {
1444 tcg_gen_mov_i64(fpu_f64[reg], t);
1445 } else {
1446 TCGv_i64 t0;
1447 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1448 t0 = tcg_temp_new_i64();
1449 tcg_gen_shri_i64(t0, t, 32);
1450 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1451 tcg_temp_free_i64(t0);
1455 int get_fp_bit(int cc)
1457 if (cc) {
1458 return 24 + cc;
1459 } else {
1460 return 23;
1464 /* Addresses computation */
1465 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1467 tcg_gen_add_tl(ret, arg0, arg1);
1469 #if defined(TARGET_MIPS64)
1470 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1471 tcg_gen_ext32s_i64(ret, ret);
1473 #endif
1476 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1477 target_long ofs)
1479 tcg_gen_addi_tl(ret, base, ofs);
1481 #if defined(TARGET_MIPS64)
1482 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1483 tcg_gen_ext32s_i64(ret, ret);
1485 #endif
1488 /* Addresses computation (translation time) */
1489 static target_long addr_add(DisasContext *ctx, target_long base,
1490 target_long offset)
1492 target_long sum = base + offset;
1494 #if defined(TARGET_MIPS64)
1495 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1496 sum = (int32_t)sum;
1498 #endif
1499 return sum;
1502 /* Sign-extract the low 32-bits to a target_long. */
1503 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1505 #if defined(TARGET_MIPS64)
1506 tcg_gen_ext32s_i64(ret, arg);
1507 #else
1508 tcg_gen_extrl_i64_i32(ret, arg);
1509 #endif
1512 /* Sign-extract the high 32-bits to a target_long. */
1513 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1515 #if defined(TARGET_MIPS64)
1516 tcg_gen_sari_i64(ret, arg, 32);
1517 #else
1518 tcg_gen_extrh_i64_i32(ret, arg);
1519 #endif
1522 bool check_cp0_enabled(DisasContext *ctx)
1524 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1525 generate_exception_end(ctx, EXCP_CpU);
1526 return false;
1528 return true;
1531 void check_cp1_enabled(DisasContext *ctx)
1533 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1534 generate_exception_err(ctx, EXCP_CpU, 1);
1539 * Verify that the processor is running with COP1X instructions enabled.
1540 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1541 * opcode tables.
1543 void check_cop1x(DisasContext *ctx)
1545 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1546 gen_reserved_instruction(ctx);
1551 * Verify that the processor is running with 64-bit floating-point
1552 * operations enabled.
1554 void check_cp1_64bitmode(DisasContext *ctx)
1556 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
1557 gen_reserved_instruction(ctx);
1562 * Verify if floating point register is valid; an operation is not defined
1563 * if bit 0 of any register specification is set and the FR bit in the
1564 * Status register equals zero, since the register numbers specify an
1565 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1566 * in the Status register equals one, both even and odd register numbers
1567 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1569 * Multiple 64 bit wide registers can be checked by calling
1570 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1572 void check_cp1_registers(DisasContext *ctx, int regs)
1574 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1575 gen_reserved_instruction(ctx);
1580 * Verify that the processor is running with DSP instructions enabled.
1581 * This is enabled by CP0 Status register MX(24) bit.
1583 static inline void check_dsp(DisasContext *ctx)
1585 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1586 if (ctx->insn_flags & ASE_DSP) {
1587 generate_exception_end(ctx, EXCP_DSPDIS);
1588 } else {
1589 gen_reserved_instruction(ctx);
1594 static inline void check_dsp_r2(DisasContext *ctx)
1596 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
1597 if (ctx->insn_flags & ASE_DSP) {
1598 generate_exception_end(ctx, EXCP_DSPDIS);
1599 } else {
1600 gen_reserved_instruction(ctx);
1605 static inline void check_dsp_r3(DisasContext *ctx)
1607 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
1608 if (ctx->insn_flags & ASE_DSP) {
1609 generate_exception_end(ctx, EXCP_DSPDIS);
1610 } else {
1611 gen_reserved_instruction(ctx);
1617 * This code generates a "reserved instruction" exception if the
1618 * CPU does not support the instruction set corresponding to flags.
1620 void check_insn(DisasContext *ctx, uint64_t flags)
1622 if (unlikely(!(ctx->insn_flags & flags))) {
1623 gen_reserved_instruction(ctx);
1628 * This code generates a "reserved instruction" exception if the
1629 * CPU has corresponding flag set which indicates that the instruction
1630 * has been removed.
1632 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
1634 if (unlikely(ctx->insn_flags & flags)) {
1635 gen_reserved_instruction(ctx);
1640 * The Linux kernel traps certain reserved instruction exceptions to
1641 * emulate the corresponding instructions. QEMU is the kernel in user
1642 * mode, so those traps are emulated by accepting the instructions.
1644 * A reserved instruction exception is generated for flagged CPUs if
1645 * QEMU runs in system mode.
1647 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1649 #ifndef CONFIG_USER_ONLY
1650 check_insn_opc_removed(ctx, flags);
1651 #endif
1655 * This code generates a "reserved instruction" exception if the
1656 * CPU does not support 64-bit paired-single (PS) floating point data type.
1658 static inline void check_ps(DisasContext *ctx)
1660 if (unlikely(!ctx->ps)) {
1661 generate_exception(ctx, EXCP_RI);
1663 check_cp1_64bitmode(ctx);
1667 * This code generates a "reserved instruction" exception if cpu is not
1668 * 64-bit or 64-bit instructions are not enabled.
1670 void check_mips_64(DisasContext *ctx)
1672 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
1673 gen_reserved_instruction(ctx);
1677 #ifndef CONFIG_USER_ONLY
1678 static inline void check_mvh(DisasContext *ctx)
1680 if (unlikely(!ctx->mvh)) {
1681 generate_exception(ctx, EXCP_RI);
1684 #endif
1687 * This code generates a "reserved instruction" exception if the
1688 * Config5 XNP bit is set.
1690 static inline void check_xnp(DisasContext *ctx)
1692 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1693 gen_reserved_instruction(ctx);
1697 #ifndef CONFIG_USER_ONLY
1699 * This code generates a "reserved instruction" exception if the
1700 * Config3 PW bit is NOT set.
1702 static inline void check_pw(DisasContext *ctx)
1704 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
1705 gen_reserved_instruction(ctx);
1708 #endif
1711 * This code generates a "reserved instruction" exception if the
1712 * Config3 MT bit is NOT set.
1714 static inline void check_mt(DisasContext *ctx)
1716 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1717 gen_reserved_instruction(ctx);
1721 #ifndef CONFIG_USER_ONLY
1723 * This code generates a "coprocessor unusable" exception if CP0 is not
1724 * available, and, if that is not the case, generates a "reserved instruction"
1725 * exception if the Config5 MT bit is NOT set. This is needed for availability
1726 * control of some of MT ASE instructions.
1728 static inline void check_cp0_mt(DisasContext *ctx)
1730 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1731 generate_exception_end(ctx, EXCP_CpU);
1732 } else {
1733 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1734 gen_reserved_instruction(ctx);
1738 #endif
1741 * This code generates a "reserved instruction" exception if the
1742 * Config5 NMS bit is set.
1744 static inline void check_nms(DisasContext *ctx)
1746 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1747 gen_reserved_instruction(ctx);
1752 * This code generates a "reserved instruction" exception if the
1753 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1754 * Config2 TL, and Config5 L2C are unset.
1756 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1758 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1759 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1760 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1761 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1762 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1763 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
1764 gen_reserved_instruction(ctx);
1769 * This code generates a "reserved instruction" exception if the
1770 * Config5 EVA bit is NOT set.
1772 static inline void check_eva(DisasContext *ctx)
1774 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
1775 gen_reserved_instruction(ctx);
1781 * Define small wrappers for gen_load_fpr* so that we have a uniform
1782 * calling interface for 32 and 64-bit FPRs. No sense in changing
1783 * all callers for gen_load_fpr32 when we need the CTX parameter for
1784 * this one use.
1786 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1787 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1788 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1789 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1790 int ft, int fs, int cc) \
1792 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1793 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
1794 switch (ifmt) { \
1795 case FMT_PS: \
1796 check_ps(ctx); \
1797 break; \
1798 case FMT_D: \
1799 if (abs) { \
1800 check_cop1x(ctx); \
1802 check_cp1_registers(ctx, fs | ft); \
1803 break; \
1804 case FMT_S: \
1805 if (abs) { \
1806 check_cop1x(ctx); \
1808 break; \
1810 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1811 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
1812 switch (n) { \
1813 case 0: \
1814 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1815 break; \
1816 case 1: \
1817 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1818 break; \
1819 case 2: \
1820 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1821 break; \
1822 case 3: \
1823 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1824 break; \
1825 case 4: \
1826 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1827 break; \
1828 case 5: \
1829 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1830 break; \
1831 case 6: \
1832 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1833 break; \
1834 case 7: \
1835 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1836 break; \
1837 case 8: \
1838 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1839 break; \
1840 case 9: \
1841 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1842 break; \
1843 case 10: \
1844 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1845 break; \
1846 case 11: \
1847 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1848 break; \
1849 case 12: \
1850 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1851 break; \
1852 case 13: \
1853 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1854 break; \
1855 case 14: \
1856 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1857 break; \
1858 case 15: \
1859 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1860 break; \
1861 default: \
1862 abort(); \
1864 tcg_temp_free_i##bits(fp0); \
1865 tcg_temp_free_i##bits(fp1); \
1868 FOP_CONDS(, 0, d, FMT_D, 64)
1869 FOP_CONDS(abs, 1, d, FMT_D, 64)
1870 FOP_CONDS(, 0, s, FMT_S, 32)
1871 FOP_CONDS(abs, 1, s, FMT_S, 32)
1872 FOP_CONDS(, 0, ps, FMT_PS, 64)
1873 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1874 #undef FOP_CONDS
1876 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1877 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
1878 int ft, int fs, int fd) \
1880 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1881 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1882 if (ifmt == FMT_D) { \
1883 check_cp1_registers(ctx, fs | ft | fd); \
1885 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1886 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1887 switch (n) { \
1888 case 0: \
1889 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1890 break; \
1891 case 1: \
1892 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1893 break; \
1894 case 2: \
1895 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1896 break; \
1897 case 3: \
1898 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1899 break; \
1900 case 4: \
1901 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1902 break; \
1903 case 5: \
1904 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1905 break; \
1906 case 6: \
1907 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1908 break; \
1909 case 7: \
1910 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1911 break; \
1912 case 8: \
1913 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1914 break; \
1915 case 9: \
1916 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1917 break; \
1918 case 10: \
1919 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1920 break; \
1921 case 11: \
1922 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1923 break; \
1924 case 12: \
1925 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1926 break; \
1927 case 13: \
1928 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1929 break; \
1930 case 14: \
1931 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1932 break; \
1933 case 15: \
1934 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1935 break; \
1936 case 17: \
1937 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1938 break; \
1939 case 18: \
1940 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1941 break; \
1942 case 19: \
1943 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1944 break; \
1945 case 25: \
1946 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1947 break; \
1948 case 26: \
1949 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1950 break; \
1951 case 27: \
1952 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1953 break; \
1954 default: \
1955 abort(); \
1957 STORE; \
1958 tcg_temp_free_i ## bits(fp0); \
1959 tcg_temp_free_i ## bits(fp1); \
1962 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1963 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
1964 #undef FOP_CONDNS
1965 #undef gen_ldcmp_fpr32
1966 #undef gen_ldcmp_fpr64
1968 /* load/store instructions. */
1969 #ifdef CONFIG_USER_ONLY
1970 #define OP_LD_ATOMIC(insn, fname) \
1971 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
1972 DisasContext *ctx) \
1974 TCGv t0 = tcg_temp_new(); \
1975 tcg_gen_mov_tl(t0, arg1); \
1976 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1977 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1978 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1979 tcg_temp_free(t0); \
1981 #else
1982 #define OP_LD_ATOMIC(insn, fname) \
1983 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
1984 DisasContext *ctx) \
1986 gen_helper_##insn(ret, cpu_env, arg1, tcg_constant_i32(mem_idx)); \
1988 #endif
1989 OP_LD_ATOMIC(ll, ld32s);
1990 #if defined(TARGET_MIPS64)
1991 OP_LD_ATOMIC(lld, ld64);
1992 #endif
1993 #undef OP_LD_ATOMIC
1995 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
1997 if (base == 0) {
1998 tcg_gen_movi_tl(addr, offset);
1999 } else if (offset == 0) {
2000 gen_load_gpr(addr, base);
2001 } else {
2002 tcg_gen_movi_tl(addr, offset);
2003 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2007 static target_ulong pc_relative_pc(DisasContext *ctx)
2009 target_ulong pc = ctx->base.pc_next;
2011 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2012 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2014 pc -= branch_bytes;
2017 pc &= ~(target_ulong)3;
2018 return pc;
2021 /* Load */
2022 static void gen_ld(DisasContext *ctx, uint32_t opc,
2023 int rt, int base, int offset)
2025 TCGv t0, t1, t2;
2026 int mem_idx = ctx->mem_idx;
2028 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2029 INSN_LOONGSON3A)) {
2031 * Loongson CPU uses a load to zero register for prefetch.
2032 * We emulate it as a NOP. On other CPU we must perform the
2033 * actual memory access.
2035 return;
2038 t0 = tcg_temp_new();
2039 gen_base_offset_addr(ctx, t0, base, offset);
2041 switch (opc) {
2042 #if defined(TARGET_MIPS64)
2043 case OPC_LWU:
2044 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2045 ctx->default_tcg_memop_mask);
2046 gen_store_gpr(t0, rt);
2047 break;
2048 case OPC_LD:
2049 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2050 ctx->default_tcg_memop_mask);
2051 gen_store_gpr(t0, rt);
2052 break;
2053 case OPC_LLD:
2054 case R6_OPC_LLD:
2055 op_ld_lld(t0, t0, mem_idx, ctx);
2056 gen_store_gpr(t0, rt);
2057 break;
2058 case OPC_LDL:
2059 t1 = tcg_temp_new();
2061 * Do a byte access to possibly trigger a page
2062 * fault with the unaligned address.
2064 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2065 tcg_gen_andi_tl(t1, t0, 7);
2066 #ifndef TARGET_WORDS_BIGENDIAN
2067 tcg_gen_xori_tl(t1, t1, 7);
2068 #endif
2069 tcg_gen_shli_tl(t1, t1, 3);
2070 tcg_gen_andi_tl(t0, t0, ~7);
2071 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2072 tcg_gen_shl_tl(t0, t0, t1);
2073 t2 = tcg_const_tl(-1);
2074 tcg_gen_shl_tl(t2, t2, t1);
2075 gen_load_gpr(t1, rt);
2076 tcg_gen_andc_tl(t1, t1, t2);
2077 tcg_temp_free(t2);
2078 tcg_gen_or_tl(t0, t0, t1);
2079 tcg_temp_free(t1);
2080 gen_store_gpr(t0, rt);
2081 break;
2082 case OPC_LDR:
2083 t1 = tcg_temp_new();
2085 * Do a byte access to possibly trigger a page
2086 * fault with the unaligned address.
2088 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2089 tcg_gen_andi_tl(t1, t0, 7);
2090 #ifdef TARGET_WORDS_BIGENDIAN
2091 tcg_gen_xori_tl(t1, t1, 7);
2092 #endif
2093 tcg_gen_shli_tl(t1, t1, 3);
2094 tcg_gen_andi_tl(t0, t0, ~7);
2095 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2096 tcg_gen_shr_tl(t0, t0, t1);
2097 tcg_gen_xori_tl(t1, t1, 63);
2098 t2 = tcg_const_tl(0xfffffffffffffffeull);
2099 tcg_gen_shl_tl(t2, t2, t1);
2100 gen_load_gpr(t1, rt);
2101 tcg_gen_and_tl(t1, t1, t2);
2102 tcg_temp_free(t2);
2103 tcg_gen_or_tl(t0, t0, t1);
2104 tcg_temp_free(t1);
2105 gen_store_gpr(t0, rt);
2106 break;
2107 case OPC_LDPC:
2108 t1 = tcg_const_tl(pc_relative_pc(ctx));
2109 gen_op_addr_add(ctx, t0, t0, t1);
2110 tcg_temp_free(t1);
2111 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2112 gen_store_gpr(t0, rt);
2113 break;
2114 #endif
2115 case OPC_LWPC:
2116 t1 = tcg_const_tl(pc_relative_pc(ctx));
2117 gen_op_addr_add(ctx, t0, t0, t1);
2118 tcg_temp_free(t1);
2119 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2120 gen_store_gpr(t0, rt);
2121 break;
2122 case OPC_LWE:
2123 mem_idx = MIPS_HFLAG_UM;
2124 /* fall through */
2125 case OPC_LW:
2126 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2127 ctx->default_tcg_memop_mask);
2128 gen_store_gpr(t0, rt);
2129 break;
2130 case OPC_LHE:
2131 mem_idx = MIPS_HFLAG_UM;
2132 /* fall through */
2133 case OPC_LH:
2134 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2135 ctx->default_tcg_memop_mask);
2136 gen_store_gpr(t0, rt);
2137 break;
2138 case OPC_LHUE:
2139 mem_idx = MIPS_HFLAG_UM;
2140 /* fall through */
2141 case OPC_LHU:
2142 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2143 ctx->default_tcg_memop_mask);
2144 gen_store_gpr(t0, rt);
2145 break;
2146 case OPC_LBE:
2147 mem_idx = MIPS_HFLAG_UM;
2148 /* fall through */
2149 case OPC_LB:
2150 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2151 gen_store_gpr(t0, rt);
2152 break;
2153 case OPC_LBUE:
2154 mem_idx = MIPS_HFLAG_UM;
2155 /* fall through */
2156 case OPC_LBU:
2157 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2158 gen_store_gpr(t0, rt);
2159 break;
2160 case OPC_LWLE:
2161 mem_idx = MIPS_HFLAG_UM;
2162 /* fall through */
2163 case OPC_LWL:
2164 t1 = tcg_temp_new();
2166 * Do a byte access to possibly trigger a page
2167 * fault with the unaligned address.
2169 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2170 tcg_gen_andi_tl(t1, t0, 3);
2171 #ifndef TARGET_WORDS_BIGENDIAN
2172 tcg_gen_xori_tl(t1, t1, 3);
2173 #endif
2174 tcg_gen_shli_tl(t1, t1, 3);
2175 tcg_gen_andi_tl(t0, t0, ~3);
2176 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2177 tcg_gen_shl_tl(t0, t0, t1);
2178 t2 = tcg_const_tl(-1);
2179 tcg_gen_shl_tl(t2, t2, t1);
2180 gen_load_gpr(t1, rt);
2181 tcg_gen_andc_tl(t1, t1, t2);
2182 tcg_temp_free(t2);
2183 tcg_gen_or_tl(t0, t0, t1);
2184 tcg_temp_free(t1);
2185 tcg_gen_ext32s_tl(t0, t0);
2186 gen_store_gpr(t0, rt);
2187 break;
2188 case OPC_LWRE:
2189 mem_idx = MIPS_HFLAG_UM;
2190 /* fall through */
2191 case OPC_LWR:
2192 t1 = tcg_temp_new();
2194 * Do a byte access to possibly trigger a page
2195 * fault with the unaligned address.
2197 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2198 tcg_gen_andi_tl(t1, t0, 3);
2199 #ifdef TARGET_WORDS_BIGENDIAN
2200 tcg_gen_xori_tl(t1, t1, 3);
2201 #endif
2202 tcg_gen_shli_tl(t1, t1, 3);
2203 tcg_gen_andi_tl(t0, t0, ~3);
2204 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2205 tcg_gen_shr_tl(t0, t0, t1);
2206 tcg_gen_xori_tl(t1, t1, 31);
2207 t2 = tcg_const_tl(0xfffffffeull);
2208 tcg_gen_shl_tl(t2, t2, t1);
2209 gen_load_gpr(t1, rt);
2210 tcg_gen_and_tl(t1, t1, t2);
2211 tcg_temp_free(t2);
2212 tcg_gen_or_tl(t0, t0, t1);
2213 tcg_temp_free(t1);
2214 tcg_gen_ext32s_tl(t0, t0);
2215 gen_store_gpr(t0, rt);
2216 break;
2217 case OPC_LLE:
2218 mem_idx = MIPS_HFLAG_UM;
2219 /* fall through */
2220 case OPC_LL:
2221 case R6_OPC_LL:
2222 op_ld_ll(t0, t0, mem_idx, ctx);
2223 gen_store_gpr(t0, rt);
2224 break;
2226 tcg_temp_free(t0);
2229 /* Store */
2230 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2231 int base, int offset)
2233 TCGv t0 = tcg_temp_new();
2234 TCGv t1 = tcg_temp_new();
2235 int mem_idx = ctx->mem_idx;
2237 gen_base_offset_addr(ctx, t0, base, offset);
2238 gen_load_gpr(t1, rt);
2239 switch (opc) {
2240 #if defined(TARGET_MIPS64)
2241 case OPC_SD:
2242 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2243 ctx->default_tcg_memop_mask);
2244 break;
2245 case OPC_SDL:
2246 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2247 break;
2248 case OPC_SDR:
2249 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2250 break;
2251 #endif
2252 case OPC_SWE:
2253 mem_idx = MIPS_HFLAG_UM;
2254 /* fall through */
2255 case OPC_SW:
2256 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2257 ctx->default_tcg_memop_mask);
2258 break;
2259 case OPC_SHE:
2260 mem_idx = MIPS_HFLAG_UM;
2261 /* fall through */
2262 case OPC_SH:
2263 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2264 ctx->default_tcg_memop_mask);
2265 break;
2266 case OPC_SBE:
2267 mem_idx = MIPS_HFLAG_UM;
2268 /* fall through */
2269 case OPC_SB:
2270 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2271 break;
2272 case OPC_SWLE:
2273 mem_idx = MIPS_HFLAG_UM;
2274 /* fall through */
2275 case OPC_SWL:
2276 gen_helper_0e2i(swl, t1, t0, mem_idx);
2277 break;
2278 case OPC_SWRE:
2279 mem_idx = MIPS_HFLAG_UM;
2280 /* fall through */
2281 case OPC_SWR:
2282 gen_helper_0e2i(swr, t1, t0, mem_idx);
2283 break;
2285 tcg_temp_free(t0);
2286 tcg_temp_free(t1);
2290 /* Store conditional */
2291 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2292 MemOp tcg_mo, bool eva)
2294 TCGv addr, t0, val;
2295 TCGLabel *l1 = gen_new_label();
2296 TCGLabel *done = gen_new_label();
2298 t0 = tcg_temp_new();
2299 addr = tcg_temp_new();
2300 /* compare the address against that of the preceding LL */
2301 gen_base_offset_addr(ctx, addr, base, offset);
2302 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2303 tcg_temp_free(addr);
2304 tcg_gen_movi_tl(t0, 0);
2305 gen_store_gpr(t0, rt);
2306 tcg_gen_br(done);
2308 gen_set_label(l1);
2309 /* generate cmpxchg */
2310 val = tcg_temp_new();
2311 gen_load_gpr(val, rt);
2312 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2313 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2314 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2315 gen_store_gpr(t0, rt);
2316 tcg_temp_free(val);
2318 gen_set_label(done);
2319 tcg_temp_free(t0);
2322 /* Load and store */
2323 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2324 TCGv t0)
2327 * Don't do NOP if destination is zero: we must perform the actual
2328 * memory access.
2330 switch (opc) {
2331 case OPC_LWC1:
2333 TCGv_i32 fp0 = tcg_temp_new_i32();
2334 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2335 ctx->default_tcg_memop_mask);
2336 gen_store_fpr32(ctx, fp0, ft);
2337 tcg_temp_free_i32(fp0);
2339 break;
2340 case OPC_SWC1:
2342 TCGv_i32 fp0 = tcg_temp_new_i32();
2343 gen_load_fpr32(ctx, fp0, ft);
2344 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2345 ctx->default_tcg_memop_mask);
2346 tcg_temp_free_i32(fp0);
2348 break;
2349 case OPC_LDC1:
2351 TCGv_i64 fp0 = tcg_temp_new_i64();
2352 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2353 ctx->default_tcg_memop_mask);
2354 gen_store_fpr64(ctx, fp0, ft);
2355 tcg_temp_free_i64(fp0);
2357 break;
2358 case OPC_SDC1:
2360 TCGv_i64 fp0 = tcg_temp_new_i64();
2361 gen_load_fpr64(ctx, fp0, ft);
2362 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2363 ctx->default_tcg_memop_mask);
2364 tcg_temp_free_i64(fp0);
2366 break;
2367 default:
2368 MIPS_INVAL("flt_ldst");
2369 gen_reserved_instruction(ctx);
2370 break;
2374 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2375 int rs, int16_t imm)
2377 TCGv t0 = tcg_temp_new();
2379 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2380 check_cp1_enabled(ctx);
2381 switch (op) {
2382 case OPC_LDC1:
2383 case OPC_SDC1:
2384 check_insn(ctx, ISA_MIPS2);
2385 /* Fallthrough */
2386 default:
2387 gen_base_offset_addr(ctx, t0, rs, imm);
2388 gen_flt_ldst(ctx, op, rt, t0);
2390 } else {
2391 generate_exception_err(ctx, EXCP_CpU, 1);
2393 tcg_temp_free(t0);
2396 /* Arithmetic with immediate operand */
2397 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2398 int rt, int rs, int imm)
2400 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2402 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2404 * If no destination, treat it as a NOP.
2405 * For addi, we must generate the overflow exception when needed.
2407 return;
2409 switch (opc) {
2410 case OPC_ADDI:
2412 TCGv t0 = tcg_temp_local_new();
2413 TCGv t1 = tcg_temp_new();
2414 TCGv t2 = tcg_temp_new();
2415 TCGLabel *l1 = gen_new_label();
2417 gen_load_gpr(t1, rs);
2418 tcg_gen_addi_tl(t0, t1, uimm);
2419 tcg_gen_ext32s_tl(t0, t0);
2421 tcg_gen_xori_tl(t1, t1, ~uimm);
2422 tcg_gen_xori_tl(t2, t0, uimm);
2423 tcg_gen_and_tl(t1, t1, t2);
2424 tcg_temp_free(t2);
2425 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2426 tcg_temp_free(t1);
2427 /* operands of same sign, result different sign */
2428 generate_exception(ctx, EXCP_OVERFLOW);
2429 gen_set_label(l1);
2430 tcg_gen_ext32s_tl(t0, t0);
2431 gen_store_gpr(t0, rt);
2432 tcg_temp_free(t0);
2434 break;
2435 case OPC_ADDIU:
2436 if (rs != 0) {
2437 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2438 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2439 } else {
2440 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2442 break;
2443 #if defined(TARGET_MIPS64)
2444 case OPC_DADDI:
2446 TCGv t0 = tcg_temp_local_new();
2447 TCGv t1 = tcg_temp_new();
2448 TCGv t2 = tcg_temp_new();
2449 TCGLabel *l1 = gen_new_label();
2451 gen_load_gpr(t1, rs);
2452 tcg_gen_addi_tl(t0, t1, uimm);
2454 tcg_gen_xori_tl(t1, t1, ~uimm);
2455 tcg_gen_xori_tl(t2, t0, uimm);
2456 tcg_gen_and_tl(t1, t1, t2);
2457 tcg_temp_free(t2);
2458 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2459 tcg_temp_free(t1);
2460 /* operands of same sign, result different sign */
2461 generate_exception(ctx, EXCP_OVERFLOW);
2462 gen_set_label(l1);
2463 gen_store_gpr(t0, rt);
2464 tcg_temp_free(t0);
2466 break;
2467 case OPC_DADDIU:
2468 if (rs != 0) {
2469 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2470 } else {
2471 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2473 break;
2474 #endif
2478 /* Logic with immediate operand */
2479 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2480 int rt, int rs, int16_t imm)
2482 target_ulong uimm;
2484 if (rt == 0) {
2485 /* If no destination, treat it as a NOP. */
2486 return;
2488 uimm = (uint16_t)imm;
2489 switch (opc) {
2490 case OPC_ANDI:
2491 if (likely(rs != 0)) {
2492 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2493 } else {
2494 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2496 break;
2497 case OPC_ORI:
2498 if (rs != 0) {
2499 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2500 } else {
2501 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2503 break;
2504 case OPC_XORI:
2505 if (likely(rs != 0)) {
2506 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2507 } else {
2508 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2510 break;
2511 case OPC_LUI:
2512 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2513 /* OPC_AUI */
2514 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2515 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2516 } else {
2517 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2519 break;
2521 default:
2522 break;
2526 /* Set on less than with immediate operand */
2527 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2528 int rt, int rs, int16_t imm)
2530 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2531 TCGv t0;
2533 if (rt == 0) {
2534 /* If no destination, treat it as a NOP. */
2535 return;
2537 t0 = tcg_temp_new();
2538 gen_load_gpr(t0, rs);
2539 switch (opc) {
2540 case OPC_SLTI:
2541 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2542 break;
2543 case OPC_SLTIU:
2544 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2545 break;
2547 tcg_temp_free(t0);
2550 /* Shifts with immediate operand */
2551 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2552 int rt, int rs, int16_t imm)
2554 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2555 TCGv t0;
2557 if (rt == 0) {
2558 /* If no destination, treat it as a NOP. */
2559 return;
2562 t0 = tcg_temp_new();
2563 gen_load_gpr(t0, rs);
2564 switch (opc) {
2565 case OPC_SLL:
2566 tcg_gen_shli_tl(t0, t0, uimm);
2567 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2568 break;
2569 case OPC_SRA:
2570 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2571 break;
2572 case OPC_SRL:
2573 if (uimm != 0) {
2574 tcg_gen_ext32u_tl(t0, t0);
2575 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2576 } else {
2577 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2579 break;
2580 case OPC_ROTR:
2581 if (uimm != 0) {
2582 TCGv_i32 t1 = tcg_temp_new_i32();
2584 tcg_gen_trunc_tl_i32(t1, t0);
2585 tcg_gen_rotri_i32(t1, t1, uimm);
2586 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2587 tcg_temp_free_i32(t1);
2588 } else {
2589 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2591 break;
2592 #if defined(TARGET_MIPS64)
2593 case OPC_DSLL:
2594 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2595 break;
2596 case OPC_DSRA:
2597 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2598 break;
2599 case OPC_DSRL:
2600 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2601 break;
2602 case OPC_DROTR:
2603 if (uimm != 0) {
2604 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2605 } else {
2606 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2608 break;
2609 case OPC_DSLL32:
2610 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2611 break;
2612 case OPC_DSRA32:
2613 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2614 break;
2615 case OPC_DSRL32:
2616 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2617 break;
2618 case OPC_DROTR32:
2619 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2620 break;
2621 #endif
2623 tcg_temp_free(t0);
2626 /* Arithmetic */
2627 static void gen_arith(DisasContext *ctx, uint32_t opc,
2628 int rd, int rs, int rt)
2630 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2631 && opc != OPC_DADD && opc != OPC_DSUB) {
2633 * If no destination, treat it as a NOP.
2634 * For add & sub, we must generate the overflow exception when needed.
2636 return;
2639 switch (opc) {
2640 case OPC_ADD:
2642 TCGv t0 = tcg_temp_local_new();
2643 TCGv t1 = tcg_temp_new();
2644 TCGv t2 = tcg_temp_new();
2645 TCGLabel *l1 = gen_new_label();
2647 gen_load_gpr(t1, rs);
2648 gen_load_gpr(t2, rt);
2649 tcg_gen_add_tl(t0, t1, t2);
2650 tcg_gen_ext32s_tl(t0, t0);
2651 tcg_gen_xor_tl(t1, t1, t2);
2652 tcg_gen_xor_tl(t2, t0, t2);
2653 tcg_gen_andc_tl(t1, t2, t1);
2654 tcg_temp_free(t2);
2655 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2656 tcg_temp_free(t1);
2657 /* operands of same sign, result different sign */
2658 generate_exception(ctx, EXCP_OVERFLOW);
2659 gen_set_label(l1);
2660 gen_store_gpr(t0, rd);
2661 tcg_temp_free(t0);
2663 break;
2664 case OPC_ADDU:
2665 if (rs != 0 && rt != 0) {
2666 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2667 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2668 } else if (rs == 0 && rt != 0) {
2669 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2670 } else if (rs != 0 && rt == 0) {
2671 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2672 } else {
2673 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2675 break;
2676 case OPC_SUB:
2678 TCGv t0 = tcg_temp_local_new();
2679 TCGv t1 = tcg_temp_new();
2680 TCGv t2 = tcg_temp_new();
2681 TCGLabel *l1 = gen_new_label();
2683 gen_load_gpr(t1, rs);
2684 gen_load_gpr(t2, rt);
2685 tcg_gen_sub_tl(t0, t1, t2);
2686 tcg_gen_ext32s_tl(t0, t0);
2687 tcg_gen_xor_tl(t2, t1, t2);
2688 tcg_gen_xor_tl(t1, t0, t1);
2689 tcg_gen_and_tl(t1, t1, t2);
2690 tcg_temp_free(t2);
2691 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2692 tcg_temp_free(t1);
2694 * operands of different sign, first operand and the result
2695 * of different sign
2697 generate_exception(ctx, EXCP_OVERFLOW);
2698 gen_set_label(l1);
2699 gen_store_gpr(t0, rd);
2700 tcg_temp_free(t0);
2702 break;
2703 case OPC_SUBU:
2704 if (rs != 0 && rt != 0) {
2705 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2706 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2707 } else if (rs == 0 && rt != 0) {
2708 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2709 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2710 } else if (rs != 0 && rt == 0) {
2711 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2712 } else {
2713 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2715 break;
2716 #if defined(TARGET_MIPS64)
2717 case OPC_DADD:
2719 TCGv t0 = tcg_temp_local_new();
2720 TCGv t1 = tcg_temp_new();
2721 TCGv t2 = tcg_temp_new();
2722 TCGLabel *l1 = gen_new_label();
2724 gen_load_gpr(t1, rs);
2725 gen_load_gpr(t2, rt);
2726 tcg_gen_add_tl(t0, t1, t2);
2727 tcg_gen_xor_tl(t1, t1, t2);
2728 tcg_gen_xor_tl(t2, t0, t2);
2729 tcg_gen_andc_tl(t1, t2, t1);
2730 tcg_temp_free(t2);
2731 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2732 tcg_temp_free(t1);
2733 /* operands of same sign, result different sign */
2734 generate_exception(ctx, EXCP_OVERFLOW);
2735 gen_set_label(l1);
2736 gen_store_gpr(t0, rd);
2737 tcg_temp_free(t0);
2739 break;
2740 case OPC_DADDU:
2741 if (rs != 0 && rt != 0) {
2742 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2743 } else if (rs == 0 && rt != 0) {
2744 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2745 } else if (rs != 0 && rt == 0) {
2746 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2747 } else {
2748 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2750 break;
2751 case OPC_DSUB:
2753 TCGv t0 = tcg_temp_local_new();
2754 TCGv t1 = tcg_temp_new();
2755 TCGv t2 = tcg_temp_new();
2756 TCGLabel *l1 = gen_new_label();
2758 gen_load_gpr(t1, rs);
2759 gen_load_gpr(t2, rt);
2760 tcg_gen_sub_tl(t0, t1, t2);
2761 tcg_gen_xor_tl(t2, t1, t2);
2762 tcg_gen_xor_tl(t1, t0, t1);
2763 tcg_gen_and_tl(t1, t1, t2);
2764 tcg_temp_free(t2);
2765 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2766 tcg_temp_free(t1);
2768 * Operands of different sign, first operand and result different
2769 * sign.
2771 generate_exception(ctx, EXCP_OVERFLOW);
2772 gen_set_label(l1);
2773 gen_store_gpr(t0, rd);
2774 tcg_temp_free(t0);
2776 break;
2777 case OPC_DSUBU:
2778 if (rs != 0 && rt != 0) {
2779 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2780 } else if (rs == 0 && rt != 0) {
2781 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2782 } else if (rs != 0 && rt == 0) {
2783 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2784 } else {
2785 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2787 break;
2788 #endif
2789 case OPC_MUL:
2790 if (likely(rs != 0 && rt != 0)) {
2791 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2792 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2793 } else {
2794 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2796 break;
2800 /* Conditional move */
2801 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2802 int rd, int rs, int rt)
2804 TCGv t0, t1, t2;
2806 if (rd == 0) {
2807 /* If no destination, treat it as a NOP. */
2808 return;
2811 t0 = tcg_temp_new();
2812 gen_load_gpr(t0, rt);
2813 t1 = tcg_const_tl(0);
2814 t2 = tcg_temp_new();
2815 gen_load_gpr(t2, rs);
2816 switch (opc) {
2817 case OPC_MOVN:
2818 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2819 break;
2820 case OPC_MOVZ:
2821 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2822 break;
2823 case OPC_SELNEZ:
2824 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2825 break;
2826 case OPC_SELEQZ:
2827 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2828 break;
2830 tcg_temp_free(t2);
2831 tcg_temp_free(t1);
2832 tcg_temp_free(t0);
2835 /* Logic */
2836 static void gen_logic(DisasContext *ctx, uint32_t opc,
2837 int rd, int rs, int rt)
2839 if (rd == 0) {
2840 /* If no destination, treat it as a NOP. */
2841 return;
2844 switch (opc) {
2845 case OPC_AND:
2846 if (likely(rs != 0 && rt != 0)) {
2847 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2848 } else {
2849 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2851 break;
2852 case OPC_NOR:
2853 if (rs != 0 && rt != 0) {
2854 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2855 } else if (rs == 0 && rt != 0) {
2856 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2857 } else if (rs != 0 && rt == 0) {
2858 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2859 } else {
2860 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2862 break;
2863 case OPC_OR:
2864 if (likely(rs != 0 && rt != 0)) {
2865 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2866 } else if (rs == 0 && rt != 0) {
2867 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2868 } else if (rs != 0 && rt == 0) {
2869 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2870 } else {
2871 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2873 break;
2874 case OPC_XOR:
2875 if (likely(rs != 0 && rt != 0)) {
2876 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2877 } else if (rs == 0 && rt != 0) {
2878 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2879 } else if (rs != 0 && rt == 0) {
2880 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2881 } else {
2882 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2884 break;
2888 /* Set on lower than */
2889 static void gen_slt(DisasContext *ctx, uint32_t opc,
2890 int rd, int rs, int rt)
2892 TCGv t0, t1;
2894 if (rd == 0) {
2895 /* If no destination, treat it as a NOP. */
2896 return;
2899 t0 = tcg_temp_new();
2900 t1 = tcg_temp_new();
2901 gen_load_gpr(t0, rs);
2902 gen_load_gpr(t1, rt);
2903 switch (opc) {
2904 case OPC_SLT:
2905 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2906 break;
2907 case OPC_SLTU:
2908 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2909 break;
2911 tcg_temp_free(t0);
2912 tcg_temp_free(t1);
2915 /* Shifts */
2916 static void gen_shift(DisasContext *ctx, uint32_t opc,
2917 int rd, int rs, int rt)
2919 TCGv t0, t1;
2921 if (rd == 0) {
2923 * If no destination, treat it as a NOP.
2924 * For add & sub, we must generate the overflow exception when needed.
2926 return;
2929 t0 = tcg_temp_new();
2930 t1 = tcg_temp_new();
2931 gen_load_gpr(t0, rs);
2932 gen_load_gpr(t1, rt);
2933 switch (opc) {
2934 case OPC_SLLV:
2935 tcg_gen_andi_tl(t0, t0, 0x1f);
2936 tcg_gen_shl_tl(t0, t1, t0);
2937 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2938 break;
2939 case OPC_SRAV:
2940 tcg_gen_andi_tl(t0, t0, 0x1f);
2941 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2942 break;
2943 case OPC_SRLV:
2944 tcg_gen_ext32u_tl(t1, t1);
2945 tcg_gen_andi_tl(t0, t0, 0x1f);
2946 tcg_gen_shr_tl(t0, t1, t0);
2947 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2948 break;
2949 case OPC_ROTRV:
2951 TCGv_i32 t2 = tcg_temp_new_i32();
2952 TCGv_i32 t3 = tcg_temp_new_i32();
2954 tcg_gen_trunc_tl_i32(t2, t0);
2955 tcg_gen_trunc_tl_i32(t3, t1);
2956 tcg_gen_andi_i32(t2, t2, 0x1f);
2957 tcg_gen_rotr_i32(t2, t3, t2);
2958 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2959 tcg_temp_free_i32(t2);
2960 tcg_temp_free_i32(t3);
2962 break;
2963 #if defined(TARGET_MIPS64)
2964 case OPC_DSLLV:
2965 tcg_gen_andi_tl(t0, t0, 0x3f);
2966 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2967 break;
2968 case OPC_DSRAV:
2969 tcg_gen_andi_tl(t0, t0, 0x3f);
2970 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2971 break;
2972 case OPC_DSRLV:
2973 tcg_gen_andi_tl(t0, t0, 0x3f);
2974 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2975 break;
2976 case OPC_DROTRV:
2977 tcg_gen_andi_tl(t0, t0, 0x3f);
2978 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2979 break;
2980 #endif
2982 tcg_temp_free(t0);
2983 tcg_temp_free(t1);
2986 /* Arithmetic on HI/LO registers */
2987 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
2989 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2990 /* Treat as NOP. */
2991 return;
2994 if (acc != 0) {
2995 check_dsp(ctx);
2998 switch (opc) {
2999 case OPC_MFHI:
3000 #if defined(TARGET_MIPS64)
3001 if (acc != 0) {
3002 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3003 } else
3004 #endif
3006 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3008 break;
3009 case OPC_MFLO:
3010 #if defined(TARGET_MIPS64)
3011 if (acc != 0) {
3012 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3013 } else
3014 #endif
3016 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3018 break;
3019 case OPC_MTHI:
3020 if (reg != 0) {
3021 #if defined(TARGET_MIPS64)
3022 if (acc != 0) {
3023 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3024 } else
3025 #endif
3027 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3029 } else {
3030 tcg_gen_movi_tl(cpu_HI[acc], 0);
3032 break;
3033 case OPC_MTLO:
3034 if (reg != 0) {
3035 #if defined(TARGET_MIPS64)
3036 if (acc != 0) {
3037 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3038 } else
3039 #endif
3041 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3043 } else {
3044 tcg_gen_movi_tl(cpu_LO[acc], 0);
3046 break;
3050 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3051 MemOp memop)
3053 TCGv t0 = tcg_const_tl(addr);
3054 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3055 gen_store_gpr(t0, reg);
3056 tcg_temp_free(t0);
3059 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3060 int rs)
3062 target_long offset;
3063 target_long addr;
3065 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3066 case OPC_ADDIUPC:
3067 if (rs != 0) {
3068 offset = sextract32(ctx->opcode << 2, 0, 21);
3069 addr = addr_add(ctx, pc, offset);
3070 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3072 break;
3073 case R6_OPC_LWPC:
3074 offset = sextract32(ctx->opcode << 2, 0, 21);
3075 addr = addr_add(ctx, pc, offset);
3076 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3077 break;
3078 #if defined(TARGET_MIPS64)
3079 case OPC_LWUPC:
3080 check_mips_64(ctx);
3081 offset = sextract32(ctx->opcode << 2, 0, 21);
3082 addr = addr_add(ctx, pc, offset);
3083 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3084 break;
3085 #endif
3086 default:
3087 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3088 case OPC_AUIPC:
3089 if (rs != 0) {
3090 offset = sextract32(ctx->opcode, 0, 16) << 16;
3091 addr = addr_add(ctx, pc, offset);
3092 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3094 break;
3095 case OPC_ALUIPC:
3096 if (rs != 0) {
3097 offset = sextract32(ctx->opcode, 0, 16) << 16;
3098 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3099 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3101 break;
3102 #if defined(TARGET_MIPS64)
3103 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3104 case R6_OPC_LDPC + (1 << 16):
3105 case R6_OPC_LDPC + (2 << 16):
3106 case R6_OPC_LDPC + (3 << 16):
3107 check_mips_64(ctx);
3108 offset = sextract32(ctx->opcode << 3, 0, 21);
3109 addr = addr_add(ctx, (pc & ~0x7), offset);
3110 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3111 break;
3112 #endif
3113 default:
3114 MIPS_INVAL("OPC_PCREL");
3115 gen_reserved_instruction(ctx);
3116 break;
3118 break;
3122 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3124 TCGv t0, t1;
3126 if (rd == 0) {
3127 /* Treat as NOP. */
3128 return;
3131 t0 = tcg_temp_new();
3132 t1 = tcg_temp_new();
3134 gen_load_gpr(t0, rs);
3135 gen_load_gpr(t1, rt);
3137 switch (opc) {
3138 case R6_OPC_DIV:
3140 TCGv t2 = tcg_temp_new();
3141 TCGv t3 = tcg_temp_new();
3142 tcg_gen_ext32s_tl(t0, t0);
3143 tcg_gen_ext32s_tl(t1, t1);
3144 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3145 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3146 tcg_gen_and_tl(t2, t2, t3);
3147 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3148 tcg_gen_or_tl(t2, t2, t3);
3149 tcg_gen_movi_tl(t3, 0);
3150 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3151 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3152 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3153 tcg_temp_free(t3);
3154 tcg_temp_free(t2);
3156 break;
3157 case R6_OPC_MOD:
3159 TCGv t2 = tcg_temp_new();
3160 TCGv t3 = tcg_temp_new();
3161 tcg_gen_ext32s_tl(t0, t0);
3162 tcg_gen_ext32s_tl(t1, t1);
3163 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3164 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3165 tcg_gen_and_tl(t2, t2, t3);
3166 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3167 tcg_gen_or_tl(t2, t2, t3);
3168 tcg_gen_movi_tl(t3, 0);
3169 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3170 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3171 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3172 tcg_temp_free(t3);
3173 tcg_temp_free(t2);
3175 break;
3176 case R6_OPC_DIVU:
3178 TCGv t2 = tcg_const_tl(0);
3179 TCGv t3 = tcg_const_tl(1);
3180 tcg_gen_ext32u_tl(t0, t0);
3181 tcg_gen_ext32u_tl(t1, t1);
3182 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3183 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3184 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3185 tcg_temp_free(t3);
3186 tcg_temp_free(t2);
3188 break;
3189 case R6_OPC_MODU:
3191 TCGv t2 = tcg_const_tl(0);
3192 TCGv t3 = tcg_const_tl(1);
3193 tcg_gen_ext32u_tl(t0, t0);
3194 tcg_gen_ext32u_tl(t1, t1);
3195 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3196 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3197 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3198 tcg_temp_free(t3);
3199 tcg_temp_free(t2);
3201 break;
3202 case R6_OPC_MUL:
3204 TCGv_i32 t2 = tcg_temp_new_i32();
3205 TCGv_i32 t3 = tcg_temp_new_i32();
3206 tcg_gen_trunc_tl_i32(t2, t0);
3207 tcg_gen_trunc_tl_i32(t3, t1);
3208 tcg_gen_mul_i32(t2, t2, t3);
3209 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3210 tcg_temp_free_i32(t2);
3211 tcg_temp_free_i32(t3);
3213 break;
3214 case R6_OPC_MUH:
3216 TCGv_i32 t2 = tcg_temp_new_i32();
3217 TCGv_i32 t3 = tcg_temp_new_i32();
3218 tcg_gen_trunc_tl_i32(t2, t0);
3219 tcg_gen_trunc_tl_i32(t3, t1);
3220 tcg_gen_muls2_i32(t2, t3, t2, t3);
3221 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3222 tcg_temp_free_i32(t2);
3223 tcg_temp_free_i32(t3);
3225 break;
3226 case R6_OPC_MULU:
3228 TCGv_i32 t2 = tcg_temp_new_i32();
3229 TCGv_i32 t3 = tcg_temp_new_i32();
3230 tcg_gen_trunc_tl_i32(t2, t0);
3231 tcg_gen_trunc_tl_i32(t3, t1);
3232 tcg_gen_mul_i32(t2, t2, t3);
3233 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3234 tcg_temp_free_i32(t2);
3235 tcg_temp_free_i32(t3);
3237 break;
3238 case R6_OPC_MUHU:
3240 TCGv_i32 t2 = tcg_temp_new_i32();
3241 TCGv_i32 t3 = tcg_temp_new_i32();
3242 tcg_gen_trunc_tl_i32(t2, t0);
3243 tcg_gen_trunc_tl_i32(t3, t1);
3244 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3245 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3246 tcg_temp_free_i32(t2);
3247 tcg_temp_free_i32(t3);
3249 break;
3250 #if defined(TARGET_MIPS64)
3251 case R6_OPC_DDIV:
3253 TCGv t2 = tcg_temp_new();
3254 TCGv t3 = tcg_temp_new();
3255 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3256 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3257 tcg_gen_and_tl(t2, t2, t3);
3258 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3259 tcg_gen_or_tl(t2, t2, t3);
3260 tcg_gen_movi_tl(t3, 0);
3261 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3262 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3263 tcg_temp_free(t3);
3264 tcg_temp_free(t2);
3266 break;
3267 case R6_OPC_DMOD:
3269 TCGv t2 = tcg_temp_new();
3270 TCGv t3 = tcg_temp_new();
3271 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3272 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3273 tcg_gen_and_tl(t2, t2, t3);
3274 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3275 tcg_gen_or_tl(t2, t2, t3);
3276 tcg_gen_movi_tl(t3, 0);
3277 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3278 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3279 tcg_temp_free(t3);
3280 tcg_temp_free(t2);
3282 break;
3283 case R6_OPC_DDIVU:
3285 TCGv t2 = tcg_const_tl(0);
3286 TCGv t3 = tcg_const_tl(1);
3287 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3288 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3289 tcg_temp_free(t3);
3290 tcg_temp_free(t2);
3292 break;
3293 case R6_OPC_DMODU:
3295 TCGv t2 = tcg_const_tl(0);
3296 TCGv t3 = tcg_const_tl(1);
3297 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3298 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3299 tcg_temp_free(t3);
3300 tcg_temp_free(t2);
3302 break;
3303 case R6_OPC_DMUL:
3304 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3305 break;
3306 case R6_OPC_DMUH:
3308 TCGv t2 = tcg_temp_new();
3309 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3310 tcg_temp_free(t2);
3312 break;
3313 case R6_OPC_DMULU:
3314 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3315 break;
3316 case R6_OPC_DMUHU:
3318 TCGv t2 = tcg_temp_new();
3319 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3320 tcg_temp_free(t2);
3322 break;
3323 #endif
3324 default:
3325 MIPS_INVAL("r6 mul/div");
3326 gen_reserved_instruction(ctx);
3327 goto out;
3329 out:
3330 tcg_temp_free(t0);
3331 tcg_temp_free(t1);
3334 #if defined(TARGET_MIPS64)
3335 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3337 TCGv t0, t1;
3339 t0 = tcg_temp_new();
3340 t1 = tcg_temp_new();
3342 gen_load_gpr(t0, rs);
3343 gen_load_gpr(t1, rt);
3345 switch (opc) {
3346 case MMI_OPC_DIV1:
3348 TCGv t2 = tcg_temp_new();
3349 TCGv t3 = tcg_temp_new();
3350 tcg_gen_ext32s_tl(t0, t0);
3351 tcg_gen_ext32s_tl(t1, t1);
3352 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3353 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3354 tcg_gen_and_tl(t2, t2, t3);
3355 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3356 tcg_gen_or_tl(t2, t2, t3);
3357 tcg_gen_movi_tl(t3, 0);
3358 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3359 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3360 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3361 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3362 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3363 tcg_temp_free(t3);
3364 tcg_temp_free(t2);
3366 break;
3367 case MMI_OPC_DIVU1:
3369 TCGv t2 = tcg_const_tl(0);
3370 TCGv t3 = tcg_const_tl(1);
3371 tcg_gen_ext32u_tl(t0, t0);
3372 tcg_gen_ext32u_tl(t1, t1);
3373 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3374 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3375 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3376 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3377 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3378 tcg_temp_free(t3);
3379 tcg_temp_free(t2);
3381 break;
3382 default:
3383 MIPS_INVAL("div1 TX79");
3384 gen_reserved_instruction(ctx);
3385 goto out;
3387 out:
3388 tcg_temp_free(t0);
3389 tcg_temp_free(t1);
3391 #endif
3393 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3394 int acc, int rs, int rt)
3396 TCGv t0, t1;
3398 t0 = tcg_temp_new();
3399 t1 = tcg_temp_new();
3401 gen_load_gpr(t0, rs);
3402 gen_load_gpr(t1, rt);
3404 if (acc != 0) {
3405 check_dsp(ctx);
3408 switch (opc) {
3409 case OPC_DIV:
3411 TCGv t2 = tcg_temp_new();
3412 TCGv t3 = tcg_temp_new();
3413 tcg_gen_ext32s_tl(t0, t0);
3414 tcg_gen_ext32s_tl(t1, t1);
3415 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3416 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3417 tcg_gen_and_tl(t2, t2, t3);
3418 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3419 tcg_gen_or_tl(t2, t2, t3);
3420 tcg_gen_movi_tl(t3, 0);
3421 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3422 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3423 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3424 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3425 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3426 tcg_temp_free(t3);
3427 tcg_temp_free(t2);
3429 break;
3430 case OPC_DIVU:
3432 TCGv t2 = tcg_const_tl(0);
3433 TCGv t3 = tcg_const_tl(1);
3434 tcg_gen_ext32u_tl(t0, t0);
3435 tcg_gen_ext32u_tl(t1, t1);
3436 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3437 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3438 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3439 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3440 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3441 tcg_temp_free(t3);
3442 tcg_temp_free(t2);
3444 break;
3445 case OPC_MULT:
3447 TCGv_i32 t2 = tcg_temp_new_i32();
3448 TCGv_i32 t3 = tcg_temp_new_i32();
3449 tcg_gen_trunc_tl_i32(t2, t0);
3450 tcg_gen_trunc_tl_i32(t3, t1);
3451 tcg_gen_muls2_i32(t2, t3, t2, t3);
3452 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3453 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3454 tcg_temp_free_i32(t2);
3455 tcg_temp_free_i32(t3);
3457 break;
3458 case OPC_MULTU:
3460 TCGv_i32 t2 = tcg_temp_new_i32();
3461 TCGv_i32 t3 = tcg_temp_new_i32();
3462 tcg_gen_trunc_tl_i32(t2, t0);
3463 tcg_gen_trunc_tl_i32(t3, t1);
3464 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3465 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3466 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3467 tcg_temp_free_i32(t2);
3468 tcg_temp_free_i32(t3);
3470 break;
3471 #if defined(TARGET_MIPS64)
3472 case OPC_DDIV:
3474 TCGv t2 = tcg_temp_new();
3475 TCGv t3 = tcg_temp_new();
3476 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3477 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3478 tcg_gen_and_tl(t2, t2, t3);
3479 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3480 tcg_gen_or_tl(t2, t2, t3);
3481 tcg_gen_movi_tl(t3, 0);
3482 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3483 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3484 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3485 tcg_temp_free(t3);
3486 tcg_temp_free(t2);
3488 break;
3489 case OPC_DDIVU:
3491 TCGv t2 = tcg_const_tl(0);
3492 TCGv t3 = tcg_const_tl(1);
3493 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3494 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3495 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3496 tcg_temp_free(t3);
3497 tcg_temp_free(t2);
3499 break;
3500 case OPC_DMULT:
3501 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3502 break;
3503 case OPC_DMULTU:
3504 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3505 break;
3506 #endif
3507 case OPC_MADD:
3509 TCGv_i64 t2 = tcg_temp_new_i64();
3510 TCGv_i64 t3 = tcg_temp_new_i64();
3512 tcg_gen_ext_tl_i64(t2, t0);
3513 tcg_gen_ext_tl_i64(t3, t1);
3514 tcg_gen_mul_i64(t2, t2, t3);
3515 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3516 tcg_gen_add_i64(t2, t2, t3);
3517 tcg_temp_free_i64(t3);
3518 gen_move_low32(cpu_LO[acc], t2);
3519 gen_move_high32(cpu_HI[acc], t2);
3520 tcg_temp_free_i64(t2);
3522 break;
3523 case OPC_MADDU:
3525 TCGv_i64 t2 = tcg_temp_new_i64();
3526 TCGv_i64 t3 = tcg_temp_new_i64();
3528 tcg_gen_ext32u_tl(t0, t0);
3529 tcg_gen_ext32u_tl(t1, t1);
3530 tcg_gen_extu_tl_i64(t2, t0);
3531 tcg_gen_extu_tl_i64(t3, t1);
3532 tcg_gen_mul_i64(t2, t2, t3);
3533 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3534 tcg_gen_add_i64(t2, t2, t3);
3535 tcg_temp_free_i64(t3);
3536 gen_move_low32(cpu_LO[acc], t2);
3537 gen_move_high32(cpu_HI[acc], t2);
3538 tcg_temp_free_i64(t2);
3540 break;
3541 case OPC_MSUB:
3543 TCGv_i64 t2 = tcg_temp_new_i64();
3544 TCGv_i64 t3 = tcg_temp_new_i64();
3546 tcg_gen_ext_tl_i64(t2, t0);
3547 tcg_gen_ext_tl_i64(t3, t1);
3548 tcg_gen_mul_i64(t2, t2, t3);
3549 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3550 tcg_gen_sub_i64(t2, t3, t2);
3551 tcg_temp_free_i64(t3);
3552 gen_move_low32(cpu_LO[acc], t2);
3553 gen_move_high32(cpu_HI[acc], t2);
3554 tcg_temp_free_i64(t2);
3556 break;
3557 case OPC_MSUBU:
3559 TCGv_i64 t2 = tcg_temp_new_i64();
3560 TCGv_i64 t3 = tcg_temp_new_i64();
3562 tcg_gen_ext32u_tl(t0, t0);
3563 tcg_gen_ext32u_tl(t1, t1);
3564 tcg_gen_extu_tl_i64(t2, t0);
3565 tcg_gen_extu_tl_i64(t3, t1);
3566 tcg_gen_mul_i64(t2, t2, t3);
3567 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3568 tcg_gen_sub_i64(t2, t3, t2);
3569 tcg_temp_free_i64(t3);
3570 gen_move_low32(cpu_LO[acc], t2);
3571 gen_move_high32(cpu_HI[acc], t2);
3572 tcg_temp_free_i64(t2);
3574 break;
3575 default:
3576 MIPS_INVAL("mul/div");
3577 gen_reserved_instruction(ctx);
3578 goto out;
3580 out:
3581 tcg_temp_free(t0);
3582 tcg_temp_free(t1);
3586 * These MULT[U] and MADD[U] instructions implemented in for example
3587 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
3588 * architectures are special three-operand variants with the syntax
3590 * MULT[U][1] rd, rs, rt
3592 * such that
3594 * (rd, LO, HI) <- rs * rt
3596 * and
3598 * MADD[U][1] rd, rs, rt
3600 * such that
3602 * (rd, LO, HI) <- (LO, HI) + rs * rt
3604 * where the low-order 32-bits of the result is placed into both the
3605 * GPR rd and the special register LO. The high-order 32-bits of the
3606 * result is placed into the special register HI.
3608 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3609 * which is the zero register that always reads as 0.
3611 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3612 int rd, int rs, int rt)
3614 TCGv t0 = tcg_temp_new();
3615 TCGv t1 = tcg_temp_new();
3616 int acc = 0;
3618 gen_load_gpr(t0, rs);
3619 gen_load_gpr(t1, rt);
3621 switch (opc) {
3622 case MMI_OPC_MULT1:
3623 acc = 1;
3624 /* Fall through */
3625 case OPC_MULT:
3627 TCGv_i32 t2 = tcg_temp_new_i32();
3628 TCGv_i32 t3 = tcg_temp_new_i32();
3629 tcg_gen_trunc_tl_i32(t2, t0);
3630 tcg_gen_trunc_tl_i32(t3, t1);
3631 tcg_gen_muls2_i32(t2, t3, t2, t3);
3632 if (rd) {
3633 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3635 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3636 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3637 tcg_temp_free_i32(t2);
3638 tcg_temp_free_i32(t3);
3640 break;
3641 case MMI_OPC_MULTU1:
3642 acc = 1;
3643 /* Fall through */
3644 case OPC_MULTU:
3646 TCGv_i32 t2 = tcg_temp_new_i32();
3647 TCGv_i32 t3 = tcg_temp_new_i32();
3648 tcg_gen_trunc_tl_i32(t2, t0);
3649 tcg_gen_trunc_tl_i32(t3, t1);
3650 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3651 if (rd) {
3652 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3654 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3655 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3656 tcg_temp_free_i32(t2);
3657 tcg_temp_free_i32(t3);
3659 break;
3660 case MMI_OPC_MADD1:
3661 acc = 1;
3662 /* Fall through */
3663 case MMI_OPC_MADD:
3665 TCGv_i64 t2 = tcg_temp_new_i64();
3666 TCGv_i64 t3 = tcg_temp_new_i64();
3668 tcg_gen_ext_tl_i64(t2, t0);
3669 tcg_gen_ext_tl_i64(t3, t1);
3670 tcg_gen_mul_i64(t2, t2, t3);
3671 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3672 tcg_gen_add_i64(t2, t2, t3);
3673 tcg_temp_free_i64(t3);
3674 gen_move_low32(cpu_LO[acc], t2);
3675 gen_move_high32(cpu_HI[acc], t2);
3676 if (rd) {
3677 gen_move_low32(cpu_gpr[rd], t2);
3679 tcg_temp_free_i64(t2);
3681 break;
3682 case MMI_OPC_MADDU1:
3683 acc = 1;
3684 /* Fall through */
3685 case MMI_OPC_MADDU:
3687 TCGv_i64 t2 = tcg_temp_new_i64();
3688 TCGv_i64 t3 = tcg_temp_new_i64();
3690 tcg_gen_ext32u_tl(t0, t0);
3691 tcg_gen_ext32u_tl(t1, t1);
3692 tcg_gen_extu_tl_i64(t2, t0);
3693 tcg_gen_extu_tl_i64(t3, t1);
3694 tcg_gen_mul_i64(t2, t2, t3);
3695 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3696 tcg_gen_add_i64(t2, t2, t3);
3697 tcg_temp_free_i64(t3);
3698 gen_move_low32(cpu_LO[acc], t2);
3699 gen_move_high32(cpu_HI[acc], t2);
3700 if (rd) {
3701 gen_move_low32(cpu_gpr[rd], t2);
3703 tcg_temp_free_i64(t2);
3705 break;
3706 default:
3707 MIPS_INVAL("mul/madd TXx9");
3708 gen_reserved_instruction(ctx);
3709 goto out;
3712 out:
3713 tcg_temp_free(t0);
3714 tcg_temp_free(t1);
3717 static void gen_cl(DisasContext *ctx, uint32_t opc,
3718 int rd, int rs)
3720 TCGv t0;
3722 if (rd == 0) {
3723 /* Treat as NOP. */
3724 return;
3726 t0 = cpu_gpr[rd];
3727 gen_load_gpr(t0, rs);
3729 switch (opc) {
3730 case OPC_CLO:
3731 case R6_OPC_CLO:
3732 #if defined(TARGET_MIPS64)
3733 case OPC_DCLO:
3734 case R6_OPC_DCLO:
3735 #endif
3736 tcg_gen_not_tl(t0, t0);
3737 break;
3740 switch (opc) {
3741 case OPC_CLO:
3742 case R6_OPC_CLO:
3743 case OPC_CLZ:
3744 case R6_OPC_CLZ:
3745 tcg_gen_ext32u_tl(t0, t0);
3746 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3747 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3748 break;
3749 #if defined(TARGET_MIPS64)
3750 case OPC_DCLO:
3751 case R6_OPC_DCLO:
3752 case OPC_DCLZ:
3753 case R6_OPC_DCLZ:
3754 tcg_gen_clzi_i64(t0, t0, 64);
3755 break;
3756 #endif
3760 /* Godson integer instructions */
3761 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3762 int rd, int rs, int rt)
3764 TCGv t0, t1;
3766 if (rd == 0) {
3767 /* Treat as NOP. */
3768 return;
3771 switch (opc) {
3772 case OPC_MULT_G_2E:
3773 case OPC_MULT_G_2F:
3774 case OPC_MULTU_G_2E:
3775 case OPC_MULTU_G_2F:
3776 #if defined(TARGET_MIPS64)
3777 case OPC_DMULT_G_2E:
3778 case OPC_DMULT_G_2F:
3779 case OPC_DMULTU_G_2E:
3780 case OPC_DMULTU_G_2F:
3781 #endif
3782 t0 = tcg_temp_new();
3783 t1 = tcg_temp_new();
3784 break;
3785 default:
3786 t0 = tcg_temp_local_new();
3787 t1 = tcg_temp_local_new();
3788 break;
3791 gen_load_gpr(t0, rs);
3792 gen_load_gpr(t1, rt);
3794 switch (opc) {
3795 case OPC_MULT_G_2E:
3796 case OPC_MULT_G_2F:
3797 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3798 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3799 break;
3800 case OPC_MULTU_G_2E:
3801 case OPC_MULTU_G_2F:
3802 tcg_gen_ext32u_tl(t0, t0);
3803 tcg_gen_ext32u_tl(t1, t1);
3804 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3805 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3806 break;
3807 case OPC_DIV_G_2E:
3808 case OPC_DIV_G_2F:
3810 TCGLabel *l1 = gen_new_label();
3811 TCGLabel *l2 = gen_new_label();
3812 TCGLabel *l3 = gen_new_label();
3813 tcg_gen_ext32s_tl(t0, t0);
3814 tcg_gen_ext32s_tl(t1, t1);
3815 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3816 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3817 tcg_gen_br(l3);
3818 gen_set_label(l1);
3819 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3820 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3821 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3822 tcg_gen_br(l3);
3823 gen_set_label(l2);
3824 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3825 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3826 gen_set_label(l3);
3828 break;
3829 case OPC_DIVU_G_2E:
3830 case OPC_DIVU_G_2F:
3832 TCGLabel *l1 = gen_new_label();
3833 TCGLabel *l2 = gen_new_label();
3834 tcg_gen_ext32u_tl(t0, t0);
3835 tcg_gen_ext32u_tl(t1, t1);
3836 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3837 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3838 tcg_gen_br(l2);
3839 gen_set_label(l1);
3840 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3841 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3842 gen_set_label(l2);
3844 break;
3845 case OPC_MOD_G_2E:
3846 case OPC_MOD_G_2F:
3848 TCGLabel *l1 = gen_new_label();
3849 TCGLabel *l2 = gen_new_label();
3850 TCGLabel *l3 = gen_new_label();
3851 tcg_gen_ext32u_tl(t0, t0);
3852 tcg_gen_ext32u_tl(t1, t1);
3853 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3854 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3855 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3856 gen_set_label(l1);
3857 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3858 tcg_gen_br(l3);
3859 gen_set_label(l2);
3860 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3861 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3862 gen_set_label(l3);
3864 break;
3865 case OPC_MODU_G_2E:
3866 case OPC_MODU_G_2F:
3868 TCGLabel *l1 = gen_new_label();
3869 TCGLabel *l2 = gen_new_label();
3870 tcg_gen_ext32u_tl(t0, t0);
3871 tcg_gen_ext32u_tl(t1, t1);
3872 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3873 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3874 tcg_gen_br(l2);
3875 gen_set_label(l1);
3876 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3877 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3878 gen_set_label(l2);
3880 break;
3881 #if defined(TARGET_MIPS64)
3882 case OPC_DMULT_G_2E:
3883 case OPC_DMULT_G_2F:
3884 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3885 break;
3886 case OPC_DMULTU_G_2E:
3887 case OPC_DMULTU_G_2F:
3888 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3889 break;
3890 case OPC_DDIV_G_2E:
3891 case OPC_DDIV_G_2F:
3893 TCGLabel *l1 = gen_new_label();
3894 TCGLabel *l2 = gen_new_label();
3895 TCGLabel *l3 = gen_new_label();
3896 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3897 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3898 tcg_gen_br(l3);
3899 gen_set_label(l1);
3900 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3901 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3902 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3903 tcg_gen_br(l3);
3904 gen_set_label(l2);
3905 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3906 gen_set_label(l3);
3908 break;
3909 case OPC_DDIVU_G_2E:
3910 case OPC_DDIVU_G_2F:
3912 TCGLabel *l1 = gen_new_label();
3913 TCGLabel *l2 = gen_new_label();
3914 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3915 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3916 tcg_gen_br(l2);
3917 gen_set_label(l1);
3918 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3919 gen_set_label(l2);
3921 break;
3922 case OPC_DMOD_G_2E:
3923 case OPC_DMOD_G_2F:
3925 TCGLabel *l1 = gen_new_label();
3926 TCGLabel *l2 = gen_new_label();
3927 TCGLabel *l3 = gen_new_label();
3928 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3929 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3930 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3931 gen_set_label(l1);
3932 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3933 tcg_gen_br(l3);
3934 gen_set_label(l2);
3935 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3936 gen_set_label(l3);
3938 break;
3939 case OPC_DMODU_G_2E:
3940 case OPC_DMODU_G_2F:
3942 TCGLabel *l1 = gen_new_label();
3943 TCGLabel *l2 = gen_new_label();
3944 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3945 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3946 tcg_gen_br(l2);
3947 gen_set_label(l1);
3948 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3949 gen_set_label(l2);
3951 break;
3952 #endif
3955 tcg_temp_free(t0);
3956 tcg_temp_free(t1);
3959 /* Loongson multimedia instructions */
3960 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3962 uint32_t opc, shift_max;
3963 TCGv_i64 t0, t1;
3964 TCGCond cond;
3966 opc = MASK_LMMI(ctx->opcode);
3967 switch (opc) {
3968 case OPC_ADD_CP2:
3969 case OPC_SUB_CP2:
3970 case OPC_DADD_CP2:
3971 case OPC_DSUB_CP2:
3972 t0 = tcg_temp_local_new_i64();
3973 t1 = tcg_temp_local_new_i64();
3974 break;
3975 default:
3976 t0 = tcg_temp_new_i64();
3977 t1 = tcg_temp_new_i64();
3978 break;
3981 check_cp1_enabled(ctx);
3982 gen_load_fpr64(ctx, t0, rs);
3983 gen_load_fpr64(ctx, t1, rt);
3985 switch (opc) {
3986 case OPC_PADDSH:
3987 gen_helper_paddsh(t0, t0, t1);
3988 break;
3989 case OPC_PADDUSH:
3990 gen_helper_paddush(t0, t0, t1);
3991 break;
3992 case OPC_PADDH:
3993 gen_helper_paddh(t0, t0, t1);
3994 break;
3995 case OPC_PADDW:
3996 gen_helper_paddw(t0, t0, t1);
3997 break;
3998 case OPC_PADDSB:
3999 gen_helper_paddsb(t0, t0, t1);
4000 break;
4001 case OPC_PADDUSB:
4002 gen_helper_paddusb(t0, t0, t1);
4003 break;
4004 case OPC_PADDB:
4005 gen_helper_paddb(t0, t0, t1);
4006 break;
4008 case OPC_PSUBSH:
4009 gen_helper_psubsh(t0, t0, t1);
4010 break;
4011 case OPC_PSUBUSH:
4012 gen_helper_psubush(t0, t0, t1);
4013 break;
4014 case OPC_PSUBH:
4015 gen_helper_psubh(t0, t0, t1);
4016 break;
4017 case OPC_PSUBW:
4018 gen_helper_psubw(t0, t0, t1);
4019 break;
4020 case OPC_PSUBSB:
4021 gen_helper_psubsb(t0, t0, t1);
4022 break;
4023 case OPC_PSUBUSB:
4024 gen_helper_psubusb(t0, t0, t1);
4025 break;
4026 case OPC_PSUBB:
4027 gen_helper_psubb(t0, t0, t1);
4028 break;
4030 case OPC_PSHUFH:
4031 gen_helper_pshufh(t0, t0, t1);
4032 break;
4033 case OPC_PACKSSWH:
4034 gen_helper_packsswh(t0, t0, t1);
4035 break;
4036 case OPC_PACKSSHB:
4037 gen_helper_packsshb(t0, t0, t1);
4038 break;
4039 case OPC_PACKUSHB:
4040 gen_helper_packushb(t0, t0, t1);
4041 break;
4043 case OPC_PUNPCKLHW:
4044 gen_helper_punpcklhw(t0, t0, t1);
4045 break;
4046 case OPC_PUNPCKHHW:
4047 gen_helper_punpckhhw(t0, t0, t1);
4048 break;
4049 case OPC_PUNPCKLBH:
4050 gen_helper_punpcklbh(t0, t0, t1);
4051 break;
4052 case OPC_PUNPCKHBH:
4053 gen_helper_punpckhbh(t0, t0, t1);
4054 break;
4055 case OPC_PUNPCKLWD:
4056 gen_helper_punpcklwd(t0, t0, t1);
4057 break;
4058 case OPC_PUNPCKHWD:
4059 gen_helper_punpckhwd(t0, t0, t1);
4060 break;
4062 case OPC_PAVGH:
4063 gen_helper_pavgh(t0, t0, t1);
4064 break;
4065 case OPC_PAVGB:
4066 gen_helper_pavgb(t0, t0, t1);
4067 break;
4068 case OPC_PMAXSH:
4069 gen_helper_pmaxsh(t0, t0, t1);
4070 break;
4071 case OPC_PMINSH:
4072 gen_helper_pminsh(t0, t0, t1);
4073 break;
4074 case OPC_PMAXUB:
4075 gen_helper_pmaxub(t0, t0, t1);
4076 break;
4077 case OPC_PMINUB:
4078 gen_helper_pminub(t0, t0, t1);
4079 break;
4081 case OPC_PCMPEQW:
4082 gen_helper_pcmpeqw(t0, t0, t1);
4083 break;
4084 case OPC_PCMPGTW:
4085 gen_helper_pcmpgtw(t0, t0, t1);
4086 break;
4087 case OPC_PCMPEQH:
4088 gen_helper_pcmpeqh(t0, t0, t1);
4089 break;
4090 case OPC_PCMPGTH:
4091 gen_helper_pcmpgth(t0, t0, t1);
4092 break;
4093 case OPC_PCMPEQB:
4094 gen_helper_pcmpeqb(t0, t0, t1);
4095 break;
4096 case OPC_PCMPGTB:
4097 gen_helper_pcmpgtb(t0, t0, t1);
4098 break;
4100 case OPC_PSLLW:
4101 gen_helper_psllw(t0, t0, t1);
4102 break;
4103 case OPC_PSLLH:
4104 gen_helper_psllh(t0, t0, t1);
4105 break;
4106 case OPC_PSRLW:
4107 gen_helper_psrlw(t0, t0, t1);
4108 break;
4109 case OPC_PSRLH:
4110 gen_helper_psrlh(t0, t0, t1);
4111 break;
4112 case OPC_PSRAW:
4113 gen_helper_psraw(t0, t0, t1);
4114 break;
4115 case OPC_PSRAH:
4116 gen_helper_psrah(t0, t0, t1);
4117 break;
4119 case OPC_PMULLH:
4120 gen_helper_pmullh(t0, t0, t1);
4121 break;
4122 case OPC_PMULHH:
4123 gen_helper_pmulhh(t0, t0, t1);
4124 break;
4125 case OPC_PMULHUH:
4126 gen_helper_pmulhuh(t0, t0, t1);
4127 break;
4128 case OPC_PMADDHW:
4129 gen_helper_pmaddhw(t0, t0, t1);
4130 break;
4132 case OPC_PASUBUB:
4133 gen_helper_pasubub(t0, t0, t1);
4134 break;
4135 case OPC_BIADD:
4136 gen_helper_biadd(t0, t0);
4137 break;
4138 case OPC_PMOVMSKB:
4139 gen_helper_pmovmskb(t0, t0);
4140 break;
4142 case OPC_PADDD:
4143 tcg_gen_add_i64(t0, t0, t1);
4144 break;
4145 case OPC_PSUBD:
4146 tcg_gen_sub_i64(t0, t0, t1);
4147 break;
4148 case OPC_XOR_CP2:
4149 tcg_gen_xor_i64(t0, t0, t1);
4150 break;
4151 case OPC_NOR_CP2:
4152 tcg_gen_nor_i64(t0, t0, t1);
4153 break;
4154 case OPC_AND_CP2:
4155 tcg_gen_and_i64(t0, t0, t1);
4156 break;
4157 case OPC_OR_CP2:
4158 tcg_gen_or_i64(t0, t0, t1);
4159 break;
4161 case OPC_PANDN:
4162 tcg_gen_andc_i64(t0, t1, t0);
4163 break;
4165 case OPC_PINSRH_0:
4166 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4167 break;
4168 case OPC_PINSRH_1:
4169 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4170 break;
4171 case OPC_PINSRH_2:
4172 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4173 break;
4174 case OPC_PINSRH_3:
4175 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4176 break;
4178 case OPC_PEXTRH:
4179 tcg_gen_andi_i64(t1, t1, 3);
4180 tcg_gen_shli_i64(t1, t1, 4);
4181 tcg_gen_shr_i64(t0, t0, t1);
4182 tcg_gen_ext16u_i64(t0, t0);
4183 break;
4185 case OPC_ADDU_CP2:
4186 tcg_gen_add_i64(t0, t0, t1);
4187 tcg_gen_ext32s_i64(t0, t0);
4188 break;
4189 case OPC_SUBU_CP2:
4190 tcg_gen_sub_i64(t0, t0, t1);
4191 tcg_gen_ext32s_i64(t0, t0);
4192 break;
4194 case OPC_SLL_CP2:
4195 shift_max = 32;
4196 goto do_shift;
4197 case OPC_SRL_CP2:
4198 shift_max = 32;
4199 goto do_shift;
4200 case OPC_SRA_CP2:
4201 shift_max = 32;
4202 goto do_shift;
4203 case OPC_DSLL_CP2:
4204 shift_max = 64;
4205 goto do_shift;
4206 case OPC_DSRL_CP2:
4207 shift_max = 64;
4208 goto do_shift;
4209 case OPC_DSRA_CP2:
4210 shift_max = 64;
4211 goto do_shift;
4212 do_shift:
4213 /* Make sure shift count isn't TCG undefined behaviour. */
4214 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4216 switch (opc) {
4217 case OPC_SLL_CP2:
4218 case OPC_DSLL_CP2:
4219 tcg_gen_shl_i64(t0, t0, t1);
4220 break;
4221 case OPC_SRA_CP2:
4222 case OPC_DSRA_CP2:
4224 * Since SRA is UndefinedResult without sign-extended inputs,
4225 * we can treat SRA and DSRA the same.
4227 tcg_gen_sar_i64(t0, t0, t1);
4228 break;
4229 case OPC_SRL_CP2:
4230 /* We want to shift in zeros for SRL; zero-extend first. */
4231 tcg_gen_ext32u_i64(t0, t0);
4232 /* FALLTHRU */
4233 case OPC_DSRL_CP2:
4234 tcg_gen_shr_i64(t0, t0, t1);
4235 break;
4238 if (shift_max == 32) {
4239 tcg_gen_ext32s_i64(t0, t0);
4242 /* Shifts larger than MAX produce zero. */
4243 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4244 tcg_gen_neg_i64(t1, t1);
4245 tcg_gen_and_i64(t0, t0, t1);
4246 break;
4248 case OPC_ADD_CP2:
4249 case OPC_DADD_CP2:
4251 TCGv_i64 t2 = tcg_temp_new_i64();
4252 TCGLabel *lab = gen_new_label();
4254 tcg_gen_mov_i64(t2, t0);
4255 tcg_gen_add_i64(t0, t1, t2);
4256 if (opc == OPC_ADD_CP2) {
4257 tcg_gen_ext32s_i64(t0, t0);
4259 tcg_gen_xor_i64(t1, t1, t2);
4260 tcg_gen_xor_i64(t2, t2, t0);
4261 tcg_gen_andc_i64(t1, t2, t1);
4262 tcg_temp_free_i64(t2);
4263 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4264 generate_exception(ctx, EXCP_OVERFLOW);
4265 gen_set_label(lab);
4266 break;
4269 case OPC_SUB_CP2:
4270 case OPC_DSUB_CP2:
4272 TCGv_i64 t2 = tcg_temp_new_i64();
4273 TCGLabel *lab = gen_new_label();
4275 tcg_gen_mov_i64(t2, t0);
4276 tcg_gen_sub_i64(t0, t1, t2);
4277 if (opc == OPC_SUB_CP2) {
4278 tcg_gen_ext32s_i64(t0, t0);
4280 tcg_gen_xor_i64(t1, t1, t2);
4281 tcg_gen_xor_i64(t2, t2, t0);
4282 tcg_gen_and_i64(t1, t1, t2);
4283 tcg_temp_free_i64(t2);
4284 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4285 generate_exception(ctx, EXCP_OVERFLOW);
4286 gen_set_label(lab);
4287 break;
4290 case OPC_PMULUW:
4291 tcg_gen_ext32u_i64(t0, t0);
4292 tcg_gen_ext32u_i64(t1, t1);
4293 tcg_gen_mul_i64(t0, t0, t1);
4294 break;
4296 case OPC_SEQU_CP2:
4297 case OPC_SEQ_CP2:
4298 cond = TCG_COND_EQ;
4299 goto do_cc_cond;
4300 break;
4301 case OPC_SLTU_CP2:
4302 cond = TCG_COND_LTU;
4303 goto do_cc_cond;
4304 break;
4305 case OPC_SLT_CP2:
4306 cond = TCG_COND_LT;
4307 goto do_cc_cond;
4308 break;
4309 case OPC_SLEU_CP2:
4310 cond = TCG_COND_LEU;
4311 goto do_cc_cond;
4312 break;
4313 case OPC_SLE_CP2:
4314 cond = TCG_COND_LE;
4315 do_cc_cond:
4317 int cc = (ctx->opcode >> 8) & 0x7;
4318 TCGv_i64 t64 = tcg_temp_new_i64();
4319 TCGv_i32 t32 = tcg_temp_new_i32();
4321 tcg_gen_setcond_i64(cond, t64, t0, t1);
4322 tcg_gen_extrl_i64_i32(t32, t64);
4323 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4324 get_fp_bit(cc), 1);
4326 tcg_temp_free_i32(t32);
4327 tcg_temp_free_i64(t64);
4329 goto no_rd;
4330 break;
4331 default:
4332 MIPS_INVAL("loongson_cp2");
4333 gen_reserved_instruction(ctx);
4334 return;
4337 gen_store_fpr64(ctx, t0, rd);
4339 no_rd:
4340 tcg_temp_free_i64(t0);
4341 tcg_temp_free_i64(t1);
4344 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4345 int rs, int rd)
4347 TCGv t0, t1, t2;
4348 TCGv_i32 fp0;
4349 #if defined(TARGET_MIPS64)
4350 int lsq_rt1 = ctx->opcode & 0x1f;
4351 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4352 #endif
4353 int shf_offset = sextract32(ctx->opcode, 6, 8);
4355 t0 = tcg_temp_new();
4357 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4358 #if defined(TARGET_MIPS64)
4359 case OPC_GSLQ:
4360 t1 = tcg_temp_new();
4361 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4362 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4363 ctx->default_tcg_memop_mask);
4364 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4365 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4366 ctx->default_tcg_memop_mask);
4367 gen_store_gpr(t1, rt);
4368 gen_store_gpr(t0, lsq_rt1);
4369 tcg_temp_free(t1);
4370 break;
4371 case OPC_GSLQC1:
4372 check_cp1_enabled(ctx);
4373 t1 = tcg_temp_new();
4374 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4375 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4376 ctx->default_tcg_memop_mask);
4377 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4378 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4379 ctx->default_tcg_memop_mask);
4380 gen_store_fpr64(ctx, t1, rt);
4381 gen_store_fpr64(ctx, t0, lsq_rt1);
4382 tcg_temp_free(t1);
4383 break;
4384 case OPC_GSSQ:
4385 t1 = tcg_temp_new();
4386 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4387 gen_load_gpr(t1, rt);
4388 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4389 ctx->default_tcg_memop_mask);
4390 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4391 gen_load_gpr(t1, lsq_rt1);
4392 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4393 ctx->default_tcg_memop_mask);
4394 tcg_temp_free(t1);
4395 break;
4396 case OPC_GSSQC1:
4397 check_cp1_enabled(ctx);
4398 t1 = tcg_temp_new();
4399 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4400 gen_load_fpr64(ctx, t1, rt);
4401 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4402 ctx->default_tcg_memop_mask);
4403 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4404 gen_load_fpr64(ctx, t1, lsq_rt1);
4405 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4406 ctx->default_tcg_memop_mask);
4407 tcg_temp_free(t1);
4408 break;
4409 #endif
4410 case OPC_GSSHFL:
4411 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4412 case OPC_GSLWLC1:
4413 check_cp1_enabled(ctx);
4414 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4415 t1 = tcg_temp_new();
4416 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4417 tcg_gen_andi_tl(t1, t0, 3);
4418 #ifndef TARGET_WORDS_BIGENDIAN
4419 tcg_gen_xori_tl(t1, t1, 3);
4420 #endif
4421 tcg_gen_shli_tl(t1, t1, 3);
4422 tcg_gen_andi_tl(t0, t0, ~3);
4423 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4424 tcg_gen_shl_tl(t0, t0, t1);
4425 t2 = tcg_const_tl(-1);
4426 tcg_gen_shl_tl(t2, t2, t1);
4427 fp0 = tcg_temp_new_i32();
4428 gen_load_fpr32(ctx, fp0, rt);
4429 tcg_gen_ext_i32_tl(t1, fp0);
4430 tcg_gen_andc_tl(t1, t1, t2);
4431 tcg_temp_free(t2);
4432 tcg_gen_or_tl(t0, t0, t1);
4433 tcg_temp_free(t1);
4434 #if defined(TARGET_MIPS64)
4435 tcg_gen_extrl_i64_i32(fp0, t0);
4436 #else
4437 tcg_gen_ext32s_tl(fp0, t0);
4438 #endif
4439 gen_store_fpr32(ctx, fp0, rt);
4440 tcg_temp_free_i32(fp0);
4441 break;
4442 case OPC_GSLWRC1:
4443 check_cp1_enabled(ctx);
4444 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4445 t1 = tcg_temp_new();
4446 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4447 tcg_gen_andi_tl(t1, t0, 3);
4448 #ifdef TARGET_WORDS_BIGENDIAN
4449 tcg_gen_xori_tl(t1, t1, 3);
4450 #endif
4451 tcg_gen_shli_tl(t1, t1, 3);
4452 tcg_gen_andi_tl(t0, t0, ~3);
4453 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4454 tcg_gen_shr_tl(t0, t0, t1);
4455 tcg_gen_xori_tl(t1, t1, 31);
4456 t2 = tcg_const_tl(0xfffffffeull);
4457 tcg_gen_shl_tl(t2, t2, t1);
4458 fp0 = tcg_temp_new_i32();
4459 gen_load_fpr32(ctx, fp0, rt);
4460 tcg_gen_ext_i32_tl(t1, fp0);
4461 tcg_gen_and_tl(t1, t1, t2);
4462 tcg_temp_free(t2);
4463 tcg_gen_or_tl(t0, t0, t1);
4464 tcg_temp_free(t1);
4465 #if defined(TARGET_MIPS64)
4466 tcg_gen_extrl_i64_i32(fp0, t0);
4467 #else
4468 tcg_gen_ext32s_tl(fp0, t0);
4469 #endif
4470 gen_store_fpr32(ctx, fp0, rt);
4471 tcg_temp_free_i32(fp0);
4472 break;
4473 #if defined(TARGET_MIPS64)
4474 case OPC_GSLDLC1:
4475 check_cp1_enabled(ctx);
4476 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4477 t1 = tcg_temp_new();
4478 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4479 tcg_gen_andi_tl(t1, t0, 7);
4480 #ifndef TARGET_WORDS_BIGENDIAN
4481 tcg_gen_xori_tl(t1, t1, 7);
4482 #endif
4483 tcg_gen_shli_tl(t1, t1, 3);
4484 tcg_gen_andi_tl(t0, t0, ~7);
4485 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4486 tcg_gen_shl_tl(t0, t0, t1);
4487 t2 = tcg_const_tl(-1);
4488 tcg_gen_shl_tl(t2, t2, t1);
4489 gen_load_fpr64(ctx, t1, rt);
4490 tcg_gen_andc_tl(t1, t1, t2);
4491 tcg_temp_free(t2);
4492 tcg_gen_or_tl(t0, t0, t1);
4493 tcg_temp_free(t1);
4494 gen_store_fpr64(ctx, t0, rt);
4495 break;
4496 case OPC_GSLDRC1:
4497 check_cp1_enabled(ctx);
4498 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4499 t1 = tcg_temp_new();
4500 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4501 tcg_gen_andi_tl(t1, t0, 7);
4502 #ifdef TARGET_WORDS_BIGENDIAN
4503 tcg_gen_xori_tl(t1, t1, 7);
4504 #endif
4505 tcg_gen_shli_tl(t1, t1, 3);
4506 tcg_gen_andi_tl(t0, t0, ~7);
4507 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4508 tcg_gen_shr_tl(t0, t0, t1);
4509 tcg_gen_xori_tl(t1, t1, 63);
4510 t2 = tcg_const_tl(0xfffffffffffffffeull);
4511 tcg_gen_shl_tl(t2, t2, t1);
4512 gen_load_fpr64(ctx, t1, rt);
4513 tcg_gen_and_tl(t1, t1, t2);
4514 tcg_temp_free(t2);
4515 tcg_gen_or_tl(t0, t0, t1);
4516 tcg_temp_free(t1);
4517 gen_store_fpr64(ctx, t0, rt);
4518 break;
4519 #endif
4520 default:
4521 MIPS_INVAL("loongson_gsshfl");
4522 gen_reserved_instruction(ctx);
4523 break;
4525 break;
4526 case OPC_GSSHFS:
4527 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4528 case OPC_GSSWLC1:
4529 check_cp1_enabled(ctx);
4530 t1 = tcg_temp_new();
4531 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4532 fp0 = tcg_temp_new_i32();
4533 gen_load_fpr32(ctx, fp0, rt);
4534 tcg_gen_ext_i32_tl(t1, fp0);
4535 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4536 tcg_temp_free_i32(fp0);
4537 tcg_temp_free(t1);
4538 break;
4539 case OPC_GSSWRC1:
4540 check_cp1_enabled(ctx);
4541 t1 = tcg_temp_new();
4542 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4543 fp0 = tcg_temp_new_i32();
4544 gen_load_fpr32(ctx, fp0, rt);
4545 tcg_gen_ext_i32_tl(t1, fp0);
4546 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4547 tcg_temp_free_i32(fp0);
4548 tcg_temp_free(t1);
4549 break;
4550 #if defined(TARGET_MIPS64)
4551 case OPC_GSSDLC1:
4552 check_cp1_enabled(ctx);
4553 t1 = tcg_temp_new();
4554 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4555 gen_load_fpr64(ctx, t1, rt);
4556 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4557 tcg_temp_free(t1);
4558 break;
4559 case OPC_GSSDRC1:
4560 check_cp1_enabled(ctx);
4561 t1 = tcg_temp_new();
4562 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4563 gen_load_fpr64(ctx, t1, rt);
4564 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4565 tcg_temp_free(t1);
4566 break;
4567 #endif
4568 default:
4569 MIPS_INVAL("loongson_gsshfs");
4570 gen_reserved_instruction(ctx);
4571 break;
4573 break;
4574 default:
4575 MIPS_INVAL("loongson_gslsq");
4576 gen_reserved_instruction(ctx);
4577 break;
4579 tcg_temp_free(t0);
4582 /* Loongson EXT LDC2/SDC2 */
4583 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4584 int rs, int rd)
4586 int offset = sextract32(ctx->opcode, 3, 8);
4587 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4588 TCGv t0, t1;
4589 TCGv_i32 fp0;
4591 /* Pre-conditions */
4592 switch (opc) {
4593 case OPC_GSLBX:
4594 case OPC_GSLHX:
4595 case OPC_GSLWX:
4596 case OPC_GSLDX:
4597 /* prefetch, implement as NOP */
4598 if (rt == 0) {
4599 return;
4601 break;
4602 case OPC_GSSBX:
4603 case OPC_GSSHX:
4604 case OPC_GSSWX:
4605 case OPC_GSSDX:
4606 break;
4607 case OPC_GSLWXC1:
4608 #if defined(TARGET_MIPS64)
4609 case OPC_GSLDXC1:
4610 #endif
4611 check_cp1_enabled(ctx);
4612 /* prefetch, implement as NOP */
4613 if (rt == 0) {
4614 return;
4616 break;
4617 case OPC_GSSWXC1:
4618 #if defined(TARGET_MIPS64)
4619 case OPC_GSSDXC1:
4620 #endif
4621 check_cp1_enabled(ctx);
4622 break;
4623 default:
4624 MIPS_INVAL("loongson_lsdc2");
4625 gen_reserved_instruction(ctx);
4626 return;
4627 break;
4630 t0 = tcg_temp_new();
4632 gen_base_offset_addr(ctx, t0, rs, offset);
4633 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4635 switch (opc) {
4636 case OPC_GSLBX:
4637 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4638 gen_store_gpr(t0, rt);
4639 break;
4640 case OPC_GSLHX:
4641 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4642 ctx->default_tcg_memop_mask);
4643 gen_store_gpr(t0, rt);
4644 break;
4645 case OPC_GSLWX:
4646 gen_base_offset_addr(ctx, t0, rs, offset);
4647 if (rd) {
4648 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4650 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4651 ctx->default_tcg_memop_mask);
4652 gen_store_gpr(t0, rt);
4653 break;
4654 #if defined(TARGET_MIPS64)
4655 case OPC_GSLDX:
4656 gen_base_offset_addr(ctx, t0, rs, offset);
4657 if (rd) {
4658 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4660 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4661 ctx->default_tcg_memop_mask);
4662 gen_store_gpr(t0, rt);
4663 break;
4664 #endif
4665 case OPC_GSLWXC1:
4666 gen_base_offset_addr(ctx, t0, rs, offset);
4667 if (rd) {
4668 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4670 fp0 = tcg_temp_new_i32();
4671 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
4672 ctx->default_tcg_memop_mask);
4673 gen_store_fpr32(ctx, fp0, rt);
4674 tcg_temp_free_i32(fp0);
4675 break;
4676 #if defined(TARGET_MIPS64)
4677 case OPC_GSLDXC1:
4678 gen_base_offset_addr(ctx, t0, rs, offset);
4679 if (rd) {
4680 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4682 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4683 ctx->default_tcg_memop_mask);
4684 gen_store_fpr64(ctx, t0, rt);
4685 break;
4686 #endif
4687 case OPC_GSSBX:
4688 t1 = tcg_temp_new();
4689 gen_load_gpr(t1, rt);
4690 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4691 tcg_temp_free(t1);
4692 break;
4693 case OPC_GSSHX:
4694 t1 = tcg_temp_new();
4695 gen_load_gpr(t1, rt);
4696 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
4697 ctx->default_tcg_memop_mask);
4698 tcg_temp_free(t1);
4699 break;
4700 case OPC_GSSWX:
4701 t1 = tcg_temp_new();
4702 gen_load_gpr(t1, rt);
4703 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
4704 ctx->default_tcg_memop_mask);
4705 tcg_temp_free(t1);
4706 break;
4707 #if defined(TARGET_MIPS64)
4708 case OPC_GSSDX:
4709 t1 = tcg_temp_new();
4710 gen_load_gpr(t1, rt);
4711 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4712 ctx->default_tcg_memop_mask);
4713 tcg_temp_free(t1);
4714 break;
4715 #endif
4716 case OPC_GSSWXC1:
4717 fp0 = tcg_temp_new_i32();
4718 gen_load_fpr32(ctx, fp0, rt);
4719 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
4720 ctx->default_tcg_memop_mask);
4721 tcg_temp_free_i32(fp0);
4722 break;
4723 #if defined(TARGET_MIPS64)
4724 case OPC_GSSDXC1:
4725 t1 = tcg_temp_new();
4726 gen_load_fpr64(ctx, t1, rt);
4727 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
4728 ctx->default_tcg_memop_mask);
4729 tcg_temp_free(t1);
4730 break;
4731 #endif
4732 default:
4733 break;
4736 tcg_temp_free(t0);
4739 /* Traps */
4740 static void gen_trap(DisasContext *ctx, uint32_t opc,
4741 int rs, int rt, int16_t imm)
4743 int cond;
4744 TCGv t0 = tcg_temp_new();
4745 TCGv t1 = tcg_temp_new();
4747 cond = 0;
4748 /* Load needed operands */
4749 switch (opc) {
4750 case OPC_TEQ:
4751 case OPC_TGE:
4752 case OPC_TGEU:
4753 case OPC_TLT:
4754 case OPC_TLTU:
4755 case OPC_TNE:
4756 /* Compare two registers */
4757 if (rs != rt) {
4758 gen_load_gpr(t0, rs);
4759 gen_load_gpr(t1, rt);
4760 cond = 1;
4762 break;
4763 case OPC_TEQI:
4764 case OPC_TGEI:
4765 case OPC_TGEIU:
4766 case OPC_TLTI:
4767 case OPC_TLTIU:
4768 case OPC_TNEI:
4769 /* Compare register to immediate */
4770 if (rs != 0 || imm != 0) {
4771 gen_load_gpr(t0, rs);
4772 tcg_gen_movi_tl(t1, (int32_t)imm);
4773 cond = 1;
4775 break;
4777 if (cond == 0) {
4778 switch (opc) {
4779 case OPC_TEQ: /* rs == rs */
4780 case OPC_TEQI: /* r0 == 0 */
4781 case OPC_TGE: /* rs >= rs */
4782 case OPC_TGEI: /* r0 >= 0 */
4783 case OPC_TGEU: /* rs >= rs unsigned */
4784 case OPC_TGEIU: /* r0 >= 0 unsigned */
4785 /* Always trap */
4786 generate_exception_end(ctx, EXCP_TRAP);
4787 break;
4788 case OPC_TLT: /* rs < rs */
4789 case OPC_TLTI: /* r0 < 0 */
4790 case OPC_TLTU: /* rs < rs unsigned */
4791 case OPC_TLTIU: /* r0 < 0 unsigned */
4792 case OPC_TNE: /* rs != rs */
4793 case OPC_TNEI: /* r0 != 0 */
4794 /* Never trap: treat as NOP. */
4795 break;
4797 } else {
4798 TCGLabel *l1 = gen_new_label();
4800 switch (opc) {
4801 case OPC_TEQ:
4802 case OPC_TEQI:
4803 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4804 break;
4805 case OPC_TGE:
4806 case OPC_TGEI:
4807 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4808 break;
4809 case OPC_TGEU:
4810 case OPC_TGEIU:
4811 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4812 break;
4813 case OPC_TLT:
4814 case OPC_TLTI:
4815 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4816 break;
4817 case OPC_TLTU:
4818 case OPC_TLTIU:
4819 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4820 break;
4821 case OPC_TNE:
4822 case OPC_TNEI:
4823 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4824 break;
4826 generate_exception(ctx, EXCP_TRAP);
4827 gen_set_label(l1);
4829 tcg_temp_free(t0);
4830 tcg_temp_free(t1);
4833 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4835 if (translator_use_goto_tb(&ctx->base, dest)) {
4836 tcg_gen_goto_tb(n);
4837 gen_save_pc(dest);
4838 tcg_gen_exit_tb(ctx->base.tb, n);
4839 } else {
4840 gen_save_pc(dest);
4841 if (ctx->base.singlestep_enabled) {
4842 save_cpu_state(ctx, 0);
4843 gen_helper_raise_exception_debug(cpu_env);
4844 } else {
4845 tcg_gen_lookup_and_goto_ptr();
4850 /* Branches (before delay slot) */
4851 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
4852 int insn_bytes,
4853 int rs, int rt, int32_t offset,
4854 int delayslot_size)
4856 target_ulong btgt = -1;
4857 int blink = 0;
4858 int bcond_compute = 0;
4859 TCGv t0 = tcg_temp_new();
4860 TCGv t1 = tcg_temp_new();
4862 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4863 #ifdef MIPS_DEBUG_DISAS
4864 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4865 TARGET_FMT_lx "\n", ctx->base.pc_next);
4866 #endif
4867 gen_reserved_instruction(ctx);
4868 goto out;
4871 /* Load needed operands */
4872 switch (opc) {
4873 case OPC_BEQ:
4874 case OPC_BEQL:
4875 case OPC_BNE:
4876 case OPC_BNEL:
4877 /* Compare two registers */
4878 if (rs != rt) {
4879 gen_load_gpr(t0, rs);
4880 gen_load_gpr(t1, rt);
4881 bcond_compute = 1;
4883 btgt = ctx->base.pc_next + insn_bytes + offset;
4884 break;
4885 case OPC_BGEZ:
4886 case OPC_BGEZAL:
4887 case OPC_BGEZALL:
4888 case OPC_BGEZL:
4889 case OPC_BGTZ:
4890 case OPC_BGTZL:
4891 case OPC_BLEZ:
4892 case OPC_BLEZL:
4893 case OPC_BLTZ:
4894 case OPC_BLTZAL:
4895 case OPC_BLTZALL:
4896 case OPC_BLTZL:
4897 /* Compare to zero */
4898 if (rs != 0) {
4899 gen_load_gpr(t0, rs);
4900 bcond_compute = 1;
4902 btgt = ctx->base.pc_next + insn_bytes + offset;
4903 break;
4904 case OPC_BPOSGE32:
4905 #if defined(TARGET_MIPS64)
4906 case OPC_BPOSGE64:
4907 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4908 #else
4909 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4910 #endif
4911 bcond_compute = 1;
4912 btgt = ctx->base.pc_next + insn_bytes + offset;
4913 break;
4914 case OPC_J:
4915 case OPC_JAL:
4916 case OPC_JALX:
4917 /* Jump to immediate */
4918 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
4919 (uint32_t)offset;
4920 break;
4921 case OPC_JR:
4922 case OPC_JALR:
4923 /* Jump to register */
4924 if (offset != 0 && offset != 16) {
4926 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4927 * others are reserved.
4929 MIPS_INVAL("jump hint");
4930 gen_reserved_instruction(ctx);
4931 goto out;
4933 gen_load_gpr(btarget, rs);
4934 break;
4935 default:
4936 MIPS_INVAL("branch/jump");
4937 gen_reserved_instruction(ctx);
4938 goto out;
4940 if (bcond_compute == 0) {
4941 /* No condition to be computed */
4942 switch (opc) {
4943 case OPC_BEQ: /* rx == rx */
4944 case OPC_BEQL: /* rx == rx likely */
4945 case OPC_BGEZ: /* 0 >= 0 */
4946 case OPC_BGEZL: /* 0 >= 0 likely */
4947 case OPC_BLEZ: /* 0 <= 0 */
4948 case OPC_BLEZL: /* 0 <= 0 likely */
4949 /* Always take */
4950 ctx->hflags |= MIPS_HFLAG_B;
4951 break;
4952 case OPC_BGEZAL: /* 0 >= 0 */
4953 case OPC_BGEZALL: /* 0 >= 0 likely */
4954 /* Always take and link */
4955 blink = 31;
4956 ctx->hflags |= MIPS_HFLAG_B;
4957 break;
4958 case OPC_BNE: /* rx != rx */
4959 case OPC_BGTZ: /* 0 > 0 */
4960 case OPC_BLTZ: /* 0 < 0 */
4961 /* Treat as NOP. */
4962 goto out;
4963 case OPC_BLTZAL: /* 0 < 0 */
4965 * Handle as an unconditional branch to get correct delay
4966 * slot checking.
4968 blink = 31;
4969 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
4970 ctx->hflags |= MIPS_HFLAG_B;
4971 break;
4972 case OPC_BLTZALL: /* 0 < 0 likely */
4973 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
4974 /* Skip the instruction in the delay slot */
4975 ctx->base.pc_next += 4;
4976 goto out;
4977 case OPC_BNEL: /* rx != rx likely */
4978 case OPC_BGTZL: /* 0 > 0 likely */
4979 case OPC_BLTZL: /* 0 < 0 likely */
4980 /* Skip the instruction in the delay slot */
4981 ctx->base.pc_next += 4;
4982 goto out;
4983 case OPC_J:
4984 ctx->hflags |= MIPS_HFLAG_B;
4985 break;
4986 case OPC_JALX:
4987 ctx->hflags |= MIPS_HFLAG_BX;
4988 /* Fallthrough */
4989 case OPC_JAL:
4990 blink = 31;
4991 ctx->hflags |= MIPS_HFLAG_B;
4992 break;
4993 case OPC_JR:
4994 ctx->hflags |= MIPS_HFLAG_BR;
4995 break;
4996 case OPC_JALR:
4997 blink = rt;
4998 ctx->hflags |= MIPS_HFLAG_BR;
4999 break;
5000 default:
5001 MIPS_INVAL("branch/jump");
5002 gen_reserved_instruction(ctx);
5003 goto out;
5005 } else {
5006 switch (opc) {
5007 case OPC_BEQ:
5008 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5009 goto not_likely;
5010 case OPC_BEQL:
5011 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5012 goto likely;
5013 case OPC_BNE:
5014 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5015 goto not_likely;
5016 case OPC_BNEL:
5017 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5018 goto likely;
5019 case OPC_BGEZ:
5020 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5021 goto not_likely;
5022 case OPC_BGEZL:
5023 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5024 goto likely;
5025 case OPC_BGEZAL:
5026 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5027 blink = 31;
5028 goto not_likely;
5029 case OPC_BGEZALL:
5030 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5031 blink = 31;
5032 goto likely;
5033 case OPC_BGTZ:
5034 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5035 goto not_likely;
5036 case OPC_BGTZL:
5037 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5038 goto likely;
5039 case OPC_BLEZ:
5040 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5041 goto not_likely;
5042 case OPC_BLEZL:
5043 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5044 goto likely;
5045 case OPC_BLTZ:
5046 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5047 goto not_likely;
5048 case OPC_BLTZL:
5049 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5050 goto likely;
5051 case OPC_BPOSGE32:
5052 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5053 goto not_likely;
5054 #if defined(TARGET_MIPS64)
5055 case OPC_BPOSGE64:
5056 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5057 goto not_likely;
5058 #endif
5059 case OPC_BLTZAL:
5060 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5061 blink = 31;
5062 not_likely:
5063 ctx->hflags |= MIPS_HFLAG_BC;
5064 break;
5065 case OPC_BLTZALL:
5066 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5067 blink = 31;
5068 likely:
5069 ctx->hflags |= MIPS_HFLAG_BL;
5070 break;
5071 default:
5072 MIPS_INVAL("conditional branch/jump");
5073 gen_reserved_instruction(ctx);
5074 goto out;
5078 ctx->btarget = btgt;
5080 switch (delayslot_size) {
5081 case 2:
5082 ctx->hflags |= MIPS_HFLAG_BDS16;
5083 break;
5084 case 4:
5085 ctx->hflags |= MIPS_HFLAG_BDS32;
5086 break;
5089 if (blink > 0) {
5090 int post_delay = insn_bytes + delayslot_size;
5091 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5093 tcg_gen_movi_tl(cpu_gpr[blink],
5094 ctx->base.pc_next + post_delay + lowbit);
5097 out:
5098 if (insn_bytes == 2) {
5099 ctx->hflags |= MIPS_HFLAG_B16;
5101 tcg_temp_free(t0);
5102 tcg_temp_free(t1);
5106 /* special3 bitfield operations */
5107 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5108 int rs, int lsb, int msb)
5110 TCGv t0 = tcg_temp_new();
5111 TCGv t1 = tcg_temp_new();
5113 gen_load_gpr(t1, rs);
5114 switch (opc) {
5115 case OPC_EXT:
5116 if (lsb + msb > 31) {
5117 goto fail;
5119 if (msb != 31) {
5120 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5121 } else {
5123 * The two checks together imply that lsb == 0,
5124 * so this is a simple sign-extension.
5126 tcg_gen_ext32s_tl(t0, t1);
5128 break;
5129 #if defined(TARGET_MIPS64)
5130 case OPC_DEXTU:
5131 lsb += 32;
5132 goto do_dext;
5133 case OPC_DEXTM:
5134 msb += 32;
5135 goto do_dext;
5136 case OPC_DEXT:
5137 do_dext:
5138 if (lsb + msb > 63) {
5139 goto fail;
5141 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5142 break;
5143 #endif
5144 case OPC_INS:
5145 if (lsb > msb) {
5146 goto fail;
5148 gen_load_gpr(t0, rt);
5149 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5150 tcg_gen_ext32s_tl(t0, t0);
5151 break;
5152 #if defined(TARGET_MIPS64)
5153 case OPC_DINSU:
5154 lsb += 32;
5155 /* FALLTHRU */
5156 case OPC_DINSM:
5157 msb += 32;
5158 /* FALLTHRU */
5159 case OPC_DINS:
5160 if (lsb > msb) {
5161 goto fail;
5163 gen_load_gpr(t0, rt);
5164 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5165 break;
5166 #endif
5167 default:
5168 fail:
5169 MIPS_INVAL("bitops");
5170 gen_reserved_instruction(ctx);
5171 tcg_temp_free(t0);
5172 tcg_temp_free(t1);
5173 return;
5175 gen_store_gpr(t0, rt);
5176 tcg_temp_free(t0);
5177 tcg_temp_free(t1);
5180 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
5182 TCGv t0;
5184 if (rd == 0) {
5185 /* If no destination, treat it as a NOP. */
5186 return;
5189 t0 = tcg_temp_new();
5190 gen_load_gpr(t0, rt);
5191 switch (op2) {
5192 case OPC_WSBH:
5194 TCGv t1 = tcg_temp_new();
5195 TCGv t2 = tcg_const_tl(0x00FF00FF);
5197 tcg_gen_shri_tl(t1, t0, 8);
5198 tcg_gen_and_tl(t1, t1, t2);
5199 tcg_gen_and_tl(t0, t0, t2);
5200 tcg_gen_shli_tl(t0, t0, 8);
5201 tcg_gen_or_tl(t0, t0, t1);
5202 tcg_temp_free(t2);
5203 tcg_temp_free(t1);
5204 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5206 break;
5207 case OPC_SEB:
5208 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5209 break;
5210 case OPC_SEH:
5211 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5212 break;
5213 #if defined(TARGET_MIPS64)
5214 case OPC_DSBH:
5216 TCGv t1 = tcg_temp_new();
5217 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5219 tcg_gen_shri_tl(t1, t0, 8);
5220 tcg_gen_and_tl(t1, t1, t2);
5221 tcg_gen_and_tl(t0, t0, t2);
5222 tcg_gen_shli_tl(t0, t0, 8);
5223 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5224 tcg_temp_free(t2);
5225 tcg_temp_free(t1);
5227 break;
5228 case OPC_DSHD:
5230 TCGv t1 = tcg_temp_new();
5231 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5233 tcg_gen_shri_tl(t1, t0, 16);
5234 tcg_gen_and_tl(t1, t1, t2);
5235 tcg_gen_and_tl(t0, t0, t2);
5236 tcg_gen_shli_tl(t0, t0, 16);
5237 tcg_gen_or_tl(t0, t0, t1);
5238 tcg_gen_shri_tl(t1, t0, 32);
5239 tcg_gen_shli_tl(t0, t0, 32);
5240 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5241 tcg_temp_free(t2);
5242 tcg_temp_free(t1);
5244 break;
5245 #endif
5246 default:
5247 MIPS_INVAL("bsfhl");
5248 gen_reserved_instruction(ctx);
5249 tcg_temp_free(t0);
5250 return;
5252 tcg_temp_free(t0);
5255 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5256 int rt, int bits)
5258 TCGv t0;
5259 if (rd == 0) {
5260 /* Treat as NOP. */
5261 return;
5263 t0 = tcg_temp_new();
5264 if (bits == 0 || bits == wordsz) {
5265 if (bits == 0) {
5266 gen_load_gpr(t0, rt);
5267 } else {
5268 gen_load_gpr(t0, rs);
5270 switch (wordsz) {
5271 case 32:
5272 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5273 break;
5274 #if defined(TARGET_MIPS64)
5275 case 64:
5276 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5277 break;
5278 #endif
5280 } else {
5281 TCGv t1 = tcg_temp_new();
5282 gen_load_gpr(t0, rt);
5283 gen_load_gpr(t1, rs);
5284 switch (wordsz) {
5285 case 32:
5287 TCGv_i64 t2 = tcg_temp_new_i64();
5288 tcg_gen_concat_tl_i64(t2, t1, t0);
5289 tcg_gen_shri_i64(t2, t2, 32 - bits);
5290 gen_move_low32(cpu_gpr[rd], t2);
5291 tcg_temp_free_i64(t2);
5293 break;
5294 #if defined(TARGET_MIPS64)
5295 case 64:
5296 tcg_gen_shli_tl(t0, t0, bits);
5297 tcg_gen_shri_tl(t1, t1, 64 - bits);
5298 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5299 break;
5300 #endif
5302 tcg_temp_free(t1);
5305 tcg_temp_free(t0);
5308 void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp)
5310 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5313 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5315 TCGv t0;
5316 if (rd == 0) {
5317 /* Treat as NOP. */
5318 return;
5320 t0 = tcg_temp_new();
5321 gen_load_gpr(t0, rt);
5322 switch (opc) {
5323 case OPC_BITSWAP:
5324 gen_helper_bitswap(cpu_gpr[rd], t0);
5325 break;
5326 #if defined(TARGET_MIPS64)
5327 case OPC_DBITSWAP:
5328 gen_helper_dbitswap(cpu_gpr[rd], t0);
5329 break;
5330 #endif
5332 tcg_temp_free(t0);
5335 #ifndef CONFIG_USER_ONLY
5336 /* CP0 (MMU and control) */
5337 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5339 TCGv_i64 t0 = tcg_temp_new_i64();
5340 TCGv_i64 t1 = tcg_temp_new_i64();
5342 tcg_gen_ext_tl_i64(t0, arg);
5343 tcg_gen_ld_i64(t1, cpu_env, off);
5344 #if defined(TARGET_MIPS64)
5345 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5346 #else
5347 tcg_gen_concat32_i64(t1, t1, t0);
5348 #endif
5349 tcg_gen_st_i64(t1, cpu_env, off);
5350 tcg_temp_free_i64(t1);
5351 tcg_temp_free_i64(t0);
5354 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5356 TCGv_i64 t0 = tcg_temp_new_i64();
5357 TCGv_i64 t1 = tcg_temp_new_i64();
5359 tcg_gen_ext_tl_i64(t0, arg);
5360 tcg_gen_ld_i64(t1, cpu_env, off);
5361 tcg_gen_concat32_i64(t1, t1, t0);
5362 tcg_gen_st_i64(t1, cpu_env, off);
5363 tcg_temp_free_i64(t1);
5364 tcg_temp_free_i64(t0);
5367 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5369 TCGv_i64 t0 = tcg_temp_new_i64();
5371 tcg_gen_ld_i64(t0, cpu_env, off);
5372 #if defined(TARGET_MIPS64)
5373 tcg_gen_shri_i64(t0, t0, 30);
5374 #else
5375 tcg_gen_shri_i64(t0, t0, 32);
5376 #endif
5377 gen_move_low32(arg, t0);
5378 tcg_temp_free_i64(t0);
5381 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5383 TCGv_i64 t0 = tcg_temp_new_i64();
5385 tcg_gen_ld_i64(t0, cpu_env, off);
5386 tcg_gen_shri_i64(t0, t0, 32 + shift);
5387 gen_move_low32(arg, t0);
5388 tcg_temp_free_i64(t0);
5391 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
5393 TCGv_i32 t0 = tcg_temp_new_i32();
5395 tcg_gen_ld_i32(t0, cpu_env, off);
5396 tcg_gen_ext_i32_tl(arg, t0);
5397 tcg_temp_free_i32(t0);
5400 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
5402 tcg_gen_ld_tl(arg, cpu_env, off);
5403 tcg_gen_ext32s_tl(arg, arg);
5406 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
5408 TCGv_i32 t0 = tcg_temp_new_i32();
5410 tcg_gen_trunc_tl_i32(t0, arg);
5411 tcg_gen_st_i32(t0, cpu_env, off);
5412 tcg_temp_free_i32(t0);
5415 #define CP0_CHECK(c) \
5416 do { \
5417 if (!(c)) { \
5418 goto cp0_unimplemented; \
5420 } while (0)
5422 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5424 const char *register_name = "invalid";
5426 switch (reg) {
5427 case CP0_REGISTER_02:
5428 switch (sel) {
5429 case 0:
5430 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5431 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5432 register_name = "EntryLo0";
5433 break;
5434 default:
5435 goto cp0_unimplemented;
5437 break;
5438 case CP0_REGISTER_03:
5439 switch (sel) {
5440 case CP0_REG03__ENTRYLO1:
5441 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5442 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5443 register_name = "EntryLo1";
5444 break;
5445 default:
5446 goto cp0_unimplemented;
5448 break;
5449 case CP0_REGISTER_09:
5450 switch (sel) {
5451 case CP0_REG09__SAAR:
5452 CP0_CHECK(ctx->saar);
5453 gen_helper_mfhc0_saar(arg, cpu_env);
5454 register_name = "SAAR";
5455 break;
5456 default:
5457 goto cp0_unimplemented;
5459 break;
5460 case CP0_REGISTER_17:
5461 switch (sel) {
5462 case CP0_REG17__LLADDR:
5463 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5464 ctx->CP0_LLAddr_shift);
5465 register_name = "LLAddr";
5466 break;
5467 case CP0_REG17__MAAR:
5468 CP0_CHECK(ctx->mrp);
5469 gen_helper_mfhc0_maar(arg, cpu_env);
5470 register_name = "MAAR";
5471 break;
5472 default:
5473 goto cp0_unimplemented;
5475 break;
5476 case CP0_REGISTER_19:
5477 switch (sel) {
5478 case CP0_REG19__WATCHHI0:
5479 case CP0_REG19__WATCHHI1:
5480 case CP0_REG19__WATCHHI2:
5481 case CP0_REG19__WATCHHI3:
5482 case CP0_REG19__WATCHHI4:
5483 case CP0_REG19__WATCHHI5:
5484 case CP0_REG19__WATCHHI6:
5485 case CP0_REG19__WATCHHI7:
5486 /* upper 32 bits are only available when Config5MI != 0 */
5487 CP0_CHECK(ctx->mi);
5488 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5489 register_name = "WatchHi";
5490 break;
5491 default:
5492 goto cp0_unimplemented;
5494 break;
5495 case CP0_REGISTER_28:
5496 switch (sel) {
5497 case 0:
5498 case 2:
5499 case 4:
5500 case 6:
5501 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5502 register_name = "TagLo";
5503 break;
5504 default:
5505 goto cp0_unimplemented;
5507 break;
5508 default:
5509 goto cp0_unimplemented;
5511 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5512 return;
5514 cp0_unimplemented:
5515 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
5516 register_name, reg, sel);
5517 tcg_gen_movi_tl(arg, 0);
5520 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5522 const char *register_name = "invalid";
5523 uint64_t mask = ctx->PAMask >> 36;
5525 switch (reg) {
5526 case CP0_REGISTER_02:
5527 switch (sel) {
5528 case 0:
5529 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5530 tcg_gen_andi_tl(arg, arg, mask);
5531 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5532 register_name = "EntryLo0";
5533 break;
5534 default:
5535 goto cp0_unimplemented;
5537 break;
5538 case CP0_REGISTER_03:
5539 switch (sel) {
5540 case CP0_REG03__ENTRYLO1:
5541 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5542 tcg_gen_andi_tl(arg, arg, mask);
5543 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5544 register_name = "EntryLo1";
5545 break;
5546 default:
5547 goto cp0_unimplemented;
5549 break;
5550 case CP0_REGISTER_09:
5551 switch (sel) {
5552 case CP0_REG09__SAAR:
5553 CP0_CHECK(ctx->saar);
5554 gen_helper_mthc0_saar(cpu_env, arg);
5555 register_name = "SAAR";
5556 break;
5557 default:
5558 goto cp0_unimplemented;
5560 break;
5561 case CP0_REGISTER_17:
5562 switch (sel) {
5563 case CP0_REG17__LLADDR:
5565 * LLAddr is read-only (the only exception is bit 0 if LLB is
5566 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5567 * relevant for modern MIPS cores supporting MTHC0, therefore
5568 * treating MTHC0 to LLAddr as NOP.
5570 register_name = "LLAddr";
5571 break;
5572 case CP0_REG17__MAAR:
5573 CP0_CHECK(ctx->mrp);
5574 gen_helper_mthc0_maar(cpu_env, arg);
5575 register_name = "MAAR";
5576 break;
5577 default:
5578 goto cp0_unimplemented;
5580 break;
5581 case CP0_REGISTER_19:
5582 switch (sel) {
5583 case CP0_REG19__WATCHHI0:
5584 case CP0_REG19__WATCHHI1:
5585 case CP0_REG19__WATCHHI2:
5586 case CP0_REG19__WATCHHI3:
5587 case CP0_REG19__WATCHHI4:
5588 case CP0_REG19__WATCHHI5:
5589 case CP0_REG19__WATCHHI6:
5590 case CP0_REG19__WATCHHI7:
5591 /* upper 32 bits are only available when Config5MI != 0 */
5592 CP0_CHECK(ctx->mi);
5593 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5594 register_name = "WatchHi";
5595 break;
5596 default:
5597 goto cp0_unimplemented;
5599 break;
5600 case CP0_REGISTER_28:
5601 switch (sel) {
5602 case 0:
5603 case 2:
5604 case 4:
5605 case 6:
5606 tcg_gen_andi_tl(arg, arg, mask);
5607 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5608 register_name = "TagLo";
5609 break;
5610 default:
5611 goto cp0_unimplemented;
5613 break;
5614 default:
5615 goto cp0_unimplemented;
5617 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5618 return;
5620 cp0_unimplemented:
5621 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5622 register_name, reg, sel);
5625 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5627 if (ctx->insn_flags & ISA_MIPS_R6) {
5628 tcg_gen_movi_tl(arg, 0);
5629 } else {
5630 tcg_gen_movi_tl(arg, ~0);
5634 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5636 const char *register_name = "invalid";
5638 if (sel != 0) {
5639 check_insn(ctx, ISA_MIPS_R1);
5642 switch (reg) {
5643 case CP0_REGISTER_00:
5644 switch (sel) {
5645 case CP0_REG00__INDEX:
5646 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5647 register_name = "Index";
5648 break;
5649 case CP0_REG00__MVPCONTROL:
5650 CP0_CHECK(ctx->insn_flags & ASE_MT);
5651 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5652 register_name = "MVPControl";
5653 break;
5654 case CP0_REG00__MVPCONF0:
5655 CP0_CHECK(ctx->insn_flags & ASE_MT);
5656 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5657 register_name = "MVPConf0";
5658 break;
5659 case CP0_REG00__MVPCONF1:
5660 CP0_CHECK(ctx->insn_flags & ASE_MT);
5661 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5662 register_name = "MVPConf1";
5663 break;
5664 case CP0_REG00__VPCONTROL:
5665 CP0_CHECK(ctx->vp);
5666 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5667 register_name = "VPControl";
5668 break;
5669 default:
5670 goto cp0_unimplemented;
5672 break;
5673 case CP0_REGISTER_01:
5674 switch (sel) {
5675 case CP0_REG01__RANDOM:
5676 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
5677 gen_helper_mfc0_random(arg, cpu_env);
5678 register_name = "Random";
5679 break;
5680 case CP0_REG01__VPECONTROL:
5681 CP0_CHECK(ctx->insn_flags & ASE_MT);
5682 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5683 register_name = "VPEControl";
5684 break;
5685 case CP0_REG01__VPECONF0:
5686 CP0_CHECK(ctx->insn_flags & ASE_MT);
5687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5688 register_name = "VPEConf0";
5689 break;
5690 case CP0_REG01__VPECONF1:
5691 CP0_CHECK(ctx->insn_flags & ASE_MT);
5692 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5693 register_name = "VPEConf1";
5694 break;
5695 case CP0_REG01__YQMASK:
5696 CP0_CHECK(ctx->insn_flags & ASE_MT);
5697 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5698 register_name = "YQMask";
5699 break;
5700 case CP0_REG01__VPESCHEDULE:
5701 CP0_CHECK(ctx->insn_flags & ASE_MT);
5702 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5703 register_name = "VPESchedule";
5704 break;
5705 case CP0_REG01__VPESCHEFBACK:
5706 CP0_CHECK(ctx->insn_flags & ASE_MT);
5707 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5708 register_name = "VPEScheFBack";
5709 break;
5710 case CP0_REG01__VPEOPT:
5711 CP0_CHECK(ctx->insn_flags & ASE_MT);
5712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5713 register_name = "VPEOpt";
5714 break;
5715 default:
5716 goto cp0_unimplemented;
5718 break;
5719 case CP0_REGISTER_02:
5720 switch (sel) {
5721 case CP0_REG02__ENTRYLO0:
5723 TCGv_i64 tmp = tcg_temp_new_i64();
5724 tcg_gen_ld_i64(tmp, cpu_env,
5725 offsetof(CPUMIPSState, CP0_EntryLo0));
5726 #if defined(TARGET_MIPS64)
5727 if (ctx->rxi) {
5728 /* Move RI/XI fields to bits 31:30 */
5729 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5730 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5732 #endif
5733 gen_move_low32(arg, tmp);
5734 tcg_temp_free_i64(tmp);
5736 register_name = "EntryLo0";
5737 break;
5738 case CP0_REG02__TCSTATUS:
5739 CP0_CHECK(ctx->insn_flags & ASE_MT);
5740 gen_helper_mfc0_tcstatus(arg, cpu_env);
5741 register_name = "TCStatus";
5742 break;
5743 case CP0_REG02__TCBIND:
5744 CP0_CHECK(ctx->insn_flags & ASE_MT);
5745 gen_helper_mfc0_tcbind(arg, cpu_env);
5746 register_name = "TCBind";
5747 break;
5748 case CP0_REG02__TCRESTART:
5749 CP0_CHECK(ctx->insn_flags & ASE_MT);
5750 gen_helper_mfc0_tcrestart(arg, cpu_env);
5751 register_name = "TCRestart";
5752 break;
5753 case CP0_REG02__TCHALT:
5754 CP0_CHECK(ctx->insn_flags & ASE_MT);
5755 gen_helper_mfc0_tchalt(arg, cpu_env);
5756 register_name = "TCHalt";
5757 break;
5758 case CP0_REG02__TCCONTEXT:
5759 CP0_CHECK(ctx->insn_flags & ASE_MT);
5760 gen_helper_mfc0_tccontext(arg, cpu_env);
5761 register_name = "TCContext";
5762 break;
5763 case CP0_REG02__TCSCHEDULE:
5764 CP0_CHECK(ctx->insn_flags & ASE_MT);
5765 gen_helper_mfc0_tcschedule(arg, cpu_env);
5766 register_name = "TCSchedule";
5767 break;
5768 case CP0_REG02__TCSCHEFBACK:
5769 CP0_CHECK(ctx->insn_flags & ASE_MT);
5770 gen_helper_mfc0_tcschefback(arg, cpu_env);
5771 register_name = "TCScheFBack";
5772 break;
5773 default:
5774 goto cp0_unimplemented;
5776 break;
5777 case CP0_REGISTER_03:
5778 switch (sel) {
5779 case CP0_REG03__ENTRYLO1:
5781 TCGv_i64 tmp = tcg_temp_new_i64();
5782 tcg_gen_ld_i64(tmp, cpu_env,
5783 offsetof(CPUMIPSState, CP0_EntryLo1));
5784 #if defined(TARGET_MIPS64)
5785 if (ctx->rxi) {
5786 /* Move RI/XI fields to bits 31:30 */
5787 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5788 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5790 #endif
5791 gen_move_low32(arg, tmp);
5792 tcg_temp_free_i64(tmp);
5794 register_name = "EntryLo1";
5795 break;
5796 case CP0_REG03__GLOBALNUM:
5797 CP0_CHECK(ctx->vp);
5798 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5799 register_name = "GlobalNumber";
5800 break;
5801 default:
5802 goto cp0_unimplemented;
5804 break;
5805 case CP0_REGISTER_04:
5806 switch (sel) {
5807 case CP0_REG04__CONTEXT:
5808 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5809 tcg_gen_ext32s_tl(arg, arg);
5810 register_name = "Context";
5811 break;
5812 case CP0_REG04__CONTEXTCONFIG:
5813 /* SmartMIPS ASE */
5814 /* gen_helper_mfc0_contextconfig(arg); */
5815 register_name = "ContextConfig";
5816 goto cp0_unimplemented;
5817 case CP0_REG04__USERLOCAL:
5818 CP0_CHECK(ctx->ulri);
5819 tcg_gen_ld_tl(arg, cpu_env,
5820 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5821 tcg_gen_ext32s_tl(arg, arg);
5822 register_name = "UserLocal";
5823 break;
5824 case CP0_REG04__MMID:
5825 CP0_CHECK(ctx->mi);
5826 gen_helper_mtc0_memorymapid(cpu_env, arg);
5827 register_name = "MMID";
5828 break;
5829 default:
5830 goto cp0_unimplemented;
5832 break;
5833 case CP0_REGISTER_05:
5834 switch (sel) {
5835 case CP0_REG05__PAGEMASK:
5836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5837 register_name = "PageMask";
5838 break;
5839 case CP0_REG05__PAGEGRAIN:
5840 check_insn(ctx, ISA_MIPS_R2);
5841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5842 register_name = "PageGrain";
5843 break;
5844 case CP0_REG05__SEGCTL0:
5845 CP0_CHECK(ctx->sc);
5846 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5847 tcg_gen_ext32s_tl(arg, arg);
5848 register_name = "SegCtl0";
5849 break;
5850 case CP0_REG05__SEGCTL1:
5851 CP0_CHECK(ctx->sc);
5852 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5853 tcg_gen_ext32s_tl(arg, arg);
5854 register_name = "SegCtl1";
5855 break;
5856 case CP0_REG05__SEGCTL2:
5857 CP0_CHECK(ctx->sc);
5858 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5859 tcg_gen_ext32s_tl(arg, arg);
5860 register_name = "SegCtl2";
5861 break;
5862 case CP0_REG05__PWBASE:
5863 check_pw(ctx);
5864 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
5865 register_name = "PWBase";
5866 break;
5867 case CP0_REG05__PWFIELD:
5868 check_pw(ctx);
5869 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
5870 register_name = "PWField";
5871 break;
5872 case CP0_REG05__PWSIZE:
5873 check_pw(ctx);
5874 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
5875 register_name = "PWSize";
5876 break;
5877 default:
5878 goto cp0_unimplemented;
5880 break;
5881 case CP0_REGISTER_06:
5882 switch (sel) {
5883 case CP0_REG06__WIRED:
5884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5885 register_name = "Wired";
5886 break;
5887 case CP0_REG06__SRSCONF0:
5888 check_insn(ctx, ISA_MIPS_R2);
5889 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5890 register_name = "SRSConf0";
5891 break;
5892 case CP0_REG06__SRSCONF1:
5893 check_insn(ctx, ISA_MIPS_R2);
5894 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5895 register_name = "SRSConf1";
5896 break;
5897 case CP0_REG06__SRSCONF2:
5898 check_insn(ctx, ISA_MIPS_R2);
5899 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5900 register_name = "SRSConf2";
5901 break;
5902 case CP0_REG06__SRSCONF3:
5903 check_insn(ctx, ISA_MIPS_R2);
5904 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5905 register_name = "SRSConf3";
5906 break;
5907 case CP0_REG06__SRSCONF4:
5908 check_insn(ctx, ISA_MIPS_R2);
5909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5910 register_name = "SRSConf4";
5911 break;
5912 case CP0_REG06__PWCTL:
5913 check_pw(ctx);
5914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
5915 register_name = "PWCtl";
5916 break;
5917 default:
5918 goto cp0_unimplemented;
5920 break;
5921 case CP0_REGISTER_07:
5922 switch (sel) {
5923 case CP0_REG07__HWRENA:
5924 check_insn(ctx, ISA_MIPS_R2);
5925 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5926 register_name = "HWREna";
5927 break;
5928 default:
5929 goto cp0_unimplemented;
5931 break;
5932 case CP0_REGISTER_08:
5933 switch (sel) {
5934 case CP0_REG08__BADVADDR:
5935 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5936 tcg_gen_ext32s_tl(arg, arg);
5937 register_name = "BadVAddr";
5938 break;
5939 case CP0_REG08__BADINSTR:
5940 CP0_CHECK(ctx->bi);
5941 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5942 register_name = "BadInstr";
5943 break;
5944 case CP0_REG08__BADINSTRP:
5945 CP0_CHECK(ctx->bp);
5946 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5947 register_name = "BadInstrP";
5948 break;
5949 case CP0_REG08__BADINSTRX:
5950 CP0_CHECK(ctx->bi);
5951 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
5952 tcg_gen_andi_tl(arg, arg, ~0xffff);
5953 register_name = "BadInstrX";
5954 break;
5955 default:
5956 goto cp0_unimplemented;
5958 break;
5959 case CP0_REGISTER_09:
5960 switch (sel) {
5961 case CP0_REG09__COUNT:
5962 /* Mark as an IO operation because we read the time. */
5963 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
5964 gen_io_start();
5966 gen_helper_mfc0_count(arg, cpu_env);
5968 * Break the TB to be able to take timer interrupts immediately
5969 * after reading count. DISAS_STOP isn't sufficient, we need to
5970 * ensure we break completely out of translated code.
5972 gen_save_pc(ctx->base.pc_next + 4);
5973 ctx->base.is_jmp = DISAS_EXIT;
5974 register_name = "Count";
5975 break;
5976 case CP0_REG09__SAARI:
5977 CP0_CHECK(ctx->saar);
5978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
5979 register_name = "SAARI";
5980 break;
5981 case CP0_REG09__SAAR:
5982 CP0_CHECK(ctx->saar);
5983 gen_helper_mfc0_saar(arg, cpu_env);
5984 register_name = "SAAR";
5985 break;
5986 default:
5987 goto cp0_unimplemented;
5989 break;
5990 case CP0_REGISTER_10:
5991 switch (sel) {
5992 case CP0_REG10__ENTRYHI:
5993 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5994 tcg_gen_ext32s_tl(arg, arg);
5995 register_name = "EntryHi";
5996 break;
5997 default:
5998 goto cp0_unimplemented;
6000 break;
6001 case CP0_REGISTER_11:
6002 switch (sel) {
6003 case CP0_REG11__COMPARE:
6004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6005 register_name = "Compare";
6006 break;
6007 /* 6,7 are implementation dependent */
6008 default:
6009 goto cp0_unimplemented;
6011 break;
6012 case CP0_REGISTER_12:
6013 switch (sel) {
6014 case CP0_REG12__STATUS:
6015 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6016 register_name = "Status";
6017 break;
6018 case CP0_REG12__INTCTL:
6019 check_insn(ctx, ISA_MIPS_R2);
6020 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6021 register_name = "IntCtl";
6022 break;
6023 case CP0_REG12__SRSCTL:
6024 check_insn(ctx, ISA_MIPS_R2);
6025 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6026 register_name = "SRSCtl";
6027 break;
6028 case CP0_REG12__SRSMAP:
6029 check_insn(ctx, ISA_MIPS_R2);
6030 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6031 register_name = "SRSMap";
6032 break;
6033 default:
6034 goto cp0_unimplemented;
6036 break;
6037 case CP0_REGISTER_13:
6038 switch (sel) {
6039 case CP0_REG13__CAUSE:
6040 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6041 register_name = "Cause";
6042 break;
6043 default:
6044 goto cp0_unimplemented;
6046 break;
6047 case CP0_REGISTER_14:
6048 switch (sel) {
6049 case CP0_REG14__EPC:
6050 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6051 tcg_gen_ext32s_tl(arg, arg);
6052 register_name = "EPC";
6053 break;
6054 default:
6055 goto cp0_unimplemented;
6057 break;
6058 case CP0_REGISTER_15:
6059 switch (sel) {
6060 case CP0_REG15__PRID:
6061 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6062 register_name = "PRid";
6063 break;
6064 case CP0_REG15__EBASE:
6065 check_insn(ctx, ISA_MIPS_R2);
6066 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6067 tcg_gen_ext32s_tl(arg, arg);
6068 register_name = "EBase";
6069 break;
6070 case CP0_REG15__CMGCRBASE:
6071 check_insn(ctx, ISA_MIPS_R2);
6072 CP0_CHECK(ctx->cmgcr);
6073 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6074 tcg_gen_ext32s_tl(arg, arg);
6075 register_name = "CMGCRBase";
6076 break;
6077 default:
6078 goto cp0_unimplemented;
6080 break;
6081 case CP0_REGISTER_16:
6082 switch (sel) {
6083 case CP0_REG16__CONFIG:
6084 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6085 register_name = "Config";
6086 break;
6087 case CP0_REG16__CONFIG1:
6088 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6089 register_name = "Config1";
6090 break;
6091 case CP0_REG16__CONFIG2:
6092 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6093 register_name = "Config2";
6094 break;
6095 case CP0_REG16__CONFIG3:
6096 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6097 register_name = "Config3";
6098 break;
6099 case CP0_REG16__CONFIG4:
6100 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6101 register_name = "Config4";
6102 break;
6103 case CP0_REG16__CONFIG5:
6104 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6105 register_name = "Config5";
6106 break;
6107 /* 6,7 are implementation dependent */
6108 case CP0_REG16__CONFIG6:
6109 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6110 register_name = "Config6";
6111 break;
6112 case CP0_REG16__CONFIG7:
6113 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6114 register_name = "Config7";
6115 break;
6116 default:
6117 goto cp0_unimplemented;
6119 break;
6120 case CP0_REGISTER_17:
6121 switch (sel) {
6122 case CP0_REG17__LLADDR:
6123 gen_helper_mfc0_lladdr(arg, cpu_env);
6124 register_name = "LLAddr";
6125 break;
6126 case CP0_REG17__MAAR:
6127 CP0_CHECK(ctx->mrp);
6128 gen_helper_mfc0_maar(arg, cpu_env);
6129 register_name = "MAAR";
6130 break;
6131 case CP0_REG17__MAARI:
6132 CP0_CHECK(ctx->mrp);
6133 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6134 register_name = "MAARI";
6135 break;
6136 default:
6137 goto cp0_unimplemented;
6139 break;
6140 case CP0_REGISTER_18:
6141 switch (sel) {
6142 case CP0_REG18__WATCHLO0:
6143 case CP0_REG18__WATCHLO1:
6144 case CP0_REG18__WATCHLO2:
6145 case CP0_REG18__WATCHLO3:
6146 case CP0_REG18__WATCHLO4:
6147 case CP0_REG18__WATCHLO5:
6148 case CP0_REG18__WATCHLO6:
6149 case CP0_REG18__WATCHLO7:
6150 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6151 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6152 register_name = "WatchLo";
6153 break;
6154 default:
6155 goto cp0_unimplemented;
6157 break;
6158 case CP0_REGISTER_19:
6159 switch (sel) {
6160 case CP0_REG19__WATCHHI0:
6161 case CP0_REG19__WATCHHI1:
6162 case CP0_REG19__WATCHHI2:
6163 case CP0_REG19__WATCHHI3:
6164 case CP0_REG19__WATCHHI4:
6165 case CP0_REG19__WATCHHI5:
6166 case CP0_REG19__WATCHHI6:
6167 case CP0_REG19__WATCHHI7:
6168 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6169 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6170 register_name = "WatchHi";
6171 break;
6172 default:
6173 goto cp0_unimplemented;
6175 break;
6176 case CP0_REGISTER_20:
6177 switch (sel) {
6178 case CP0_REG20__XCONTEXT:
6179 #if defined(TARGET_MIPS64)
6180 check_insn(ctx, ISA_MIPS3);
6181 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6182 tcg_gen_ext32s_tl(arg, arg);
6183 register_name = "XContext";
6184 break;
6185 #endif
6186 default:
6187 goto cp0_unimplemented;
6189 break;
6190 case CP0_REGISTER_21:
6191 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6192 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6193 switch (sel) {
6194 case 0:
6195 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6196 register_name = "Framemask";
6197 break;
6198 default:
6199 goto cp0_unimplemented;
6201 break;
6202 case CP0_REGISTER_22:
6203 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6204 register_name = "'Diagnostic"; /* implementation dependent */
6205 break;
6206 case CP0_REGISTER_23:
6207 switch (sel) {
6208 case CP0_REG23__DEBUG:
6209 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6210 register_name = "Debug";
6211 break;
6212 case CP0_REG23__TRACECONTROL:
6213 /* PDtrace support */
6214 /* gen_helper_mfc0_tracecontrol(arg); */
6215 register_name = "TraceControl";
6216 goto cp0_unimplemented;
6217 case CP0_REG23__TRACECONTROL2:
6218 /* PDtrace support */
6219 /* gen_helper_mfc0_tracecontrol2(arg); */
6220 register_name = "TraceControl2";
6221 goto cp0_unimplemented;
6222 case CP0_REG23__USERTRACEDATA1:
6223 /* PDtrace support */
6224 /* gen_helper_mfc0_usertracedata1(arg);*/
6225 register_name = "UserTraceData1";
6226 goto cp0_unimplemented;
6227 case CP0_REG23__TRACEIBPC:
6228 /* PDtrace support */
6229 /* gen_helper_mfc0_traceibpc(arg); */
6230 register_name = "TraceIBPC";
6231 goto cp0_unimplemented;
6232 case CP0_REG23__TRACEDBPC:
6233 /* PDtrace support */
6234 /* gen_helper_mfc0_tracedbpc(arg); */
6235 register_name = "TraceDBPC";
6236 goto cp0_unimplemented;
6237 default:
6238 goto cp0_unimplemented;
6240 break;
6241 case CP0_REGISTER_24:
6242 switch (sel) {
6243 case CP0_REG24__DEPC:
6244 /* EJTAG support */
6245 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6246 tcg_gen_ext32s_tl(arg, arg);
6247 register_name = "DEPC";
6248 break;
6249 default:
6250 goto cp0_unimplemented;
6252 break;
6253 case CP0_REGISTER_25:
6254 switch (sel) {
6255 case CP0_REG25__PERFCTL0:
6256 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6257 register_name = "Performance0";
6258 break;
6259 case CP0_REG25__PERFCNT0:
6260 /* gen_helper_mfc0_performance1(arg); */
6261 register_name = "Performance1";
6262 goto cp0_unimplemented;
6263 case CP0_REG25__PERFCTL1:
6264 /* gen_helper_mfc0_performance2(arg); */
6265 register_name = "Performance2";
6266 goto cp0_unimplemented;
6267 case CP0_REG25__PERFCNT1:
6268 /* gen_helper_mfc0_performance3(arg); */
6269 register_name = "Performance3";
6270 goto cp0_unimplemented;
6271 case CP0_REG25__PERFCTL2:
6272 /* gen_helper_mfc0_performance4(arg); */
6273 register_name = "Performance4";
6274 goto cp0_unimplemented;
6275 case CP0_REG25__PERFCNT2:
6276 /* gen_helper_mfc0_performance5(arg); */
6277 register_name = "Performance5";
6278 goto cp0_unimplemented;
6279 case CP0_REG25__PERFCTL3:
6280 /* gen_helper_mfc0_performance6(arg); */
6281 register_name = "Performance6";
6282 goto cp0_unimplemented;
6283 case CP0_REG25__PERFCNT3:
6284 /* gen_helper_mfc0_performance7(arg); */
6285 register_name = "Performance7";
6286 goto cp0_unimplemented;
6287 default:
6288 goto cp0_unimplemented;
6290 break;
6291 case CP0_REGISTER_26:
6292 switch (sel) {
6293 case CP0_REG26__ERRCTL:
6294 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6295 register_name = "ErrCtl";
6296 break;
6297 default:
6298 goto cp0_unimplemented;
6300 break;
6301 case CP0_REGISTER_27:
6302 switch (sel) {
6303 case CP0_REG27__CACHERR:
6304 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6305 register_name = "CacheErr";
6306 break;
6307 default:
6308 goto cp0_unimplemented;
6310 break;
6311 case CP0_REGISTER_28:
6312 switch (sel) {
6313 case CP0_REG28__TAGLO:
6314 case CP0_REG28__TAGLO1:
6315 case CP0_REG28__TAGLO2:
6316 case CP0_REG28__TAGLO3:
6318 TCGv_i64 tmp = tcg_temp_new_i64();
6319 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6320 gen_move_low32(arg, tmp);
6321 tcg_temp_free_i64(tmp);
6323 register_name = "TagLo";
6324 break;
6325 case CP0_REG28__DATALO:
6326 case CP0_REG28__DATALO1:
6327 case CP0_REG28__DATALO2:
6328 case CP0_REG28__DATALO3:
6329 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6330 register_name = "DataLo";
6331 break;
6332 default:
6333 goto cp0_unimplemented;
6335 break;
6336 case CP0_REGISTER_29:
6337 switch (sel) {
6338 case CP0_REG29__TAGHI:
6339 case CP0_REG29__TAGHI1:
6340 case CP0_REG29__TAGHI2:
6341 case CP0_REG29__TAGHI3:
6342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6343 register_name = "TagHi";
6344 break;
6345 case CP0_REG29__DATAHI:
6346 case CP0_REG29__DATAHI1:
6347 case CP0_REG29__DATAHI2:
6348 case CP0_REG29__DATAHI3:
6349 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6350 register_name = "DataHi";
6351 break;
6352 default:
6353 goto cp0_unimplemented;
6355 break;
6356 case CP0_REGISTER_30:
6357 switch (sel) {
6358 case CP0_REG30__ERROREPC:
6359 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6360 tcg_gen_ext32s_tl(arg, arg);
6361 register_name = "ErrorEPC";
6362 break;
6363 default:
6364 goto cp0_unimplemented;
6366 break;
6367 case CP0_REGISTER_31:
6368 switch (sel) {
6369 case CP0_REG31__DESAVE:
6370 /* EJTAG support */
6371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6372 register_name = "DESAVE";
6373 break;
6374 case CP0_REG31__KSCRATCH1:
6375 case CP0_REG31__KSCRATCH2:
6376 case CP0_REG31__KSCRATCH3:
6377 case CP0_REG31__KSCRATCH4:
6378 case CP0_REG31__KSCRATCH5:
6379 case CP0_REG31__KSCRATCH6:
6380 CP0_CHECK(ctx->kscrexist & (1 << sel));
6381 tcg_gen_ld_tl(arg, cpu_env,
6382 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
6383 tcg_gen_ext32s_tl(arg, arg);
6384 register_name = "KScratch";
6385 break;
6386 default:
6387 goto cp0_unimplemented;
6389 break;
6390 default:
6391 goto cp0_unimplemented;
6393 trace_mips_translate_c0("mfc0", register_name, reg, sel);
6394 return;
6396 cp0_unimplemented:
6397 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6398 register_name, reg, sel);
6399 gen_mfc0_unimplemented(ctx, arg);
6402 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6404 const char *register_name = "invalid";
6406 if (sel != 0) {
6407 check_insn(ctx, ISA_MIPS_R1);
6410 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6411 gen_io_start();
6414 switch (reg) {
6415 case CP0_REGISTER_00:
6416 switch (sel) {
6417 case CP0_REG00__INDEX:
6418 gen_helper_mtc0_index(cpu_env, arg);
6419 register_name = "Index";
6420 break;
6421 case CP0_REG00__MVPCONTROL:
6422 CP0_CHECK(ctx->insn_flags & ASE_MT);
6423 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6424 register_name = "MVPControl";
6425 break;
6426 case CP0_REG00__MVPCONF0:
6427 CP0_CHECK(ctx->insn_flags & ASE_MT);
6428 /* ignored */
6429 register_name = "MVPConf0";
6430 break;
6431 case CP0_REG00__MVPCONF1:
6432 CP0_CHECK(ctx->insn_flags & ASE_MT);
6433 /* ignored */
6434 register_name = "MVPConf1";
6435 break;
6436 case CP0_REG00__VPCONTROL:
6437 CP0_CHECK(ctx->vp);
6438 /* ignored */
6439 register_name = "VPControl";
6440 break;
6441 default:
6442 goto cp0_unimplemented;
6444 break;
6445 case CP0_REGISTER_01:
6446 switch (sel) {
6447 case CP0_REG01__RANDOM:
6448 /* ignored */
6449 register_name = "Random";
6450 break;
6451 case CP0_REG01__VPECONTROL:
6452 CP0_CHECK(ctx->insn_flags & ASE_MT);
6453 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6454 register_name = "VPEControl";
6455 break;
6456 case CP0_REG01__VPECONF0:
6457 CP0_CHECK(ctx->insn_flags & ASE_MT);
6458 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6459 register_name = "VPEConf0";
6460 break;
6461 case CP0_REG01__VPECONF1:
6462 CP0_CHECK(ctx->insn_flags & ASE_MT);
6463 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6464 register_name = "VPEConf1";
6465 break;
6466 case CP0_REG01__YQMASK:
6467 CP0_CHECK(ctx->insn_flags & ASE_MT);
6468 gen_helper_mtc0_yqmask(cpu_env, arg);
6469 register_name = "YQMask";
6470 break;
6471 case CP0_REG01__VPESCHEDULE:
6472 CP0_CHECK(ctx->insn_flags & ASE_MT);
6473 tcg_gen_st_tl(arg, cpu_env,
6474 offsetof(CPUMIPSState, CP0_VPESchedule));
6475 register_name = "VPESchedule";
6476 break;
6477 case CP0_REG01__VPESCHEFBACK:
6478 CP0_CHECK(ctx->insn_flags & ASE_MT);
6479 tcg_gen_st_tl(arg, cpu_env,
6480 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6481 register_name = "VPEScheFBack";
6482 break;
6483 case CP0_REG01__VPEOPT:
6484 CP0_CHECK(ctx->insn_flags & ASE_MT);
6485 gen_helper_mtc0_vpeopt(cpu_env, arg);
6486 register_name = "VPEOpt";
6487 break;
6488 default:
6489 goto cp0_unimplemented;
6491 break;
6492 case CP0_REGISTER_02:
6493 switch (sel) {
6494 case CP0_REG02__ENTRYLO0:
6495 gen_helper_mtc0_entrylo0(cpu_env, arg);
6496 register_name = "EntryLo0";
6497 break;
6498 case CP0_REG02__TCSTATUS:
6499 CP0_CHECK(ctx->insn_flags & ASE_MT);
6500 gen_helper_mtc0_tcstatus(cpu_env, arg);
6501 register_name = "TCStatus";
6502 break;
6503 case CP0_REG02__TCBIND:
6504 CP0_CHECK(ctx->insn_flags & ASE_MT);
6505 gen_helper_mtc0_tcbind(cpu_env, arg);
6506 register_name = "TCBind";
6507 break;
6508 case CP0_REG02__TCRESTART:
6509 CP0_CHECK(ctx->insn_flags & ASE_MT);
6510 gen_helper_mtc0_tcrestart(cpu_env, arg);
6511 register_name = "TCRestart";
6512 break;
6513 case CP0_REG02__TCHALT:
6514 CP0_CHECK(ctx->insn_flags & ASE_MT);
6515 gen_helper_mtc0_tchalt(cpu_env, arg);
6516 register_name = "TCHalt";
6517 break;
6518 case CP0_REG02__TCCONTEXT:
6519 CP0_CHECK(ctx->insn_flags & ASE_MT);
6520 gen_helper_mtc0_tccontext(cpu_env, arg);
6521 register_name = "TCContext";
6522 break;
6523 case CP0_REG02__TCSCHEDULE:
6524 CP0_CHECK(ctx->insn_flags & ASE_MT);
6525 gen_helper_mtc0_tcschedule(cpu_env, arg);
6526 register_name = "TCSchedule";
6527 break;
6528 case CP0_REG02__TCSCHEFBACK:
6529 CP0_CHECK(ctx->insn_flags & ASE_MT);
6530 gen_helper_mtc0_tcschefback(cpu_env, arg);
6531 register_name = "TCScheFBack";
6532 break;
6533 default:
6534 goto cp0_unimplemented;
6536 break;
6537 case CP0_REGISTER_03:
6538 switch (sel) {
6539 case CP0_REG03__ENTRYLO1:
6540 gen_helper_mtc0_entrylo1(cpu_env, arg);
6541 register_name = "EntryLo1";
6542 break;
6543 case CP0_REG03__GLOBALNUM:
6544 CP0_CHECK(ctx->vp);
6545 /* ignored */
6546 register_name = "GlobalNumber";
6547 break;
6548 default:
6549 goto cp0_unimplemented;
6551 break;
6552 case CP0_REGISTER_04:
6553 switch (sel) {
6554 case CP0_REG04__CONTEXT:
6555 gen_helper_mtc0_context(cpu_env, arg);
6556 register_name = "Context";
6557 break;
6558 case CP0_REG04__CONTEXTCONFIG:
6559 /* SmartMIPS ASE */
6560 /* gen_helper_mtc0_contextconfig(arg); */
6561 register_name = "ContextConfig";
6562 goto cp0_unimplemented;
6563 case CP0_REG04__USERLOCAL:
6564 CP0_CHECK(ctx->ulri);
6565 tcg_gen_st_tl(arg, cpu_env,
6566 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6567 register_name = "UserLocal";
6568 break;
6569 case CP0_REG04__MMID:
6570 CP0_CHECK(ctx->mi);
6571 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6572 register_name = "MMID";
6573 break;
6574 default:
6575 goto cp0_unimplemented;
6577 break;
6578 case CP0_REGISTER_05:
6579 switch (sel) {
6580 case CP0_REG05__PAGEMASK:
6581 gen_helper_mtc0_pagemask(cpu_env, arg);
6582 register_name = "PageMask";
6583 break;
6584 case CP0_REG05__PAGEGRAIN:
6585 check_insn(ctx, ISA_MIPS_R2);
6586 gen_helper_mtc0_pagegrain(cpu_env, arg);
6587 register_name = "PageGrain";
6588 ctx->base.is_jmp = DISAS_STOP;
6589 break;
6590 case CP0_REG05__SEGCTL0:
6591 CP0_CHECK(ctx->sc);
6592 gen_helper_mtc0_segctl0(cpu_env, arg);
6593 register_name = "SegCtl0";
6594 break;
6595 case CP0_REG05__SEGCTL1:
6596 CP0_CHECK(ctx->sc);
6597 gen_helper_mtc0_segctl1(cpu_env, arg);
6598 register_name = "SegCtl1";
6599 break;
6600 case CP0_REG05__SEGCTL2:
6601 CP0_CHECK(ctx->sc);
6602 gen_helper_mtc0_segctl2(cpu_env, arg);
6603 register_name = "SegCtl2";
6604 break;
6605 case CP0_REG05__PWBASE:
6606 check_pw(ctx);
6607 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6608 register_name = "PWBase";
6609 break;
6610 case CP0_REG05__PWFIELD:
6611 check_pw(ctx);
6612 gen_helper_mtc0_pwfield(cpu_env, arg);
6613 register_name = "PWField";
6614 break;
6615 case CP0_REG05__PWSIZE:
6616 check_pw(ctx);
6617 gen_helper_mtc0_pwsize(cpu_env, arg);
6618 register_name = "PWSize";
6619 break;
6620 default:
6621 goto cp0_unimplemented;
6623 break;
6624 case CP0_REGISTER_06:
6625 switch (sel) {
6626 case CP0_REG06__WIRED:
6627 gen_helper_mtc0_wired(cpu_env, arg);
6628 register_name = "Wired";
6629 break;
6630 case CP0_REG06__SRSCONF0:
6631 check_insn(ctx, ISA_MIPS_R2);
6632 gen_helper_mtc0_srsconf0(cpu_env, arg);
6633 register_name = "SRSConf0";
6634 break;
6635 case CP0_REG06__SRSCONF1:
6636 check_insn(ctx, ISA_MIPS_R2);
6637 gen_helper_mtc0_srsconf1(cpu_env, arg);
6638 register_name = "SRSConf1";
6639 break;
6640 case CP0_REG06__SRSCONF2:
6641 check_insn(ctx, ISA_MIPS_R2);
6642 gen_helper_mtc0_srsconf2(cpu_env, arg);
6643 register_name = "SRSConf2";
6644 break;
6645 case CP0_REG06__SRSCONF3:
6646 check_insn(ctx, ISA_MIPS_R2);
6647 gen_helper_mtc0_srsconf3(cpu_env, arg);
6648 register_name = "SRSConf3";
6649 break;
6650 case CP0_REG06__SRSCONF4:
6651 check_insn(ctx, ISA_MIPS_R2);
6652 gen_helper_mtc0_srsconf4(cpu_env, arg);
6653 register_name = "SRSConf4";
6654 break;
6655 case CP0_REG06__PWCTL:
6656 check_pw(ctx);
6657 gen_helper_mtc0_pwctl(cpu_env, arg);
6658 register_name = "PWCtl";
6659 break;
6660 default:
6661 goto cp0_unimplemented;
6663 break;
6664 case CP0_REGISTER_07:
6665 switch (sel) {
6666 case CP0_REG07__HWRENA:
6667 check_insn(ctx, ISA_MIPS_R2);
6668 gen_helper_mtc0_hwrena(cpu_env, arg);
6669 ctx->base.is_jmp = DISAS_STOP;
6670 register_name = "HWREna";
6671 break;
6672 default:
6673 goto cp0_unimplemented;
6675 break;
6676 case CP0_REGISTER_08:
6677 switch (sel) {
6678 case CP0_REG08__BADVADDR:
6679 /* ignored */
6680 register_name = "BadVAddr";
6681 break;
6682 case CP0_REG08__BADINSTR:
6683 /* ignored */
6684 register_name = "BadInstr";
6685 break;
6686 case CP0_REG08__BADINSTRP:
6687 /* ignored */
6688 register_name = "BadInstrP";
6689 break;
6690 case CP0_REG08__BADINSTRX:
6691 /* ignored */
6692 register_name = "BadInstrX";
6693 break;
6694 default:
6695 goto cp0_unimplemented;
6697 break;
6698 case CP0_REGISTER_09:
6699 switch (sel) {
6700 case CP0_REG09__COUNT:
6701 gen_helper_mtc0_count(cpu_env, arg);
6702 register_name = "Count";
6703 break;
6704 case CP0_REG09__SAARI:
6705 CP0_CHECK(ctx->saar);
6706 gen_helper_mtc0_saari(cpu_env, arg);
6707 register_name = "SAARI";
6708 break;
6709 case CP0_REG09__SAAR:
6710 CP0_CHECK(ctx->saar);
6711 gen_helper_mtc0_saar(cpu_env, arg);
6712 register_name = "SAAR";
6713 break;
6714 default:
6715 goto cp0_unimplemented;
6717 break;
6718 case CP0_REGISTER_10:
6719 switch (sel) {
6720 case CP0_REG10__ENTRYHI:
6721 gen_helper_mtc0_entryhi(cpu_env, arg);
6722 register_name = "EntryHi";
6723 break;
6724 default:
6725 goto cp0_unimplemented;
6727 break;
6728 case CP0_REGISTER_11:
6729 switch (sel) {
6730 case CP0_REG11__COMPARE:
6731 gen_helper_mtc0_compare(cpu_env, arg);
6732 register_name = "Compare";
6733 break;
6734 /* 6,7 are implementation dependent */
6735 default:
6736 goto cp0_unimplemented;
6738 break;
6739 case CP0_REGISTER_12:
6740 switch (sel) {
6741 case CP0_REG12__STATUS:
6742 save_cpu_state(ctx, 1);
6743 gen_helper_mtc0_status(cpu_env, arg);
6744 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6745 gen_save_pc(ctx->base.pc_next + 4);
6746 ctx->base.is_jmp = DISAS_EXIT;
6747 register_name = "Status";
6748 break;
6749 case CP0_REG12__INTCTL:
6750 check_insn(ctx, ISA_MIPS_R2);
6751 gen_helper_mtc0_intctl(cpu_env, arg);
6752 /* Stop translation as we may have switched the execution mode */
6753 ctx->base.is_jmp = DISAS_STOP;
6754 register_name = "IntCtl";
6755 break;
6756 case CP0_REG12__SRSCTL:
6757 check_insn(ctx, ISA_MIPS_R2);
6758 gen_helper_mtc0_srsctl(cpu_env, arg);
6759 /* Stop translation as we may have switched the execution mode */
6760 ctx->base.is_jmp = DISAS_STOP;
6761 register_name = "SRSCtl";
6762 break;
6763 case CP0_REG12__SRSMAP:
6764 check_insn(ctx, ISA_MIPS_R2);
6765 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6766 /* Stop translation as we may have switched the execution mode */
6767 ctx->base.is_jmp = DISAS_STOP;
6768 register_name = "SRSMap";
6769 break;
6770 default:
6771 goto cp0_unimplemented;
6773 break;
6774 case CP0_REGISTER_13:
6775 switch (sel) {
6776 case CP0_REG13__CAUSE:
6777 save_cpu_state(ctx, 1);
6778 gen_helper_mtc0_cause(cpu_env, arg);
6780 * Stop translation as we may have triggered an interrupt.
6781 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6782 * translated code to check for pending interrupts.
6784 gen_save_pc(ctx->base.pc_next + 4);
6785 ctx->base.is_jmp = DISAS_EXIT;
6786 register_name = "Cause";
6787 break;
6788 default:
6789 goto cp0_unimplemented;
6791 break;
6792 case CP0_REGISTER_14:
6793 switch (sel) {
6794 case CP0_REG14__EPC:
6795 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6796 register_name = "EPC";
6797 break;
6798 default:
6799 goto cp0_unimplemented;
6801 break;
6802 case CP0_REGISTER_15:
6803 switch (sel) {
6804 case CP0_REG15__PRID:
6805 /* ignored */
6806 register_name = "PRid";
6807 break;
6808 case CP0_REG15__EBASE:
6809 check_insn(ctx, ISA_MIPS_R2);
6810 gen_helper_mtc0_ebase(cpu_env, arg);
6811 register_name = "EBase";
6812 break;
6813 default:
6814 goto cp0_unimplemented;
6816 break;
6817 case CP0_REGISTER_16:
6818 switch (sel) {
6819 case CP0_REG16__CONFIG:
6820 gen_helper_mtc0_config0(cpu_env, arg);
6821 register_name = "Config";
6822 /* Stop translation as we may have switched the execution mode */
6823 ctx->base.is_jmp = DISAS_STOP;
6824 break;
6825 case CP0_REG16__CONFIG1:
6826 /* ignored, read only */
6827 register_name = "Config1";
6828 break;
6829 case CP0_REG16__CONFIG2:
6830 gen_helper_mtc0_config2(cpu_env, arg);
6831 register_name = "Config2";
6832 /* Stop translation as we may have switched the execution mode */
6833 ctx->base.is_jmp = DISAS_STOP;
6834 break;
6835 case CP0_REG16__CONFIG3:
6836 gen_helper_mtc0_config3(cpu_env, arg);
6837 register_name = "Config3";
6838 /* Stop translation as we may have switched the execution mode */
6839 ctx->base.is_jmp = DISAS_STOP;
6840 break;
6841 case CP0_REG16__CONFIG4:
6842 gen_helper_mtc0_config4(cpu_env, arg);
6843 register_name = "Config4";
6844 ctx->base.is_jmp = DISAS_STOP;
6845 break;
6846 case CP0_REG16__CONFIG5:
6847 gen_helper_mtc0_config5(cpu_env, arg);
6848 register_name = "Config5";
6849 /* Stop translation as we may have switched the execution mode */
6850 ctx->base.is_jmp = DISAS_STOP;
6851 break;
6852 /* 6,7 are implementation dependent */
6853 case CP0_REG16__CONFIG6:
6854 /* ignored */
6855 register_name = "Config6";
6856 break;
6857 case CP0_REG16__CONFIG7:
6858 /* ignored */
6859 register_name = "Config7";
6860 break;
6861 default:
6862 register_name = "Invalid config selector";
6863 goto cp0_unimplemented;
6865 break;
6866 case CP0_REGISTER_17:
6867 switch (sel) {
6868 case CP0_REG17__LLADDR:
6869 gen_helper_mtc0_lladdr(cpu_env, arg);
6870 register_name = "LLAddr";
6871 break;
6872 case CP0_REG17__MAAR:
6873 CP0_CHECK(ctx->mrp);
6874 gen_helper_mtc0_maar(cpu_env, arg);
6875 register_name = "MAAR";
6876 break;
6877 case CP0_REG17__MAARI:
6878 CP0_CHECK(ctx->mrp);
6879 gen_helper_mtc0_maari(cpu_env, arg);
6880 register_name = "MAARI";
6881 break;
6882 default:
6883 goto cp0_unimplemented;
6885 break;
6886 case CP0_REGISTER_18:
6887 switch (sel) {
6888 case CP0_REG18__WATCHLO0:
6889 case CP0_REG18__WATCHLO1:
6890 case CP0_REG18__WATCHLO2:
6891 case CP0_REG18__WATCHLO3:
6892 case CP0_REG18__WATCHLO4:
6893 case CP0_REG18__WATCHLO5:
6894 case CP0_REG18__WATCHLO6:
6895 case CP0_REG18__WATCHLO7:
6896 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6897 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6898 register_name = "WatchLo";
6899 break;
6900 default:
6901 goto cp0_unimplemented;
6903 break;
6904 case CP0_REGISTER_19:
6905 switch (sel) {
6906 case CP0_REG19__WATCHHI0:
6907 case CP0_REG19__WATCHHI1:
6908 case CP0_REG19__WATCHHI2:
6909 case CP0_REG19__WATCHHI3:
6910 case CP0_REG19__WATCHHI4:
6911 case CP0_REG19__WATCHHI5:
6912 case CP0_REG19__WATCHHI6:
6913 case CP0_REG19__WATCHHI7:
6914 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6915 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6916 register_name = "WatchHi";
6917 break;
6918 default:
6919 goto cp0_unimplemented;
6921 break;
6922 case CP0_REGISTER_20:
6923 switch (sel) {
6924 case CP0_REG20__XCONTEXT:
6925 #if defined(TARGET_MIPS64)
6926 check_insn(ctx, ISA_MIPS3);
6927 gen_helper_mtc0_xcontext(cpu_env, arg);
6928 register_name = "XContext";
6929 break;
6930 #endif
6931 default:
6932 goto cp0_unimplemented;
6934 break;
6935 case CP0_REGISTER_21:
6936 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6937 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6938 switch (sel) {
6939 case 0:
6940 gen_helper_mtc0_framemask(cpu_env, arg);
6941 register_name = "Framemask";
6942 break;
6943 default:
6944 goto cp0_unimplemented;
6946 break;
6947 case CP0_REGISTER_22:
6948 /* ignored */
6949 register_name = "Diagnostic"; /* implementation dependent */
6950 break;
6951 case CP0_REGISTER_23:
6952 switch (sel) {
6953 case CP0_REG23__DEBUG:
6954 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6955 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6956 gen_save_pc(ctx->base.pc_next + 4);
6957 ctx->base.is_jmp = DISAS_EXIT;
6958 register_name = "Debug";
6959 break;
6960 case CP0_REG23__TRACECONTROL:
6961 /* PDtrace support */
6962 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
6963 register_name = "TraceControl";
6964 /* Stop translation as we may have switched the execution mode */
6965 ctx->base.is_jmp = DISAS_STOP;
6966 goto cp0_unimplemented;
6967 case CP0_REG23__TRACECONTROL2:
6968 /* PDtrace support */
6969 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
6970 register_name = "TraceControl2";
6971 /* Stop translation as we may have switched the execution mode */
6972 ctx->base.is_jmp = DISAS_STOP;
6973 goto cp0_unimplemented;
6974 case CP0_REG23__USERTRACEDATA1:
6975 /* Stop translation as we may have switched the execution mode */
6976 ctx->base.is_jmp = DISAS_STOP;
6977 /* PDtrace support */
6978 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
6979 register_name = "UserTraceData";
6980 /* Stop translation as we may have switched the execution mode */
6981 ctx->base.is_jmp = DISAS_STOP;
6982 goto cp0_unimplemented;
6983 case CP0_REG23__TRACEIBPC:
6984 /* PDtrace support */
6985 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
6986 /* Stop translation as we may have switched the execution mode */
6987 ctx->base.is_jmp = DISAS_STOP;
6988 register_name = "TraceIBPC";
6989 goto cp0_unimplemented;
6990 case CP0_REG23__TRACEDBPC:
6991 /* PDtrace support */
6992 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
6993 /* Stop translation as we may have switched the execution mode */
6994 ctx->base.is_jmp = DISAS_STOP;
6995 register_name = "TraceDBPC";
6996 goto cp0_unimplemented;
6997 default:
6998 goto cp0_unimplemented;
7000 break;
7001 case CP0_REGISTER_24:
7002 switch (sel) {
7003 case CP0_REG24__DEPC:
7004 /* EJTAG support */
7005 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7006 register_name = "DEPC";
7007 break;
7008 default:
7009 goto cp0_unimplemented;
7011 break;
7012 case CP0_REGISTER_25:
7013 switch (sel) {
7014 case CP0_REG25__PERFCTL0:
7015 gen_helper_mtc0_performance0(cpu_env, arg);
7016 register_name = "Performance0";
7017 break;
7018 case CP0_REG25__PERFCNT0:
7019 /* gen_helper_mtc0_performance1(arg); */
7020 register_name = "Performance1";
7021 goto cp0_unimplemented;
7022 case CP0_REG25__PERFCTL1:
7023 /* gen_helper_mtc0_performance2(arg); */
7024 register_name = "Performance2";
7025 goto cp0_unimplemented;
7026 case CP0_REG25__PERFCNT1:
7027 /* gen_helper_mtc0_performance3(arg); */
7028 register_name = "Performance3";
7029 goto cp0_unimplemented;
7030 case CP0_REG25__PERFCTL2:
7031 /* gen_helper_mtc0_performance4(arg); */
7032 register_name = "Performance4";
7033 goto cp0_unimplemented;
7034 case CP0_REG25__PERFCNT2:
7035 /* gen_helper_mtc0_performance5(arg); */
7036 register_name = "Performance5";
7037 goto cp0_unimplemented;
7038 case CP0_REG25__PERFCTL3:
7039 /* gen_helper_mtc0_performance6(arg); */
7040 register_name = "Performance6";
7041 goto cp0_unimplemented;
7042 case CP0_REG25__PERFCNT3:
7043 /* gen_helper_mtc0_performance7(arg); */
7044 register_name = "Performance7";
7045 goto cp0_unimplemented;
7046 default:
7047 goto cp0_unimplemented;
7049 break;
7050 case CP0_REGISTER_26:
7051 switch (sel) {
7052 case CP0_REG26__ERRCTL:
7053 gen_helper_mtc0_errctl(cpu_env, arg);
7054 ctx->base.is_jmp = DISAS_STOP;
7055 register_name = "ErrCtl";
7056 break;
7057 default:
7058 goto cp0_unimplemented;
7060 break;
7061 case CP0_REGISTER_27:
7062 switch (sel) {
7063 case CP0_REG27__CACHERR:
7064 /* ignored */
7065 register_name = "CacheErr";
7066 break;
7067 default:
7068 goto cp0_unimplemented;
7070 break;
7071 case CP0_REGISTER_28:
7072 switch (sel) {
7073 case CP0_REG28__TAGLO:
7074 case CP0_REG28__TAGLO1:
7075 case CP0_REG28__TAGLO2:
7076 case CP0_REG28__TAGLO3:
7077 gen_helper_mtc0_taglo(cpu_env, arg);
7078 register_name = "TagLo";
7079 break;
7080 case CP0_REG28__DATALO:
7081 case CP0_REG28__DATALO1:
7082 case CP0_REG28__DATALO2:
7083 case CP0_REG28__DATALO3:
7084 gen_helper_mtc0_datalo(cpu_env, arg);
7085 register_name = "DataLo";
7086 break;
7087 default:
7088 goto cp0_unimplemented;
7090 break;
7091 case CP0_REGISTER_29:
7092 switch (sel) {
7093 case CP0_REG29__TAGHI:
7094 case CP0_REG29__TAGHI1:
7095 case CP0_REG29__TAGHI2:
7096 case CP0_REG29__TAGHI3:
7097 gen_helper_mtc0_taghi(cpu_env, arg);
7098 register_name = "TagHi";
7099 break;
7100 case CP0_REG29__DATAHI:
7101 case CP0_REG29__DATAHI1:
7102 case CP0_REG29__DATAHI2:
7103 case CP0_REG29__DATAHI3:
7104 gen_helper_mtc0_datahi(cpu_env, arg);
7105 register_name = "DataHi";
7106 break;
7107 default:
7108 register_name = "invalid sel";
7109 goto cp0_unimplemented;
7111 break;
7112 case CP0_REGISTER_30:
7113 switch (sel) {
7114 case CP0_REG30__ERROREPC:
7115 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7116 register_name = "ErrorEPC";
7117 break;
7118 default:
7119 goto cp0_unimplemented;
7121 break;
7122 case CP0_REGISTER_31:
7123 switch (sel) {
7124 case CP0_REG31__DESAVE:
7125 /* EJTAG support */
7126 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7127 register_name = "DESAVE";
7128 break;
7129 case CP0_REG31__KSCRATCH1:
7130 case CP0_REG31__KSCRATCH2:
7131 case CP0_REG31__KSCRATCH3:
7132 case CP0_REG31__KSCRATCH4:
7133 case CP0_REG31__KSCRATCH5:
7134 case CP0_REG31__KSCRATCH6:
7135 CP0_CHECK(ctx->kscrexist & (1 << sel));
7136 tcg_gen_st_tl(arg, cpu_env,
7137 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7138 register_name = "KScratch";
7139 break;
7140 default:
7141 goto cp0_unimplemented;
7143 break;
7144 default:
7145 goto cp0_unimplemented;
7147 trace_mips_translate_c0("mtc0", register_name, reg, sel);
7149 /* For simplicity assume that all writes can cause interrupts. */
7150 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7152 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7153 * translated code to check for pending interrupts.
7155 gen_save_pc(ctx->base.pc_next + 4);
7156 ctx->base.is_jmp = DISAS_EXIT;
7158 return;
7160 cp0_unimplemented:
7161 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7162 register_name, reg, sel);
7165 #if defined(TARGET_MIPS64)
7166 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7168 const char *register_name = "invalid";
7170 if (sel != 0) {
7171 check_insn(ctx, ISA_MIPS_R1);
7174 switch (reg) {
7175 case CP0_REGISTER_00:
7176 switch (sel) {
7177 case CP0_REG00__INDEX:
7178 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7179 register_name = "Index";
7180 break;
7181 case CP0_REG00__MVPCONTROL:
7182 CP0_CHECK(ctx->insn_flags & ASE_MT);
7183 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7184 register_name = "MVPControl";
7185 break;
7186 case CP0_REG00__MVPCONF0:
7187 CP0_CHECK(ctx->insn_flags & ASE_MT);
7188 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7189 register_name = "MVPConf0";
7190 break;
7191 case CP0_REG00__MVPCONF1:
7192 CP0_CHECK(ctx->insn_flags & ASE_MT);
7193 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7194 register_name = "MVPConf1";
7195 break;
7196 case CP0_REG00__VPCONTROL:
7197 CP0_CHECK(ctx->vp);
7198 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7199 register_name = "VPControl";
7200 break;
7201 default:
7202 goto cp0_unimplemented;
7204 break;
7205 case CP0_REGISTER_01:
7206 switch (sel) {
7207 case CP0_REG01__RANDOM:
7208 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7209 gen_helper_mfc0_random(arg, cpu_env);
7210 register_name = "Random";
7211 break;
7212 case CP0_REG01__VPECONTROL:
7213 CP0_CHECK(ctx->insn_flags & ASE_MT);
7214 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7215 register_name = "VPEControl";
7216 break;
7217 case CP0_REG01__VPECONF0:
7218 CP0_CHECK(ctx->insn_flags & ASE_MT);
7219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7220 register_name = "VPEConf0";
7221 break;
7222 case CP0_REG01__VPECONF1:
7223 CP0_CHECK(ctx->insn_flags & ASE_MT);
7224 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7225 register_name = "VPEConf1";
7226 break;
7227 case CP0_REG01__YQMASK:
7228 CP0_CHECK(ctx->insn_flags & ASE_MT);
7229 tcg_gen_ld_tl(arg, cpu_env,
7230 offsetof(CPUMIPSState, CP0_YQMask));
7231 register_name = "YQMask";
7232 break;
7233 case CP0_REG01__VPESCHEDULE:
7234 CP0_CHECK(ctx->insn_flags & ASE_MT);
7235 tcg_gen_ld_tl(arg, cpu_env,
7236 offsetof(CPUMIPSState, CP0_VPESchedule));
7237 register_name = "VPESchedule";
7238 break;
7239 case CP0_REG01__VPESCHEFBACK:
7240 CP0_CHECK(ctx->insn_flags & ASE_MT);
7241 tcg_gen_ld_tl(arg, cpu_env,
7242 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7243 register_name = "VPEScheFBack";
7244 break;
7245 case CP0_REG01__VPEOPT:
7246 CP0_CHECK(ctx->insn_flags & ASE_MT);
7247 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7248 register_name = "VPEOpt";
7249 break;
7250 default:
7251 goto cp0_unimplemented;
7253 break;
7254 case CP0_REGISTER_02:
7255 switch (sel) {
7256 case CP0_REG02__ENTRYLO0:
7257 tcg_gen_ld_tl(arg, cpu_env,
7258 offsetof(CPUMIPSState, CP0_EntryLo0));
7259 register_name = "EntryLo0";
7260 break;
7261 case CP0_REG02__TCSTATUS:
7262 CP0_CHECK(ctx->insn_flags & ASE_MT);
7263 gen_helper_mfc0_tcstatus(arg, cpu_env);
7264 register_name = "TCStatus";
7265 break;
7266 case CP0_REG02__TCBIND:
7267 CP0_CHECK(ctx->insn_flags & ASE_MT);
7268 gen_helper_mfc0_tcbind(arg, cpu_env);
7269 register_name = "TCBind";
7270 break;
7271 case CP0_REG02__TCRESTART:
7272 CP0_CHECK(ctx->insn_flags & ASE_MT);
7273 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7274 register_name = "TCRestart";
7275 break;
7276 case CP0_REG02__TCHALT:
7277 CP0_CHECK(ctx->insn_flags & ASE_MT);
7278 gen_helper_dmfc0_tchalt(arg, cpu_env);
7279 register_name = "TCHalt";
7280 break;
7281 case CP0_REG02__TCCONTEXT:
7282 CP0_CHECK(ctx->insn_flags & ASE_MT);
7283 gen_helper_dmfc0_tccontext(arg, cpu_env);
7284 register_name = "TCContext";
7285 break;
7286 case CP0_REG02__TCSCHEDULE:
7287 CP0_CHECK(ctx->insn_flags & ASE_MT);
7288 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7289 register_name = "TCSchedule";
7290 break;
7291 case CP0_REG02__TCSCHEFBACK:
7292 CP0_CHECK(ctx->insn_flags & ASE_MT);
7293 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7294 register_name = "TCScheFBack";
7295 break;
7296 default:
7297 goto cp0_unimplemented;
7299 break;
7300 case CP0_REGISTER_03:
7301 switch (sel) {
7302 case CP0_REG03__ENTRYLO1:
7303 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7304 register_name = "EntryLo1";
7305 break;
7306 case CP0_REG03__GLOBALNUM:
7307 CP0_CHECK(ctx->vp);
7308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7309 register_name = "GlobalNumber";
7310 break;
7311 default:
7312 goto cp0_unimplemented;
7314 break;
7315 case CP0_REGISTER_04:
7316 switch (sel) {
7317 case CP0_REG04__CONTEXT:
7318 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7319 register_name = "Context";
7320 break;
7321 case CP0_REG04__CONTEXTCONFIG:
7322 /* SmartMIPS ASE */
7323 /* gen_helper_dmfc0_contextconfig(arg); */
7324 register_name = "ContextConfig";
7325 goto cp0_unimplemented;
7326 case CP0_REG04__USERLOCAL:
7327 CP0_CHECK(ctx->ulri);
7328 tcg_gen_ld_tl(arg, cpu_env,
7329 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7330 register_name = "UserLocal";
7331 break;
7332 case CP0_REG04__MMID:
7333 CP0_CHECK(ctx->mi);
7334 gen_helper_mtc0_memorymapid(cpu_env, arg);
7335 register_name = "MMID";
7336 break;
7337 default:
7338 goto cp0_unimplemented;
7340 break;
7341 case CP0_REGISTER_05:
7342 switch (sel) {
7343 case CP0_REG05__PAGEMASK:
7344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7345 register_name = "PageMask";
7346 break;
7347 case CP0_REG05__PAGEGRAIN:
7348 check_insn(ctx, ISA_MIPS_R2);
7349 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7350 register_name = "PageGrain";
7351 break;
7352 case CP0_REG05__SEGCTL0:
7353 CP0_CHECK(ctx->sc);
7354 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7355 register_name = "SegCtl0";
7356 break;
7357 case CP0_REG05__SEGCTL1:
7358 CP0_CHECK(ctx->sc);
7359 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7360 register_name = "SegCtl1";
7361 break;
7362 case CP0_REG05__SEGCTL2:
7363 CP0_CHECK(ctx->sc);
7364 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7365 register_name = "SegCtl2";
7366 break;
7367 case CP0_REG05__PWBASE:
7368 check_pw(ctx);
7369 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7370 register_name = "PWBase";
7371 break;
7372 case CP0_REG05__PWFIELD:
7373 check_pw(ctx);
7374 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7375 register_name = "PWField";
7376 break;
7377 case CP0_REG05__PWSIZE:
7378 check_pw(ctx);
7379 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7380 register_name = "PWSize";
7381 break;
7382 default:
7383 goto cp0_unimplemented;
7385 break;
7386 case CP0_REGISTER_06:
7387 switch (sel) {
7388 case CP0_REG06__WIRED:
7389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7390 register_name = "Wired";
7391 break;
7392 case CP0_REG06__SRSCONF0:
7393 check_insn(ctx, ISA_MIPS_R2);
7394 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7395 register_name = "SRSConf0";
7396 break;
7397 case CP0_REG06__SRSCONF1:
7398 check_insn(ctx, ISA_MIPS_R2);
7399 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7400 register_name = "SRSConf1";
7401 break;
7402 case CP0_REG06__SRSCONF2:
7403 check_insn(ctx, ISA_MIPS_R2);
7404 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7405 register_name = "SRSConf2";
7406 break;
7407 case CP0_REG06__SRSCONF3:
7408 check_insn(ctx, ISA_MIPS_R2);
7409 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7410 register_name = "SRSConf3";
7411 break;
7412 case CP0_REG06__SRSCONF4:
7413 check_insn(ctx, ISA_MIPS_R2);
7414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7415 register_name = "SRSConf4";
7416 break;
7417 case CP0_REG06__PWCTL:
7418 check_pw(ctx);
7419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7420 register_name = "PWCtl";
7421 break;
7422 default:
7423 goto cp0_unimplemented;
7425 break;
7426 case CP0_REGISTER_07:
7427 switch (sel) {
7428 case CP0_REG07__HWRENA:
7429 check_insn(ctx, ISA_MIPS_R2);
7430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7431 register_name = "HWREna";
7432 break;
7433 default:
7434 goto cp0_unimplemented;
7436 break;
7437 case CP0_REGISTER_08:
7438 switch (sel) {
7439 case CP0_REG08__BADVADDR:
7440 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7441 register_name = "BadVAddr";
7442 break;
7443 case CP0_REG08__BADINSTR:
7444 CP0_CHECK(ctx->bi);
7445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7446 register_name = "BadInstr";
7447 break;
7448 case CP0_REG08__BADINSTRP:
7449 CP0_CHECK(ctx->bp);
7450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7451 register_name = "BadInstrP";
7452 break;
7453 case CP0_REG08__BADINSTRX:
7454 CP0_CHECK(ctx->bi);
7455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7456 tcg_gen_andi_tl(arg, arg, ~0xffff);
7457 register_name = "BadInstrX";
7458 break;
7459 default:
7460 goto cp0_unimplemented;
7462 break;
7463 case CP0_REGISTER_09:
7464 switch (sel) {
7465 case CP0_REG09__COUNT:
7466 /* Mark as an IO operation because we read the time. */
7467 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7468 gen_io_start();
7470 gen_helper_mfc0_count(arg, cpu_env);
7472 * Break the TB to be able to take timer interrupts immediately
7473 * after reading count. DISAS_STOP isn't sufficient, we need to
7474 * ensure we break completely out of translated code.
7476 gen_save_pc(ctx->base.pc_next + 4);
7477 ctx->base.is_jmp = DISAS_EXIT;
7478 register_name = "Count";
7479 break;
7480 case CP0_REG09__SAARI:
7481 CP0_CHECK(ctx->saar);
7482 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7483 register_name = "SAARI";
7484 break;
7485 case CP0_REG09__SAAR:
7486 CP0_CHECK(ctx->saar);
7487 gen_helper_dmfc0_saar(arg, cpu_env);
7488 register_name = "SAAR";
7489 break;
7490 default:
7491 goto cp0_unimplemented;
7493 break;
7494 case CP0_REGISTER_10:
7495 switch (sel) {
7496 case CP0_REG10__ENTRYHI:
7497 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7498 register_name = "EntryHi";
7499 break;
7500 default:
7501 goto cp0_unimplemented;
7503 break;
7504 case CP0_REGISTER_11:
7505 switch (sel) {
7506 case CP0_REG11__COMPARE:
7507 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7508 register_name = "Compare";
7509 break;
7510 /* 6,7 are implementation dependent */
7511 default:
7512 goto cp0_unimplemented;
7514 break;
7515 case CP0_REGISTER_12:
7516 switch (sel) {
7517 case CP0_REG12__STATUS:
7518 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7519 register_name = "Status";
7520 break;
7521 case CP0_REG12__INTCTL:
7522 check_insn(ctx, ISA_MIPS_R2);
7523 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7524 register_name = "IntCtl";
7525 break;
7526 case CP0_REG12__SRSCTL:
7527 check_insn(ctx, ISA_MIPS_R2);
7528 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7529 register_name = "SRSCtl";
7530 break;
7531 case CP0_REG12__SRSMAP:
7532 check_insn(ctx, ISA_MIPS_R2);
7533 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7534 register_name = "SRSMap";
7535 break;
7536 default:
7537 goto cp0_unimplemented;
7539 break;
7540 case CP0_REGISTER_13:
7541 switch (sel) {
7542 case CP0_REG13__CAUSE:
7543 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7544 register_name = "Cause";
7545 break;
7546 default:
7547 goto cp0_unimplemented;
7549 break;
7550 case CP0_REGISTER_14:
7551 switch (sel) {
7552 case CP0_REG14__EPC:
7553 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7554 register_name = "EPC";
7555 break;
7556 default:
7557 goto cp0_unimplemented;
7559 break;
7560 case CP0_REGISTER_15:
7561 switch (sel) {
7562 case CP0_REG15__PRID:
7563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7564 register_name = "PRid";
7565 break;
7566 case CP0_REG15__EBASE:
7567 check_insn(ctx, ISA_MIPS_R2);
7568 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7569 register_name = "EBase";
7570 break;
7571 case CP0_REG15__CMGCRBASE:
7572 check_insn(ctx, ISA_MIPS_R2);
7573 CP0_CHECK(ctx->cmgcr);
7574 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7575 register_name = "CMGCRBase";
7576 break;
7577 default:
7578 goto cp0_unimplemented;
7580 break;
7581 case CP0_REGISTER_16:
7582 switch (sel) {
7583 case CP0_REG16__CONFIG:
7584 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7585 register_name = "Config";
7586 break;
7587 case CP0_REG16__CONFIG1:
7588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7589 register_name = "Config1";
7590 break;
7591 case CP0_REG16__CONFIG2:
7592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7593 register_name = "Config2";
7594 break;
7595 case CP0_REG16__CONFIG3:
7596 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7597 register_name = "Config3";
7598 break;
7599 case CP0_REG16__CONFIG4:
7600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7601 register_name = "Config4";
7602 break;
7603 case CP0_REG16__CONFIG5:
7604 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7605 register_name = "Config5";
7606 break;
7607 /* 6,7 are implementation dependent */
7608 case CP0_REG16__CONFIG6:
7609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7610 register_name = "Config6";
7611 break;
7612 case CP0_REG16__CONFIG7:
7613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7614 register_name = "Config7";
7615 break;
7616 default:
7617 goto cp0_unimplemented;
7619 break;
7620 case CP0_REGISTER_17:
7621 switch (sel) {
7622 case CP0_REG17__LLADDR:
7623 gen_helper_dmfc0_lladdr(arg, cpu_env);
7624 register_name = "LLAddr";
7625 break;
7626 case CP0_REG17__MAAR:
7627 CP0_CHECK(ctx->mrp);
7628 gen_helper_dmfc0_maar(arg, cpu_env);
7629 register_name = "MAAR";
7630 break;
7631 case CP0_REG17__MAARI:
7632 CP0_CHECK(ctx->mrp);
7633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7634 register_name = "MAARI";
7635 break;
7636 default:
7637 goto cp0_unimplemented;
7639 break;
7640 case CP0_REGISTER_18:
7641 switch (sel) {
7642 case CP0_REG18__WATCHLO0:
7643 case CP0_REG18__WATCHLO1:
7644 case CP0_REG18__WATCHLO2:
7645 case CP0_REG18__WATCHLO3:
7646 case CP0_REG18__WATCHLO4:
7647 case CP0_REG18__WATCHLO5:
7648 case CP0_REG18__WATCHLO6:
7649 case CP0_REG18__WATCHLO7:
7650 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7651 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7652 register_name = "WatchLo";
7653 break;
7654 default:
7655 goto cp0_unimplemented;
7657 break;
7658 case CP0_REGISTER_19:
7659 switch (sel) {
7660 case CP0_REG19__WATCHHI0:
7661 case CP0_REG19__WATCHHI1:
7662 case CP0_REG19__WATCHHI2:
7663 case CP0_REG19__WATCHHI3:
7664 case CP0_REG19__WATCHHI4:
7665 case CP0_REG19__WATCHHI5:
7666 case CP0_REG19__WATCHHI6:
7667 case CP0_REG19__WATCHHI7:
7668 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7669 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
7670 register_name = "WatchHi";
7671 break;
7672 default:
7673 goto cp0_unimplemented;
7675 break;
7676 case CP0_REGISTER_20:
7677 switch (sel) {
7678 case CP0_REG20__XCONTEXT:
7679 check_insn(ctx, ISA_MIPS3);
7680 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7681 register_name = "XContext";
7682 break;
7683 default:
7684 goto cp0_unimplemented;
7686 break;
7687 case CP0_REGISTER_21:
7688 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7689 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7690 switch (sel) {
7691 case 0:
7692 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7693 register_name = "Framemask";
7694 break;
7695 default:
7696 goto cp0_unimplemented;
7698 break;
7699 case CP0_REGISTER_22:
7700 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7701 register_name = "'Diagnostic"; /* implementation dependent */
7702 break;
7703 case CP0_REGISTER_23:
7704 switch (sel) {
7705 case CP0_REG23__DEBUG:
7706 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7707 register_name = "Debug";
7708 break;
7709 case CP0_REG23__TRACECONTROL:
7710 /* PDtrace support */
7711 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
7712 register_name = "TraceControl";
7713 goto cp0_unimplemented;
7714 case CP0_REG23__TRACECONTROL2:
7715 /* PDtrace support */
7716 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
7717 register_name = "TraceControl2";
7718 goto cp0_unimplemented;
7719 case CP0_REG23__USERTRACEDATA1:
7720 /* PDtrace support */
7721 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
7722 register_name = "UserTraceData1";
7723 goto cp0_unimplemented;
7724 case CP0_REG23__TRACEIBPC:
7725 /* PDtrace support */
7726 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
7727 register_name = "TraceIBPC";
7728 goto cp0_unimplemented;
7729 case CP0_REG23__TRACEDBPC:
7730 /* PDtrace support */
7731 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
7732 register_name = "TraceDBPC";
7733 goto cp0_unimplemented;
7734 default:
7735 goto cp0_unimplemented;
7737 break;
7738 case CP0_REGISTER_24:
7739 switch (sel) {
7740 case CP0_REG24__DEPC:
7741 /* EJTAG support */
7742 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7743 register_name = "DEPC";
7744 break;
7745 default:
7746 goto cp0_unimplemented;
7748 break;
7749 case CP0_REGISTER_25:
7750 switch (sel) {
7751 case CP0_REG25__PERFCTL0:
7752 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7753 register_name = "Performance0";
7754 break;
7755 case CP0_REG25__PERFCNT0:
7756 /* gen_helper_dmfc0_performance1(arg); */
7757 register_name = "Performance1";
7758 goto cp0_unimplemented;
7759 case CP0_REG25__PERFCTL1:
7760 /* gen_helper_dmfc0_performance2(arg); */
7761 register_name = "Performance2";
7762 goto cp0_unimplemented;
7763 case CP0_REG25__PERFCNT1:
7764 /* gen_helper_dmfc0_performance3(arg); */
7765 register_name = "Performance3";
7766 goto cp0_unimplemented;
7767 case CP0_REG25__PERFCTL2:
7768 /* gen_helper_dmfc0_performance4(arg); */
7769 register_name = "Performance4";
7770 goto cp0_unimplemented;
7771 case CP0_REG25__PERFCNT2:
7772 /* gen_helper_dmfc0_performance5(arg); */
7773 register_name = "Performance5";
7774 goto cp0_unimplemented;
7775 case CP0_REG25__PERFCTL3:
7776 /* gen_helper_dmfc0_performance6(arg); */
7777 register_name = "Performance6";
7778 goto cp0_unimplemented;
7779 case CP0_REG25__PERFCNT3:
7780 /* gen_helper_dmfc0_performance7(arg); */
7781 register_name = "Performance7";
7782 goto cp0_unimplemented;
7783 default:
7784 goto cp0_unimplemented;
7786 break;
7787 case CP0_REGISTER_26:
7788 switch (sel) {
7789 case CP0_REG26__ERRCTL:
7790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7791 register_name = "ErrCtl";
7792 break;
7793 default:
7794 goto cp0_unimplemented;
7796 break;
7797 case CP0_REGISTER_27:
7798 switch (sel) {
7799 /* ignored */
7800 case CP0_REG27__CACHERR:
7801 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7802 register_name = "CacheErr";
7803 break;
7804 default:
7805 goto cp0_unimplemented;
7807 break;
7808 case CP0_REGISTER_28:
7809 switch (sel) {
7810 case CP0_REG28__TAGLO:
7811 case CP0_REG28__TAGLO1:
7812 case CP0_REG28__TAGLO2:
7813 case CP0_REG28__TAGLO3:
7814 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7815 register_name = "TagLo";
7816 break;
7817 case CP0_REG28__DATALO:
7818 case CP0_REG28__DATALO1:
7819 case CP0_REG28__DATALO2:
7820 case CP0_REG28__DATALO3:
7821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7822 register_name = "DataLo";
7823 break;
7824 default:
7825 goto cp0_unimplemented;
7827 break;
7828 case CP0_REGISTER_29:
7829 switch (sel) {
7830 case CP0_REG29__TAGHI:
7831 case CP0_REG29__TAGHI1:
7832 case CP0_REG29__TAGHI2:
7833 case CP0_REG29__TAGHI3:
7834 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7835 register_name = "TagHi";
7836 break;
7837 case CP0_REG29__DATAHI:
7838 case CP0_REG29__DATAHI1:
7839 case CP0_REG29__DATAHI2:
7840 case CP0_REG29__DATAHI3:
7841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7842 register_name = "DataHi";
7843 break;
7844 default:
7845 goto cp0_unimplemented;
7847 break;
7848 case CP0_REGISTER_30:
7849 switch (sel) {
7850 case CP0_REG30__ERROREPC:
7851 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7852 register_name = "ErrorEPC";
7853 break;
7854 default:
7855 goto cp0_unimplemented;
7857 break;
7858 case CP0_REGISTER_31:
7859 switch (sel) {
7860 case CP0_REG31__DESAVE:
7861 /* EJTAG support */
7862 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7863 register_name = "DESAVE";
7864 break;
7865 case CP0_REG31__KSCRATCH1:
7866 case CP0_REG31__KSCRATCH2:
7867 case CP0_REG31__KSCRATCH3:
7868 case CP0_REG31__KSCRATCH4:
7869 case CP0_REG31__KSCRATCH5:
7870 case CP0_REG31__KSCRATCH6:
7871 CP0_CHECK(ctx->kscrexist & (1 << sel));
7872 tcg_gen_ld_tl(arg, cpu_env,
7873 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7874 register_name = "KScratch";
7875 break;
7876 default:
7877 goto cp0_unimplemented;
7879 break;
7880 default:
7881 goto cp0_unimplemented;
7883 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
7884 return;
7886 cp0_unimplemented:
7887 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
7888 register_name, reg, sel);
7889 gen_mfc0_unimplemented(ctx, arg);
7892 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7894 const char *register_name = "invalid";
7896 if (sel != 0) {
7897 check_insn(ctx, ISA_MIPS_R1);
7900 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7901 gen_io_start();
7904 switch (reg) {
7905 case CP0_REGISTER_00:
7906 switch (sel) {
7907 case CP0_REG00__INDEX:
7908 gen_helper_mtc0_index(cpu_env, arg);
7909 register_name = "Index";
7910 break;
7911 case CP0_REG00__MVPCONTROL:
7912 CP0_CHECK(ctx->insn_flags & ASE_MT);
7913 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7914 register_name = "MVPControl";
7915 break;
7916 case CP0_REG00__MVPCONF0:
7917 CP0_CHECK(ctx->insn_flags & ASE_MT);
7918 /* ignored */
7919 register_name = "MVPConf0";
7920 break;
7921 case CP0_REG00__MVPCONF1:
7922 CP0_CHECK(ctx->insn_flags & ASE_MT);
7923 /* ignored */
7924 register_name = "MVPConf1";
7925 break;
7926 case CP0_REG00__VPCONTROL:
7927 CP0_CHECK(ctx->vp);
7928 /* ignored */
7929 register_name = "VPControl";
7930 break;
7931 default:
7932 goto cp0_unimplemented;
7934 break;
7935 case CP0_REGISTER_01:
7936 switch (sel) {
7937 case CP0_REG01__RANDOM:
7938 /* ignored */
7939 register_name = "Random";
7940 break;
7941 case CP0_REG01__VPECONTROL:
7942 CP0_CHECK(ctx->insn_flags & ASE_MT);
7943 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7944 register_name = "VPEControl";
7945 break;
7946 case CP0_REG01__VPECONF0:
7947 CP0_CHECK(ctx->insn_flags & ASE_MT);
7948 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7949 register_name = "VPEConf0";
7950 break;
7951 case CP0_REG01__VPECONF1:
7952 CP0_CHECK(ctx->insn_flags & ASE_MT);
7953 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7954 register_name = "VPEConf1";
7955 break;
7956 case CP0_REG01__YQMASK:
7957 CP0_CHECK(ctx->insn_flags & ASE_MT);
7958 gen_helper_mtc0_yqmask(cpu_env, arg);
7959 register_name = "YQMask";
7960 break;
7961 case CP0_REG01__VPESCHEDULE:
7962 CP0_CHECK(ctx->insn_flags & ASE_MT);
7963 tcg_gen_st_tl(arg, cpu_env,
7964 offsetof(CPUMIPSState, CP0_VPESchedule));
7965 register_name = "VPESchedule";
7966 break;
7967 case CP0_REG01__VPESCHEFBACK:
7968 CP0_CHECK(ctx->insn_flags & ASE_MT);
7969 tcg_gen_st_tl(arg, cpu_env,
7970 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7971 register_name = "VPEScheFBack";
7972 break;
7973 case CP0_REG01__VPEOPT:
7974 CP0_CHECK(ctx->insn_flags & ASE_MT);
7975 gen_helper_mtc0_vpeopt(cpu_env, arg);
7976 register_name = "VPEOpt";
7977 break;
7978 default:
7979 goto cp0_unimplemented;
7981 break;
7982 case CP0_REGISTER_02:
7983 switch (sel) {
7984 case CP0_REG02__ENTRYLO0:
7985 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7986 register_name = "EntryLo0";
7987 break;
7988 case CP0_REG02__TCSTATUS:
7989 CP0_CHECK(ctx->insn_flags & ASE_MT);
7990 gen_helper_mtc0_tcstatus(cpu_env, arg);
7991 register_name = "TCStatus";
7992 break;
7993 case CP0_REG02__TCBIND:
7994 CP0_CHECK(ctx->insn_flags & ASE_MT);
7995 gen_helper_mtc0_tcbind(cpu_env, arg);
7996 register_name = "TCBind";
7997 break;
7998 case CP0_REG02__TCRESTART:
7999 CP0_CHECK(ctx->insn_flags & ASE_MT);
8000 gen_helper_mtc0_tcrestart(cpu_env, arg);
8001 register_name = "TCRestart";
8002 break;
8003 case CP0_REG02__TCHALT:
8004 CP0_CHECK(ctx->insn_flags & ASE_MT);
8005 gen_helper_mtc0_tchalt(cpu_env, arg);
8006 register_name = "TCHalt";
8007 break;
8008 case CP0_REG02__TCCONTEXT:
8009 CP0_CHECK(ctx->insn_flags & ASE_MT);
8010 gen_helper_mtc0_tccontext(cpu_env, arg);
8011 register_name = "TCContext";
8012 break;
8013 case CP0_REG02__TCSCHEDULE:
8014 CP0_CHECK(ctx->insn_flags & ASE_MT);
8015 gen_helper_mtc0_tcschedule(cpu_env, arg);
8016 register_name = "TCSchedule";
8017 break;
8018 case CP0_REG02__TCSCHEFBACK:
8019 CP0_CHECK(ctx->insn_flags & ASE_MT);
8020 gen_helper_mtc0_tcschefback(cpu_env, arg);
8021 register_name = "TCScheFBack";
8022 break;
8023 default:
8024 goto cp0_unimplemented;
8026 break;
8027 case CP0_REGISTER_03:
8028 switch (sel) {
8029 case CP0_REG03__ENTRYLO1:
8030 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8031 register_name = "EntryLo1";
8032 break;
8033 case CP0_REG03__GLOBALNUM:
8034 CP0_CHECK(ctx->vp);
8035 /* ignored */
8036 register_name = "GlobalNumber";
8037 break;
8038 default:
8039 goto cp0_unimplemented;
8041 break;
8042 case CP0_REGISTER_04:
8043 switch (sel) {
8044 case CP0_REG04__CONTEXT:
8045 gen_helper_mtc0_context(cpu_env, arg);
8046 register_name = "Context";
8047 break;
8048 case CP0_REG04__CONTEXTCONFIG:
8049 /* SmartMIPS ASE */
8050 /* gen_helper_dmtc0_contextconfig(arg); */
8051 register_name = "ContextConfig";
8052 goto cp0_unimplemented;
8053 case CP0_REG04__USERLOCAL:
8054 CP0_CHECK(ctx->ulri);
8055 tcg_gen_st_tl(arg, cpu_env,
8056 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8057 register_name = "UserLocal";
8058 break;
8059 case CP0_REG04__MMID:
8060 CP0_CHECK(ctx->mi);
8061 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8062 register_name = "MMID";
8063 break;
8064 default:
8065 goto cp0_unimplemented;
8067 break;
8068 case CP0_REGISTER_05:
8069 switch (sel) {
8070 case CP0_REG05__PAGEMASK:
8071 gen_helper_mtc0_pagemask(cpu_env, arg);
8072 register_name = "PageMask";
8073 break;
8074 case CP0_REG05__PAGEGRAIN:
8075 check_insn(ctx, ISA_MIPS_R2);
8076 gen_helper_mtc0_pagegrain(cpu_env, arg);
8077 register_name = "PageGrain";
8078 break;
8079 case CP0_REG05__SEGCTL0:
8080 CP0_CHECK(ctx->sc);
8081 gen_helper_mtc0_segctl0(cpu_env, arg);
8082 register_name = "SegCtl0";
8083 break;
8084 case CP0_REG05__SEGCTL1:
8085 CP0_CHECK(ctx->sc);
8086 gen_helper_mtc0_segctl1(cpu_env, arg);
8087 register_name = "SegCtl1";
8088 break;
8089 case CP0_REG05__SEGCTL2:
8090 CP0_CHECK(ctx->sc);
8091 gen_helper_mtc0_segctl2(cpu_env, arg);
8092 register_name = "SegCtl2";
8093 break;
8094 case CP0_REG05__PWBASE:
8095 check_pw(ctx);
8096 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8097 register_name = "PWBase";
8098 break;
8099 case CP0_REG05__PWFIELD:
8100 check_pw(ctx);
8101 gen_helper_mtc0_pwfield(cpu_env, arg);
8102 register_name = "PWField";
8103 break;
8104 case CP0_REG05__PWSIZE:
8105 check_pw(ctx);
8106 gen_helper_mtc0_pwsize(cpu_env, arg);
8107 register_name = "PWSize";
8108 break;
8109 default:
8110 goto cp0_unimplemented;
8112 break;
8113 case CP0_REGISTER_06:
8114 switch (sel) {
8115 case CP0_REG06__WIRED:
8116 gen_helper_mtc0_wired(cpu_env, arg);
8117 register_name = "Wired";
8118 break;
8119 case CP0_REG06__SRSCONF0:
8120 check_insn(ctx, ISA_MIPS_R2);
8121 gen_helper_mtc0_srsconf0(cpu_env, arg);
8122 register_name = "SRSConf0";
8123 break;
8124 case CP0_REG06__SRSCONF1:
8125 check_insn(ctx, ISA_MIPS_R2);
8126 gen_helper_mtc0_srsconf1(cpu_env, arg);
8127 register_name = "SRSConf1";
8128 break;
8129 case CP0_REG06__SRSCONF2:
8130 check_insn(ctx, ISA_MIPS_R2);
8131 gen_helper_mtc0_srsconf2(cpu_env, arg);
8132 register_name = "SRSConf2";
8133 break;
8134 case CP0_REG06__SRSCONF3:
8135 check_insn(ctx, ISA_MIPS_R2);
8136 gen_helper_mtc0_srsconf3(cpu_env, arg);
8137 register_name = "SRSConf3";
8138 break;
8139 case CP0_REG06__SRSCONF4:
8140 check_insn(ctx, ISA_MIPS_R2);
8141 gen_helper_mtc0_srsconf4(cpu_env, arg);
8142 register_name = "SRSConf4";
8143 break;
8144 case CP0_REG06__PWCTL:
8145 check_pw(ctx);
8146 gen_helper_mtc0_pwctl(cpu_env, arg);
8147 register_name = "PWCtl";
8148 break;
8149 default:
8150 goto cp0_unimplemented;
8152 break;
8153 case CP0_REGISTER_07:
8154 switch (sel) {
8155 case CP0_REG07__HWRENA:
8156 check_insn(ctx, ISA_MIPS_R2);
8157 gen_helper_mtc0_hwrena(cpu_env, arg);
8158 ctx->base.is_jmp = DISAS_STOP;
8159 register_name = "HWREna";
8160 break;
8161 default:
8162 goto cp0_unimplemented;
8164 break;
8165 case CP0_REGISTER_08:
8166 switch (sel) {
8167 case CP0_REG08__BADVADDR:
8168 /* ignored */
8169 register_name = "BadVAddr";
8170 break;
8171 case CP0_REG08__BADINSTR:
8172 /* ignored */
8173 register_name = "BadInstr";
8174 break;
8175 case CP0_REG08__BADINSTRP:
8176 /* ignored */
8177 register_name = "BadInstrP";
8178 break;
8179 case CP0_REG08__BADINSTRX:
8180 /* ignored */
8181 register_name = "BadInstrX";
8182 break;
8183 default:
8184 goto cp0_unimplemented;
8186 break;
8187 case CP0_REGISTER_09:
8188 switch (sel) {
8189 case CP0_REG09__COUNT:
8190 gen_helper_mtc0_count(cpu_env, arg);
8191 register_name = "Count";
8192 break;
8193 case CP0_REG09__SAARI:
8194 CP0_CHECK(ctx->saar);
8195 gen_helper_mtc0_saari(cpu_env, arg);
8196 register_name = "SAARI";
8197 break;
8198 case CP0_REG09__SAAR:
8199 CP0_CHECK(ctx->saar);
8200 gen_helper_mtc0_saar(cpu_env, arg);
8201 register_name = "SAAR";
8202 break;
8203 default:
8204 goto cp0_unimplemented;
8206 /* Stop translation as we may have switched the execution mode */
8207 ctx->base.is_jmp = DISAS_STOP;
8208 break;
8209 case CP0_REGISTER_10:
8210 switch (sel) {
8211 case CP0_REG10__ENTRYHI:
8212 gen_helper_mtc0_entryhi(cpu_env, arg);
8213 register_name = "EntryHi";
8214 break;
8215 default:
8216 goto cp0_unimplemented;
8218 break;
8219 case CP0_REGISTER_11:
8220 switch (sel) {
8221 case CP0_REG11__COMPARE:
8222 gen_helper_mtc0_compare(cpu_env, arg);
8223 register_name = "Compare";
8224 break;
8225 /* 6,7 are implementation dependent */
8226 default:
8227 goto cp0_unimplemented;
8229 /* Stop translation as we may have switched the execution mode */
8230 ctx->base.is_jmp = DISAS_STOP;
8231 break;
8232 case CP0_REGISTER_12:
8233 switch (sel) {
8234 case CP0_REG12__STATUS:
8235 save_cpu_state(ctx, 1);
8236 gen_helper_mtc0_status(cpu_env, arg);
8237 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8238 gen_save_pc(ctx->base.pc_next + 4);
8239 ctx->base.is_jmp = DISAS_EXIT;
8240 register_name = "Status";
8241 break;
8242 case CP0_REG12__INTCTL:
8243 check_insn(ctx, ISA_MIPS_R2);
8244 gen_helper_mtc0_intctl(cpu_env, arg);
8245 /* Stop translation as we may have switched the execution mode */
8246 ctx->base.is_jmp = DISAS_STOP;
8247 register_name = "IntCtl";
8248 break;
8249 case CP0_REG12__SRSCTL:
8250 check_insn(ctx, ISA_MIPS_R2);
8251 gen_helper_mtc0_srsctl(cpu_env, arg);
8252 /* Stop translation as we may have switched the execution mode */
8253 ctx->base.is_jmp = DISAS_STOP;
8254 register_name = "SRSCtl";
8255 break;
8256 case CP0_REG12__SRSMAP:
8257 check_insn(ctx, ISA_MIPS_R2);
8258 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8259 /* Stop translation as we may have switched the execution mode */
8260 ctx->base.is_jmp = DISAS_STOP;
8261 register_name = "SRSMap";
8262 break;
8263 default:
8264 goto cp0_unimplemented;
8266 break;
8267 case CP0_REGISTER_13:
8268 switch (sel) {
8269 case CP0_REG13__CAUSE:
8270 save_cpu_state(ctx, 1);
8271 gen_helper_mtc0_cause(cpu_env, arg);
8273 * Stop translation as we may have triggered an interrupt.
8274 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8275 * translated code to check for pending interrupts.
8277 gen_save_pc(ctx->base.pc_next + 4);
8278 ctx->base.is_jmp = DISAS_EXIT;
8279 register_name = "Cause";
8280 break;
8281 default:
8282 goto cp0_unimplemented;
8284 break;
8285 case CP0_REGISTER_14:
8286 switch (sel) {
8287 case CP0_REG14__EPC:
8288 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8289 register_name = "EPC";
8290 break;
8291 default:
8292 goto cp0_unimplemented;
8294 break;
8295 case CP0_REGISTER_15:
8296 switch (sel) {
8297 case CP0_REG15__PRID:
8298 /* ignored */
8299 register_name = "PRid";
8300 break;
8301 case CP0_REG15__EBASE:
8302 check_insn(ctx, ISA_MIPS_R2);
8303 gen_helper_mtc0_ebase(cpu_env, arg);
8304 register_name = "EBase";
8305 break;
8306 default:
8307 goto cp0_unimplemented;
8309 break;
8310 case CP0_REGISTER_16:
8311 switch (sel) {
8312 case CP0_REG16__CONFIG:
8313 gen_helper_mtc0_config0(cpu_env, arg);
8314 register_name = "Config";
8315 /* Stop translation as we may have switched the execution mode */
8316 ctx->base.is_jmp = DISAS_STOP;
8317 break;
8318 case CP0_REG16__CONFIG1:
8319 /* ignored, read only */
8320 register_name = "Config1";
8321 break;
8322 case CP0_REG16__CONFIG2:
8323 gen_helper_mtc0_config2(cpu_env, arg);
8324 register_name = "Config2";
8325 /* Stop translation as we may have switched the execution mode */
8326 ctx->base.is_jmp = DISAS_STOP;
8327 break;
8328 case CP0_REG16__CONFIG3:
8329 gen_helper_mtc0_config3(cpu_env, arg);
8330 register_name = "Config3";
8331 /* Stop translation as we may have switched the execution mode */
8332 ctx->base.is_jmp = DISAS_STOP;
8333 break;
8334 case CP0_REG16__CONFIG4:
8335 /* currently ignored */
8336 register_name = "Config4";
8337 break;
8338 case CP0_REG16__CONFIG5:
8339 gen_helper_mtc0_config5(cpu_env, arg);
8340 register_name = "Config5";
8341 /* Stop translation as we may have switched the execution mode */
8342 ctx->base.is_jmp = DISAS_STOP;
8343 break;
8344 /* 6,7 are implementation dependent */
8345 default:
8346 register_name = "Invalid config selector";
8347 goto cp0_unimplemented;
8349 break;
8350 case CP0_REGISTER_17:
8351 switch (sel) {
8352 case CP0_REG17__LLADDR:
8353 gen_helper_mtc0_lladdr(cpu_env, arg);
8354 register_name = "LLAddr";
8355 break;
8356 case CP0_REG17__MAAR:
8357 CP0_CHECK(ctx->mrp);
8358 gen_helper_mtc0_maar(cpu_env, arg);
8359 register_name = "MAAR";
8360 break;
8361 case CP0_REG17__MAARI:
8362 CP0_CHECK(ctx->mrp);
8363 gen_helper_mtc0_maari(cpu_env, arg);
8364 register_name = "MAARI";
8365 break;
8366 default:
8367 goto cp0_unimplemented;
8369 break;
8370 case CP0_REGISTER_18:
8371 switch (sel) {
8372 case CP0_REG18__WATCHLO0:
8373 case CP0_REG18__WATCHLO1:
8374 case CP0_REG18__WATCHLO2:
8375 case CP0_REG18__WATCHLO3:
8376 case CP0_REG18__WATCHLO4:
8377 case CP0_REG18__WATCHLO5:
8378 case CP0_REG18__WATCHLO6:
8379 case CP0_REG18__WATCHLO7:
8380 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8381 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8382 register_name = "WatchLo";
8383 break;
8384 default:
8385 goto cp0_unimplemented;
8387 break;
8388 case CP0_REGISTER_19:
8389 switch (sel) {
8390 case CP0_REG19__WATCHHI0:
8391 case CP0_REG19__WATCHHI1:
8392 case CP0_REG19__WATCHHI2:
8393 case CP0_REG19__WATCHHI3:
8394 case CP0_REG19__WATCHHI4:
8395 case CP0_REG19__WATCHHI5:
8396 case CP0_REG19__WATCHHI6:
8397 case CP0_REG19__WATCHHI7:
8398 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8399 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8400 register_name = "WatchHi";
8401 break;
8402 default:
8403 goto cp0_unimplemented;
8405 break;
8406 case CP0_REGISTER_20:
8407 switch (sel) {
8408 case CP0_REG20__XCONTEXT:
8409 check_insn(ctx, ISA_MIPS3);
8410 gen_helper_mtc0_xcontext(cpu_env, arg);
8411 register_name = "XContext";
8412 break;
8413 default:
8414 goto cp0_unimplemented;
8416 break;
8417 case CP0_REGISTER_21:
8418 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8419 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8420 switch (sel) {
8421 case 0:
8422 gen_helper_mtc0_framemask(cpu_env, arg);
8423 register_name = "Framemask";
8424 break;
8425 default:
8426 goto cp0_unimplemented;
8428 break;
8429 case CP0_REGISTER_22:
8430 /* ignored */
8431 register_name = "Diagnostic"; /* implementation dependent */
8432 break;
8433 case CP0_REGISTER_23:
8434 switch (sel) {
8435 case CP0_REG23__DEBUG:
8436 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8437 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8438 gen_save_pc(ctx->base.pc_next + 4);
8439 ctx->base.is_jmp = DISAS_EXIT;
8440 register_name = "Debug";
8441 break;
8442 case CP0_REG23__TRACECONTROL:
8443 /* PDtrace support */
8444 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8445 /* Stop translation as we may have switched the execution mode */
8446 ctx->base.is_jmp = DISAS_STOP;
8447 register_name = "TraceControl";
8448 goto cp0_unimplemented;
8449 case CP0_REG23__TRACECONTROL2:
8450 /* PDtrace support */
8451 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8452 /* Stop translation as we may have switched the execution mode */
8453 ctx->base.is_jmp = DISAS_STOP;
8454 register_name = "TraceControl2";
8455 goto cp0_unimplemented;
8456 case CP0_REG23__USERTRACEDATA1:
8457 /* PDtrace support */
8458 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8459 /* Stop translation as we may have switched the execution mode */
8460 ctx->base.is_jmp = DISAS_STOP;
8461 register_name = "UserTraceData1";
8462 goto cp0_unimplemented;
8463 case CP0_REG23__TRACEIBPC:
8464 /* PDtrace support */
8465 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8466 /* Stop translation as we may have switched the execution mode */
8467 ctx->base.is_jmp = DISAS_STOP;
8468 register_name = "TraceIBPC";
8469 goto cp0_unimplemented;
8470 case CP0_REG23__TRACEDBPC:
8471 /* PDtrace support */
8472 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8473 /* Stop translation as we may have switched the execution mode */
8474 ctx->base.is_jmp = DISAS_STOP;
8475 register_name = "TraceDBPC";
8476 goto cp0_unimplemented;
8477 default:
8478 goto cp0_unimplemented;
8480 break;
8481 case CP0_REGISTER_24:
8482 switch (sel) {
8483 case CP0_REG24__DEPC:
8484 /* EJTAG support */
8485 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8486 register_name = "DEPC";
8487 break;
8488 default:
8489 goto cp0_unimplemented;
8491 break;
8492 case CP0_REGISTER_25:
8493 switch (sel) {
8494 case CP0_REG25__PERFCTL0:
8495 gen_helper_mtc0_performance0(cpu_env, arg);
8496 register_name = "Performance0";
8497 break;
8498 case CP0_REG25__PERFCNT0:
8499 /* gen_helper_mtc0_performance1(cpu_env, arg); */
8500 register_name = "Performance1";
8501 goto cp0_unimplemented;
8502 case CP0_REG25__PERFCTL1:
8503 /* gen_helper_mtc0_performance2(cpu_env, arg); */
8504 register_name = "Performance2";
8505 goto cp0_unimplemented;
8506 case CP0_REG25__PERFCNT1:
8507 /* gen_helper_mtc0_performance3(cpu_env, arg); */
8508 register_name = "Performance3";
8509 goto cp0_unimplemented;
8510 case CP0_REG25__PERFCTL2:
8511 /* gen_helper_mtc0_performance4(cpu_env, arg); */
8512 register_name = "Performance4";
8513 goto cp0_unimplemented;
8514 case CP0_REG25__PERFCNT2:
8515 /* gen_helper_mtc0_performance5(cpu_env, arg); */
8516 register_name = "Performance5";
8517 goto cp0_unimplemented;
8518 case CP0_REG25__PERFCTL3:
8519 /* gen_helper_mtc0_performance6(cpu_env, arg); */
8520 register_name = "Performance6";
8521 goto cp0_unimplemented;
8522 case CP0_REG25__PERFCNT3:
8523 /* gen_helper_mtc0_performance7(cpu_env, arg); */
8524 register_name = "Performance7";
8525 goto cp0_unimplemented;
8526 default:
8527 goto cp0_unimplemented;
8529 break;
8530 case CP0_REGISTER_26:
8531 switch (sel) {
8532 case CP0_REG26__ERRCTL:
8533 gen_helper_mtc0_errctl(cpu_env, arg);
8534 ctx->base.is_jmp = DISAS_STOP;
8535 register_name = "ErrCtl";
8536 break;
8537 default:
8538 goto cp0_unimplemented;
8540 break;
8541 case CP0_REGISTER_27:
8542 switch (sel) {
8543 case CP0_REG27__CACHERR:
8544 /* ignored */
8545 register_name = "CacheErr";
8546 break;
8547 default:
8548 goto cp0_unimplemented;
8550 break;
8551 case CP0_REGISTER_28:
8552 switch (sel) {
8553 case CP0_REG28__TAGLO:
8554 case CP0_REG28__TAGLO1:
8555 case CP0_REG28__TAGLO2:
8556 case CP0_REG28__TAGLO3:
8557 gen_helper_mtc0_taglo(cpu_env, arg);
8558 register_name = "TagLo";
8559 break;
8560 case CP0_REG28__DATALO:
8561 case CP0_REG28__DATALO1:
8562 case CP0_REG28__DATALO2:
8563 case CP0_REG28__DATALO3:
8564 gen_helper_mtc0_datalo(cpu_env, arg);
8565 register_name = "DataLo";
8566 break;
8567 default:
8568 goto cp0_unimplemented;
8570 break;
8571 case CP0_REGISTER_29:
8572 switch (sel) {
8573 case CP0_REG29__TAGHI:
8574 case CP0_REG29__TAGHI1:
8575 case CP0_REG29__TAGHI2:
8576 case CP0_REG29__TAGHI3:
8577 gen_helper_mtc0_taghi(cpu_env, arg);
8578 register_name = "TagHi";
8579 break;
8580 case CP0_REG29__DATAHI:
8581 case CP0_REG29__DATAHI1:
8582 case CP0_REG29__DATAHI2:
8583 case CP0_REG29__DATAHI3:
8584 gen_helper_mtc0_datahi(cpu_env, arg);
8585 register_name = "DataHi";
8586 break;
8587 default:
8588 register_name = "invalid sel";
8589 goto cp0_unimplemented;
8591 break;
8592 case CP0_REGISTER_30:
8593 switch (sel) {
8594 case CP0_REG30__ERROREPC:
8595 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8596 register_name = "ErrorEPC";
8597 break;
8598 default:
8599 goto cp0_unimplemented;
8601 break;
8602 case CP0_REGISTER_31:
8603 switch (sel) {
8604 case CP0_REG31__DESAVE:
8605 /* EJTAG support */
8606 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8607 register_name = "DESAVE";
8608 break;
8609 case CP0_REG31__KSCRATCH1:
8610 case CP0_REG31__KSCRATCH2:
8611 case CP0_REG31__KSCRATCH3:
8612 case CP0_REG31__KSCRATCH4:
8613 case CP0_REG31__KSCRATCH5:
8614 case CP0_REG31__KSCRATCH6:
8615 CP0_CHECK(ctx->kscrexist & (1 << sel));
8616 tcg_gen_st_tl(arg, cpu_env,
8617 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8618 register_name = "KScratch";
8619 break;
8620 default:
8621 goto cp0_unimplemented;
8623 break;
8624 default:
8625 goto cp0_unimplemented;
8627 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
8629 /* For simplicity assume that all writes can cause interrupts. */
8630 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8632 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8633 * translated code to check for pending interrupts.
8635 gen_save_pc(ctx->base.pc_next + 4);
8636 ctx->base.is_jmp = DISAS_EXIT;
8638 return;
8640 cp0_unimplemented:
8641 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8642 register_name, reg, sel);
8644 #endif /* TARGET_MIPS64 */
8646 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8647 int u, int sel, int h)
8649 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8650 TCGv t0 = tcg_temp_local_new();
8652 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8653 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8654 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8655 tcg_gen_movi_tl(t0, -1);
8656 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8657 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8658 tcg_gen_movi_tl(t0, -1);
8659 } else if (u == 0) {
8660 switch (rt) {
8661 case 1:
8662 switch (sel) {
8663 case 1:
8664 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8665 break;
8666 case 2:
8667 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8668 break;
8669 default:
8670 goto die;
8671 break;
8673 break;
8674 case 2:
8675 switch (sel) {
8676 case 1:
8677 gen_helper_mftc0_tcstatus(t0, cpu_env);
8678 break;
8679 case 2:
8680 gen_helper_mftc0_tcbind(t0, cpu_env);
8681 break;
8682 case 3:
8683 gen_helper_mftc0_tcrestart(t0, cpu_env);
8684 break;
8685 case 4:
8686 gen_helper_mftc0_tchalt(t0, cpu_env);
8687 break;
8688 case 5:
8689 gen_helper_mftc0_tccontext(t0, cpu_env);
8690 break;
8691 case 6:
8692 gen_helper_mftc0_tcschedule(t0, cpu_env);
8693 break;
8694 case 7:
8695 gen_helper_mftc0_tcschefback(t0, cpu_env);
8696 break;
8697 default:
8698 gen_mfc0(ctx, t0, rt, sel);
8699 break;
8701 break;
8702 case 10:
8703 switch (sel) {
8704 case 0:
8705 gen_helper_mftc0_entryhi(t0, cpu_env);
8706 break;
8707 default:
8708 gen_mfc0(ctx, t0, rt, sel);
8709 break;
8711 break;
8712 case 12:
8713 switch (sel) {
8714 case 0:
8715 gen_helper_mftc0_status(t0, cpu_env);
8716 break;
8717 default:
8718 gen_mfc0(ctx, t0, rt, sel);
8719 break;
8721 break;
8722 case 13:
8723 switch (sel) {
8724 case 0:
8725 gen_helper_mftc0_cause(t0, cpu_env);
8726 break;
8727 default:
8728 goto die;
8729 break;
8731 break;
8732 case 14:
8733 switch (sel) {
8734 case 0:
8735 gen_helper_mftc0_epc(t0, cpu_env);
8736 break;
8737 default:
8738 goto die;
8739 break;
8741 break;
8742 case 15:
8743 switch (sel) {
8744 case 1:
8745 gen_helper_mftc0_ebase(t0, cpu_env);
8746 break;
8747 default:
8748 goto die;
8749 break;
8751 break;
8752 case 16:
8753 switch (sel) {
8754 case 0:
8755 case 1:
8756 case 2:
8757 case 3:
8758 case 4:
8759 case 5:
8760 case 6:
8761 case 7:
8762 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
8763 break;
8764 default:
8765 goto die;
8766 break;
8768 break;
8769 case 23:
8770 switch (sel) {
8771 case 0:
8772 gen_helper_mftc0_debug(t0, cpu_env);
8773 break;
8774 default:
8775 gen_mfc0(ctx, t0, rt, sel);
8776 break;
8778 break;
8779 default:
8780 gen_mfc0(ctx, t0, rt, sel);
8782 } else {
8783 switch (sel) {
8784 /* GPR registers. */
8785 case 0:
8786 gen_helper_1e0i(mftgpr, t0, rt);
8787 break;
8788 /* Auxiliary CPU registers */
8789 case 1:
8790 switch (rt) {
8791 case 0:
8792 gen_helper_1e0i(mftlo, t0, 0);
8793 break;
8794 case 1:
8795 gen_helper_1e0i(mfthi, t0, 0);
8796 break;
8797 case 2:
8798 gen_helper_1e0i(mftacx, t0, 0);
8799 break;
8800 case 4:
8801 gen_helper_1e0i(mftlo, t0, 1);
8802 break;
8803 case 5:
8804 gen_helper_1e0i(mfthi, t0, 1);
8805 break;
8806 case 6:
8807 gen_helper_1e0i(mftacx, t0, 1);
8808 break;
8809 case 8:
8810 gen_helper_1e0i(mftlo, t0, 2);
8811 break;
8812 case 9:
8813 gen_helper_1e0i(mfthi, t0, 2);
8814 break;
8815 case 10:
8816 gen_helper_1e0i(mftacx, t0, 2);
8817 break;
8818 case 12:
8819 gen_helper_1e0i(mftlo, t0, 3);
8820 break;
8821 case 13:
8822 gen_helper_1e0i(mfthi, t0, 3);
8823 break;
8824 case 14:
8825 gen_helper_1e0i(mftacx, t0, 3);
8826 break;
8827 case 16:
8828 gen_helper_mftdsp(t0, cpu_env);
8829 break;
8830 default:
8831 goto die;
8833 break;
8834 /* Floating point (COP1). */
8835 case 2:
8836 /* XXX: For now we support only a single FPU context. */
8837 if (h == 0) {
8838 TCGv_i32 fp0 = tcg_temp_new_i32();
8840 gen_load_fpr32(ctx, fp0, rt);
8841 tcg_gen_ext_i32_tl(t0, fp0);
8842 tcg_temp_free_i32(fp0);
8843 } else {
8844 TCGv_i32 fp0 = tcg_temp_new_i32();
8846 gen_load_fpr32h(ctx, fp0, rt);
8847 tcg_gen_ext_i32_tl(t0, fp0);
8848 tcg_temp_free_i32(fp0);
8850 break;
8851 case 3:
8852 /* XXX: For now we support only a single FPU context. */
8853 gen_helper_1e0i(cfc1, t0, rt);
8854 break;
8855 /* COP2: Not implemented. */
8856 case 4:
8857 case 5:
8858 /* fall through */
8859 default:
8860 goto die;
8863 trace_mips_translate_tr("mftr", rt, u, sel, h);
8864 gen_store_gpr(t0, rd);
8865 tcg_temp_free(t0);
8866 return;
8868 die:
8869 tcg_temp_free(t0);
8870 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
8871 gen_reserved_instruction(ctx);
8874 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
8875 int u, int sel, int h)
8877 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8878 TCGv t0 = tcg_temp_local_new();
8880 gen_load_gpr(t0, rt);
8881 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8882 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8883 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8884 /* NOP */
8886 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8887 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8888 /* NOP */
8890 } else if (u == 0) {
8891 switch (rd) {
8892 case 1:
8893 switch (sel) {
8894 case 1:
8895 gen_helper_mttc0_vpecontrol(cpu_env, t0);
8896 break;
8897 case 2:
8898 gen_helper_mttc0_vpeconf0(cpu_env, t0);
8899 break;
8900 default:
8901 goto die;
8902 break;
8904 break;
8905 case 2:
8906 switch (sel) {
8907 case 1:
8908 gen_helper_mttc0_tcstatus(cpu_env, t0);
8909 break;
8910 case 2:
8911 gen_helper_mttc0_tcbind(cpu_env, t0);
8912 break;
8913 case 3:
8914 gen_helper_mttc0_tcrestart(cpu_env, t0);
8915 break;
8916 case 4:
8917 gen_helper_mttc0_tchalt(cpu_env, t0);
8918 break;
8919 case 5:
8920 gen_helper_mttc0_tccontext(cpu_env, t0);
8921 break;
8922 case 6:
8923 gen_helper_mttc0_tcschedule(cpu_env, t0);
8924 break;
8925 case 7:
8926 gen_helper_mttc0_tcschefback(cpu_env, t0);
8927 break;
8928 default:
8929 gen_mtc0(ctx, t0, rd, sel);
8930 break;
8932 break;
8933 case 10:
8934 switch (sel) {
8935 case 0:
8936 gen_helper_mttc0_entryhi(cpu_env, t0);
8937 break;
8938 default:
8939 gen_mtc0(ctx, t0, rd, sel);
8940 break;
8942 break;
8943 case 12:
8944 switch (sel) {
8945 case 0:
8946 gen_helper_mttc0_status(cpu_env, t0);
8947 break;
8948 default:
8949 gen_mtc0(ctx, t0, rd, sel);
8950 break;
8952 break;
8953 case 13:
8954 switch (sel) {
8955 case 0:
8956 gen_helper_mttc0_cause(cpu_env, t0);
8957 break;
8958 default:
8959 goto die;
8960 break;
8962 break;
8963 case 15:
8964 switch (sel) {
8965 case 1:
8966 gen_helper_mttc0_ebase(cpu_env, t0);
8967 break;
8968 default:
8969 goto die;
8970 break;
8972 break;
8973 case 23:
8974 switch (sel) {
8975 case 0:
8976 gen_helper_mttc0_debug(cpu_env, t0);
8977 break;
8978 default:
8979 gen_mtc0(ctx, t0, rd, sel);
8980 break;
8982 break;
8983 default:
8984 gen_mtc0(ctx, t0, rd, sel);
8986 } else {
8987 switch (sel) {
8988 /* GPR registers. */
8989 case 0:
8990 gen_helper_0e1i(mttgpr, t0, rd);
8991 break;
8992 /* Auxiliary CPU registers */
8993 case 1:
8994 switch (rd) {
8995 case 0:
8996 gen_helper_0e1i(mttlo, t0, 0);
8997 break;
8998 case 1:
8999 gen_helper_0e1i(mtthi, t0, 0);
9000 break;
9001 case 2:
9002 gen_helper_0e1i(mttacx, t0, 0);
9003 break;
9004 case 4:
9005 gen_helper_0e1i(mttlo, t0, 1);
9006 break;
9007 case 5:
9008 gen_helper_0e1i(mtthi, t0, 1);
9009 break;
9010 case 6:
9011 gen_helper_0e1i(mttacx, t0, 1);
9012 break;
9013 case 8:
9014 gen_helper_0e1i(mttlo, t0, 2);
9015 break;
9016 case 9:
9017 gen_helper_0e1i(mtthi, t0, 2);
9018 break;
9019 case 10:
9020 gen_helper_0e1i(mttacx, t0, 2);
9021 break;
9022 case 12:
9023 gen_helper_0e1i(mttlo, t0, 3);
9024 break;
9025 case 13:
9026 gen_helper_0e1i(mtthi, t0, 3);
9027 break;
9028 case 14:
9029 gen_helper_0e1i(mttacx, t0, 3);
9030 break;
9031 case 16:
9032 gen_helper_mttdsp(cpu_env, t0);
9033 break;
9034 default:
9035 goto die;
9037 break;
9038 /* Floating point (COP1). */
9039 case 2:
9040 /* XXX: For now we support only a single FPU context. */
9041 if (h == 0) {
9042 TCGv_i32 fp0 = tcg_temp_new_i32();
9044 tcg_gen_trunc_tl_i32(fp0, t0);
9045 gen_store_fpr32(ctx, fp0, rd);
9046 tcg_temp_free_i32(fp0);
9047 } else {
9048 TCGv_i32 fp0 = tcg_temp_new_i32();
9050 tcg_gen_trunc_tl_i32(fp0, t0);
9051 gen_store_fpr32h(ctx, fp0, rd);
9052 tcg_temp_free_i32(fp0);
9054 break;
9055 case 3:
9056 /* XXX: For now we support only a single FPU context. */
9057 gen_helper_0e2i(ctc1, t0, tcg_constant_i32(rd), rt);
9058 /* Stop translation as we may have changed hflags */
9059 ctx->base.is_jmp = DISAS_STOP;
9060 break;
9061 /* COP2: Not implemented. */
9062 case 4:
9063 case 5:
9064 /* fall through */
9065 default:
9066 goto die;
9069 trace_mips_translate_tr("mttr", rd, u, sel, h);
9070 tcg_temp_free(t0);
9071 return;
9073 die:
9074 tcg_temp_free(t0);
9075 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9076 gen_reserved_instruction(ctx);
9079 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9080 int rt, int rd)
9082 const char *opn = "ldst";
9084 check_cp0_enabled(ctx);
9085 switch (opc) {
9086 case OPC_MFC0:
9087 if (rt == 0) {
9088 /* Treat as NOP. */
9089 return;
9091 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9092 opn = "mfc0";
9093 break;
9094 case OPC_MTC0:
9096 TCGv t0 = tcg_temp_new();
9098 gen_load_gpr(t0, rt);
9099 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9100 tcg_temp_free(t0);
9102 opn = "mtc0";
9103 break;
9104 #if defined(TARGET_MIPS64)
9105 case OPC_DMFC0:
9106 check_insn(ctx, ISA_MIPS3);
9107 if (rt == 0) {
9108 /* Treat as NOP. */
9109 return;
9111 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9112 opn = "dmfc0";
9113 break;
9114 case OPC_DMTC0:
9115 check_insn(ctx, ISA_MIPS3);
9117 TCGv t0 = tcg_temp_new();
9119 gen_load_gpr(t0, rt);
9120 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9121 tcg_temp_free(t0);
9123 opn = "dmtc0";
9124 break;
9125 #endif
9126 case OPC_MFHC0:
9127 check_mvh(ctx);
9128 if (rt == 0) {
9129 /* Treat as NOP. */
9130 return;
9132 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9133 opn = "mfhc0";
9134 break;
9135 case OPC_MTHC0:
9136 check_mvh(ctx);
9138 TCGv t0 = tcg_temp_new();
9139 gen_load_gpr(t0, rt);
9140 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9141 tcg_temp_free(t0);
9143 opn = "mthc0";
9144 break;
9145 case OPC_MFTR:
9146 check_cp0_enabled(ctx);
9147 if (rd == 0) {
9148 /* Treat as NOP. */
9149 return;
9151 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9152 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9153 opn = "mftr";
9154 break;
9155 case OPC_MTTR:
9156 check_cp0_enabled(ctx);
9157 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9158 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9159 opn = "mttr";
9160 break;
9161 case OPC_TLBWI:
9162 opn = "tlbwi";
9163 if (!env->tlb->helper_tlbwi) {
9164 goto die;
9166 gen_helper_tlbwi(cpu_env);
9167 break;
9168 case OPC_TLBINV:
9169 opn = "tlbinv";
9170 if (ctx->ie >= 2) {
9171 if (!env->tlb->helper_tlbinv) {
9172 goto die;
9174 gen_helper_tlbinv(cpu_env);
9175 } /* treat as nop if TLBINV not supported */
9176 break;
9177 case OPC_TLBINVF:
9178 opn = "tlbinvf";
9179 if (ctx->ie >= 2) {
9180 if (!env->tlb->helper_tlbinvf) {
9181 goto die;
9183 gen_helper_tlbinvf(cpu_env);
9184 } /* treat as nop if TLBINV not supported */
9185 break;
9186 case OPC_TLBWR:
9187 opn = "tlbwr";
9188 if (!env->tlb->helper_tlbwr) {
9189 goto die;
9191 gen_helper_tlbwr(cpu_env);
9192 break;
9193 case OPC_TLBP:
9194 opn = "tlbp";
9195 if (!env->tlb->helper_tlbp) {
9196 goto die;
9198 gen_helper_tlbp(cpu_env);
9199 break;
9200 case OPC_TLBR:
9201 opn = "tlbr";
9202 if (!env->tlb->helper_tlbr) {
9203 goto die;
9205 gen_helper_tlbr(cpu_env);
9206 break;
9207 case OPC_ERET: /* OPC_ERETNC */
9208 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9209 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9210 goto die;
9211 } else {
9212 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9213 if (ctx->opcode & (1 << bit_shift)) {
9214 /* OPC_ERETNC */
9215 opn = "eretnc";
9216 check_insn(ctx, ISA_MIPS_R5);
9217 gen_helper_eretnc(cpu_env);
9218 } else {
9219 /* OPC_ERET */
9220 opn = "eret";
9221 check_insn(ctx, ISA_MIPS2);
9222 gen_helper_eret(cpu_env);
9224 ctx->base.is_jmp = DISAS_EXIT;
9226 break;
9227 case OPC_DERET:
9228 opn = "deret";
9229 check_insn(ctx, ISA_MIPS_R1);
9230 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9231 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9232 goto die;
9234 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9235 MIPS_INVAL(opn);
9236 gen_reserved_instruction(ctx);
9237 } else {
9238 gen_helper_deret(cpu_env);
9239 ctx->base.is_jmp = DISAS_EXIT;
9241 break;
9242 case OPC_WAIT:
9243 opn = "wait";
9244 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
9245 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9246 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9247 goto die;
9249 /* If we get an exception, we want to restart at next instruction */
9250 ctx->base.pc_next += 4;
9251 save_cpu_state(ctx, 1);
9252 ctx->base.pc_next -= 4;
9253 gen_helper_wait(cpu_env);
9254 ctx->base.is_jmp = DISAS_NORETURN;
9255 break;
9256 default:
9257 die:
9258 MIPS_INVAL(opn);
9259 gen_reserved_instruction(ctx);
9260 return;
9262 (void)opn; /* avoid a compiler warning */
9264 #endif /* !CONFIG_USER_ONLY */
9266 /* CP1 Branches (before delay slot) */
9267 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9268 int32_t cc, int32_t offset)
9270 target_ulong btarget;
9271 TCGv_i32 t0 = tcg_temp_new_i32();
9273 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9274 gen_reserved_instruction(ctx);
9275 goto out;
9278 if (cc != 0) {
9279 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
9282 btarget = ctx->base.pc_next + 4 + offset;
9284 switch (op) {
9285 case OPC_BC1F:
9286 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9287 tcg_gen_not_i32(t0, t0);
9288 tcg_gen_andi_i32(t0, t0, 1);
9289 tcg_gen_extu_i32_tl(bcond, t0);
9290 goto not_likely;
9291 case OPC_BC1FL:
9292 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9293 tcg_gen_not_i32(t0, t0);
9294 tcg_gen_andi_i32(t0, t0, 1);
9295 tcg_gen_extu_i32_tl(bcond, t0);
9296 goto likely;
9297 case OPC_BC1T:
9298 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9299 tcg_gen_andi_i32(t0, t0, 1);
9300 tcg_gen_extu_i32_tl(bcond, t0);
9301 goto not_likely;
9302 case OPC_BC1TL:
9303 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9304 tcg_gen_andi_i32(t0, t0, 1);
9305 tcg_gen_extu_i32_tl(bcond, t0);
9306 likely:
9307 ctx->hflags |= MIPS_HFLAG_BL;
9308 break;
9309 case OPC_BC1FANY2:
9311 TCGv_i32 t1 = tcg_temp_new_i32();
9312 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9313 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9314 tcg_gen_nand_i32(t0, t0, t1);
9315 tcg_temp_free_i32(t1);
9316 tcg_gen_andi_i32(t0, t0, 1);
9317 tcg_gen_extu_i32_tl(bcond, t0);
9319 goto not_likely;
9320 case OPC_BC1TANY2:
9322 TCGv_i32 t1 = tcg_temp_new_i32();
9323 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9324 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9325 tcg_gen_or_i32(t0, t0, t1);
9326 tcg_temp_free_i32(t1);
9327 tcg_gen_andi_i32(t0, t0, 1);
9328 tcg_gen_extu_i32_tl(bcond, t0);
9330 goto not_likely;
9331 case OPC_BC1FANY4:
9333 TCGv_i32 t1 = tcg_temp_new_i32();
9334 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9335 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9336 tcg_gen_and_i32(t0, t0, t1);
9337 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9338 tcg_gen_and_i32(t0, t0, t1);
9339 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9340 tcg_gen_nand_i32(t0, t0, t1);
9341 tcg_temp_free_i32(t1);
9342 tcg_gen_andi_i32(t0, t0, 1);
9343 tcg_gen_extu_i32_tl(bcond, t0);
9345 goto not_likely;
9346 case OPC_BC1TANY4:
9348 TCGv_i32 t1 = tcg_temp_new_i32();
9349 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9350 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9351 tcg_gen_or_i32(t0, t0, t1);
9352 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9353 tcg_gen_or_i32(t0, t0, t1);
9354 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9355 tcg_gen_or_i32(t0, t0, t1);
9356 tcg_temp_free_i32(t1);
9357 tcg_gen_andi_i32(t0, t0, 1);
9358 tcg_gen_extu_i32_tl(bcond, t0);
9360 not_likely:
9361 ctx->hflags |= MIPS_HFLAG_BC;
9362 break;
9363 default:
9364 MIPS_INVAL("cp1 cond branch");
9365 gen_reserved_instruction(ctx);
9366 goto out;
9368 ctx->btarget = btarget;
9369 ctx->hflags |= MIPS_HFLAG_BDS32;
9370 out:
9371 tcg_temp_free_i32(t0);
9374 /* R6 CP1 Branches */
9375 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9376 int32_t ft, int32_t offset,
9377 int delayslot_size)
9379 target_ulong btarget;
9380 TCGv_i64 t0 = tcg_temp_new_i64();
9382 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9383 #ifdef MIPS_DEBUG_DISAS
9384 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9385 "\n", ctx->base.pc_next);
9386 #endif
9387 gen_reserved_instruction(ctx);
9388 goto out;
9391 gen_load_fpr64(ctx, t0, ft);
9392 tcg_gen_andi_i64(t0, t0, 1);
9394 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9396 switch (op) {
9397 case OPC_BC1EQZ:
9398 tcg_gen_xori_i64(t0, t0, 1);
9399 ctx->hflags |= MIPS_HFLAG_BC;
9400 break;
9401 case OPC_BC1NEZ:
9402 /* t0 already set */
9403 ctx->hflags |= MIPS_HFLAG_BC;
9404 break;
9405 default:
9406 MIPS_INVAL("cp1 cond branch");
9407 gen_reserved_instruction(ctx);
9408 goto out;
9411 tcg_gen_trunc_i64_tl(bcond, t0);
9413 ctx->btarget = btarget;
9415 switch (delayslot_size) {
9416 case 2:
9417 ctx->hflags |= MIPS_HFLAG_BDS16;
9418 break;
9419 case 4:
9420 ctx->hflags |= MIPS_HFLAG_BDS32;
9421 break;
9424 out:
9425 tcg_temp_free_i64(t0);
9428 /* Coprocessor 1 (FPU) */
9430 #define FOP(func, fmt) (((fmt) << 21) | (func))
9432 enum fopcode {
9433 OPC_ADD_S = FOP(0, FMT_S),
9434 OPC_SUB_S = FOP(1, FMT_S),
9435 OPC_MUL_S = FOP(2, FMT_S),
9436 OPC_DIV_S = FOP(3, FMT_S),
9437 OPC_SQRT_S = FOP(4, FMT_S),
9438 OPC_ABS_S = FOP(5, FMT_S),
9439 OPC_MOV_S = FOP(6, FMT_S),
9440 OPC_NEG_S = FOP(7, FMT_S),
9441 OPC_ROUND_L_S = FOP(8, FMT_S),
9442 OPC_TRUNC_L_S = FOP(9, FMT_S),
9443 OPC_CEIL_L_S = FOP(10, FMT_S),
9444 OPC_FLOOR_L_S = FOP(11, FMT_S),
9445 OPC_ROUND_W_S = FOP(12, FMT_S),
9446 OPC_TRUNC_W_S = FOP(13, FMT_S),
9447 OPC_CEIL_W_S = FOP(14, FMT_S),
9448 OPC_FLOOR_W_S = FOP(15, FMT_S),
9449 OPC_SEL_S = FOP(16, FMT_S),
9450 OPC_MOVCF_S = FOP(17, FMT_S),
9451 OPC_MOVZ_S = FOP(18, FMT_S),
9452 OPC_MOVN_S = FOP(19, FMT_S),
9453 OPC_SELEQZ_S = FOP(20, FMT_S),
9454 OPC_RECIP_S = FOP(21, FMT_S),
9455 OPC_RSQRT_S = FOP(22, FMT_S),
9456 OPC_SELNEZ_S = FOP(23, FMT_S),
9457 OPC_MADDF_S = FOP(24, FMT_S),
9458 OPC_MSUBF_S = FOP(25, FMT_S),
9459 OPC_RINT_S = FOP(26, FMT_S),
9460 OPC_CLASS_S = FOP(27, FMT_S),
9461 OPC_MIN_S = FOP(28, FMT_S),
9462 OPC_RECIP2_S = FOP(28, FMT_S),
9463 OPC_MINA_S = FOP(29, FMT_S),
9464 OPC_RECIP1_S = FOP(29, FMT_S),
9465 OPC_MAX_S = FOP(30, FMT_S),
9466 OPC_RSQRT1_S = FOP(30, FMT_S),
9467 OPC_MAXA_S = FOP(31, FMT_S),
9468 OPC_RSQRT2_S = FOP(31, FMT_S),
9469 OPC_CVT_D_S = FOP(33, FMT_S),
9470 OPC_CVT_W_S = FOP(36, FMT_S),
9471 OPC_CVT_L_S = FOP(37, FMT_S),
9472 OPC_CVT_PS_S = FOP(38, FMT_S),
9473 OPC_CMP_F_S = FOP(48, FMT_S),
9474 OPC_CMP_UN_S = FOP(49, FMT_S),
9475 OPC_CMP_EQ_S = FOP(50, FMT_S),
9476 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9477 OPC_CMP_OLT_S = FOP(52, FMT_S),
9478 OPC_CMP_ULT_S = FOP(53, FMT_S),
9479 OPC_CMP_OLE_S = FOP(54, FMT_S),
9480 OPC_CMP_ULE_S = FOP(55, FMT_S),
9481 OPC_CMP_SF_S = FOP(56, FMT_S),
9482 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9483 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9484 OPC_CMP_NGL_S = FOP(59, FMT_S),
9485 OPC_CMP_LT_S = FOP(60, FMT_S),
9486 OPC_CMP_NGE_S = FOP(61, FMT_S),
9487 OPC_CMP_LE_S = FOP(62, FMT_S),
9488 OPC_CMP_NGT_S = FOP(63, FMT_S),
9490 OPC_ADD_D = FOP(0, FMT_D),
9491 OPC_SUB_D = FOP(1, FMT_D),
9492 OPC_MUL_D = FOP(2, FMT_D),
9493 OPC_DIV_D = FOP(3, FMT_D),
9494 OPC_SQRT_D = FOP(4, FMT_D),
9495 OPC_ABS_D = FOP(5, FMT_D),
9496 OPC_MOV_D = FOP(6, FMT_D),
9497 OPC_NEG_D = FOP(7, FMT_D),
9498 OPC_ROUND_L_D = FOP(8, FMT_D),
9499 OPC_TRUNC_L_D = FOP(9, FMT_D),
9500 OPC_CEIL_L_D = FOP(10, FMT_D),
9501 OPC_FLOOR_L_D = FOP(11, FMT_D),
9502 OPC_ROUND_W_D = FOP(12, FMT_D),
9503 OPC_TRUNC_W_D = FOP(13, FMT_D),
9504 OPC_CEIL_W_D = FOP(14, FMT_D),
9505 OPC_FLOOR_W_D = FOP(15, FMT_D),
9506 OPC_SEL_D = FOP(16, FMT_D),
9507 OPC_MOVCF_D = FOP(17, FMT_D),
9508 OPC_MOVZ_D = FOP(18, FMT_D),
9509 OPC_MOVN_D = FOP(19, FMT_D),
9510 OPC_SELEQZ_D = FOP(20, FMT_D),
9511 OPC_RECIP_D = FOP(21, FMT_D),
9512 OPC_RSQRT_D = FOP(22, FMT_D),
9513 OPC_SELNEZ_D = FOP(23, FMT_D),
9514 OPC_MADDF_D = FOP(24, FMT_D),
9515 OPC_MSUBF_D = FOP(25, FMT_D),
9516 OPC_RINT_D = FOP(26, FMT_D),
9517 OPC_CLASS_D = FOP(27, FMT_D),
9518 OPC_MIN_D = FOP(28, FMT_D),
9519 OPC_RECIP2_D = FOP(28, FMT_D),
9520 OPC_MINA_D = FOP(29, FMT_D),
9521 OPC_RECIP1_D = FOP(29, FMT_D),
9522 OPC_MAX_D = FOP(30, FMT_D),
9523 OPC_RSQRT1_D = FOP(30, FMT_D),
9524 OPC_MAXA_D = FOP(31, FMT_D),
9525 OPC_RSQRT2_D = FOP(31, FMT_D),
9526 OPC_CVT_S_D = FOP(32, FMT_D),
9527 OPC_CVT_W_D = FOP(36, FMT_D),
9528 OPC_CVT_L_D = FOP(37, FMT_D),
9529 OPC_CMP_F_D = FOP(48, FMT_D),
9530 OPC_CMP_UN_D = FOP(49, FMT_D),
9531 OPC_CMP_EQ_D = FOP(50, FMT_D),
9532 OPC_CMP_UEQ_D = FOP(51, FMT_D),
9533 OPC_CMP_OLT_D = FOP(52, FMT_D),
9534 OPC_CMP_ULT_D = FOP(53, FMT_D),
9535 OPC_CMP_OLE_D = FOP(54, FMT_D),
9536 OPC_CMP_ULE_D = FOP(55, FMT_D),
9537 OPC_CMP_SF_D = FOP(56, FMT_D),
9538 OPC_CMP_NGLE_D = FOP(57, FMT_D),
9539 OPC_CMP_SEQ_D = FOP(58, FMT_D),
9540 OPC_CMP_NGL_D = FOP(59, FMT_D),
9541 OPC_CMP_LT_D = FOP(60, FMT_D),
9542 OPC_CMP_NGE_D = FOP(61, FMT_D),
9543 OPC_CMP_LE_D = FOP(62, FMT_D),
9544 OPC_CMP_NGT_D = FOP(63, FMT_D),
9546 OPC_CVT_S_W = FOP(32, FMT_W),
9547 OPC_CVT_D_W = FOP(33, FMT_W),
9548 OPC_CVT_S_L = FOP(32, FMT_L),
9549 OPC_CVT_D_L = FOP(33, FMT_L),
9550 OPC_CVT_PS_PW = FOP(38, FMT_W),
9552 OPC_ADD_PS = FOP(0, FMT_PS),
9553 OPC_SUB_PS = FOP(1, FMT_PS),
9554 OPC_MUL_PS = FOP(2, FMT_PS),
9555 OPC_DIV_PS = FOP(3, FMT_PS),
9556 OPC_ABS_PS = FOP(5, FMT_PS),
9557 OPC_MOV_PS = FOP(6, FMT_PS),
9558 OPC_NEG_PS = FOP(7, FMT_PS),
9559 OPC_MOVCF_PS = FOP(17, FMT_PS),
9560 OPC_MOVZ_PS = FOP(18, FMT_PS),
9561 OPC_MOVN_PS = FOP(19, FMT_PS),
9562 OPC_ADDR_PS = FOP(24, FMT_PS),
9563 OPC_MULR_PS = FOP(26, FMT_PS),
9564 OPC_RECIP2_PS = FOP(28, FMT_PS),
9565 OPC_RECIP1_PS = FOP(29, FMT_PS),
9566 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9567 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9569 OPC_CVT_S_PU = FOP(32, FMT_PS),
9570 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9571 OPC_CVT_S_PL = FOP(40, FMT_PS),
9572 OPC_PLL_PS = FOP(44, FMT_PS),
9573 OPC_PLU_PS = FOP(45, FMT_PS),
9574 OPC_PUL_PS = FOP(46, FMT_PS),
9575 OPC_PUU_PS = FOP(47, FMT_PS),
9576 OPC_CMP_F_PS = FOP(48, FMT_PS),
9577 OPC_CMP_UN_PS = FOP(49, FMT_PS),
9578 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
9579 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
9580 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
9581 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
9582 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
9583 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
9584 OPC_CMP_SF_PS = FOP(56, FMT_PS),
9585 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
9586 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
9587 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
9588 OPC_CMP_LT_PS = FOP(60, FMT_PS),
9589 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
9590 OPC_CMP_LE_PS = FOP(62, FMT_PS),
9591 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
9594 enum r6_f_cmp_op {
9595 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9596 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9597 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9598 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9599 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9600 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9601 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9602 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9603 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9604 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9605 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9606 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9607 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9608 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9609 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9610 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9611 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9612 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9613 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9614 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9615 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9616 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9618 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9619 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9620 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9621 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9622 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9623 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9624 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9625 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9626 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9627 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9628 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9629 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9630 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9631 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9632 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9633 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9634 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9635 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9636 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9637 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9638 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9639 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9642 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
9644 TCGv t0 = tcg_temp_new();
9646 switch (opc) {
9647 case OPC_MFC1:
9649 TCGv_i32 fp0 = tcg_temp_new_i32();
9651 gen_load_fpr32(ctx, fp0, fs);
9652 tcg_gen_ext_i32_tl(t0, fp0);
9653 tcg_temp_free_i32(fp0);
9655 gen_store_gpr(t0, rt);
9656 break;
9657 case OPC_MTC1:
9658 gen_load_gpr(t0, rt);
9660 TCGv_i32 fp0 = tcg_temp_new_i32();
9662 tcg_gen_trunc_tl_i32(fp0, t0);
9663 gen_store_fpr32(ctx, fp0, fs);
9664 tcg_temp_free_i32(fp0);
9666 break;
9667 case OPC_CFC1:
9668 gen_helper_1e0i(cfc1, t0, fs);
9669 gen_store_gpr(t0, rt);
9670 break;
9671 case OPC_CTC1:
9672 gen_load_gpr(t0, rt);
9673 save_cpu_state(ctx, 0);
9674 gen_helper_0e2i(ctc1, t0, tcg_constant_i32(fs), rt);
9675 /* Stop translation as we may have changed hflags */
9676 ctx->base.is_jmp = DISAS_STOP;
9677 break;
9678 #if defined(TARGET_MIPS64)
9679 case OPC_DMFC1:
9680 gen_load_fpr64(ctx, t0, fs);
9681 gen_store_gpr(t0, rt);
9682 break;
9683 case OPC_DMTC1:
9684 gen_load_gpr(t0, rt);
9685 gen_store_fpr64(ctx, t0, fs);
9686 break;
9687 #endif
9688 case OPC_MFHC1:
9690 TCGv_i32 fp0 = tcg_temp_new_i32();
9692 gen_load_fpr32h(ctx, fp0, fs);
9693 tcg_gen_ext_i32_tl(t0, fp0);
9694 tcg_temp_free_i32(fp0);
9696 gen_store_gpr(t0, rt);
9697 break;
9698 case OPC_MTHC1:
9699 gen_load_gpr(t0, rt);
9701 TCGv_i32 fp0 = tcg_temp_new_i32();
9703 tcg_gen_trunc_tl_i32(fp0, t0);
9704 gen_store_fpr32h(ctx, fp0, fs);
9705 tcg_temp_free_i32(fp0);
9707 break;
9708 default:
9709 MIPS_INVAL("cp1 move");
9710 gen_reserved_instruction(ctx);
9711 goto out;
9714 out:
9715 tcg_temp_free(t0);
9718 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
9720 TCGLabel *l1;
9721 TCGCond cond;
9722 TCGv_i32 t0;
9724 if (rd == 0) {
9725 /* Treat as NOP. */
9726 return;
9729 if (tf) {
9730 cond = TCG_COND_EQ;
9731 } else {
9732 cond = TCG_COND_NE;
9735 l1 = gen_new_label();
9736 t0 = tcg_temp_new_i32();
9737 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9738 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9739 tcg_temp_free_i32(t0);
9740 gen_load_gpr(cpu_gpr[rd], rs);
9741 gen_set_label(l1);
9744 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9745 int tf)
9747 int cond;
9748 TCGv_i32 t0 = tcg_temp_new_i32();
9749 TCGLabel *l1 = gen_new_label();
9751 if (tf) {
9752 cond = TCG_COND_EQ;
9753 } else {
9754 cond = TCG_COND_NE;
9757 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9758 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9759 gen_load_fpr32(ctx, t0, fs);
9760 gen_store_fpr32(ctx, t0, fd);
9761 gen_set_label(l1);
9762 tcg_temp_free_i32(t0);
9765 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
9766 int tf)
9768 int cond;
9769 TCGv_i32 t0 = tcg_temp_new_i32();
9770 TCGv_i64 fp0;
9771 TCGLabel *l1 = gen_new_label();
9773 if (tf) {
9774 cond = TCG_COND_EQ;
9775 } else {
9776 cond = TCG_COND_NE;
9779 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9780 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9781 tcg_temp_free_i32(t0);
9782 fp0 = tcg_temp_new_i64();
9783 gen_load_fpr64(ctx, fp0, fs);
9784 gen_store_fpr64(ctx, fp0, fd);
9785 tcg_temp_free_i64(fp0);
9786 gen_set_label(l1);
9789 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9790 int cc, int tf)
9792 int cond;
9793 TCGv_i32 t0 = tcg_temp_new_i32();
9794 TCGLabel *l1 = gen_new_label();
9795 TCGLabel *l2 = gen_new_label();
9797 if (tf) {
9798 cond = TCG_COND_EQ;
9799 } else {
9800 cond = TCG_COND_NE;
9803 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9804 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9805 gen_load_fpr32(ctx, t0, fs);
9806 gen_store_fpr32(ctx, t0, fd);
9807 gen_set_label(l1);
9809 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
9810 tcg_gen_brcondi_i32(cond, t0, 0, l2);
9811 gen_load_fpr32h(ctx, t0, fs);
9812 gen_store_fpr32h(ctx, t0, fd);
9813 tcg_temp_free_i32(t0);
9814 gen_set_label(l2);
9817 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9818 int fs)
9820 TCGv_i32 t1 = tcg_const_i32(0);
9821 TCGv_i32 fp0 = tcg_temp_new_i32();
9822 TCGv_i32 fp1 = tcg_temp_new_i32();
9823 TCGv_i32 fp2 = tcg_temp_new_i32();
9824 gen_load_fpr32(ctx, fp0, fd);
9825 gen_load_fpr32(ctx, fp1, ft);
9826 gen_load_fpr32(ctx, fp2, fs);
9828 switch (op1) {
9829 case OPC_SEL_S:
9830 tcg_gen_andi_i32(fp0, fp0, 1);
9831 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9832 break;
9833 case OPC_SELEQZ_S:
9834 tcg_gen_andi_i32(fp1, fp1, 1);
9835 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9836 break;
9837 case OPC_SELNEZ_S:
9838 tcg_gen_andi_i32(fp1, fp1, 1);
9839 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9840 break;
9841 default:
9842 MIPS_INVAL("gen_sel_s");
9843 gen_reserved_instruction(ctx);
9844 break;
9847 gen_store_fpr32(ctx, fp0, fd);
9848 tcg_temp_free_i32(fp2);
9849 tcg_temp_free_i32(fp1);
9850 tcg_temp_free_i32(fp0);
9851 tcg_temp_free_i32(t1);
9854 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9855 int fs)
9857 TCGv_i64 t1 = tcg_const_i64(0);
9858 TCGv_i64 fp0 = tcg_temp_new_i64();
9859 TCGv_i64 fp1 = tcg_temp_new_i64();
9860 TCGv_i64 fp2 = tcg_temp_new_i64();
9861 gen_load_fpr64(ctx, fp0, fd);
9862 gen_load_fpr64(ctx, fp1, ft);
9863 gen_load_fpr64(ctx, fp2, fs);
9865 switch (op1) {
9866 case OPC_SEL_D:
9867 tcg_gen_andi_i64(fp0, fp0, 1);
9868 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9869 break;
9870 case OPC_SELEQZ_D:
9871 tcg_gen_andi_i64(fp1, fp1, 1);
9872 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9873 break;
9874 case OPC_SELNEZ_D:
9875 tcg_gen_andi_i64(fp1, fp1, 1);
9876 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9877 break;
9878 default:
9879 MIPS_INVAL("gen_sel_d");
9880 gen_reserved_instruction(ctx);
9881 break;
9884 gen_store_fpr64(ctx, fp0, fd);
9885 tcg_temp_free_i64(fp2);
9886 tcg_temp_free_i64(fp1);
9887 tcg_temp_free_i64(fp0);
9888 tcg_temp_free_i64(t1);
9891 static void gen_farith(DisasContext *ctx, enum fopcode op1,
9892 int ft, int fs, int fd, int cc)
9894 uint32_t func = ctx->opcode & 0x3f;
9895 switch (op1) {
9896 case OPC_ADD_S:
9898 TCGv_i32 fp0 = tcg_temp_new_i32();
9899 TCGv_i32 fp1 = tcg_temp_new_i32();
9901 gen_load_fpr32(ctx, fp0, fs);
9902 gen_load_fpr32(ctx, fp1, ft);
9903 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
9904 tcg_temp_free_i32(fp1);
9905 gen_store_fpr32(ctx, fp0, fd);
9906 tcg_temp_free_i32(fp0);
9908 break;
9909 case OPC_SUB_S:
9911 TCGv_i32 fp0 = tcg_temp_new_i32();
9912 TCGv_i32 fp1 = tcg_temp_new_i32();
9914 gen_load_fpr32(ctx, fp0, fs);
9915 gen_load_fpr32(ctx, fp1, ft);
9916 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
9917 tcg_temp_free_i32(fp1);
9918 gen_store_fpr32(ctx, fp0, fd);
9919 tcg_temp_free_i32(fp0);
9921 break;
9922 case OPC_MUL_S:
9924 TCGv_i32 fp0 = tcg_temp_new_i32();
9925 TCGv_i32 fp1 = tcg_temp_new_i32();
9927 gen_load_fpr32(ctx, fp0, fs);
9928 gen_load_fpr32(ctx, fp1, ft);
9929 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
9930 tcg_temp_free_i32(fp1);
9931 gen_store_fpr32(ctx, fp0, fd);
9932 tcg_temp_free_i32(fp0);
9934 break;
9935 case OPC_DIV_S:
9937 TCGv_i32 fp0 = tcg_temp_new_i32();
9938 TCGv_i32 fp1 = tcg_temp_new_i32();
9940 gen_load_fpr32(ctx, fp0, fs);
9941 gen_load_fpr32(ctx, fp1, ft);
9942 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
9943 tcg_temp_free_i32(fp1);
9944 gen_store_fpr32(ctx, fp0, fd);
9945 tcg_temp_free_i32(fp0);
9947 break;
9948 case OPC_SQRT_S:
9950 TCGv_i32 fp0 = tcg_temp_new_i32();
9952 gen_load_fpr32(ctx, fp0, fs);
9953 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
9954 gen_store_fpr32(ctx, fp0, fd);
9955 tcg_temp_free_i32(fp0);
9957 break;
9958 case OPC_ABS_S:
9960 TCGv_i32 fp0 = tcg_temp_new_i32();
9962 gen_load_fpr32(ctx, fp0, fs);
9963 if (ctx->abs2008) {
9964 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9965 } else {
9966 gen_helper_float_abs_s(fp0, fp0);
9968 gen_store_fpr32(ctx, fp0, fd);
9969 tcg_temp_free_i32(fp0);
9971 break;
9972 case OPC_MOV_S:
9974 TCGv_i32 fp0 = tcg_temp_new_i32();
9976 gen_load_fpr32(ctx, fp0, fs);
9977 gen_store_fpr32(ctx, fp0, fd);
9978 tcg_temp_free_i32(fp0);
9980 break;
9981 case OPC_NEG_S:
9983 TCGv_i32 fp0 = tcg_temp_new_i32();
9985 gen_load_fpr32(ctx, fp0, fs);
9986 if (ctx->abs2008) {
9987 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9988 } else {
9989 gen_helper_float_chs_s(fp0, fp0);
9991 gen_store_fpr32(ctx, fp0, fd);
9992 tcg_temp_free_i32(fp0);
9994 break;
9995 case OPC_ROUND_L_S:
9996 check_cp1_64bitmode(ctx);
9998 TCGv_i32 fp32 = tcg_temp_new_i32();
9999 TCGv_i64 fp64 = tcg_temp_new_i64();
10001 gen_load_fpr32(ctx, fp32, fs);
10002 if (ctx->nan2008) {
10003 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10004 } else {
10005 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10007 tcg_temp_free_i32(fp32);
10008 gen_store_fpr64(ctx, fp64, fd);
10009 tcg_temp_free_i64(fp64);
10011 break;
10012 case OPC_TRUNC_L_S:
10013 check_cp1_64bitmode(ctx);
10015 TCGv_i32 fp32 = tcg_temp_new_i32();
10016 TCGv_i64 fp64 = tcg_temp_new_i64();
10018 gen_load_fpr32(ctx, fp32, fs);
10019 if (ctx->nan2008) {
10020 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10021 } else {
10022 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10024 tcg_temp_free_i32(fp32);
10025 gen_store_fpr64(ctx, fp64, fd);
10026 tcg_temp_free_i64(fp64);
10028 break;
10029 case OPC_CEIL_L_S:
10030 check_cp1_64bitmode(ctx);
10032 TCGv_i32 fp32 = tcg_temp_new_i32();
10033 TCGv_i64 fp64 = tcg_temp_new_i64();
10035 gen_load_fpr32(ctx, fp32, fs);
10036 if (ctx->nan2008) {
10037 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10038 } else {
10039 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10041 tcg_temp_free_i32(fp32);
10042 gen_store_fpr64(ctx, fp64, fd);
10043 tcg_temp_free_i64(fp64);
10045 break;
10046 case OPC_FLOOR_L_S:
10047 check_cp1_64bitmode(ctx);
10049 TCGv_i32 fp32 = tcg_temp_new_i32();
10050 TCGv_i64 fp64 = tcg_temp_new_i64();
10052 gen_load_fpr32(ctx, fp32, fs);
10053 if (ctx->nan2008) {
10054 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10055 } else {
10056 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10058 tcg_temp_free_i32(fp32);
10059 gen_store_fpr64(ctx, fp64, fd);
10060 tcg_temp_free_i64(fp64);
10062 break;
10063 case OPC_ROUND_W_S:
10065 TCGv_i32 fp0 = tcg_temp_new_i32();
10067 gen_load_fpr32(ctx, fp0, fs);
10068 if (ctx->nan2008) {
10069 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10070 } else {
10071 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10073 gen_store_fpr32(ctx, fp0, fd);
10074 tcg_temp_free_i32(fp0);
10076 break;
10077 case OPC_TRUNC_W_S:
10079 TCGv_i32 fp0 = tcg_temp_new_i32();
10081 gen_load_fpr32(ctx, fp0, fs);
10082 if (ctx->nan2008) {
10083 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10084 } else {
10085 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10087 gen_store_fpr32(ctx, fp0, fd);
10088 tcg_temp_free_i32(fp0);
10090 break;
10091 case OPC_CEIL_W_S:
10093 TCGv_i32 fp0 = tcg_temp_new_i32();
10095 gen_load_fpr32(ctx, fp0, fs);
10096 if (ctx->nan2008) {
10097 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10098 } else {
10099 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10101 gen_store_fpr32(ctx, fp0, fd);
10102 tcg_temp_free_i32(fp0);
10104 break;
10105 case OPC_FLOOR_W_S:
10107 TCGv_i32 fp0 = tcg_temp_new_i32();
10109 gen_load_fpr32(ctx, fp0, fs);
10110 if (ctx->nan2008) {
10111 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10112 } else {
10113 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10115 gen_store_fpr32(ctx, fp0, fd);
10116 tcg_temp_free_i32(fp0);
10118 break;
10119 case OPC_SEL_S:
10120 check_insn(ctx, ISA_MIPS_R6);
10121 gen_sel_s(ctx, op1, fd, ft, fs);
10122 break;
10123 case OPC_SELEQZ_S:
10124 check_insn(ctx, ISA_MIPS_R6);
10125 gen_sel_s(ctx, op1, fd, ft, fs);
10126 break;
10127 case OPC_SELNEZ_S:
10128 check_insn(ctx, ISA_MIPS_R6);
10129 gen_sel_s(ctx, op1, fd, ft, fs);
10130 break;
10131 case OPC_MOVCF_S:
10132 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10133 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10134 break;
10135 case OPC_MOVZ_S:
10136 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10138 TCGLabel *l1 = gen_new_label();
10139 TCGv_i32 fp0;
10141 if (ft != 0) {
10142 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10144 fp0 = tcg_temp_new_i32();
10145 gen_load_fpr32(ctx, fp0, fs);
10146 gen_store_fpr32(ctx, fp0, fd);
10147 tcg_temp_free_i32(fp0);
10148 gen_set_label(l1);
10150 break;
10151 case OPC_MOVN_S:
10152 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10154 TCGLabel *l1 = gen_new_label();
10155 TCGv_i32 fp0;
10157 if (ft != 0) {
10158 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10159 fp0 = tcg_temp_new_i32();
10160 gen_load_fpr32(ctx, fp0, fs);
10161 gen_store_fpr32(ctx, fp0, fd);
10162 tcg_temp_free_i32(fp0);
10163 gen_set_label(l1);
10166 break;
10167 case OPC_RECIP_S:
10169 TCGv_i32 fp0 = tcg_temp_new_i32();
10171 gen_load_fpr32(ctx, fp0, fs);
10172 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10173 gen_store_fpr32(ctx, fp0, fd);
10174 tcg_temp_free_i32(fp0);
10176 break;
10177 case OPC_RSQRT_S:
10179 TCGv_i32 fp0 = tcg_temp_new_i32();
10181 gen_load_fpr32(ctx, fp0, fs);
10182 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10183 gen_store_fpr32(ctx, fp0, fd);
10184 tcg_temp_free_i32(fp0);
10186 break;
10187 case OPC_MADDF_S:
10188 check_insn(ctx, ISA_MIPS_R6);
10190 TCGv_i32 fp0 = tcg_temp_new_i32();
10191 TCGv_i32 fp1 = tcg_temp_new_i32();
10192 TCGv_i32 fp2 = tcg_temp_new_i32();
10193 gen_load_fpr32(ctx, fp0, fs);
10194 gen_load_fpr32(ctx, fp1, ft);
10195 gen_load_fpr32(ctx, fp2, fd);
10196 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10197 gen_store_fpr32(ctx, fp2, fd);
10198 tcg_temp_free_i32(fp2);
10199 tcg_temp_free_i32(fp1);
10200 tcg_temp_free_i32(fp0);
10202 break;
10203 case OPC_MSUBF_S:
10204 check_insn(ctx, ISA_MIPS_R6);
10206 TCGv_i32 fp0 = tcg_temp_new_i32();
10207 TCGv_i32 fp1 = tcg_temp_new_i32();
10208 TCGv_i32 fp2 = tcg_temp_new_i32();
10209 gen_load_fpr32(ctx, fp0, fs);
10210 gen_load_fpr32(ctx, fp1, ft);
10211 gen_load_fpr32(ctx, fp2, fd);
10212 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10213 gen_store_fpr32(ctx, fp2, fd);
10214 tcg_temp_free_i32(fp2);
10215 tcg_temp_free_i32(fp1);
10216 tcg_temp_free_i32(fp0);
10218 break;
10219 case OPC_RINT_S:
10220 check_insn(ctx, ISA_MIPS_R6);
10222 TCGv_i32 fp0 = tcg_temp_new_i32();
10223 gen_load_fpr32(ctx, fp0, fs);
10224 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10225 gen_store_fpr32(ctx, fp0, fd);
10226 tcg_temp_free_i32(fp0);
10228 break;
10229 case OPC_CLASS_S:
10230 check_insn(ctx, ISA_MIPS_R6);
10232 TCGv_i32 fp0 = tcg_temp_new_i32();
10233 gen_load_fpr32(ctx, fp0, fs);
10234 gen_helper_float_class_s(fp0, cpu_env, fp0);
10235 gen_store_fpr32(ctx, fp0, fd);
10236 tcg_temp_free_i32(fp0);
10238 break;
10239 case OPC_MIN_S: /* OPC_RECIP2_S */
10240 if (ctx->insn_flags & ISA_MIPS_R6) {
10241 /* OPC_MIN_S */
10242 TCGv_i32 fp0 = tcg_temp_new_i32();
10243 TCGv_i32 fp1 = tcg_temp_new_i32();
10244 TCGv_i32 fp2 = tcg_temp_new_i32();
10245 gen_load_fpr32(ctx, fp0, fs);
10246 gen_load_fpr32(ctx, fp1, ft);
10247 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10248 gen_store_fpr32(ctx, fp2, fd);
10249 tcg_temp_free_i32(fp2);
10250 tcg_temp_free_i32(fp1);
10251 tcg_temp_free_i32(fp0);
10252 } else {
10253 /* OPC_RECIP2_S */
10254 check_cp1_64bitmode(ctx);
10256 TCGv_i32 fp0 = tcg_temp_new_i32();
10257 TCGv_i32 fp1 = tcg_temp_new_i32();
10259 gen_load_fpr32(ctx, fp0, fs);
10260 gen_load_fpr32(ctx, fp1, ft);
10261 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10262 tcg_temp_free_i32(fp1);
10263 gen_store_fpr32(ctx, fp0, fd);
10264 tcg_temp_free_i32(fp0);
10267 break;
10268 case OPC_MINA_S: /* OPC_RECIP1_S */
10269 if (ctx->insn_flags & ISA_MIPS_R6) {
10270 /* OPC_MINA_S */
10271 TCGv_i32 fp0 = tcg_temp_new_i32();
10272 TCGv_i32 fp1 = tcg_temp_new_i32();
10273 TCGv_i32 fp2 = tcg_temp_new_i32();
10274 gen_load_fpr32(ctx, fp0, fs);
10275 gen_load_fpr32(ctx, fp1, ft);
10276 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10277 gen_store_fpr32(ctx, fp2, fd);
10278 tcg_temp_free_i32(fp2);
10279 tcg_temp_free_i32(fp1);
10280 tcg_temp_free_i32(fp0);
10281 } else {
10282 /* OPC_RECIP1_S */
10283 check_cp1_64bitmode(ctx);
10285 TCGv_i32 fp0 = tcg_temp_new_i32();
10287 gen_load_fpr32(ctx, fp0, fs);
10288 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10289 gen_store_fpr32(ctx, fp0, fd);
10290 tcg_temp_free_i32(fp0);
10293 break;
10294 case OPC_MAX_S: /* OPC_RSQRT1_S */
10295 if (ctx->insn_flags & ISA_MIPS_R6) {
10296 /* OPC_MAX_S */
10297 TCGv_i32 fp0 = tcg_temp_new_i32();
10298 TCGv_i32 fp1 = tcg_temp_new_i32();
10299 gen_load_fpr32(ctx, fp0, fs);
10300 gen_load_fpr32(ctx, fp1, ft);
10301 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10302 gen_store_fpr32(ctx, fp1, fd);
10303 tcg_temp_free_i32(fp1);
10304 tcg_temp_free_i32(fp0);
10305 } else {
10306 /* OPC_RSQRT1_S */
10307 check_cp1_64bitmode(ctx);
10309 TCGv_i32 fp0 = tcg_temp_new_i32();
10311 gen_load_fpr32(ctx, fp0, fs);
10312 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10313 gen_store_fpr32(ctx, fp0, fd);
10314 tcg_temp_free_i32(fp0);
10317 break;
10318 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10319 if (ctx->insn_flags & ISA_MIPS_R6) {
10320 /* OPC_MAXA_S */
10321 TCGv_i32 fp0 = tcg_temp_new_i32();
10322 TCGv_i32 fp1 = tcg_temp_new_i32();
10323 gen_load_fpr32(ctx, fp0, fs);
10324 gen_load_fpr32(ctx, fp1, ft);
10325 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10326 gen_store_fpr32(ctx, fp1, fd);
10327 tcg_temp_free_i32(fp1);
10328 tcg_temp_free_i32(fp0);
10329 } else {
10330 /* OPC_RSQRT2_S */
10331 check_cp1_64bitmode(ctx);
10333 TCGv_i32 fp0 = tcg_temp_new_i32();
10334 TCGv_i32 fp1 = tcg_temp_new_i32();
10336 gen_load_fpr32(ctx, fp0, fs);
10337 gen_load_fpr32(ctx, fp1, ft);
10338 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10339 tcg_temp_free_i32(fp1);
10340 gen_store_fpr32(ctx, fp0, fd);
10341 tcg_temp_free_i32(fp0);
10344 break;
10345 case OPC_CVT_D_S:
10346 check_cp1_registers(ctx, fd);
10348 TCGv_i32 fp32 = tcg_temp_new_i32();
10349 TCGv_i64 fp64 = tcg_temp_new_i64();
10351 gen_load_fpr32(ctx, fp32, fs);
10352 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10353 tcg_temp_free_i32(fp32);
10354 gen_store_fpr64(ctx, fp64, fd);
10355 tcg_temp_free_i64(fp64);
10357 break;
10358 case OPC_CVT_W_S:
10360 TCGv_i32 fp0 = tcg_temp_new_i32();
10362 gen_load_fpr32(ctx, fp0, fs);
10363 if (ctx->nan2008) {
10364 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10365 } else {
10366 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10368 gen_store_fpr32(ctx, fp0, fd);
10369 tcg_temp_free_i32(fp0);
10371 break;
10372 case OPC_CVT_L_S:
10373 check_cp1_64bitmode(ctx);
10375 TCGv_i32 fp32 = tcg_temp_new_i32();
10376 TCGv_i64 fp64 = tcg_temp_new_i64();
10378 gen_load_fpr32(ctx, fp32, fs);
10379 if (ctx->nan2008) {
10380 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10381 } else {
10382 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10384 tcg_temp_free_i32(fp32);
10385 gen_store_fpr64(ctx, fp64, fd);
10386 tcg_temp_free_i64(fp64);
10388 break;
10389 case OPC_CVT_PS_S:
10390 check_ps(ctx);
10392 TCGv_i64 fp64 = tcg_temp_new_i64();
10393 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10394 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10396 gen_load_fpr32(ctx, fp32_0, fs);
10397 gen_load_fpr32(ctx, fp32_1, ft);
10398 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10399 tcg_temp_free_i32(fp32_1);
10400 tcg_temp_free_i32(fp32_0);
10401 gen_store_fpr64(ctx, fp64, fd);
10402 tcg_temp_free_i64(fp64);
10404 break;
10405 case OPC_CMP_F_S:
10406 case OPC_CMP_UN_S:
10407 case OPC_CMP_EQ_S:
10408 case OPC_CMP_UEQ_S:
10409 case OPC_CMP_OLT_S:
10410 case OPC_CMP_ULT_S:
10411 case OPC_CMP_OLE_S:
10412 case OPC_CMP_ULE_S:
10413 case OPC_CMP_SF_S:
10414 case OPC_CMP_NGLE_S:
10415 case OPC_CMP_SEQ_S:
10416 case OPC_CMP_NGL_S:
10417 case OPC_CMP_LT_S:
10418 case OPC_CMP_NGE_S:
10419 case OPC_CMP_LE_S:
10420 case OPC_CMP_NGT_S:
10421 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10422 if (ctx->opcode & (1 << 6)) {
10423 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
10424 } else {
10425 gen_cmp_s(ctx, func - 48, ft, fs, cc);
10427 break;
10428 case OPC_ADD_D:
10429 check_cp1_registers(ctx, fs | ft | fd);
10431 TCGv_i64 fp0 = tcg_temp_new_i64();
10432 TCGv_i64 fp1 = tcg_temp_new_i64();
10434 gen_load_fpr64(ctx, fp0, fs);
10435 gen_load_fpr64(ctx, fp1, ft);
10436 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10437 tcg_temp_free_i64(fp1);
10438 gen_store_fpr64(ctx, fp0, fd);
10439 tcg_temp_free_i64(fp0);
10441 break;
10442 case OPC_SUB_D:
10443 check_cp1_registers(ctx, fs | ft | fd);
10445 TCGv_i64 fp0 = tcg_temp_new_i64();
10446 TCGv_i64 fp1 = tcg_temp_new_i64();
10448 gen_load_fpr64(ctx, fp0, fs);
10449 gen_load_fpr64(ctx, fp1, ft);
10450 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10451 tcg_temp_free_i64(fp1);
10452 gen_store_fpr64(ctx, fp0, fd);
10453 tcg_temp_free_i64(fp0);
10455 break;
10456 case OPC_MUL_D:
10457 check_cp1_registers(ctx, fs | ft | fd);
10459 TCGv_i64 fp0 = tcg_temp_new_i64();
10460 TCGv_i64 fp1 = tcg_temp_new_i64();
10462 gen_load_fpr64(ctx, fp0, fs);
10463 gen_load_fpr64(ctx, fp1, ft);
10464 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10465 tcg_temp_free_i64(fp1);
10466 gen_store_fpr64(ctx, fp0, fd);
10467 tcg_temp_free_i64(fp0);
10469 break;
10470 case OPC_DIV_D:
10471 check_cp1_registers(ctx, fs | ft | fd);
10473 TCGv_i64 fp0 = tcg_temp_new_i64();
10474 TCGv_i64 fp1 = tcg_temp_new_i64();
10476 gen_load_fpr64(ctx, fp0, fs);
10477 gen_load_fpr64(ctx, fp1, ft);
10478 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10479 tcg_temp_free_i64(fp1);
10480 gen_store_fpr64(ctx, fp0, fd);
10481 tcg_temp_free_i64(fp0);
10483 break;
10484 case OPC_SQRT_D:
10485 check_cp1_registers(ctx, fs | fd);
10487 TCGv_i64 fp0 = tcg_temp_new_i64();
10489 gen_load_fpr64(ctx, fp0, fs);
10490 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10491 gen_store_fpr64(ctx, fp0, fd);
10492 tcg_temp_free_i64(fp0);
10494 break;
10495 case OPC_ABS_D:
10496 check_cp1_registers(ctx, fs | fd);
10498 TCGv_i64 fp0 = tcg_temp_new_i64();
10500 gen_load_fpr64(ctx, fp0, fs);
10501 if (ctx->abs2008) {
10502 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10503 } else {
10504 gen_helper_float_abs_d(fp0, fp0);
10506 gen_store_fpr64(ctx, fp0, fd);
10507 tcg_temp_free_i64(fp0);
10509 break;
10510 case OPC_MOV_D:
10511 check_cp1_registers(ctx, fs | fd);
10513 TCGv_i64 fp0 = tcg_temp_new_i64();
10515 gen_load_fpr64(ctx, fp0, fs);
10516 gen_store_fpr64(ctx, fp0, fd);
10517 tcg_temp_free_i64(fp0);
10519 break;
10520 case OPC_NEG_D:
10521 check_cp1_registers(ctx, fs | fd);
10523 TCGv_i64 fp0 = tcg_temp_new_i64();
10525 gen_load_fpr64(ctx, fp0, fs);
10526 if (ctx->abs2008) {
10527 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10528 } else {
10529 gen_helper_float_chs_d(fp0, fp0);
10531 gen_store_fpr64(ctx, fp0, fd);
10532 tcg_temp_free_i64(fp0);
10534 break;
10535 case OPC_ROUND_L_D:
10536 check_cp1_64bitmode(ctx);
10538 TCGv_i64 fp0 = tcg_temp_new_i64();
10540 gen_load_fpr64(ctx, fp0, fs);
10541 if (ctx->nan2008) {
10542 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10543 } else {
10544 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10546 gen_store_fpr64(ctx, fp0, fd);
10547 tcg_temp_free_i64(fp0);
10549 break;
10550 case OPC_TRUNC_L_D:
10551 check_cp1_64bitmode(ctx);
10553 TCGv_i64 fp0 = tcg_temp_new_i64();
10555 gen_load_fpr64(ctx, fp0, fs);
10556 if (ctx->nan2008) {
10557 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10558 } else {
10559 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10561 gen_store_fpr64(ctx, fp0, fd);
10562 tcg_temp_free_i64(fp0);
10564 break;
10565 case OPC_CEIL_L_D:
10566 check_cp1_64bitmode(ctx);
10568 TCGv_i64 fp0 = tcg_temp_new_i64();
10570 gen_load_fpr64(ctx, fp0, fs);
10571 if (ctx->nan2008) {
10572 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10573 } else {
10574 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10576 gen_store_fpr64(ctx, fp0, fd);
10577 tcg_temp_free_i64(fp0);
10579 break;
10580 case OPC_FLOOR_L_D:
10581 check_cp1_64bitmode(ctx);
10583 TCGv_i64 fp0 = tcg_temp_new_i64();
10585 gen_load_fpr64(ctx, fp0, fs);
10586 if (ctx->nan2008) {
10587 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10588 } else {
10589 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10591 gen_store_fpr64(ctx, fp0, fd);
10592 tcg_temp_free_i64(fp0);
10594 break;
10595 case OPC_ROUND_W_D:
10596 check_cp1_registers(ctx, fs);
10598 TCGv_i32 fp32 = tcg_temp_new_i32();
10599 TCGv_i64 fp64 = tcg_temp_new_i64();
10601 gen_load_fpr64(ctx, fp64, fs);
10602 if (ctx->nan2008) {
10603 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10604 } else {
10605 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10607 tcg_temp_free_i64(fp64);
10608 gen_store_fpr32(ctx, fp32, fd);
10609 tcg_temp_free_i32(fp32);
10611 break;
10612 case OPC_TRUNC_W_D:
10613 check_cp1_registers(ctx, fs);
10615 TCGv_i32 fp32 = tcg_temp_new_i32();
10616 TCGv_i64 fp64 = tcg_temp_new_i64();
10618 gen_load_fpr64(ctx, fp64, fs);
10619 if (ctx->nan2008) {
10620 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10621 } else {
10622 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10624 tcg_temp_free_i64(fp64);
10625 gen_store_fpr32(ctx, fp32, fd);
10626 tcg_temp_free_i32(fp32);
10628 break;
10629 case OPC_CEIL_W_D:
10630 check_cp1_registers(ctx, fs);
10632 TCGv_i32 fp32 = tcg_temp_new_i32();
10633 TCGv_i64 fp64 = tcg_temp_new_i64();
10635 gen_load_fpr64(ctx, fp64, fs);
10636 if (ctx->nan2008) {
10637 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10638 } else {
10639 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10641 tcg_temp_free_i64(fp64);
10642 gen_store_fpr32(ctx, fp32, fd);
10643 tcg_temp_free_i32(fp32);
10645 break;
10646 case OPC_FLOOR_W_D:
10647 check_cp1_registers(ctx, fs);
10649 TCGv_i32 fp32 = tcg_temp_new_i32();
10650 TCGv_i64 fp64 = tcg_temp_new_i64();
10652 gen_load_fpr64(ctx, fp64, fs);
10653 if (ctx->nan2008) {
10654 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10655 } else {
10656 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10658 tcg_temp_free_i64(fp64);
10659 gen_store_fpr32(ctx, fp32, fd);
10660 tcg_temp_free_i32(fp32);
10662 break;
10663 case OPC_SEL_D:
10664 check_insn(ctx, ISA_MIPS_R6);
10665 gen_sel_d(ctx, op1, fd, ft, fs);
10666 break;
10667 case OPC_SELEQZ_D:
10668 check_insn(ctx, ISA_MIPS_R6);
10669 gen_sel_d(ctx, op1, fd, ft, fs);
10670 break;
10671 case OPC_SELNEZ_D:
10672 check_insn(ctx, ISA_MIPS_R6);
10673 gen_sel_d(ctx, op1, fd, ft, fs);
10674 break;
10675 case OPC_MOVCF_D:
10676 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10677 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10678 break;
10679 case OPC_MOVZ_D:
10680 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10682 TCGLabel *l1 = gen_new_label();
10683 TCGv_i64 fp0;
10685 if (ft != 0) {
10686 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10688 fp0 = tcg_temp_new_i64();
10689 gen_load_fpr64(ctx, fp0, fs);
10690 gen_store_fpr64(ctx, fp0, fd);
10691 tcg_temp_free_i64(fp0);
10692 gen_set_label(l1);
10694 break;
10695 case OPC_MOVN_D:
10696 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10698 TCGLabel *l1 = gen_new_label();
10699 TCGv_i64 fp0;
10701 if (ft != 0) {
10702 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10703 fp0 = tcg_temp_new_i64();
10704 gen_load_fpr64(ctx, fp0, fs);
10705 gen_store_fpr64(ctx, fp0, fd);
10706 tcg_temp_free_i64(fp0);
10707 gen_set_label(l1);
10710 break;
10711 case OPC_RECIP_D:
10712 check_cp1_registers(ctx, fs | fd);
10714 TCGv_i64 fp0 = tcg_temp_new_i64();
10716 gen_load_fpr64(ctx, fp0, fs);
10717 gen_helper_float_recip_d(fp0, cpu_env, fp0);
10718 gen_store_fpr64(ctx, fp0, fd);
10719 tcg_temp_free_i64(fp0);
10721 break;
10722 case OPC_RSQRT_D:
10723 check_cp1_registers(ctx, fs | fd);
10725 TCGv_i64 fp0 = tcg_temp_new_i64();
10727 gen_load_fpr64(ctx, fp0, fs);
10728 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
10729 gen_store_fpr64(ctx, fp0, fd);
10730 tcg_temp_free_i64(fp0);
10732 break;
10733 case OPC_MADDF_D:
10734 check_insn(ctx, ISA_MIPS_R6);
10736 TCGv_i64 fp0 = tcg_temp_new_i64();
10737 TCGv_i64 fp1 = tcg_temp_new_i64();
10738 TCGv_i64 fp2 = tcg_temp_new_i64();
10739 gen_load_fpr64(ctx, fp0, fs);
10740 gen_load_fpr64(ctx, fp1, ft);
10741 gen_load_fpr64(ctx, fp2, fd);
10742 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
10743 gen_store_fpr64(ctx, fp2, fd);
10744 tcg_temp_free_i64(fp2);
10745 tcg_temp_free_i64(fp1);
10746 tcg_temp_free_i64(fp0);
10748 break;
10749 case OPC_MSUBF_D:
10750 check_insn(ctx, ISA_MIPS_R6);
10752 TCGv_i64 fp0 = tcg_temp_new_i64();
10753 TCGv_i64 fp1 = tcg_temp_new_i64();
10754 TCGv_i64 fp2 = tcg_temp_new_i64();
10755 gen_load_fpr64(ctx, fp0, fs);
10756 gen_load_fpr64(ctx, fp1, ft);
10757 gen_load_fpr64(ctx, fp2, fd);
10758 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
10759 gen_store_fpr64(ctx, fp2, fd);
10760 tcg_temp_free_i64(fp2);
10761 tcg_temp_free_i64(fp1);
10762 tcg_temp_free_i64(fp0);
10764 break;
10765 case OPC_RINT_D:
10766 check_insn(ctx, ISA_MIPS_R6);
10768 TCGv_i64 fp0 = tcg_temp_new_i64();
10769 gen_load_fpr64(ctx, fp0, fs);
10770 gen_helper_float_rint_d(fp0, cpu_env, fp0);
10771 gen_store_fpr64(ctx, fp0, fd);
10772 tcg_temp_free_i64(fp0);
10774 break;
10775 case OPC_CLASS_D:
10776 check_insn(ctx, ISA_MIPS_R6);
10778 TCGv_i64 fp0 = tcg_temp_new_i64();
10779 gen_load_fpr64(ctx, fp0, fs);
10780 gen_helper_float_class_d(fp0, cpu_env, fp0);
10781 gen_store_fpr64(ctx, fp0, fd);
10782 tcg_temp_free_i64(fp0);
10784 break;
10785 case OPC_MIN_D: /* OPC_RECIP2_D */
10786 if (ctx->insn_flags & ISA_MIPS_R6) {
10787 /* OPC_MIN_D */
10788 TCGv_i64 fp0 = tcg_temp_new_i64();
10789 TCGv_i64 fp1 = tcg_temp_new_i64();
10790 gen_load_fpr64(ctx, fp0, fs);
10791 gen_load_fpr64(ctx, fp1, ft);
10792 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
10793 gen_store_fpr64(ctx, fp1, fd);
10794 tcg_temp_free_i64(fp1);
10795 tcg_temp_free_i64(fp0);
10796 } else {
10797 /* OPC_RECIP2_D */
10798 check_cp1_64bitmode(ctx);
10800 TCGv_i64 fp0 = tcg_temp_new_i64();
10801 TCGv_i64 fp1 = tcg_temp_new_i64();
10803 gen_load_fpr64(ctx, fp0, fs);
10804 gen_load_fpr64(ctx, fp1, ft);
10805 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
10806 tcg_temp_free_i64(fp1);
10807 gen_store_fpr64(ctx, fp0, fd);
10808 tcg_temp_free_i64(fp0);
10811 break;
10812 case OPC_MINA_D: /* OPC_RECIP1_D */
10813 if (ctx->insn_flags & ISA_MIPS_R6) {
10814 /* OPC_MINA_D */
10815 TCGv_i64 fp0 = tcg_temp_new_i64();
10816 TCGv_i64 fp1 = tcg_temp_new_i64();
10817 gen_load_fpr64(ctx, fp0, fs);
10818 gen_load_fpr64(ctx, fp1, ft);
10819 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
10820 gen_store_fpr64(ctx, fp1, fd);
10821 tcg_temp_free_i64(fp1);
10822 tcg_temp_free_i64(fp0);
10823 } else {
10824 /* OPC_RECIP1_D */
10825 check_cp1_64bitmode(ctx);
10827 TCGv_i64 fp0 = tcg_temp_new_i64();
10829 gen_load_fpr64(ctx, fp0, fs);
10830 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
10831 gen_store_fpr64(ctx, fp0, fd);
10832 tcg_temp_free_i64(fp0);
10835 break;
10836 case OPC_MAX_D: /* OPC_RSQRT1_D */
10837 if (ctx->insn_flags & ISA_MIPS_R6) {
10838 /* OPC_MAX_D */
10839 TCGv_i64 fp0 = tcg_temp_new_i64();
10840 TCGv_i64 fp1 = tcg_temp_new_i64();
10841 gen_load_fpr64(ctx, fp0, fs);
10842 gen_load_fpr64(ctx, fp1, ft);
10843 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
10844 gen_store_fpr64(ctx, fp1, fd);
10845 tcg_temp_free_i64(fp1);
10846 tcg_temp_free_i64(fp0);
10847 } else {
10848 /* OPC_RSQRT1_D */
10849 check_cp1_64bitmode(ctx);
10851 TCGv_i64 fp0 = tcg_temp_new_i64();
10853 gen_load_fpr64(ctx, fp0, fs);
10854 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
10855 gen_store_fpr64(ctx, fp0, fd);
10856 tcg_temp_free_i64(fp0);
10859 break;
10860 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10861 if (ctx->insn_flags & ISA_MIPS_R6) {
10862 /* OPC_MAXA_D */
10863 TCGv_i64 fp0 = tcg_temp_new_i64();
10864 TCGv_i64 fp1 = tcg_temp_new_i64();
10865 gen_load_fpr64(ctx, fp0, fs);
10866 gen_load_fpr64(ctx, fp1, ft);
10867 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10868 gen_store_fpr64(ctx, fp1, fd);
10869 tcg_temp_free_i64(fp1);
10870 tcg_temp_free_i64(fp0);
10871 } else {
10872 /* OPC_RSQRT2_D */
10873 check_cp1_64bitmode(ctx);
10875 TCGv_i64 fp0 = tcg_temp_new_i64();
10876 TCGv_i64 fp1 = tcg_temp_new_i64();
10878 gen_load_fpr64(ctx, fp0, fs);
10879 gen_load_fpr64(ctx, fp1, ft);
10880 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10881 tcg_temp_free_i64(fp1);
10882 gen_store_fpr64(ctx, fp0, fd);
10883 tcg_temp_free_i64(fp0);
10886 break;
10887 case OPC_CMP_F_D:
10888 case OPC_CMP_UN_D:
10889 case OPC_CMP_EQ_D:
10890 case OPC_CMP_UEQ_D:
10891 case OPC_CMP_OLT_D:
10892 case OPC_CMP_ULT_D:
10893 case OPC_CMP_OLE_D:
10894 case OPC_CMP_ULE_D:
10895 case OPC_CMP_SF_D:
10896 case OPC_CMP_NGLE_D:
10897 case OPC_CMP_SEQ_D:
10898 case OPC_CMP_NGL_D:
10899 case OPC_CMP_LT_D:
10900 case OPC_CMP_NGE_D:
10901 case OPC_CMP_LE_D:
10902 case OPC_CMP_NGT_D:
10903 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10904 if (ctx->opcode & (1 << 6)) {
10905 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
10906 } else {
10907 gen_cmp_d(ctx, func - 48, ft, fs, cc);
10909 break;
10910 case OPC_CVT_S_D:
10911 check_cp1_registers(ctx, fs);
10913 TCGv_i32 fp32 = tcg_temp_new_i32();
10914 TCGv_i64 fp64 = tcg_temp_new_i64();
10916 gen_load_fpr64(ctx, fp64, fs);
10917 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
10918 tcg_temp_free_i64(fp64);
10919 gen_store_fpr32(ctx, fp32, fd);
10920 tcg_temp_free_i32(fp32);
10922 break;
10923 case OPC_CVT_W_D:
10924 check_cp1_registers(ctx, fs);
10926 TCGv_i32 fp32 = tcg_temp_new_i32();
10927 TCGv_i64 fp64 = tcg_temp_new_i64();
10929 gen_load_fpr64(ctx, fp64, fs);
10930 if (ctx->nan2008) {
10931 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
10932 } else {
10933 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
10935 tcg_temp_free_i64(fp64);
10936 gen_store_fpr32(ctx, fp32, fd);
10937 tcg_temp_free_i32(fp32);
10939 break;
10940 case OPC_CVT_L_D:
10941 check_cp1_64bitmode(ctx);
10943 TCGv_i64 fp0 = tcg_temp_new_i64();
10945 gen_load_fpr64(ctx, fp0, fs);
10946 if (ctx->nan2008) {
10947 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
10948 } else {
10949 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
10951 gen_store_fpr64(ctx, fp0, fd);
10952 tcg_temp_free_i64(fp0);
10954 break;
10955 case OPC_CVT_S_W:
10957 TCGv_i32 fp0 = tcg_temp_new_i32();
10959 gen_load_fpr32(ctx, fp0, fs);
10960 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
10961 gen_store_fpr32(ctx, fp0, fd);
10962 tcg_temp_free_i32(fp0);
10964 break;
10965 case OPC_CVT_D_W:
10966 check_cp1_registers(ctx, fd);
10968 TCGv_i32 fp32 = tcg_temp_new_i32();
10969 TCGv_i64 fp64 = tcg_temp_new_i64();
10971 gen_load_fpr32(ctx, fp32, fs);
10972 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
10973 tcg_temp_free_i32(fp32);
10974 gen_store_fpr64(ctx, fp64, fd);
10975 tcg_temp_free_i64(fp64);
10977 break;
10978 case OPC_CVT_S_L:
10979 check_cp1_64bitmode(ctx);
10981 TCGv_i32 fp32 = tcg_temp_new_i32();
10982 TCGv_i64 fp64 = tcg_temp_new_i64();
10984 gen_load_fpr64(ctx, fp64, fs);
10985 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10986 tcg_temp_free_i64(fp64);
10987 gen_store_fpr32(ctx, fp32, fd);
10988 tcg_temp_free_i32(fp32);
10990 break;
10991 case OPC_CVT_D_L:
10992 check_cp1_64bitmode(ctx);
10994 TCGv_i64 fp0 = tcg_temp_new_i64();
10996 gen_load_fpr64(ctx, fp0, fs);
10997 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10998 gen_store_fpr64(ctx, fp0, fd);
10999 tcg_temp_free_i64(fp0);
11001 break;
11002 case OPC_CVT_PS_PW:
11003 check_ps(ctx);
11005 TCGv_i64 fp0 = tcg_temp_new_i64();
11007 gen_load_fpr64(ctx, fp0, fs);
11008 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11009 gen_store_fpr64(ctx, fp0, fd);
11010 tcg_temp_free_i64(fp0);
11012 break;
11013 case OPC_ADD_PS:
11014 check_ps(ctx);
11016 TCGv_i64 fp0 = tcg_temp_new_i64();
11017 TCGv_i64 fp1 = tcg_temp_new_i64();
11019 gen_load_fpr64(ctx, fp0, fs);
11020 gen_load_fpr64(ctx, fp1, ft);
11021 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11022 tcg_temp_free_i64(fp1);
11023 gen_store_fpr64(ctx, fp0, fd);
11024 tcg_temp_free_i64(fp0);
11026 break;
11027 case OPC_SUB_PS:
11028 check_ps(ctx);
11030 TCGv_i64 fp0 = tcg_temp_new_i64();
11031 TCGv_i64 fp1 = tcg_temp_new_i64();
11033 gen_load_fpr64(ctx, fp0, fs);
11034 gen_load_fpr64(ctx, fp1, ft);
11035 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11036 tcg_temp_free_i64(fp1);
11037 gen_store_fpr64(ctx, fp0, fd);
11038 tcg_temp_free_i64(fp0);
11040 break;
11041 case OPC_MUL_PS:
11042 check_ps(ctx);
11044 TCGv_i64 fp0 = tcg_temp_new_i64();
11045 TCGv_i64 fp1 = tcg_temp_new_i64();
11047 gen_load_fpr64(ctx, fp0, fs);
11048 gen_load_fpr64(ctx, fp1, ft);
11049 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11050 tcg_temp_free_i64(fp1);
11051 gen_store_fpr64(ctx, fp0, fd);
11052 tcg_temp_free_i64(fp0);
11054 break;
11055 case OPC_ABS_PS:
11056 check_ps(ctx);
11058 TCGv_i64 fp0 = tcg_temp_new_i64();
11060 gen_load_fpr64(ctx, fp0, fs);
11061 gen_helper_float_abs_ps(fp0, fp0);
11062 gen_store_fpr64(ctx, fp0, fd);
11063 tcg_temp_free_i64(fp0);
11065 break;
11066 case OPC_MOV_PS:
11067 check_ps(ctx);
11069 TCGv_i64 fp0 = tcg_temp_new_i64();
11071 gen_load_fpr64(ctx, fp0, fs);
11072 gen_store_fpr64(ctx, fp0, fd);
11073 tcg_temp_free_i64(fp0);
11075 break;
11076 case OPC_NEG_PS:
11077 check_ps(ctx);
11079 TCGv_i64 fp0 = tcg_temp_new_i64();
11081 gen_load_fpr64(ctx, fp0, fs);
11082 gen_helper_float_chs_ps(fp0, fp0);
11083 gen_store_fpr64(ctx, fp0, fd);
11084 tcg_temp_free_i64(fp0);
11086 break;
11087 case OPC_MOVCF_PS:
11088 check_ps(ctx);
11089 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11090 break;
11091 case OPC_MOVZ_PS:
11092 check_ps(ctx);
11094 TCGLabel *l1 = gen_new_label();
11095 TCGv_i64 fp0;
11097 if (ft != 0) {
11098 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11100 fp0 = tcg_temp_new_i64();
11101 gen_load_fpr64(ctx, fp0, fs);
11102 gen_store_fpr64(ctx, fp0, fd);
11103 tcg_temp_free_i64(fp0);
11104 gen_set_label(l1);
11106 break;
11107 case OPC_MOVN_PS:
11108 check_ps(ctx);
11110 TCGLabel *l1 = gen_new_label();
11111 TCGv_i64 fp0;
11113 if (ft != 0) {
11114 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11115 fp0 = tcg_temp_new_i64();
11116 gen_load_fpr64(ctx, fp0, fs);
11117 gen_store_fpr64(ctx, fp0, fd);
11118 tcg_temp_free_i64(fp0);
11119 gen_set_label(l1);
11122 break;
11123 case OPC_ADDR_PS:
11124 check_ps(ctx);
11126 TCGv_i64 fp0 = tcg_temp_new_i64();
11127 TCGv_i64 fp1 = tcg_temp_new_i64();
11129 gen_load_fpr64(ctx, fp0, ft);
11130 gen_load_fpr64(ctx, fp1, fs);
11131 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11132 tcg_temp_free_i64(fp1);
11133 gen_store_fpr64(ctx, fp0, fd);
11134 tcg_temp_free_i64(fp0);
11136 break;
11137 case OPC_MULR_PS:
11138 check_ps(ctx);
11140 TCGv_i64 fp0 = tcg_temp_new_i64();
11141 TCGv_i64 fp1 = tcg_temp_new_i64();
11143 gen_load_fpr64(ctx, fp0, ft);
11144 gen_load_fpr64(ctx, fp1, fs);
11145 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11146 tcg_temp_free_i64(fp1);
11147 gen_store_fpr64(ctx, fp0, fd);
11148 tcg_temp_free_i64(fp0);
11150 break;
11151 case OPC_RECIP2_PS:
11152 check_ps(ctx);
11154 TCGv_i64 fp0 = tcg_temp_new_i64();
11155 TCGv_i64 fp1 = tcg_temp_new_i64();
11157 gen_load_fpr64(ctx, fp0, fs);
11158 gen_load_fpr64(ctx, fp1, ft);
11159 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11160 tcg_temp_free_i64(fp1);
11161 gen_store_fpr64(ctx, fp0, fd);
11162 tcg_temp_free_i64(fp0);
11164 break;
11165 case OPC_RECIP1_PS:
11166 check_ps(ctx);
11168 TCGv_i64 fp0 = tcg_temp_new_i64();
11170 gen_load_fpr64(ctx, fp0, fs);
11171 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11172 gen_store_fpr64(ctx, fp0, fd);
11173 tcg_temp_free_i64(fp0);
11175 break;
11176 case OPC_RSQRT1_PS:
11177 check_ps(ctx);
11179 TCGv_i64 fp0 = tcg_temp_new_i64();
11181 gen_load_fpr64(ctx, fp0, fs);
11182 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11183 gen_store_fpr64(ctx, fp0, fd);
11184 tcg_temp_free_i64(fp0);
11186 break;
11187 case OPC_RSQRT2_PS:
11188 check_ps(ctx);
11190 TCGv_i64 fp0 = tcg_temp_new_i64();
11191 TCGv_i64 fp1 = tcg_temp_new_i64();
11193 gen_load_fpr64(ctx, fp0, fs);
11194 gen_load_fpr64(ctx, fp1, ft);
11195 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11196 tcg_temp_free_i64(fp1);
11197 gen_store_fpr64(ctx, fp0, fd);
11198 tcg_temp_free_i64(fp0);
11200 break;
11201 case OPC_CVT_S_PU:
11202 check_cp1_64bitmode(ctx);
11204 TCGv_i32 fp0 = tcg_temp_new_i32();
11206 gen_load_fpr32h(ctx, fp0, fs);
11207 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11208 gen_store_fpr32(ctx, fp0, fd);
11209 tcg_temp_free_i32(fp0);
11211 break;
11212 case OPC_CVT_PW_PS:
11213 check_ps(ctx);
11215 TCGv_i64 fp0 = tcg_temp_new_i64();
11217 gen_load_fpr64(ctx, fp0, fs);
11218 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11219 gen_store_fpr64(ctx, fp0, fd);
11220 tcg_temp_free_i64(fp0);
11222 break;
11223 case OPC_CVT_S_PL:
11224 check_cp1_64bitmode(ctx);
11226 TCGv_i32 fp0 = tcg_temp_new_i32();
11228 gen_load_fpr32(ctx, fp0, fs);
11229 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11230 gen_store_fpr32(ctx, fp0, fd);
11231 tcg_temp_free_i32(fp0);
11233 break;
11234 case OPC_PLL_PS:
11235 check_ps(ctx);
11237 TCGv_i32 fp0 = tcg_temp_new_i32();
11238 TCGv_i32 fp1 = tcg_temp_new_i32();
11240 gen_load_fpr32(ctx, fp0, fs);
11241 gen_load_fpr32(ctx, fp1, ft);
11242 gen_store_fpr32h(ctx, fp0, fd);
11243 gen_store_fpr32(ctx, fp1, fd);
11244 tcg_temp_free_i32(fp0);
11245 tcg_temp_free_i32(fp1);
11247 break;
11248 case OPC_PLU_PS:
11249 check_ps(ctx);
11251 TCGv_i32 fp0 = tcg_temp_new_i32();
11252 TCGv_i32 fp1 = tcg_temp_new_i32();
11254 gen_load_fpr32(ctx, fp0, fs);
11255 gen_load_fpr32h(ctx, fp1, ft);
11256 gen_store_fpr32(ctx, fp1, fd);
11257 gen_store_fpr32h(ctx, fp0, fd);
11258 tcg_temp_free_i32(fp0);
11259 tcg_temp_free_i32(fp1);
11261 break;
11262 case OPC_PUL_PS:
11263 check_ps(ctx);
11265 TCGv_i32 fp0 = tcg_temp_new_i32();
11266 TCGv_i32 fp1 = tcg_temp_new_i32();
11268 gen_load_fpr32h(ctx, fp0, fs);
11269 gen_load_fpr32(ctx, fp1, ft);
11270 gen_store_fpr32(ctx, fp1, fd);
11271 gen_store_fpr32h(ctx, fp0, fd);
11272 tcg_temp_free_i32(fp0);
11273 tcg_temp_free_i32(fp1);
11275 break;
11276 case OPC_PUU_PS:
11277 check_ps(ctx);
11279 TCGv_i32 fp0 = tcg_temp_new_i32();
11280 TCGv_i32 fp1 = tcg_temp_new_i32();
11282 gen_load_fpr32h(ctx, fp0, fs);
11283 gen_load_fpr32h(ctx, fp1, ft);
11284 gen_store_fpr32(ctx, fp1, fd);
11285 gen_store_fpr32h(ctx, fp0, fd);
11286 tcg_temp_free_i32(fp0);
11287 tcg_temp_free_i32(fp1);
11289 break;
11290 case OPC_CMP_F_PS:
11291 case OPC_CMP_UN_PS:
11292 case OPC_CMP_EQ_PS:
11293 case OPC_CMP_UEQ_PS:
11294 case OPC_CMP_OLT_PS:
11295 case OPC_CMP_ULT_PS:
11296 case OPC_CMP_OLE_PS:
11297 case OPC_CMP_ULE_PS:
11298 case OPC_CMP_SF_PS:
11299 case OPC_CMP_NGLE_PS:
11300 case OPC_CMP_SEQ_PS:
11301 case OPC_CMP_NGL_PS:
11302 case OPC_CMP_LT_PS:
11303 case OPC_CMP_NGE_PS:
11304 case OPC_CMP_LE_PS:
11305 case OPC_CMP_NGT_PS:
11306 if (ctx->opcode & (1 << 6)) {
11307 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
11308 } else {
11309 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
11311 break;
11312 default:
11313 MIPS_INVAL("farith");
11314 gen_reserved_instruction(ctx);
11315 return;
11319 /* Coprocessor 3 (FPU) */
11320 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
11321 int fd, int fs, int base, int index)
11323 TCGv t0 = tcg_temp_new();
11325 if (base == 0) {
11326 gen_load_gpr(t0, index);
11327 } else if (index == 0) {
11328 gen_load_gpr(t0, base);
11329 } else {
11330 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11333 * Don't do NOP if destination is zero: we must perform the actual
11334 * memory access.
11336 switch (opc) {
11337 case OPC_LWXC1:
11338 check_cop1x(ctx);
11340 TCGv_i32 fp0 = tcg_temp_new_i32();
11342 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11343 tcg_gen_trunc_tl_i32(fp0, t0);
11344 gen_store_fpr32(ctx, fp0, fd);
11345 tcg_temp_free_i32(fp0);
11347 break;
11348 case OPC_LDXC1:
11349 check_cop1x(ctx);
11350 check_cp1_registers(ctx, fd);
11352 TCGv_i64 fp0 = tcg_temp_new_i64();
11353 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11354 gen_store_fpr64(ctx, fp0, fd);
11355 tcg_temp_free_i64(fp0);
11357 break;
11358 case OPC_LUXC1:
11359 check_cp1_64bitmode(ctx);
11360 tcg_gen_andi_tl(t0, t0, ~0x7);
11362 TCGv_i64 fp0 = tcg_temp_new_i64();
11364 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11365 gen_store_fpr64(ctx, fp0, fd);
11366 tcg_temp_free_i64(fp0);
11368 break;
11369 case OPC_SWXC1:
11370 check_cop1x(ctx);
11372 TCGv_i32 fp0 = tcg_temp_new_i32();
11373 gen_load_fpr32(ctx, fp0, fs);
11374 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11375 tcg_temp_free_i32(fp0);
11377 break;
11378 case OPC_SDXC1:
11379 check_cop1x(ctx);
11380 check_cp1_registers(ctx, fs);
11382 TCGv_i64 fp0 = tcg_temp_new_i64();
11383 gen_load_fpr64(ctx, fp0, fs);
11384 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11385 tcg_temp_free_i64(fp0);
11387 break;
11388 case OPC_SUXC1:
11389 check_cp1_64bitmode(ctx);
11390 tcg_gen_andi_tl(t0, t0, ~0x7);
11392 TCGv_i64 fp0 = tcg_temp_new_i64();
11393 gen_load_fpr64(ctx, fp0, fs);
11394 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11395 tcg_temp_free_i64(fp0);
11397 break;
11399 tcg_temp_free(t0);
11402 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
11403 int fd, int fr, int fs, int ft)
11405 switch (opc) {
11406 case OPC_ALNV_PS:
11407 check_ps(ctx);
11409 TCGv t0 = tcg_temp_local_new();
11410 TCGv_i32 fp = tcg_temp_new_i32();
11411 TCGv_i32 fph = tcg_temp_new_i32();
11412 TCGLabel *l1 = gen_new_label();
11413 TCGLabel *l2 = gen_new_label();
11415 gen_load_gpr(t0, fr);
11416 tcg_gen_andi_tl(t0, t0, 0x7);
11418 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11419 gen_load_fpr32(ctx, fp, fs);
11420 gen_load_fpr32h(ctx, fph, fs);
11421 gen_store_fpr32(ctx, fp, fd);
11422 gen_store_fpr32h(ctx, fph, fd);
11423 tcg_gen_br(l2);
11424 gen_set_label(l1);
11425 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11426 tcg_temp_free(t0);
11427 #ifdef TARGET_WORDS_BIGENDIAN
11428 gen_load_fpr32(ctx, fp, fs);
11429 gen_load_fpr32h(ctx, fph, ft);
11430 gen_store_fpr32h(ctx, fp, fd);
11431 gen_store_fpr32(ctx, fph, fd);
11432 #else
11433 gen_load_fpr32h(ctx, fph, fs);
11434 gen_load_fpr32(ctx, fp, ft);
11435 gen_store_fpr32(ctx, fph, fd);
11436 gen_store_fpr32h(ctx, fp, fd);
11437 #endif
11438 gen_set_label(l2);
11439 tcg_temp_free_i32(fp);
11440 tcg_temp_free_i32(fph);
11442 break;
11443 case OPC_MADD_S:
11444 check_cop1x(ctx);
11446 TCGv_i32 fp0 = tcg_temp_new_i32();
11447 TCGv_i32 fp1 = tcg_temp_new_i32();
11448 TCGv_i32 fp2 = tcg_temp_new_i32();
11450 gen_load_fpr32(ctx, fp0, fs);
11451 gen_load_fpr32(ctx, fp1, ft);
11452 gen_load_fpr32(ctx, fp2, fr);
11453 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11454 tcg_temp_free_i32(fp0);
11455 tcg_temp_free_i32(fp1);
11456 gen_store_fpr32(ctx, fp2, fd);
11457 tcg_temp_free_i32(fp2);
11459 break;
11460 case OPC_MADD_D:
11461 check_cop1x(ctx);
11462 check_cp1_registers(ctx, fd | fs | ft | fr);
11464 TCGv_i64 fp0 = tcg_temp_new_i64();
11465 TCGv_i64 fp1 = tcg_temp_new_i64();
11466 TCGv_i64 fp2 = tcg_temp_new_i64();
11468 gen_load_fpr64(ctx, fp0, fs);
11469 gen_load_fpr64(ctx, fp1, ft);
11470 gen_load_fpr64(ctx, fp2, fr);
11471 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11472 tcg_temp_free_i64(fp0);
11473 tcg_temp_free_i64(fp1);
11474 gen_store_fpr64(ctx, fp2, fd);
11475 tcg_temp_free_i64(fp2);
11477 break;
11478 case OPC_MADD_PS:
11479 check_ps(ctx);
11481 TCGv_i64 fp0 = tcg_temp_new_i64();
11482 TCGv_i64 fp1 = tcg_temp_new_i64();
11483 TCGv_i64 fp2 = tcg_temp_new_i64();
11485 gen_load_fpr64(ctx, fp0, fs);
11486 gen_load_fpr64(ctx, fp1, ft);
11487 gen_load_fpr64(ctx, fp2, fr);
11488 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11489 tcg_temp_free_i64(fp0);
11490 tcg_temp_free_i64(fp1);
11491 gen_store_fpr64(ctx, fp2, fd);
11492 tcg_temp_free_i64(fp2);
11494 break;
11495 case OPC_MSUB_S:
11496 check_cop1x(ctx);
11498 TCGv_i32 fp0 = tcg_temp_new_i32();
11499 TCGv_i32 fp1 = tcg_temp_new_i32();
11500 TCGv_i32 fp2 = tcg_temp_new_i32();
11502 gen_load_fpr32(ctx, fp0, fs);
11503 gen_load_fpr32(ctx, fp1, ft);
11504 gen_load_fpr32(ctx, fp2, fr);
11505 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11506 tcg_temp_free_i32(fp0);
11507 tcg_temp_free_i32(fp1);
11508 gen_store_fpr32(ctx, fp2, fd);
11509 tcg_temp_free_i32(fp2);
11511 break;
11512 case OPC_MSUB_D:
11513 check_cop1x(ctx);
11514 check_cp1_registers(ctx, fd | fs | ft | fr);
11516 TCGv_i64 fp0 = tcg_temp_new_i64();
11517 TCGv_i64 fp1 = tcg_temp_new_i64();
11518 TCGv_i64 fp2 = tcg_temp_new_i64();
11520 gen_load_fpr64(ctx, fp0, fs);
11521 gen_load_fpr64(ctx, fp1, ft);
11522 gen_load_fpr64(ctx, fp2, fr);
11523 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11524 tcg_temp_free_i64(fp0);
11525 tcg_temp_free_i64(fp1);
11526 gen_store_fpr64(ctx, fp2, fd);
11527 tcg_temp_free_i64(fp2);
11529 break;
11530 case OPC_MSUB_PS:
11531 check_ps(ctx);
11533 TCGv_i64 fp0 = tcg_temp_new_i64();
11534 TCGv_i64 fp1 = tcg_temp_new_i64();
11535 TCGv_i64 fp2 = tcg_temp_new_i64();
11537 gen_load_fpr64(ctx, fp0, fs);
11538 gen_load_fpr64(ctx, fp1, ft);
11539 gen_load_fpr64(ctx, fp2, fr);
11540 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11541 tcg_temp_free_i64(fp0);
11542 tcg_temp_free_i64(fp1);
11543 gen_store_fpr64(ctx, fp2, fd);
11544 tcg_temp_free_i64(fp2);
11546 break;
11547 case OPC_NMADD_S:
11548 check_cop1x(ctx);
11550 TCGv_i32 fp0 = tcg_temp_new_i32();
11551 TCGv_i32 fp1 = tcg_temp_new_i32();
11552 TCGv_i32 fp2 = tcg_temp_new_i32();
11554 gen_load_fpr32(ctx, fp0, fs);
11555 gen_load_fpr32(ctx, fp1, ft);
11556 gen_load_fpr32(ctx, fp2, fr);
11557 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11558 tcg_temp_free_i32(fp0);
11559 tcg_temp_free_i32(fp1);
11560 gen_store_fpr32(ctx, fp2, fd);
11561 tcg_temp_free_i32(fp2);
11563 break;
11564 case OPC_NMADD_D:
11565 check_cop1x(ctx);
11566 check_cp1_registers(ctx, fd | fs | ft | fr);
11568 TCGv_i64 fp0 = tcg_temp_new_i64();
11569 TCGv_i64 fp1 = tcg_temp_new_i64();
11570 TCGv_i64 fp2 = tcg_temp_new_i64();
11572 gen_load_fpr64(ctx, fp0, fs);
11573 gen_load_fpr64(ctx, fp1, ft);
11574 gen_load_fpr64(ctx, fp2, fr);
11575 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11576 tcg_temp_free_i64(fp0);
11577 tcg_temp_free_i64(fp1);
11578 gen_store_fpr64(ctx, fp2, fd);
11579 tcg_temp_free_i64(fp2);
11581 break;
11582 case OPC_NMADD_PS:
11583 check_ps(ctx);
11585 TCGv_i64 fp0 = tcg_temp_new_i64();
11586 TCGv_i64 fp1 = tcg_temp_new_i64();
11587 TCGv_i64 fp2 = tcg_temp_new_i64();
11589 gen_load_fpr64(ctx, fp0, fs);
11590 gen_load_fpr64(ctx, fp1, ft);
11591 gen_load_fpr64(ctx, fp2, fr);
11592 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11593 tcg_temp_free_i64(fp0);
11594 tcg_temp_free_i64(fp1);
11595 gen_store_fpr64(ctx, fp2, fd);
11596 tcg_temp_free_i64(fp2);
11598 break;
11599 case OPC_NMSUB_S:
11600 check_cop1x(ctx);
11602 TCGv_i32 fp0 = tcg_temp_new_i32();
11603 TCGv_i32 fp1 = tcg_temp_new_i32();
11604 TCGv_i32 fp2 = tcg_temp_new_i32();
11606 gen_load_fpr32(ctx, fp0, fs);
11607 gen_load_fpr32(ctx, fp1, ft);
11608 gen_load_fpr32(ctx, fp2, fr);
11609 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11610 tcg_temp_free_i32(fp0);
11611 tcg_temp_free_i32(fp1);
11612 gen_store_fpr32(ctx, fp2, fd);
11613 tcg_temp_free_i32(fp2);
11615 break;
11616 case OPC_NMSUB_D:
11617 check_cop1x(ctx);
11618 check_cp1_registers(ctx, fd | fs | ft | fr);
11620 TCGv_i64 fp0 = tcg_temp_new_i64();
11621 TCGv_i64 fp1 = tcg_temp_new_i64();
11622 TCGv_i64 fp2 = tcg_temp_new_i64();
11624 gen_load_fpr64(ctx, fp0, fs);
11625 gen_load_fpr64(ctx, fp1, ft);
11626 gen_load_fpr64(ctx, fp2, fr);
11627 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11628 tcg_temp_free_i64(fp0);
11629 tcg_temp_free_i64(fp1);
11630 gen_store_fpr64(ctx, fp2, fd);
11631 tcg_temp_free_i64(fp2);
11633 break;
11634 case OPC_NMSUB_PS:
11635 check_ps(ctx);
11637 TCGv_i64 fp0 = tcg_temp_new_i64();
11638 TCGv_i64 fp1 = tcg_temp_new_i64();
11639 TCGv_i64 fp2 = tcg_temp_new_i64();
11641 gen_load_fpr64(ctx, fp0, fs);
11642 gen_load_fpr64(ctx, fp1, ft);
11643 gen_load_fpr64(ctx, fp2, fr);
11644 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11645 tcg_temp_free_i64(fp0);
11646 tcg_temp_free_i64(fp1);
11647 gen_store_fpr64(ctx, fp2, fd);
11648 tcg_temp_free_i64(fp2);
11650 break;
11651 default:
11652 MIPS_INVAL("flt3_arith");
11653 gen_reserved_instruction(ctx);
11654 return;
11658 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11660 TCGv t0;
11662 #if !defined(CONFIG_USER_ONLY)
11664 * The Linux kernel will emulate rdhwr if it's not supported natively.
11665 * Therefore only check the ISA in system mode.
11667 check_insn(ctx, ISA_MIPS_R2);
11668 #endif
11669 t0 = tcg_temp_new();
11671 switch (rd) {
11672 case 0:
11673 gen_helper_rdhwr_cpunum(t0, cpu_env);
11674 gen_store_gpr(t0, rt);
11675 break;
11676 case 1:
11677 gen_helper_rdhwr_synci_step(t0, cpu_env);
11678 gen_store_gpr(t0, rt);
11679 break;
11680 case 2:
11681 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11682 gen_io_start();
11684 gen_helper_rdhwr_cc(t0, cpu_env);
11685 gen_store_gpr(t0, rt);
11687 * Break the TB to be able to take timer interrupts immediately
11688 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
11689 * we break completely out of translated code.
11691 gen_save_pc(ctx->base.pc_next + 4);
11692 ctx->base.is_jmp = DISAS_EXIT;
11693 break;
11694 case 3:
11695 gen_helper_rdhwr_ccres(t0, cpu_env);
11696 gen_store_gpr(t0, rt);
11697 break;
11698 case 4:
11699 check_insn(ctx, ISA_MIPS_R6);
11700 if (sel != 0) {
11702 * Performance counter registers are not implemented other than
11703 * control register 0.
11705 generate_exception(ctx, EXCP_RI);
11707 gen_helper_rdhwr_performance(t0, cpu_env);
11708 gen_store_gpr(t0, rt);
11709 break;
11710 case 5:
11711 check_insn(ctx, ISA_MIPS_R6);
11712 gen_helper_rdhwr_xnp(t0, cpu_env);
11713 gen_store_gpr(t0, rt);
11714 break;
11715 case 29:
11716 #if defined(CONFIG_USER_ONLY)
11717 tcg_gen_ld_tl(t0, cpu_env,
11718 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11719 gen_store_gpr(t0, rt);
11720 break;
11721 #else
11722 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11723 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
11724 tcg_gen_ld_tl(t0, cpu_env,
11725 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11726 gen_store_gpr(t0, rt);
11727 } else {
11728 gen_reserved_instruction(ctx);
11730 break;
11731 #endif
11732 default: /* Invalid */
11733 MIPS_INVAL("rdhwr");
11734 gen_reserved_instruction(ctx);
11735 break;
11737 tcg_temp_free(t0);
11740 static inline void clear_branch_hflags(DisasContext *ctx)
11742 ctx->hflags &= ~MIPS_HFLAG_BMASK;
11743 if (ctx->base.is_jmp == DISAS_NEXT) {
11744 save_cpu_state(ctx, 0);
11745 } else {
11747 * It is not safe to save ctx->hflags as hflags may be changed
11748 * in execution time by the instruction in delay / forbidden slot.
11750 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11754 static void gen_branch(DisasContext *ctx, int insn_bytes)
11756 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11757 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
11758 /* Branches completion */
11759 clear_branch_hflags(ctx);
11760 ctx->base.is_jmp = DISAS_NORETURN;
11761 /* FIXME: Need to clear can_do_io. */
11762 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
11763 case MIPS_HFLAG_FBNSLOT:
11764 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
11765 break;
11766 case MIPS_HFLAG_B:
11767 /* unconditional branch */
11768 if (proc_hflags & MIPS_HFLAG_BX) {
11769 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11771 gen_goto_tb(ctx, 0, ctx->btarget);
11772 break;
11773 case MIPS_HFLAG_BL:
11774 /* blikely taken case */
11775 gen_goto_tb(ctx, 0, ctx->btarget);
11776 break;
11777 case MIPS_HFLAG_BC:
11778 /* Conditional branch */
11780 TCGLabel *l1 = gen_new_label();
11782 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11783 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
11784 gen_set_label(l1);
11785 gen_goto_tb(ctx, 0, ctx->btarget);
11787 break;
11788 case MIPS_HFLAG_BR:
11789 /* unconditional branch to register */
11790 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
11791 TCGv t0 = tcg_temp_new();
11792 TCGv_i32 t1 = tcg_temp_new_i32();
11794 tcg_gen_andi_tl(t0, btarget, 0x1);
11795 tcg_gen_trunc_tl_i32(t1, t0);
11796 tcg_temp_free(t0);
11797 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11798 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11799 tcg_gen_or_i32(hflags, hflags, t1);
11800 tcg_temp_free_i32(t1);
11802 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11803 } else {
11804 tcg_gen_mov_tl(cpu_PC, btarget);
11806 if (ctx->base.singlestep_enabled) {
11807 save_cpu_state(ctx, 0);
11808 gen_helper_raise_exception_debug(cpu_env);
11810 tcg_gen_lookup_and_goto_ptr();
11811 break;
11812 default:
11813 LOG_DISAS("unknown branch 0x%x\n", proc_hflags);
11814 gen_reserved_instruction(ctx);
11819 /* Compact Branches */
11820 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11821 int rs, int rt, int32_t offset)
11823 int bcond_compute = 0;
11824 TCGv t0 = tcg_temp_new();
11825 TCGv t1 = tcg_temp_new();
11826 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11828 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11829 #ifdef MIPS_DEBUG_DISAS
11830 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11831 "\n", ctx->base.pc_next);
11832 #endif
11833 gen_reserved_instruction(ctx);
11834 goto out;
11837 /* Load needed operands and calculate btarget */
11838 switch (opc) {
11839 /* compact branch */
11840 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11841 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11842 gen_load_gpr(t0, rs);
11843 gen_load_gpr(t1, rt);
11844 bcond_compute = 1;
11845 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11846 if (rs <= rt && rs == 0) {
11847 /* OPC_BEQZALC, OPC_BNEZALC */
11848 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11850 break;
11851 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11852 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11853 gen_load_gpr(t0, rs);
11854 gen_load_gpr(t1, rt);
11855 bcond_compute = 1;
11856 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11857 break;
11858 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11859 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11860 if (rs == 0 || rs == rt) {
11861 /* OPC_BLEZALC, OPC_BGEZALC */
11862 /* OPC_BGTZALC, OPC_BLTZALC */
11863 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11865 gen_load_gpr(t0, rs);
11866 gen_load_gpr(t1, rt);
11867 bcond_compute = 1;
11868 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11869 break;
11870 case OPC_BC:
11871 case OPC_BALC:
11872 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11873 break;
11874 case OPC_BEQZC:
11875 case OPC_BNEZC:
11876 if (rs != 0) {
11877 /* OPC_BEQZC, OPC_BNEZC */
11878 gen_load_gpr(t0, rs);
11879 bcond_compute = 1;
11880 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11881 } else {
11882 /* OPC_JIC, OPC_JIALC */
11883 TCGv tbase = tcg_temp_new();
11884 TCGv toffset = tcg_temp_new();
11886 gen_load_gpr(tbase, rt);
11887 tcg_gen_movi_tl(toffset, offset);
11888 gen_op_addr_add(ctx, btarget, tbase, toffset);
11889 tcg_temp_free(tbase);
11890 tcg_temp_free(toffset);
11892 break;
11893 default:
11894 MIPS_INVAL("Compact branch/jump");
11895 gen_reserved_instruction(ctx);
11896 goto out;
11899 if (bcond_compute == 0) {
11900 /* Unconditional compact branch */
11901 switch (opc) {
11902 case OPC_JIALC:
11903 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11904 /* Fallthrough */
11905 case OPC_JIC:
11906 ctx->hflags |= MIPS_HFLAG_BR;
11907 break;
11908 case OPC_BALC:
11909 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11910 /* Fallthrough */
11911 case OPC_BC:
11912 ctx->hflags |= MIPS_HFLAG_B;
11913 break;
11914 default:
11915 MIPS_INVAL("Compact branch/jump");
11916 gen_reserved_instruction(ctx);
11917 goto out;
11920 /* Generating branch here as compact branches don't have delay slot */
11921 gen_branch(ctx, 4);
11922 } else {
11923 /* Conditional compact branch */
11924 TCGLabel *fs = gen_new_label();
11925 save_cpu_state(ctx, 0);
11927 switch (opc) {
11928 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11929 if (rs == 0 && rt != 0) {
11930 /* OPC_BLEZALC */
11931 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11932 } else if (rs != 0 && rt != 0 && rs == rt) {
11933 /* OPC_BGEZALC */
11934 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11935 } else {
11936 /* OPC_BGEUC */
11937 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11939 break;
11940 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11941 if (rs == 0 && rt != 0) {
11942 /* OPC_BGTZALC */
11943 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11944 } else if (rs != 0 && rt != 0 && rs == rt) {
11945 /* OPC_BLTZALC */
11946 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11947 } else {
11948 /* OPC_BLTUC */
11949 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11951 break;
11952 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11953 if (rs == 0 && rt != 0) {
11954 /* OPC_BLEZC */
11955 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11956 } else if (rs != 0 && rt != 0 && rs == rt) {
11957 /* OPC_BGEZC */
11958 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11959 } else {
11960 /* OPC_BGEC */
11961 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11963 break;
11964 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11965 if (rs == 0 && rt != 0) {
11966 /* OPC_BGTZC */
11967 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11968 } else if (rs != 0 && rt != 0 && rs == rt) {
11969 /* OPC_BLTZC */
11970 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11971 } else {
11972 /* OPC_BLTC */
11973 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11975 break;
11976 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11977 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11978 if (rs >= rt) {
11979 /* OPC_BOVC, OPC_BNVC */
11980 TCGv t2 = tcg_temp_new();
11981 TCGv t3 = tcg_temp_new();
11982 TCGv t4 = tcg_temp_new();
11983 TCGv input_overflow = tcg_temp_new();
11985 gen_load_gpr(t0, rs);
11986 gen_load_gpr(t1, rt);
11987 tcg_gen_ext32s_tl(t2, t0);
11988 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11989 tcg_gen_ext32s_tl(t3, t1);
11990 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11991 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11993 tcg_gen_add_tl(t4, t2, t3);
11994 tcg_gen_ext32s_tl(t4, t4);
11995 tcg_gen_xor_tl(t2, t2, t3);
11996 tcg_gen_xor_tl(t3, t4, t3);
11997 tcg_gen_andc_tl(t2, t3, t2);
11998 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11999 tcg_gen_or_tl(t4, t4, input_overflow);
12000 if (opc == OPC_BOVC) {
12001 /* OPC_BOVC */
12002 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12003 } else {
12004 /* OPC_BNVC */
12005 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12007 tcg_temp_free(input_overflow);
12008 tcg_temp_free(t4);
12009 tcg_temp_free(t3);
12010 tcg_temp_free(t2);
12011 } else if (rs < rt && rs == 0) {
12012 /* OPC_BEQZALC, OPC_BNEZALC */
12013 if (opc == OPC_BEQZALC) {
12014 /* OPC_BEQZALC */
12015 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12016 } else {
12017 /* OPC_BNEZALC */
12018 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12020 } else {
12021 /* OPC_BEQC, OPC_BNEC */
12022 if (opc == OPC_BEQC) {
12023 /* OPC_BEQC */
12024 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12025 } else {
12026 /* OPC_BNEC */
12027 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12030 break;
12031 case OPC_BEQZC:
12032 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12033 break;
12034 case OPC_BNEZC:
12035 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12036 break;
12037 default:
12038 MIPS_INVAL("Compact conditional branch/jump");
12039 gen_reserved_instruction(ctx);
12040 goto out;
12043 /* Generating branch here as compact branches don't have delay slot */
12044 gen_goto_tb(ctx, 1, ctx->btarget);
12045 gen_set_label(fs);
12047 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12050 out:
12051 tcg_temp_free(t0);
12052 tcg_temp_free(t1);
12055 void gen_addiupc(DisasContext *ctx, int rx, int imm,
12056 int is_64_bit, int extended)
12058 TCGv t0;
12060 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12061 gen_reserved_instruction(ctx);
12062 return;
12065 t0 = tcg_temp_new();
12067 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12068 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12069 if (!is_64_bit) {
12070 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12073 tcg_temp_free(t0);
12076 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12077 int16_t offset)
12079 TCGv_i32 t0 = tcg_const_i32(op);
12080 TCGv t1 = tcg_temp_new();
12081 gen_base_offset_addr(ctx, t1, base, offset);
12082 gen_helper_cache(cpu_env, t1, t0);
12083 tcg_temp_free(t1);
12084 tcg_temp_free_i32(t0);
12087 static inline bool is_uhi(int sdbbp_code)
12089 #ifdef CONFIG_USER_ONLY
12090 return false;
12091 #else
12092 return semihosting_enabled() && sdbbp_code == 1;
12093 #endif
12096 #ifdef CONFIG_USER_ONLY
12097 /* The above should dead-code away any calls to this..*/
12098 static inline void gen_helper_do_semihosting(void *env)
12100 g_assert_not_reached();
12102 #endif
12104 void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
12106 TCGv t0 = tcg_temp_new();
12107 TCGv t1 = tcg_temp_new();
12109 gen_load_gpr(t0, base);
12111 if (index != 0) {
12112 gen_load_gpr(t1, index);
12113 tcg_gen_shli_tl(t1, t1, 2);
12114 gen_op_addr_add(ctx, t0, t1, t0);
12117 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12118 gen_store_gpr(t1, rd);
12120 tcg_temp_free(t0);
12121 tcg_temp_free(t1);
12124 static void gen_sync(int stype)
12126 TCGBar tcg_mo = TCG_BAR_SC;
12128 switch (stype) {
12129 case 0x4: /* SYNC_WMB */
12130 tcg_mo |= TCG_MO_ST_ST;
12131 break;
12132 case 0x10: /* SYNC_MB */
12133 tcg_mo |= TCG_MO_ALL;
12134 break;
12135 case 0x11: /* SYNC_ACQUIRE */
12136 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
12137 break;
12138 case 0x12: /* SYNC_RELEASE */
12139 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
12140 break;
12141 case 0x13: /* SYNC_RMB */
12142 tcg_mo |= TCG_MO_LD_LD;
12143 break;
12144 default:
12145 tcg_mo |= TCG_MO_ALL;
12146 break;
12149 tcg_gen_mb(tcg_mo);
12152 /* ISA extensions (ASEs) */
12154 /* MIPS16 extension to MIPS32 */
12155 #include "mips16e_translate.c.inc"
12157 /* microMIPS extension to MIPS32/MIPS64 */
12160 * Values for microMIPS fmt field. Variable-width, depending on which
12161 * formats the instruction supports.
12163 enum {
12164 FMT_SD_S = 0,
12165 FMT_SD_D = 1,
12167 FMT_SDPS_S = 0,
12168 FMT_SDPS_D = 1,
12169 FMT_SDPS_PS = 2,
12171 FMT_SWL_S = 0,
12172 FMT_SWL_W = 1,
12173 FMT_SWL_L = 2,
12175 FMT_DWL_D = 0,
12176 FMT_DWL_W = 1,
12177 FMT_DWL_L = 2
12180 #include "micromips_translate.c.inc"
12182 #include "nanomips_translate.c.inc"
12184 /* MIPSDSP functions. */
12185 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
12186 int rd, int base, int offset)
12188 TCGv t0;
12190 check_dsp(ctx);
12191 t0 = tcg_temp_new();
12193 if (base == 0) {
12194 gen_load_gpr(t0, offset);
12195 } else if (offset == 0) {
12196 gen_load_gpr(t0, base);
12197 } else {
12198 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
12201 switch (opc) {
12202 case OPC_LBUX:
12203 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
12204 gen_store_gpr(t0, rd);
12205 break;
12206 case OPC_LHX:
12207 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
12208 gen_store_gpr(t0, rd);
12209 break;
12210 case OPC_LWX:
12211 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12212 gen_store_gpr(t0, rd);
12213 break;
12214 #if defined(TARGET_MIPS64)
12215 case OPC_LDX:
12216 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
12217 gen_store_gpr(t0, rd);
12218 break;
12219 #endif
12221 tcg_temp_free(t0);
12224 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
12225 int ret, int v1, int v2)
12227 TCGv v1_t;
12228 TCGv v2_t;
12230 if (ret == 0) {
12231 /* Treat as NOP. */
12232 return;
12235 v1_t = tcg_temp_new();
12236 v2_t = tcg_temp_new();
12238 gen_load_gpr(v1_t, v1);
12239 gen_load_gpr(v2_t, v2);
12241 switch (op1) {
12242 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
12243 case OPC_MULT_G_2E:
12244 check_dsp_r2(ctx);
12245 switch (op2) {
12246 case OPC_ADDUH_QB:
12247 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
12248 break;
12249 case OPC_ADDUH_R_QB:
12250 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12251 break;
12252 case OPC_ADDQH_PH:
12253 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
12254 break;
12255 case OPC_ADDQH_R_PH:
12256 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12257 break;
12258 case OPC_ADDQH_W:
12259 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
12260 break;
12261 case OPC_ADDQH_R_W:
12262 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12263 break;
12264 case OPC_SUBUH_QB:
12265 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
12266 break;
12267 case OPC_SUBUH_R_QB:
12268 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12269 break;
12270 case OPC_SUBQH_PH:
12271 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
12272 break;
12273 case OPC_SUBQH_R_PH:
12274 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12275 break;
12276 case OPC_SUBQH_W:
12277 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
12278 break;
12279 case OPC_SUBQH_R_W:
12280 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12281 break;
12283 break;
12284 case OPC_ABSQ_S_PH_DSP:
12285 switch (op2) {
12286 case OPC_ABSQ_S_QB:
12287 check_dsp_r2(ctx);
12288 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
12289 break;
12290 case OPC_ABSQ_S_PH:
12291 check_dsp(ctx);
12292 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
12293 break;
12294 case OPC_ABSQ_S_W:
12295 check_dsp(ctx);
12296 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
12297 break;
12298 case OPC_PRECEQ_W_PHL:
12299 check_dsp(ctx);
12300 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
12301 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12302 break;
12303 case OPC_PRECEQ_W_PHR:
12304 check_dsp(ctx);
12305 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
12306 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
12307 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12308 break;
12309 case OPC_PRECEQU_PH_QBL:
12310 check_dsp(ctx);
12311 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
12312 break;
12313 case OPC_PRECEQU_PH_QBR:
12314 check_dsp(ctx);
12315 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
12316 break;
12317 case OPC_PRECEQU_PH_QBLA:
12318 check_dsp(ctx);
12319 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
12320 break;
12321 case OPC_PRECEQU_PH_QBRA:
12322 check_dsp(ctx);
12323 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
12324 break;
12325 case OPC_PRECEU_PH_QBL:
12326 check_dsp(ctx);
12327 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
12328 break;
12329 case OPC_PRECEU_PH_QBR:
12330 check_dsp(ctx);
12331 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
12332 break;
12333 case OPC_PRECEU_PH_QBLA:
12334 check_dsp(ctx);
12335 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
12336 break;
12337 case OPC_PRECEU_PH_QBRA:
12338 check_dsp(ctx);
12339 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
12340 break;
12342 break;
12343 case OPC_ADDU_QB_DSP:
12344 switch (op2) {
12345 case OPC_ADDQ_PH:
12346 check_dsp(ctx);
12347 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12348 break;
12349 case OPC_ADDQ_S_PH:
12350 check_dsp(ctx);
12351 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12352 break;
12353 case OPC_ADDQ_S_W:
12354 check_dsp(ctx);
12355 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12356 break;
12357 case OPC_ADDU_QB:
12358 check_dsp(ctx);
12359 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12360 break;
12361 case OPC_ADDU_S_QB:
12362 check_dsp(ctx);
12363 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12364 break;
12365 case OPC_ADDU_PH:
12366 check_dsp_r2(ctx);
12367 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12368 break;
12369 case OPC_ADDU_S_PH:
12370 check_dsp_r2(ctx);
12371 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12372 break;
12373 case OPC_SUBQ_PH:
12374 check_dsp(ctx);
12375 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12376 break;
12377 case OPC_SUBQ_S_PH:
12378 check_dsp(ctx);
12379 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12380 break;
12381 case OPC_SUBQ_S_W:
12382 check_dsp(ctx);
12383 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12384 break;
12385 case OPC_SUBU_QB:
12386 check_dsp(ctx);
12387 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12388 break;
12389 case OPC_SUBU_S_QB:
12390 check_dsp(ctx);
12391 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12392 break;
12393 case OPC_SUBU_PH:
12394 check_dsp_r2(ctx);
12395 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12396 break;
12397 case OPC_SUBU_S_PH:
12398 check_dsp_r2(ctx);
12399 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12400 break;
12401 case OPC_ADDSC:
12402 check_dsp(ctx);
12403 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12404 break;
12405 case OPC_ADDWC:
12406 check_dsp(ctx);
12407 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12408 break;
12409 case OPC_MODSUB:
12410 check_dsp(ctx);
12411 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
12412 break;
12413 case OPC_RADDU_W_QB:
12414 check_dsp(ctx);
12415 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
12416 break;
12418 break;
12419 case OPC_CMPU_EQ_QB_DSP:
12420 switch (op2) {
12421 case OPC_PRECR_QB_PH:
12422 check_dsp_r2(ctx);
12423 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12424 break;
12425 case OPC_PRECRQ_QB_PH:
12426 check_dsp(ctx);
12427 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12428 break;
12429 case OPC_PRECR_SRA_PH_W:
12430 check_dsp_r2(ctx);
12432 TCGv_i32 sa_t = tcg_const_i32(v2);
12433 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
12434 cpu_gpr[ret]);
12435 tcg_temp_free_i32(sa_t);
12436 break;
12438 case OPC_PRECR_SRA_R_PH_W:
12439 check_dsp_r2(ctx);
12441 TCGv_i32 sa_t = tcg_const_i32(v2);
12442 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
12443 cpu_gpr[ret]);
12444 tcg_temp_free_i32(sa_t);
12445 break;
12447 case OPC_PRECRQ_PH_W:
12448 check_dsp(ctx);
12449 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
12450 break;
12451 case OPC_PRECRQ_RS_PH_W:
12452 check_dsp(ctx);
12453 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12454 break;
12455 case OPC_PRECRQU_S_QB_PH:
12456 check_dsp(ctx);
12457 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12458 break;
12460 break;
12461 #ifdef TARGET_MIPS64
12462 case OPC_ABSQ_S_QH_DSP:
12463 switch (op2) {
12464 case OPC_PRECEQ_L_PWL:
12465 check_dsp(ctx);
12466 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
12467 break;
12468 case OPC_PRECEQ_L_PWR:
12469 check_dsp(ctx);
12470 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
12471 break;
12472 case OPC_PRECEQ_PW_QHL:
12473 check_dsp(ctx);
12474 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
12475 break;
12476 case OPC_PRECEQ_PW_QHR:
12477 check_dsp(ctx);
12478 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
12479 break;
12480 case OPC_PRECEQ_PW_QHLA:
12481 check_dsp(ctx);
12482 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
12483 break;
12484 case OPC_PRECEQ_PW_QHRA:
12485 check_dsp(ctx);
12486 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
12487 break;
12488 case OPC_PRECEQU_QH_OBL:
12489 check_dsp(ctx);
12490 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
12491 break;
12492 case OPC_PRECEQU_QH_OBR:
12493 check_dsp(ctx);
12494 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
12495 break;
12496 case OPC_PRECEQU_QH_OBLA:
12497 check_dsp(ctx);
12498 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
12499 break;
12500 case OPC_PRECEQU_QH_OBRA:
12501 check_dsp(ctx);
12502 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
12503 break;
12504 case OPC_PRECEU_QH_OBL:
12505 check_dsp(ctx);
12506 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
12507 break;
12508 case OPC_PRECEU_QH_OBR:
12509 check_dsp(ctx);
12510 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
12511 break;
12512 case OPC_PRECEU_QH_OBLA:
12513 check_dsp(ctx);
12514 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
12515 break;
12516 case OPC_PRECEU_QH_OBRA:
12517 check_dsp(ctx);
12518 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
12519 break;
12520 case OPC_ABSQ_S_OB:
12521 check_dsp_r2(ctx);
12522 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
12523 break;
12524 case OPC_ABSQ_S_PW:
12525 check_dsp(ctx);
12526 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
12527 break;
12528 case OPC_ABSQ_S_QH:
12529 check_dsp(ctx);
12530 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
12531 break;
12533 break;
12534 case OPC_ADDU_OB_DSP:
12535 switch (op2) {
12536 case OPC_RADDU_L_OB:
12537 check_dsp(ctx);
12538 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
12539 break;
12540 case OPC_SUBQ_PW:
12541 check_dsp(ctx);
12542 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12543 break;
12544 case OPC_SUBQ_S_PW:
12545 check_dsp(ctx);
12546 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12547 break;
12548 case OPC_SUBQ_QH:
12549 check_dsp(ctx);
12550 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12551 break;
12552 case OPC_SUBQ_S_QH:
12553 check_dsp(ctx);
12554 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12555 break;
12556 case OPC_SUBU_OB:
12557 check_dsp(ctx);
12558 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12559 break;
12560 case OPC_SUBU_S_OB:
12561 check_dsp(ctx);
12562 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12563 break;
12564 case OPC_SUBU_QH:
12565 check_dsp_r2(ctx);
12566 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12567 break;
12568 case OPC_SUBU_S_QH:
12569 check_dsp_r2(ctx);
12570 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12571 break;
12572 case OPC_SUBUH_OB:
12573 check_dsp_r2(ctx);
12574 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
12575 break;
12576 case OPC_SUBUH_R_OB:
12577 check_dsp_r2(ctx);
12578 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12579 break;
12580 case OPC_ADDQ_PW:
12581 check_dsp(ctx);
12582 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12583 break;
12584 case OPC_ADDQ_S_PW:
12585 check_dsp(ctx);
12586 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12587 break;
12588 case OPC_ADDQ_QH:
12589 check_dsp(ctx);
12590 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12591 break;
12592 case OPC_ADDQ_S_QH:
12593 check_dsp(ctx);
12594 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12595 break;
12596 case OPC_ADDU_OB:
12597 check_dsp(ctx);
12598 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12599 break;
12600 case OPC_ADDU_S_OB:
12601 check_dsp(ctx);
12602 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12603 break;
12604 case OPC_ADDU_QH:
12605 check_dsp_r2(ctx);
12606 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12607 break;
12608 case OPC_ADDU_S_QH:
12609 check_dsp_r2(ctx);
12610 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12611 break;
12612 case OPC_ADDUH_OB:
12613 check_dsp_r2(ctx);
12614 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
12615 break;
12616 case OPC_ADDUH_R_OB:
12617 check_dsp_r2(ctx);
12618 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12619 break;
12621 break;
12622 case OPC_CMPU_EQ_OB_DSP:
12623 switch (op2) {
12624 case OPC_PRECR_OB_QH:
12625 check_dsp_r2(ctx);
12626 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12627 break;
12628 case OPC_PRECR_SRA_QH_PW:
12629 check_dsp_r2(ctx);
12631 TCGv_i32 ret_t = tcg_const_i32(ret);
12632 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
12633 tcg_temp_free_i32(ret_t);
12634 break;
12636 case OPC_PRECR_SRA_R_QH_PW:
12637 check_dsp_r2(ctx);
12639 TCGv_i32 sa_v = tcg_const_i32(ret);
12640 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
12641 tcg_temp_free_i32(sa_v);
12642 break;
12644 case OPC_PRECRQ_OB_QH:
12645 check_dsp(ctx);
12646 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12647 break;
12648 case OPC_PRECRQ_PW_L:
12649 check_dsp(ctx);
12650 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
12651 break;
12652 case OPC_PRECRQ_QH_PW:
12653 check_dsp(ctx);
12654 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
12655 break;
12656 case OPC_PRECRQ_RS_QH_PW:
12657 check_dsp(ctx);
12658 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12659 break;
12660 case OPC_PRECRQU_S_OB_QH:
12661 check_dsp(ctx);
12662 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12663 break;
12665 break;
12666 #endif
12669 tcg_temp_free(v1_t);
12670 tcg_temp_free(v2_t);
12673 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
12674 int ret, int v1, int v2)
12676 uint32_t op2;
12677 TCGv t0;
12678 TCGv v1_t;
12679 TCGv v2_t;
12681 if (ret == 0) {
12682 /* Treat as NOP. */
12683 return;
12686 t0 = tcg_temp_new();
12687 v1_t = tcg_temp_new();
12688 v2_t = tcg_temp_new();
12690 tcg_gen_movi_tl(t0, v1);
12691 gen_load_gpr(v1_t, v1);
12692 gen_load_gpr(v2_t, v2);
12694 switch (opc) {
12695 case OPC_SHLL_QB_DSP:
12697 op2 = MASK_SHLL_QB(ctx->opcode);
12698 switch (op2) {
12699 case OPC_SHLL_QB:
12700 check_dsp(ctx);
12701 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
12702 break;
12703 case OPC_SHLLV_QB:
12704 check_dsp(ctx);
12705 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12706 break;
12707 case OPC_SHLL_PH:
12708 check_dsp(ctx);
12709 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
12710 break;
12711 case OPC_SHLLV_PH:
12712 check_dsp(ctx);
12713 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12714 break;
12715 case OPC_SHLL_S_PH:
12716 check_dsp(ctx);
12717 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
12718 break;
12719 case OPC_SHLLV_S_PH:
12720 check_dsp(ctx);
12721 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12722 break;
12723 case OPC_SHLL_S_W:
12724 check_dsp(ctx);
12725 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
12726 break;
12727 case OPC_SHLLV_S_W:
12728 check_dsp(ctx);
12729 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12730 break;
12731 case OPC_SHRL_QB:
12732 check_dsp(ctx);
12733 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
12734 break;
12735 case OPC_SHRLV_QB:
12736 check_dsp(ctx);
12737 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
12738 break;
12739 case OPC_SHRL_PH:
12740 check_dsp_r2(ctx);
12741 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
12742 break;
12743 case OPC_SHRLV_PH:
12744 check_dsp_r2(ctx);
12745 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
12746 break;
12747 case OPC_SHRA_QB:
12748 check_dsp_r2(ctx);
12749 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
12750 break;
12751 case OPC_SHRA_R_QB:
12752 check_dsp_r2(ctx);
12753 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
12754 break;
12755 case OPC_SHRAV_QB:
12756 check_dsp_r2(ctx);
12757 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
12758 break;
12759 case OPC_SHRAV_R_QB:
12760 check_dsp_r2(ctx);
12761 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
12762 break;
12763 case OPC_SHRA_PH:
12764 check_dsp(ctx);
12765 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
12766 break;
12767 case OPC_SHRA_R_PH:
12768 check_dsp(ctx);
12769 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
12770 break;
12771 case OPC_SHRAV_PH:
12772 check_dsp(ctx);
12773 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
12774 break;
12775 case OPC_SHRAV_R_PH:
12776 check_dsp(ctx);
12777 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
12778 break;
12779 case OPC_SHRA_R_W:
12780 check_dsp(ctx);
12781 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
12782 break;
12783 case OPC_SHRAV_R_W:
12784 check_dsp(ctx);
12785 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
12786 break;
12787 default: /* Invalid */
12788 MIPS_INVAL("MASK SHLL.QB");
12789 gen_reserved_instruction(ctx);
12790 break;
12792 break;
12794 #ifdef TARGET_MIPS64
12795 case OPC_SHLL_OB_DSP:
12796 op2 = MASK_SHLL_OB(ctx->opcode);
12797 switch (op2) {
12798 case OPC_SHLL_PW:
12799 check_dsp(ctx);
12800 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
12801 break;
12802 case OPC_SHLLV_PW:
12803 check_dsp(ctx);
12804 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12805 break;
12806 case OPC_SHLL_S_PW:
12807 check_dsp(ctx);
12808 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
12809 break;
12810 case OPC_SHLLV_S_PW:
12811 check_dsp(ctx);
12812 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12813 break;
12814 case OPC_SHLL_OB:
12815 check_dsp(ctx);
12816 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
12817 break;
12818 case OPC_SHLLV_OB:
12819 check_dsp(ctx);
12820 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12821 break;
12822 case OPC_SHLL_QH:
12823 check_dsp(ctx);
12824 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
12825 break;
12826 case OPC_SHLLV_QH:
12827 check_dsp(ctx);
12828 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12829 break;
12830 case OPC_SHLL_S_QH:
12831 check_dsp(ctx);
12832 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
12833 break;
12834 case OPC_SHLLV_S_QH:
12835 check_dsp(ctx);
12836 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12837 break;
12838 case OPC_SHRA_OB:
12839 check_dsp_r2(ctx);
12840 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
12841 break;
12842 case OPC_SHRAV_OB:
12843 check_dsp_r2(ctx);
12844 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
12845 break;
12846 case OPC_SHRA_R_OB:
12847 check_dsp_r2(ctx);
12848 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
12849 break;
12850 case OPC_SHRAV_R_OB:
12851 check_dsp_r2(ctx);
12852 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
12853 break;
12854 case OPC_SHRA_PW:
12855 check_dsp(ctx);
12856 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
12857 break;
12858 case OPC_SHRAV_PW:
12859 check_dsp(ctx);
12860 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
12861 break;
12862 case OPC_SHRA_R_PW:
12863 check_dsp(ctx);
12864 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
12865 break;
12866 case OPC_SHRAV_R_PW:
12867 check_dsp(ctx);
12868 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
12869 break;
12870 case OPC_SHRA_QH:
12871 check_dsp(ctx);
12872 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
12873 break;
12874 case OPC_SHRAV_QH:
12875 check_dsp(ctx);
12876 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
12877 break;
12878 case OPC_SHRA_R_QH:
12879 check_dsp(ctx);
12880 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
12881 break;
12882 case OPC_SHRAV_R_QH:
12883 check_dsp(ctx);
12884 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
12885 break;
12886 case OPC_SHRL_OB:
12887 check_dsp(ctx);
12888 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
12889 break;
12890 case OPC_SHRLV_OB:
12891 check_dsp(ctx);
12892 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
12893 break;
12894 case OPC_SHRL_QH:
12895 check_dsp_r2(ctx);
12896 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
12897 break;
12898 case OPC_SHRLV_QH:
12899 check_dsp_r2(ctx);
12900 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
12901 break;
12902 default: /* Invalid */
12903 MIPS_INVAL("MASK SHLL.OB");
12904 gen_reserved_instruction(ctx);
12905 break;
12907 break;
12908 #endif
12911 tcg_temp_free(t0);
12912 tcg_temp_free(v1_t);
12913 tcg_temp_free(v2_t);
12916 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
12917 int ret, int v1, int v2, int check_ret)
12919 TCGv_i32 t0;
12920 TCGv v1_t;
12921 TCGv v2_t;
12923 if ((ret == 0) && (check_ret == 1)) {
12924 /* Treat as NOP. */
12925 return;
12928 t0 = tcg_temp_new_i32();
12929 v1_t = tcg_temp_new();
12930 v2_t = tcg_temp_new();
12932 tcg_gen_movi_i32(t0, ret);
12933 gen_load_gpr(v1_t, v1);
12934 gen_load_gpr(v2_t, v2);
12936 switch (op1) {
12938 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
12939 * the same mask and op1.
12941 case OPC_MULT_G_2E:
12942 check_dsp_r2(ctx);
12943 switch (op2) {
12944 case OPC_MUL_PH:
12945 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12946 break;
12947 case OPC_MUL_S_PH:
12948 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12949 break;
12950 case OPC_MULQ_S_W:
12951 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12952 break;
12953 case OPC_MULQ_RS_W:
12954 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12955 break;
12957 break;
12958 case OPC_DPA_W_PH_DSP:
12959 switch (op2) {
12960 case OPC_DPAU_H_QBL:
12961 check_dsp(ctx);
12962 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
12963 break;
12964 case OPC_DPAU_H_QBR:
12965 check_dsp(ctx);
12966 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
12967 break;
12968 case OPC_DPSU_H_QBL:
12969 check_dsp(ctx);
12970 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
12971 break;
12972 case OPC_DPSU_H_QBR:
12973 check_dsp(ctx);
12974 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
12975 break;
12976 case OPC_DPA_W_PH:
12977 check_dsp_r2(ctx);
12978 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
12979 break;
12980 case OPC_DPAX_W_PH:
12981 check_dsp_r2(ctx);
12982 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
12983 break;
12984 case OPC_DPAQ_S_W_PH:
12985 check_dsp(ctx);
12986 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
12987 break;
12988 case OPC_DPAQX_S_W_PH:
12989 check_dsp_r2(ctx);
12990 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
12991 break;
12992 case OPC_DPAQX_SA_W_PH:
12993 check_dsp_r2(ctx);
12994 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
12995 break;
12996 case OPC_DPS_W_PH:
12997 check_dsp_r2(ctx);
12998 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
12999 break;
13000 case OPC_DPSX_W_PH:
13001 check_dsp_r2(ctx);
13002 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
13003 break;
13004 case OPC_DPSQ_S_W_PH:
13005 check_dsp(ctx);
13006 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13007 break;
13008 case OPC_DPSQX_S_W_PH:
13009 check_dsp_r2(ctx);
13010 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13011 break;
13012 case OPC_DPSQX_SA_W_PH:
13013 check_dsp_r2(ctx);
13014 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13015 break;
13016 case OPC_MULSAQ_S_W_PH:
13017 check_dsp(ctx);
13018 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13019 break;
13020 case OPC_DPAQ_SA_L_W:
13021 check_dsp(ctx);
13022 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13023 break;
13024 case OPC_DPSQ_SA_L_W:
13025 check_dsp(ctx);
13026 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13027 break;
13028 case OPC_MAQ_S_W_PHL:
13029 check_dsp(ctx);
13030 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
13031 break;
13032 case OPC_MAQ_S_W_PHR:
13033 check_dsp(ctx);
13034 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
13035 break;
13036 case OPC_MAQ_SA_W_PHL:
13037 check_dsp(ctx);
13038 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
13039 break;
13040 case OPC_MAQ_SA_W_PHR:
13041 check_dsp(ctx);
13042 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
13043 break;
13044 case OPC_MULSA_W_PH:
13045 check_dsp_r2(ctx);
13046 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
13047 break;
13049 break;
13050 #ifdef TARGET_MIPS64
13051 case OPC_DPAQ_W_QH_DSP:
13053 int ac = ret & 0x03;
13054 tcg_gen_movi_i32(t0, ac);
13056 switch (op2) {
13057 case OPC_DMADD:
13058 check_dsp(ctx);
13059 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
13060 break;
13061 case OPC_DMADDU:
13062 check_dsp(ctx);
13063 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
13064 break;
13065 case OPC_DMSUB:
13066 check_dsp(ctx);
13067 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
13068 break;
13069 case OPC_DMSUBU:
13070 check_dsp(ctx);
13071 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
13072 break;
13073 case OPC_DPA_W_QH:
13074 check_dsp_r2(ctx);
13075 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
13076 break;
13077 case OPC_DPAQ_S_W_QH:
13078 check_dsp(ctx);
13079 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13080 break;
13081 case OPC_DPAQ_SA_L_PW:
13082 check_dsp(ctx);
13083 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13084 break;
13085 case OPC_DPAU_H_OBL:
13086 check_dsp(ctx);
13087 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
13088 break;
13089 case OPC_DPAU_H_OBR:
13090 check_dsp(ctx);
13091 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
13092 break;
13093 case OPC_DPS_W_QH:
13094 check_dsp_r2(ctx);
13095 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
13096 break;
13097 case OPC_DPSQ_S_W_QH:
13098 check_dsp(ctx);
13099 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13100 break;
13101 case OPC_DPSQ_SA_L_PW:
13102 check_dsp(ctx);
13103 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13104 break;
13105 case OPC_DPSU_H_OBL:
13106 check_dsp(ctx);
13107 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
13108 break;
13109 case OPC_DPSU_H_OBR:
13110 check_dsp(ctx);
13111 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
13112 break;
13113 case OPC_MAQ_S_L_PWL:
13114 check_dsp(ctx);
13115 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
13116 break;
13117 case OPC_MAQ_S_L_PWR:
13118 check_dsp(ctx);
13119 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
13120 break;
13121 case OPC_MAQ_S_W_QHLL:
13122 check_dsp(ctx);
13123 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
13124 break;
13125 case OPC_MAQ_SA_W_QHLL:
13126 check_dsp(ctx);
13127 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
13128 break;
13129 case OPC_MAQ_S_W_QHLR:
13130 check_dsp(ctx);
13131 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
13132 break;
13133 case OPC_MAQ_SA_W_QHLR:
13134 check_dsp(ctx);
13135 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
13136 break;
13137 case OPC_MAQ_S_W_QHRL:
13138 check_dsp(ctx);
13139 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
13140 break;
13141 case OPC_MAQ_SA_W_QHRL:
13142 check_dsp(ctx);
13143 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
13144 break;
13145 case OPC_MAQ_S_W_QHRR:
13146 check_dsp(ctx);
13147 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
13148 break;
13149 case OPC_MAQ_SA_W_QHRR:
13150 check_dsp(ctx);
13151 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
13152 break;
13153 case OPC_MULSAQ_S_L_PW:
13154 check_dsp(ctx);
13155 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
13156 break;
13157 case OPC_MULSAQ_S_W_QH:
13158 check_dsp(ctx);
13159 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13160 break;
13163 break;
13164 #endif
13165 case OPC_ADDU_QB_DSP:
13166 switch (op2) {
13167 case OPC_MULEU_S_PH_QBL:
13168 check_dsp(ctx);
13169 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13170 break;
13171 case OPC_MULEU_S_PH_QBR:
13172 check_dsp(ctx);
13173 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13174 break;
13175 case OPC_MULQ_RS_PH:
13176 check_dsp(ctx);
13177 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13178 break;
13179 case OPC_MULEQ_S_W_PHL:
13180 check_dsp(ctx);
13181 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13182 break;
13183 case OPC_MULEQ_S_W_PHR:
13184 check_dsp(ctx);
13185 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13186 break;
13187 case OPC_MULQ_S_PH:
13188 check_dsp_r2(ctx);
13189 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13190 break;
13192 break;
13193 #ifdef TARGET_MIPS64
13194 case OPC_ADDU_OB_DSP:
13195 switch (op2) {
13196 case OPC_MULEQ_S_PW_QHL:
13197 check_dsp(ctx);
13198 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13199 break;
13200 case OPC_MULEQ_S_PW_QHR:
13201 check_dsp(ctx);
13202 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13203 break;
13204 case OPC_MULEU_S_QH_OBL:
13205 check_dsp(ctx);
13206 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13207 break;
13208 case OPC_MULEU_S_QH_OBR:
13209 check_dsp(ctx);
13210 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13211 break;
13212 case OPC_MULQ_RS_QH:
13213 check_dsp(ctx);
13214 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13215 break;
13217 break;
13218 #endif
13221 tcg_temp_free_i32(t0);
13222 tcg_temp_free(v1_t);
13223 tcg_temp_free(v2_t);
13226 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
13227 int ret, int val)
13229 int16_t imm;
13230 TCGv t0;
13231 TCGv val_t;
13233 if (ret == 0) {
13234 /* Treat as NOP. */
13235 return;
13238 t0 = tcg_temp_new();
13239 val_t = tcg_temp_new();
13240 gen_load_gpr(val_t, val);
13242 switch (op1) {
13243 case OPC_ABSQ_S_PH_DSP:
13244 switch (op2) {
13245 case OPC_BITREV:
13246 check_dsp(ctx);
13247 gen_helper_bitrev(cpu_gpr[ret], val_t);
13248 break;
13249 case OPC_REPL_QB:
13250 check_dsp(ctx);
13252 target_long result;
13253 imm = (ctx->opcode >> 16) & 0xFF;
13254 result = (uint32_t)imm << 24 |
13255 (uint32_t)imm << 16 |
13256 (uint32_t)imm << 8 |
13257 (uint32_t)imm;
13258 result = (int32_t)result;
13259 tcg_gen_movi_tl(cpu_gpr[ret], result);
13261 break;
13262 case OPC_REPLV_QB:
13263 check_dsp(ctx);
13264 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13265 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13266 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13267 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13268 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13269 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13270 break;
13271 case OPC_REPL_PH:
13272 check_dsp(ctx);
13274 imm = (ctx->opcode >> 16) & 0x03FF;
13275 imm = (int16_t)(imm << 6) >> 6;
13276 tcg_gen_movi_tl(cpu_gpr[ret], \
13277 (target_long)((int32_t)imm << 16 | \
13278 (uint16_t)imm));
13280 break;
13281 case OPC_REPLV_PH:
13282 check_dsp(ctx);
13283 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13284 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13285 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13286 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13287 break;
13289 break;
13290 #ifdef TARGET_MIPS64
13291 case OPC_ABSQ_S_QH_DSP:
13292 switch (op2) {
13293 case OPC_REPL_OB:
13294 check_dsp(ctx);
13296 target_long temp;
13298 imm = (ctx->opcode >> 16) & 0xFF;
13299 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
13300 temp = (temp << 16) | temp;
13301 temp = (temp << 32) | temp;
13302 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13303 break;
13305 case OPC_REPL_PW:
13306 check_dsp(ctx);
13308 target_long temp;
13310 imm = (ctx->opcode >> 16) & 0x03FF;
13311 imm = (int16_t)(imm << 6) >> 6;
13312 temp = ((target_long)imm << 32) \
13313 | ((target_long)imm & 0xFFFFFFFF);
13314 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13315 break;
13317 case OPC_REPL_QH:
13318 check_dsp(ctx);
13320 target_long temp;
13322 imm = (ctx->opcode >> 16) & 0x03FF;
13323 imm = (int16_t)(imm << 6) >> 6;
13325 temp = ((uint64_t)(uint16_t)imm << 48) |
13326 ((uint64_t)(uint16_t)imm << 32) |
13327 ((uint64_t)(uint16_t)imm << 16) |
13328 (uint64_t)(uint16_t)imm;
13329 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13330 break;
13332 case OPC_REPLV_OB:
13333 check_dsp(ctx);
13334 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13335 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13336 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13337 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13338 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13339 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13340 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13341 break;
13342 case OPC_REPLV_PW:
13343 check_dsp(ctx);
13344 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
13345 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13346 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13347 break;
13348 case OPC_REPLV_QH:
13349 check_dsp(ctx);
13350 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13351 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13352 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13353 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13354 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13355 break;
13357 break;
13358 #endif
13360 tcg_temp_free(t0);
13361 tcg_temp_free(val_t);
13364 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
13365 uint32_t op1, uint32_t op2,
13366 int ret, int v1, int v2, int check_ret)
13368 TCGv t1;
13369 TCGv v1_t;
13370 TCGv v2_t;
13372 if ((ret == 0) && (check_ret == 1)) {
13373 /* Treat as NOP. */
13374 return;
13377 t1 = tcg_temp_new();
13378 v1_t = tcg_temp_new();
13379 v2_t = tcg_temp_new();
13381 gen_load_gpr(v1_t, v1);
13382 gen_load_gpr(v2_t, v2);
13384 switch (op1) {
13385 case OPC_CMPU_EQ_QB_DSP:
13386 switch (op2) {
13387 case OPC_CMPU_EQ_QB:
13388 check_dsp(ctx);
13389 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
13390 break;
13391 case OPC_CMPU_LT_QB:
13392 check_dsp(ctx);
13393 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
13394 break;
13395 case OPC_CMPU_LE_QB:
13396 check_dsp(ctx);
13397 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
13398 break;
13399 case OPC_CMPGU_EQ_QB:
13400 check_dsp(ctx);
13401 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
13402 break;
13403 case OPC_CMPGU_LT_QB:
13404 check_dsp(ctx);
13405 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
13406 break;
13407 case OPC_CMPGU_LE_QB:
13408 check_dsp(ctx);
13409 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
13410 break;
13411 case OPC_CMPGDU_EQ_QB:
13412 check_dsp_r2(ctx);
13413 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
13414 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13415 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13416 tcg_gen_shli_tl(t1, t1, 24);
13417 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13418 break;
13419 case OPC_CMPGDU_LT_QB:
13420 check_dsp_r2(ctx);
13421 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
13422 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13423 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13424 tcg_gen_shli_tl(t1, t1, 24);
13425 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13426 break;
13427 case OPC_CMPGDU_LE_QB:
13428 check_dsp_r2(ctx);
13429 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
13430 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13431 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13432 tcg_gen_shli_tl(t1, t1, 24);
13433 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13434 break;
13435 case OPC_CMP_EQ_PH:
13436 check_dsp(ctx);
13437 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
13438 break;
13439 case OPC_CMP_LT_PH:
13440 check_dsp(ctx);
13441 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
13442 break;
13443 case OPC_CMP_LE_PH:
13444 check_dsp(ctx);
13445 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
13446 break;
13447 case OPC_PICK_QB:
13448 check_dsp(ctx);
13449 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13450 break;
13451 case OPC_PICK_PH:
13452 check_dsp(ctx);
13453 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13454 break;
13455 case OPC_PACKRL_PH:
13456 check_dsp(ctx);
13457 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
13458 break;
13460 break;
13461 #ifdef TARGET_MIPS64
13462 case OPC_CMPU_EQ_OB_DSP:
13463 switch (op2) {
13464 case OPC_CMP_EQ_PW:
13465 check_dsp(ctx);
13466 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
13467 break;
13468 case OPC_CMP_LT_PW:
13469 check_dsp(ctx);
13470 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
13471 break;
13472 case OPC_CMP_LE_PW:
13473 check_dsp(ctx);
13474 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
13475 break;
13476 case OPC_CMP_EQ_QH:
13477 check_dsp(ctx);
13478 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
13479 break;
13480 case OPC_CMP_LT_QH:
13481 check_dsp(ctx);
13482 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
13483 break;
13484 case OPC_CMP_LE_QH:
13485 check_dsp(ctx);
13486 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
13487 break;
13488 case OPC_CMPGDU_EQ_OB:
13489 check_dsp_r2(ctx);
13490 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13491 break;
13492 case OPC_CMPGDU_LT_OB:
13493 check_dsp_r2(ctx);
13494 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13495 break;
13496 case OPC_CMPGDU_LE_OB:
13497 check_dsp_r2(ctx);
13498 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13499 break;
13500 case OPC_CMPGU_EQ_OB:
13501 check_dsp(ctx);
13502 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
13503 break;
13504 case OPC_CMPGU_LT_OB:
13505 check_dsp(ctx);
13506 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
13507 break;
13508 case OPC_CMPGU_LE_OB:
13509 check_dsp(ctx);
13510 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
13511 break;
13512 case OPC_CMPU_EQ_OB:
13513 check_dsp(ctx);
13514 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
13515 break;
13516 case OPC_CMPU_LT_OB:
13517 check_dsp(ctx);
13518 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
13519 break;
13520 case OPC_CMPU_LE_OB:
13521 check_dsp(ctx);
13522 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
13523 break;
13524 case OPC_PACKRL_PW:
13525 check_dsp(ctx);
13526 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
13527 break;
13528 case OPC_PICK_OB:
13529 check_dsp(ctx);
13530 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13531 break;
13532 case OPC_PICK_PW:
13533 check_dsp(ctx);
13534 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13535 break;
13536 case OPC_PICK_QH:
13537 check_dsp(ctx);
13538 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13539 break;
13541 break;
13542 #endif
13545 tcg_temp_free(t1);
13546 tcg_temp_free(v1_t);
13547 tcg_temp_free(v2_t);
13550 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
13551 uint32_t op1, int rt, int rs, int sa)
13553 TCGv t0;
13555 check_dsp_r2(ctx);
13557 if (rt == 0) {
13558 /* Treat as NOP. */
13559 return;
13562 t0 = tcg_temp_new();
13563 gen_load_gpr(t0, rs);
13565 switch (op1) {
13566 case OPC_APPEND_DSP:
13567 switch (MASK_APPEND(ctx->opcode)) {
13568 case OPC_APPEND:
13569 if (sa != 0) {
13570 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
13572 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
13573 break;
13574 case OPC_PREPEND:
13575 if (sa != 0) {
13576 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
13577 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
13578 tcg_gen_shli_tl(t0, t0, 32 - sa);
13579 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13581 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
13582 break;
13583 case OPC_BALIGN:
13584 sa &= 3;
13585 if (sa != 0 && sa != 2) {
13586 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
13587 tcg_gen_ext32u_tl(t0, t0);
13588 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
13589 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13591 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
13592 break;
13593 default: /* Invalid */
13594 MIPS_INVAL("MASK APPEND");
13595 gen_reserved_instruction(ctx);
13596 break;
13598 break;
13599 #ifdef TARGET_MIPS64
13600 case OPC_DAPPEND_DSP:
13601 switch (MASK_DAPPEND(ctx->opcode)) {
13602 case OPC_DAPPEND:
13603 if (sa != 0) {
13604 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
13606 break;
13607 case OPC_PREPENDD:
13608 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
13609 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
13610 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
13611 break;
13612 case OPC_PREPENDW:
13613 if (sa != 0) {
13614 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
13615 tcg_gen_shli_tl(t0, t0, 64 - sa);
13616 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13618 break;
13619 case OPC_DBALIGN:
13620 sa &= 7;
13621 if (sa != 0 && sa != 2 && sa != 4) {
13622 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
13623 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
13624 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13626 break;
13627 default: /* Invalid */
13628 MIPS_INVAL("MASK DAPPEND");
13629 gen_reserved_instruction(ctx);
13630 break;
13632 break;
13633 #endif
13635 tcg_temp_free(t0);
13638 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
13639 int ret, int v1, int v2, int check_ret)
13642 TCGv t0;
13643 TCGv t1;
13644 TCGv v1_t;
13645 TCGv v2_t;
13646 int16_t imm;
13648 if ((ret == 0) && (check_ret == 1)) {
13649 /* Treat as NOP. */
13650 return;
13653 t0 = tcg_temp_new();
13654 t1 = tcg_temp_new();
13655 v1_t = tcg_temp_new();
13656 v2_t = tcg_temp_new();
13658 gen_load_gpr(v1_t, v1);
13659 gen_load_gpr(v2_t, v2);
13661 switch (op1) {
13662 case OPC_EXTR_W_DSP:
13663 check_dsp(ctx);
13664 switch (op2) {
13665 case OPC_EXTR_W:
13666 tcg_gen_movi_tl(t0, v2);
13667 tcg_gen_movi_tl(t1, v1);
13668 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
13669 break;
13670 case OPC_EXTR_R_W:
13671 tcg_gen_movi_tl(t0, v2);
13672 tcg_gen_movi_tl(t1, v1);
13673 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
13674 break;
13675 case OPC_EXTR_RS_W:
13676 tcg_gen_movi_tl(t0, v2);
13677 tcg_gen_movi_tl(t1, v1);
13678 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
13679 break;
13680 case OPC_EXTR_S_H:
13681 tcg_gen_movi_tl(t0, v2);
13682 tcg_gen_movi_tl(t1, v1);
13683 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
13684 break;
13685 case OPC_EXTRV_S_H:
13686 tcg_gen_movi_tl(t0, v2);
13687 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
13688 break;
13689 case OPC_EXTRV_W:
13690 tcg_gen_movi_tl(t0, v2);
13691 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13692 break;
13693 case OPC_EXTRV_R_W:
13694 tcg_gen_movi_tl(t0, v2);
13695 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13696 break;
13697 case OPC_EXTRV_RS_W:
13698 tcg_gen_movi_tl(t0, v2);
13699 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13700 break;
13701 case OPC_EXTP:
13702 tcg_gen_movi_tl(t0, v2);
13703 tcg_gen_movi_tl(t1, v1);
13704 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
13705 break;
13706 case OPC_EXTPV:
13707 tcg_gen_movi_tl(t0, v2);
13708 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
13709 break;
13710 case OPC_EXTPDP:
13711 tcg_gen_movi_tl(t0, v2);
13712 tcg_gen_movi_tl(t1, v1);
13713 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
13714 break;
13715 case OPC_EXTPDPV:
13716 tcg_gen_movi_tl(t0, v2);
13717 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
13718 break;
13719 case OPC_SHILO:
13720 imm = (ctx->opcode >> 20) & 0x3F;
13721 tcg_gen_movi_tl(t0, ret);
13722 tcg_gen_movi_tl(t1, imm);
13723 gen_helper_shilo(t0, t1, cpu_env);
13724 break;
13725 case OPC_SHILOV:
13726 tcg_gen_movi_tl(t0, ret);
13727 gen_helper_shilo(t0, v1_t, cpu_env);
13728 break;
13729 case OPC_MTHLIP:
13730 tcg_gen_movi_tl(t0, ret);
13731 gen_helper_mthlip(t0, v1_t, cpu_env);
13732 break;
13733 case OPC_WRDSP:
13734 imm = (ctx->opcode >> 11) & 0x3FF;
13735 tcg_gen_movi_tl(t0, imm);
13736 gen_helper_wrdsp(v1_t, t0, cpu_env);
13737 break;
13738 case OPC_RDDSP:
13739 imm = (ctx->opcode >> 16) & 0x03FF;
13740 tcg_gen_movi_tl(t0, imm);
13741 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
13742 break;
13744 break;
13745 #ifdef TARGET_MIPS64
13746 case OPC_DEXTR_W_DSP:
13747 check_dsp(ctx);
13748 switch (op2) {
13749 case OPC_DMTHLIP:
13750 tcg_gen_movi_tl(t0, ret);
13751 gen_helper_dmthlip(v1_t, t0, cpu_env);
13752 break;
13753 case OPC_DSHILO:
13755 int shift = (ctx->opcode >> 19) & 0x7F;
13756 int ac = (ctx->opcode >> 11) & 0x03;
13757 tcg_gen_movi_tl(t0, shift);
13758 tcg_gen_movi_tl(t1, ac);
13759 gen_helper_dshilo(t0, t1, cpu_env);
13760 break;
13762 case OPC_DSHILOV:
13764 int ac = (ctx->opcode >> 11) & 0x03;
13765 tcg_gen_movi_tl(t0, ac);
13766 gen_helper_dshilo(v1_t, t0, cpu_env);
13767 break;
13769 case OPC_DEXTP:
13770 tcg_gen_movi_tl(t0, v2);
13771 tcg_gen_movi_tl(t1, v1);
13773 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
13774 break;
13775 case OPC_DEXTPV:
13776 tcg_gen_movi_tl(t0, v2);
13777 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
13778 break;
13779 case OPC_DEXTPDP:
13780 tcg_gen_movi_tl(t0, v2);
13781 tcg_gen_movi_tl(t1, v1);
13782 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
13783 break;
13784 case OPC_DEXTPDPV:
13785 tcg_gen_movi_tl(t0, v2);
13786 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
13787 break;
13788 case OPC_DEXTR_L:
13789 tcg_gen_movi_tl(t0, v2);
13790 tcg_gen_movi_tl(t1, v1);
13791 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
13792 break;
13793 case OPC_DEXTR_R_L:
13794 tcg_gen_movi_tl(t0, v2);
13795 tcg_gen_movi_tl(t1, v1);
13796 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
13797 break;
13798 case OPC_DEXTR_RS_L:
13799 tcg_gen_movi_tl(t0, v2);
13800 tcg_gen_movi_tl(t1, v1);
13801 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
13802 break;
13803 case OPC_DEXTR_W:
13804 tcg_gen_movi_tl(t0, v2);
13805 tcg_gen_movi_tl(t1, v1);
13806 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
13807 break;
13808 case OPC_DEXTR_R_W:
13809 tcg_gen_movi_tl(t0, v2);
13810 tcg_gen_movi_tl(t1, v1);
13811 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
13812 break;
13813 case OPC_DEXTR_RS_W:
13814 tcg_gen_movi_tl(t0, v2);
13815 tcg_gen_movi_tl(t1, v1);
13816 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
13817 break;
13818 case OPC_DEXTR_S_H:
13819 tcg_gen_movi_tl(t0, v2);
13820 tcg_gen_movi_tl(t1, v1);
13821 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
13822 break;
13823 case OPC_DEXTRV_S_H:
13824 tcg_gen_movi_tl(t0, v2);
13825 tcg_gen_movi_tl(t1, v1);
13826 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
13827 break;
13828 case OPC_DEXTRV_L:
13829 tcg_gen_movi_tl(t0, v2);
13830 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
13831 break;
13832 case OPC_DEXTRV_R_L:
13833 tcg_gen_movi_tl(t0, v2);
13834 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
13835 break;
13836 case OPC_DEXTRV_RS_L:
13837 tcg_gen_movi_tl(t0, v2);
13838 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
13839 break;
13840 case OPC_DEXTRV_W:
13841 tcg_gen_movi_tl(t0, v2);
13842 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13843 break;
13844 case OPC_DEXTRV_R_W:
13845 tcg_gen_movi_tl(t0, v2);
13846 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13847 break;
13848 case OPC_DEXTRV_RS_W:
13849 tcg_gen_movi_tl(t0, v2);
13850 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13851 break;
13853 break;
13854 #endif
13857 tcg_temp_free(t0);
13858 tcg_temp_free(t1);
13859 tcg_temp_free(v1_t);
13860 tcg_temp_free(v2_t);
13863 /* End MIPSDSP functions. */
13865 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
13867 int rs, rt, rd, sa;
13868 uint32_t op1, op2;
13870 rs = (ctx->opcode >> 21) & 0x1f;
13871 rt = (ctx->opcode >> 16) & 0x1f;
13872 rd = (ctx->opcode >> 11) & 0x1f;
13873 sa = (ctx->opcode >> 6) & 0x1f;
13875 op1 = MASK_SPECIAL(ctx->opcode);
13876 switch (op1) {
13877 case OPC_MULT:
13878 case OPC_MULTU:
13879 case OPC_DIV:
13880 case OPC_DIVU:
13881 op2 = MASK_R6_MULDIV(ctx->opcode);
13882 switch (op2) {
13883 case R6_OPC_MUL:
13884 case R6_OPC_MUH:
13885 case R6_OPC_MULU:
13886 case R6_OPC_MUHU:
13887 case R6_OPC_DIV:
13888 case R6_OPC_MOD:
13889 case R6_OPC_DIVU:
13890 case R6_OPC_MODU:
13891 gen_r6_muldiv(ctx, op2, rd, rs, rt);
13892 break;
13893 default:
13894 MIPS_INVAL("special_r6 muldiv");
13895 gen_reserved_instruction(ctx);
13896 break;
13898 break;
13899 case OPC_SELEQZ:
13900 case OPC_SELNEZ:
13901 gen_cond_move(ctx, op1, rd, rs, rt);
13902 break;
13903 case R6_OPC_CLO:
13904 case R6_OPC_CLZ:
13905 if (rt == 0 && sa == 1) {
13907 * Major opcode and function field is shared with preR6 MFHI/MTHI.
13908 * We need additionally to check other fields.
13910 gen_cl(ctx, op1, rd, rs);
13911 } else {
13912 gen_reserved_instruction(ctx);
13914 break;
13915 case R6_OPC_SDBBP:
13916 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
13917 gen_helper_do_semihosting(cpu_env);
13918 } else {
13919 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13920 gen_reserved_instruction(ctx);
13921 } else {
13922 generate_exception_end(ctx, EXCP_DBp);
13925 break;
13926 #if defined(TARGET_MIPS64)
13927 case R6_OPC_DCLO:
13928 case R6_OPC_DCLZ:
13929 if (rt == 0 && sa == 1) {
13931 * Major opcode and function field is shared with preR6 MFHI/MTHI.
13932 * We need additionally to check other fields.
13934 check_mips_64(ctx);
13935 gen_cl(ctx, op1, rd, rs);
13936 } else {
13937 gen_reserved_instruction(ctx);
13939 break;
13940 case OPC_DMULT:
13941 case OPC_DMULTU:
13942 case OPC_DDIV:
13943 case OPC_DDIVU:
13945 op2 = MASK_R6_MULDIV(ctx->opcode);
13946 switch (op2) {
13947 case R6_OPC_DMUL:
13948 case R6_OPC_DMUH:
13949 case R6_OPC_DMULU:
13950 case R6_OPC_DMUHU:
13951 case R6_OPC_DDIV:
13952 case R6_OPC_DMOD:
13953 case R6_OPC_DDIVU:
13954 case R6_OPC_DMODU:
13955 check_mips_64(ctx);
13956 gen_r6_muldiv(ctx, op2, rd, rs, rt);
13957 break;
13958 default:
13959 MIPS_INVAL("special_r6 muldiv");
13960 gen_reserved_instruction(ctx);
13961 break;
13963 break;
13964 #endif
13965 default: /* Invalid */
13966 MIPS_INVAL("special_r6");
13967 gen_reserved_instruction(ctx);
13968 break;
13972 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
13974 int rs = extract32(ctx->opcode, 21, 5);
13975 int rt = extract32(ctx->opcode, 16, 5);
13976 int rd = extract32(ctx->opcode, 11, 5);
13977 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
13979 switch (op1) {
13980 case OPC_MOVN: /* Conditional move */
13981 case OPC_MOVZ:
13982 gen_cond_move(ctx, op1, rd, rs, rt);
13983 break;
13984 case OPC_MFHI: /* Move from HI/LO */
13985 case OPC_MFLO:
13986 gen_HILO(ctx, op1, 0, rd);
13987 break;
13988 case OPC_MTHI:
13989 case OPC_MTLO: /* Move to HI/LO */
13990 gen_HILO(ctx, op1, 0, rs);
13991 break;
13992 case OPC_MULT:
13993 case OPC_MULTU:
13994 gen_mul_txx9(ctx, op1, rd, rs, rt);
13995 break;
13996 case OPC_DIV:
13997 case OPC_DIVU:
13998 gen_muldiv(ctx, op1, 0, rs, rt);
13999 break;
14000 #if defined(TARGET_MIPS64)
14001 case OPC_DMULT:
14002 case OPC_DMULTU:
14003 case OPC_DDIV:
14004 case OPC_DDIVU:
14005 check_insn_opc_user_only(ctx, INSN_R5900);
14006 gen_muldiv(ctx, op1, 0, rs, rt);
14007 break;
14008 #endif
14009 case OPC_JR:
14010 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
14011 break;
14012 default: /* Invalid */
14013 MIPS_INVAL("special_tx79");
14014 gen_reserved_instruction(ctx);
14015 break;
14019 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
14021 int rs, rt, rd;
14022 uint32_t op1;
14024 rs = (ctx->opcode >> 21) & 0x1f;
14025 rt = (ctx->opcode >> 16) & 0x1f;
14026 rd = (ctx->opcode >> 11) & 0x1f;
14028 op1 = MASK_SPECIAL(ctx->opcode);
14029 switch (op1) {
14030 case OPC_MOVN: /* Conditional move */
14031 case OPC_MOVZ:
14032 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
14033 INSN_LOONGSON2E | INSN_LOONGSON2F);
14034 gen_cond_move(ctx, op1, rd, rs, rt);
14035 break;
14036 case OPC_MFHI: /* Move from HI/LO */
14037 case OPC_MFLO:
14038 gen_HILO(ctx, op1, rs & 3, rd);
14039 break;
14040 case OPC_MTHI:
14041 case OPC_MTLO: /* Move to HI/LO */
14042 gen_HILO(ctx, op1, rd & 3, rs);
14043 break;
14044 case OPC_MOVCI:
14045 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
14046 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14047 check_cp1_enabled(ctx);
14048 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
14049 (ctx->opcode >> 16) & 1);
14050 } else {
14051 generate_exception_err(ctx, EXCP_CpU, 1);
14053 break;
14054 case OPC_MULT:
14055 case OPC_MULTU:
14056 gen_muldiv(ctx, op1, rd & 3, rs, rt);
14057 break;
14058 case OPC_DIV:
14059 case OPC_DIVU:
14060 gen_muldiv(ctx, op1, 0, rs, rt);
14061 break;
14062 #if defined(TARGET_MIPS64)
14063 case OPC_DMULT:
14064 case OPC_DMULTU:
14065 case OPC_DDIV:
14066 case OPC_DDIVU:
14067 check_insn(ctx, ISA_MIPS3);
14068 check_mips_64(ctx);
14069 gen_muldiv(ctx, op1, 0, rs, rt);
14070 break;
14071 #endif
14072 case OPC_JR:
14073 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
14074 break;
14075 case OPC_SPIM:
14076 #ifdef MIPS_STRICT_STANDARD
14077 MIPS_INVAL("SPIM");
14078 gen_reserved_instruction(ctx);
14079 #else
14080 /* Implemented as RI exception for now. */
14081 MIPS_INVAL("spim (unofficial)");
14082 gen_reserved_instruction(ctx);
14083 #endif
14084 break;
14085 default: /* Invalid */
14086 MIPS_INVAL("special_legacy");
14087 gen_reserved_instruction(ctx);
14088 break;
14092 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
14094 int rs, rt, rd, sa;
14095 uint32_t op1;
14097 rs = (ctx->opcode >> 21) & 0x1f;
14098 rt = (ctx->opcode >> 16) & 0x1f;
14099 rd = (ctx->opcode >> 11) & 0x1f;
14100 sa = (ctx->opcode >> 6) & 0x1f;
14102 op1 = MASK_SPECIAL(ctx->opcode);
14103 switch (op1) {
14104 case OPC_SLL: /* Shift with immediate */
14105 if (sa == 5 && rd == 0 &&
14106 rs == 0 && rt == 0) { /* PAUSE */
14107 if ((ctx->insn_flags & ISA_MIPS_R6) &&
14108 (ctx->hflags & MIPS_HFLAG_BMASK)) {
14109 gen_reserved_instruction(ctx);
14110 break;
14113 /* Fallthrough */
14114 case OPC_SRA:
14115 gen_shift_imm(ctx, op1, rd, rt, sa);
14116 break;
14117 case OPC_SRL:
14118 switch ((ctx->opcode >> 21) & 0x1f) {
14119 case 1:
14120 /* rotr is decoded as srl on non-R2 CPUs */
14121 if (ctx->insn_flags & ISA_MIPS_R2) {
14122 op1 = OPC_ROTR;
14124 /* Fallthrough */
14125 case 0:
14126 gen_shift_imm(ctx, op1, rd, rt, sa);
14127 break;
14128 default:
14129 gen_reserved_instruction(ctx);
14130 break;
14132 break;
14133 case OPC_ADD:
14134 case OPC_ADDU:
14135 case OPC_SUB:
14136 case OPC_SUBU:
14137 gen_arith(ctx, op1, rd, rs, rt);
14138 break;
14139 case OPC_SLLV: /* Shifts */
14140 case OPC_SRAV:
14141 gen_shift(ctx, op1, rd, rs, rt);
14142 break;
14143 case OPC_SRLV:
14144 switch ((ctx->opcode >> 6) & 0x1f) {
14145 case 1:
14146 /* rotrv is decoded as srlv on non-R2 CPUs */
14147 if (ctx->insn_flags & ISA_MIPS_R2) {
14148 op1 = OPC_ROTRV;
14150 /* Fallthrough */
14151 case 0:
14152 gen_shift(ctx, op1, rd, rs, rt);
14153 break;
14154 default:
14155 gen_reserved_instruction(ctx);
14156 break;
14158 break;
14159 case OPC_SLT: /* Set on less than */
14160 case OPC_SLTU:
14161 gen_slt(ctx, op1, rd, rs, rt);
14162 break;
14163 case OPC_AND: /* Logic*/
14164 case OPC_OR:
14165 case OPC_NOR:
14166 case OPC_XOR:
14167 gen_logic(ctx, op1, rd, rs, rt);
14168 break;
14169 case OPC_JALR:
14170 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
14171 break;
14172 case OPC_TGE: /* Traps */
14173 case OPC_TGEU:
14174 case OPC_TLT:
14175 case OPC_TLTU:
14176 case OPC_TEQ:
14177 case OPC_TNE:
14178 check_insn(ctx, ISA_MIPS2);
14179 gen_trap(ctx, op1, rs, rt, -1);
14180 break;
14181 case OPC_PMON:
14182 /* Pmon entry point, also R4010 selsl */
14183 #ifdef MIPS_STRICT_STANDARD
14184 MIPS_INVAL("PMON / selsl");
14185 gen_reserved_instruction(ctx);
14186 #else
14187 gen_helper_pmon(cpu_env, tcg_constant_i32(sa));
14188 #endif
14189 break;
14190 case OPC_SYSCALL:
14191 generate_exception_end(ctx, EXCP_SYSCALL);
14192 break;
14193 case OPC_BREAK:
14194 generate_exception_end(ctx, EXCP_BREAK);
14195 break;
14196 case OPC_SYNC:
14197 check_insn(ctx, ISA_MIPS2);
14198 gen_sync(extract32(ctx->opcode, 6, 5));
14199 break;
14201 #if defined(TARGET_MIPS64)
14202 /* MIPS64 specific opcodes */
14203 case OPC_DSLL:
14204 case OPC_DSRA:
14205 case OPC_DSLL32:
14206 case OPC_DSRA32:
14207 check_insn(ctx, ISA_MIPS3);
14208 check_mips_64(ctx);
14209 gen_shift_imm(ctx, op1, rd, rt, sa);
14210 break;
14211 case OPC_DSRL:
14212 switch ((ctx->opcode >> 21) & 0x1f) {
14213 case 1:
14214 /* drotr is decoded as dsrl on non-R2 CPUs */
14215 if (ctx->insn_flags & ISA_MIPS_R2) {
14216 op1 = OPC_DROTR;
14218 /* Fallthrough */
14219 case 0:
14220 check_insn(ctx, ISA_MIPS3);
14221 check_mips_64(ctx);
14222 gen_shift_imm(ctx, op1, rd, rt, sa);
14223 break;
14224 default:
14225 gen_reserved_instruction(ctx);
14226 break;
14228 break;
14229 case OPC_DSRL32:
14230 switch ((ctx->opcode >> 21) & 0x1f) {
14231 case 1:
14232 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
14233 if (ctx->insn_flags & ISA_MIPS_R2) {
14234 op1 = OPC_DROTR32;
14236 /* Fallthrough */
14237 case 0:
14238 check_insn(ctx, ISA_MIPS3);
14239 check_mips_64(ctx);
14240 gen_shift_imm(ctx, op1, rd, rt, sa);
14241 break;
14242 default:
14243 gen_reserved_instruction(ctx);
14244 break;
14246 break;
14247 case OPC_DADD:
14248 case OPC_DADDU:
14249 case OPC_DSUB:
14250 case OPC_DSUBU:
14251 check_insn(ctx, ISA_MIPS3);
14252 check_mips_64(ctx);
14253 gen_arith(ctx, op1, rd, rs, rt);
14254 break;
14255 case OPC_DSLLV:
14256 case OPC_DSRAV:
14257 check_insn(ctx, ISA_MIPS3);
14258 check_mips_64(ctx);
14259 gen_shift(ctx, op1, rd, rs, rt);
14260 break;
14261 case OPC_DSRLV:
14262 switch ((ctx->opcode >> 6) & 0x1f) {
14263 case 1:
14264 /* drotrv is decoded as dsrlv on non-R2 CPUs */
14265 if (ctx->insn_flags & ISA_MIPS_R2) {
14266 op1 = OPC_DROTRV;
14268 /* Fallthrough */
14269 case 0:
14270 check_insn(ctx, ISA_MIPS3);
14271 check_mips_64(ctx);
14272 gen_shift(ctx, op1, rd, rs, rt);
14273 break;
14274 default:
14275 gen_reserved_instruction(ctx);
14276 break;
14278 break;
14279 #endif
14280 default:
14281 if (ctx->insn_flags & ISA_MIPS_R6) {
14282 decode_opc_special_r6(env, ctx);
14283 } else if (ctx->insn_flags & INSN_R5900) {
14284 decode_opc_special_tx79(env, ctx);
14285 } else {
14286 decode_opc_special_legacy(env, ctx);
14292 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
14294 int rs, rt, rd;
14295 uint32_t op1;
14297 rs = (ctx->opcode >> 21) & 0x1f;
14298 rt = (ctx->opcode >> 16) & 0x1f;
14299 rd = (ctx->opcode >> 11) & 0x1f;
14301 op1 = MASK_SPECIAL2(ctx->opcode);
14302 switch (op1) {
14303 case OPC_MADD: /* Multiply and add/sub */
14304 case OPC_MADDU:
14305 case OPC_MSUB:
14306 case OPC_MSUBU:
14307 check_insn(ctx, ISA_MIPS_R1);
14308 gen_muldiv(ctx, op1, rd & 3, rs, rt);
14309 break;
14310 case OPC_MUL:
14311 gen_arith(ctx, op1, rd, rs, rt);
14312 break;
14313 case OPC_DIV_G_2F:
14314 case OPC_DIVU_G_2F:
14315 case OPC_MULT_G_2F:
14316 case OPC_MULTU_G_2F:
14317 case OPC_MOD_G_2F:
14318 case OPC_MODU_G_2F:
14319 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
14320 gen_loongson_integer(ctx, op1, rd, rs, rt);
14321 break;
14322 case OPC_CLO:
14323 case OPC_CLZ:
14324 check_insn(ctx, ISA_MIPS_R1);
14325 gen_cl(ctx, op1, rd, rs);
14326 break;
14327 case OPC_SDBBP:
14328 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
14329 gen_helper_do_semihosting(cpu_env);
14330 } else {
14332 * XXX: not clear which exception should be raised
14333 * when in debug mode...
14335 check_insn(ctx, ISA_MIPS_R1);
14336 generate_exception_end(ctx, EXCP_DBp);
14338 break;
14339 #if defined(TARGET_MIPS64)
14340 case OPC_DCLO:
14341 case OPC_DCLZ:
14342 check_insn(ctx, ISA_MIPS_R1);
14343 check_mips_64(ctx);
14344 gen_cl(ctx, op1, rd, rs);
14345 break;
14346 case OPC_DMULT_G_2F:
14347 case OPC_DMULTU_G_2F:
14348 case OPC_DDIV_G_2F:
14349 case OPC_DDIVU_G_2F:
14350 case OPC_DMOD_G_2F:
14351 case OPC_DMODU_G_2F:
14352 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
14353 gen_loongson_integer(ctx, op1, rd, rs, rt);
14354 break;
14355 #endif
14356 default: /* Invalid */
14357 MIPS_INVAL("special2_legacy");
14358 gen_reserved_instruction(ctx);
14359 break;
14363 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
14365 int rs, rt, rd, sa;
14366 uint32_t op1, op2;
14367 int16_t imm;
14369 rs = (ctx->opcode >> 21) & 0x1f;
14370 rt = (ctx->opcode >> 16) & 0x1f;
14371 rd = (ctx->opcode >> 11) & 0x1f;
14372 sa = (ctx->opcode >> 6) & 0x1f;
14373 imm = (int16_t)ctx->opcode >> 7;
14375 op1 = MASK_SPECIAL3(ctx->opcode);
14376 switch (op1) {
14377 case R6_OPC_PREF:
14378 if (rt >= 24) {
14379 /* hint codes 24-31 are reserved and signal RI */
14380 gen_reserved_instruction(ctx);
14382 /* Treat as NOP. */
14383 break;
14384 case R6_OPC_CACHE:
14385 check_cp0_enabled(ctx);
14386 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14387 gen_cache_operation(ctx, rt, rs, imm);
14389 break;
14390 case R6_OPC_SC:
14391 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
14392 break;
14393 case R6_OPC_LL:
14394 gen_ld(ctx, op1, rt, rs, imm);
14395 break;
14396 case OPC_BSHFL:
14398 if (rd == 0) {
14399 /* Treat as NOP. */
14400 break;
14402 op2 = MASK_BSHFL(ctx->opcode);
14403 switch (op2) {
14404 case OPC_ALIGN:
14405 case OPC_ALIGN_1:
14406 case OPC_ALIGN_2:
14407 case OPC_ALIGN_3:
14408 gen_align(ctx, 32, rd, rs, rt, sa & 3);
14409 break;
14410 case OPC_BITSWAP:
14411 gen_bitswap(ctx, op2, rd, rt);
14412 break;
14415 break;
14416 #ifndef CONFIG_USER_ONLY
14417 case OPC_GINV:
14418 if (unlikely(ctx->gi <= 1)) {
14419 gen_reserved_instruction(ctx);
14421 check_cp0_enabled(ctx);
14422 switch ((ctx->opcode >> 6) & 3) {
14423 case 0: /* GINVI */
14424 /* Treat as NOP. */
14425 break;
14426 case 2: /* GINVT */
14427 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
14428 break;
14429 default:
14430 gen_reserved_instruction(ctx);
14431 break;
14433 break;
14434 #endif
14435 #if defined(TARGET_MIPS64)
14436 case R6_OPC_SCD:
14437 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
14438 break;
14439 case R6_OPC_LLD:
14440 gen_ld(ctx, op1, rt, rs, imm);
14441 break;
14442 case OPC_DBSHFL:
14443 check_mips_64(ctx);
14445 if (rd == 0) {
14446 /* Treat as NOP. */
14447 break;
14449 op2 = MASK_DBSHFL(ctx->opcode);
14450 switch (op2) {
14451 case OPC_DALIGN:
14452 case OPC_DALIGN_1:
14453 case OPC_DALIGN_2:
14454 case OPC_DALIGN_3:
14455 case OPC_DALIGN_4:
14456 case OPC_DALIGN_5:
14457 case OPC_DALIGN_6:
14458 case OPC_DALIGN_7:
14459 gen_align(ctx, 64, rd, rs, rt, sa & 7);
14460 break;
14461 case OPC_DBITSWAP:
14462 gen_bitswap(ctx, op2, rd, rt);
14463 break;
14467 break;
14468 #endif
14469 default: /* Invalid */
14470 MIPS_INVAL("special3_r6");
14471 gen_reserved_instruction(ctx);
14472 break;
14476 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
14478 int rs, rt, rd;
14479 uint32_t op1, op2;
14481 rs = (ctx->opcode >> 21) & 0x1f;
14482 rt = (ctx->opcode >> 16) & 0x1f;
14483 rd = (ctx->opcode >> 11) & 0x1f;
14485 op1 = MASK_SPECIAL3(ctx->opcode);
14486 switch (op1) {
14487 case OPC_DIV_G_2E:
14488 case OPC_DIVU_G_2E:
14489 case OPC_MOD_G_2E:
14490 case OPC_MODU_G_2E:
14491 case OPC_MULT_G_2E:
14492 case OPC_MULTU_G_2E:
14494 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14495 * the same mask and op1.
14497 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
14498 op2 = MASK_ADDUH_QB(ctx->opcode);
14499 switch (op2) {
14500 case OPC_ADDUH_QB:
14501 case OPC_ADDUH_R_QB:
14502 case OPC_ADDQH_PH:
14503 case OPC_ADDQH_R_PH:
14504 case OPC_ADDQH_W:
14505 case OPC_ADDQH_R_W:
14506 case OPC_SUBUH_QB:
14507 case OPC_SUBUH_R_QB:
14508 case OPC_SUBQH_PH:
14509 case OPC_SUBQH_R_PH:
14510 case OPC_SUBQH_W:
14511 case OPC_SUBQH_R_W:
14512 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14513 break;
14514 case OPC_MUL_PH:
14515 case OPC_MUL_S_PH:
14516 case OPC_MULQ_S_W:
14517 case OPC_MULQ_RS_W:
14518 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14519 break;
14520 default:
14521 MIPS_INVAL("MASK ADDUH.QB");
14522 gen_reserved_instruction(ctx);
14523 break;
14525 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
14526 gen_loongson_integer(ctx, op1, rd, rs, rt);
14527 } else {
14528 gen_reserved_instruction(ctx);
14530 break;
14531 case OPC_LX_DSP:
14532 op2 = MASK_LX(ctx->opcode);
14533 switch (op2) {
14534 #if defined(TARGET_MIPS64)
14535 case OPC_LDX:
14536 #endif
14537 case OPC_LBUX:
14538 case OPC_LHX:
14539 case OPC_LWX:
14540 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
14541 break;
14542 default: /* Invalid */
14543 MIPS_INVAL("MASK LX");
14544 gen_reserved_instruction(ctx);
14545 break;
14547 break;
14548 case OPC_ABSQ_S_PH_DSP:
14549 op2 = MASK_ABSQ_S_PH(ctx->opcode);
14550 switch (op2) {
14551 case OPC_ABSQ_S_QB:
14552 case OPC_ABSQ_S_PH:
14553 case OPC_ABSQ_S_W:
14554 case OPC_PRECEQ_W_PHL:
14555 case OPC_PRECEQ_W_PHR:
14556 case OPC_PRECEQU_PH_QBL:
14557 case OPC_PRECEQU_PH_QBR:
14558 case OPC_PRECEQU_PH_QBLA:
14559 case OPC_PRECEQU_PH_QBRA:
14560 case OPC_PRECEU_PH_QBL:
14561 case OPC_PRECEU_PH_QBR:
14562 case OPC_PRECEU_PH_QBLA:
14563 case OPC_PRECEU_PH_QBRA:
14564 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14565 break;
14566 case OPC_BITREV:
14567 case OPC_REPL_QB:
14568 case OPC_REPLV_QB:
14569 case OPC_REPL_PH:
14570 case OPC_REPLV_PH:
14571 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
14572 break;
14573 default:
14574 MIPS_INVAL("MASK ABSQ_S.PH");
14575 gen_reserved_instruction(ctx);
14576 break;
14578 break;
14579 case OPC_ADDU_QB_DSP:
14580 op2 = MASK_ADDU_QB(ctx->opcode);
14581 switch (op2) {
14582 case OPC_ADDQ_PH:
14583 case OPC_ADDQ_S_PH:
14584 case OPC_ADDQ_S_W:
14585 case OPC_ADDU_QB:
14586 case OPC_ADDU_S_QB:
14587 case OPC_ADDU_PH:
14588 case OPC_ADDU_S_PH:
14589 case OPC_SUBQ_PH:
14590 case OPC_SUBQ_S_PH:
14591 case OPC_SUBQ_S_W:
14592 case OPC_SUBU_QB:
14593 case OPC_SUBU_S_QB:
14594 case OPC_SUBU_PH:
14595 case OPC_SUBU_S_PH:
14596 case OPC_ADDSC:
14597 case OPC_ADDWC:
14598 case OPC_MODSUB:
14599 case OPC_RADDU_W_QB:
14600 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14601 break;
14602 case OPC_MULEU_S_PH_QBL:
14603 case OPC_MULEU_S_PH_QBR:
14604 case OPC_MULQ_RS_PH:
14605 case OPC_MULEQ_S_W_PHL:
14606 case OPC_MULEQ_S_W_PHR:
14607 case OPC_MULQ_S_PH:
14608 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14609 break;
14610 default: /* Invalid */
14611 MIPS_INVAL("MASK ADDU.QB");
14612 gen_reserved_instruction(ctx);
14613 break;
14616 break;
14617 case OPC_CMPU_EQ_QB_DSP:
14618 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
14619 switch (op2) {
14620 case OPC_PRECR_SRA_PH_W:
14621 case OPC_PRECR_SRA_R_PH_W:
14622 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14623 break;
14624 case OPC_PRECR_QB_PH:
14625 case OPC_PRECRQ_QB_PH:
14626 case OPC_PRECRQ_PH_W:
14627 case OPC_PRECRQ_RS_PH_W:
14628 case OPC_PRECRQU_S_QB_PH:
14629 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14630 break;
14631 case OPC_CMPU_EQ_QB:
14632 case OPC_CMPU_LT_QB:
14633 case OPC_CMPU_LE_QB:
14634 case OPC_CMP_EQ_PH:
14635 case OPC_CMP_LT_PH:
14636 case OPC_CMP_LE_PH:
14637 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
14638 break;
14639 case OPC_CMPGU_EQ_QB:
14640 case OPC_CMPGU_LT_QB:
14641 case OPC_CMPGU_LE_QB:
14642 case OPC_CMPGDU_EQ_QB:
14643 case OPC_CMPGDU_LT_QB:
14644 case OPC_CMPGDU_LE_QB:
14645 case OPC_PICK_QB:
14646 case OPC_PICK_PH:
14647 case OPC_PACKRL_PH:
14648 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
14649 break;
14650 default: /* Invalid */
14651 MIPS_INVAL("MASK CMPU.EQ.QB");
14652 gen_reserved_instruction(ctx);
14653 break;
14655 break;
14656 case OPC_SHLL_QB_DSP:
14657 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14658 break;
14659 case OPC_DPA_W_PH_DSP:
14660 op2 = MASK_DPA_W_PH(ctx->opcode);
14661 switch (op2) {
14662 case OPC_DPAU_H_QBL:
14663 case OPC_DPAU_H_QBR:
14664 case OPC_DPSU_H_QBL:
14665 case OPC_DPSU_H_QBR:
14666 case OPC_DPA_W_PH:
14667 case OPC_DPAX_W_PH:
14668 case OPC_DPAQ_S_W_PH:
14669 case OPC_DPAQX_S_W_PH:
14670 case OPC_DPAQX_SA_W_PH:
14671 case OPC_DPS_W_PH:
14672 case OPC_DPSX_W_PH:
14673 case OPC_DPSQ_S_W_PH:
14674 case OPC_DPSQX_S_W_PH:
14675 case OPC_DPSQX_SA_W_PH:
14676 case OPC_MULSAQ_S_W_PH:
14677 case OPC_DPAQ_SA_L_W:
14678 case OPC_DPSQ_SA_L_W:
14679 case OPC_MAQ_S_W_PHL:
14680 case OPC_MAQ_S_W_PHR:
14681 case OPC_MAQ_SA_W_PHL:
14682 case OPC_MAQ_SA_W_PHR:
14683 case OPC_MULSA_W_PH:
14684 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14685 break;
14686 default: /* Invalid */
14687 MIPS_INVAL("MASK DPAW.PH");
14688 gen_reserved_instruction(ctx);
14689 break;
14691 break;
14692 case OPC_INSV_DSP:
14693 op2 = MASK_INSV(ctx->opcode);
14694 switch (op2) {
14695 case OPC_INSV:
14696 check_dsp(ctx);
14698 TCGv t0, t1;
14700 if (rt == 0) {
14701 break;
14704 t0 = tcg_temp_new();
14705 t1 = tcg_temp_new();
14707 gen_load_gpr(t0, rt);
14708 gen_load_gpr(t1, rs);
14710 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
14712 tcg_temp_free(t0);
14713 tcg_temp_free(t1);
14714 break;
14716 default: /* Invalid */
14717 MIPS_INVAL("MASK INSV");
14718 gen_reserved_instruction(ctx);
14719 break;
14721 break;
14722 case OPC_APPEND_DSP:
14723 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
14724 break;
14725 case OPC_EXTR_W_DSP:
14726 op2 = MASK_EXTR_W(ctx->opcode);
14727 switch (op2) {
14728 case OPC_EXTR_W:
14729 case OPC_EXTR_R_W:
14730 case OPC_EXTR_RS_W:
14731 case OPC_EXTR_S_H:
14732 case OPC_EXTRV_S_H:
14733 case OPC_EXTRV_W:
14734 case OPC_EXTRV_R_W:
14735 case OPC_EXTRV_RS_W:
14736 case OPC_EXTP:
14737 case OPC_EXTPV:
14738 case OPC_EXTPDP:
14739 case OPC_EXTPDPV:
14740 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
14741 break;
14742 case OPC_RDDSP:
14743 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
14744 break;
14745 case OPC_SHILO:
14746 case OPC_SHILOV:
14747 case OPC_MTHLIP:
14748 case OPC_WRDSP:
14749 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
14750 break;
14751 default: /* Invalid */
14752 MIPS_INVAL("MASK EXTR.W");
14753 gen_reserved_instruction(ctx);
14754 break;
14756 break;
14757 #if defined(TARGET_MIPS64)
14758 case OPC_DDIV_G_2E:
14759 case OPC_DDIVU_G_2E:
14760 case OPC_DMULT_G_2E:
14761 case OPC_DMULTU_G_2E:
14762 case OPC_DMOD_G_2E:
14763 case OPC_DMODU_G_2E:
14764 check_insn(ctx, INSN_LOONGSON2E);
14765 gen_loongson_integer(ctx, op1, rd, rs, rt);
14766 break;
14767 case OPC_ABSQ_S_QH_DSP:
14768 op2 = MASK_ABSQ_S_QH(ctx->opcode);
14769 switch (op2) {
14770 case OPC_PRECEQ_L_PWL:
14771 case OPC_PRECEQ_L_PWR:
14772 case OPC_PRECEQ_PW_QHL:
14773 case OPC_PRECEQ_PW_QHR:
14774 case OPC_PRECEQ_PW_QHLA:
14775 case OPC_PRECEQ_PW_QHRA:
14776 case OPC_PRECEQU_QH_OBL:
14777 case OPC_PRECEQU_QH_OBR:
14778 case OPC_PRECEQU_QH_OBLA:
14779 case OPC_PRECEQU_QH_OBRA:
14780 case OPC_PRECEU_QH_OBL:
14781 case OPC_PRECEU_QH_OBR:
14782 case OPC_PRECEU_QH_OBLA:
14783 case OPC_PRECEU_QH_OBRA:
14784 case OPC_ABSQ_S_OB:
14785 case OPC_ABSQ_S_PW:
14786 case OPC_ABSQ_S_QH:
14787 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14788 break;
14789 case OPC_REPL_OB:
14790 case OPC_REPL_PW:
14791 case OPC_REPL_QH:
14792 case OPC_REPLV_OB:
14793 case OPC_REPLV_PW:
14794 case OPC_REPLV_QH:
14795 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
14796 break;
14797 default: /* Invalid */
14798 MIPS_INVAL("MASK ABSQ_S.QH");
14799 gen_reserved_instruction(ctx);
14800 break;
14802 break;
14803 case OPC_ADDU_OB_DSP:
14804 op2 = MASK_ADDU_OB(ctx->opcode);
14805 switch (op2) {
14806 case OPC_RADDU_L_OB:
14807 case OPC_SUBQ_PW:
14808 case OPC_SUBQ_S_PW:
14809 case OPC_SUBQ_QH:
14810 case OPC_SUBQ_S_QH:
14811 case OPC_SUBU_OB:
14812 case OPC_SUBU_S_OB:
14813 case OPC_SUBU_QH:
14814 case OPC_SUBU_S_QH:
14815 case OPC_SUBUH_OB:
14816 case OPC_SUBUH_R_OB:
14817 case OPC_ADDQ_PW:
14818 case OPC_ADDQ_S_PW:
14819 case OPC_ADDQ_QH:
14820 case OPC_ADDQ_S_QH:
14821 case OPC_ADDU_OB:
14822 case OPC_ADDU_S_OB:
14823 case OPC_ADDU_QH:
14824 case OPC_ADDU_S_QH:
14825 case OPC_ADDUH_OB:
14826 case OPC_ADDUH_R_OB:
14827 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14828 break;
14829 case OPC_MULEQ_S_PW_QHL:
14830 case OPC_MULEQ_S_PW_QHR:
14831 case OPC_MULEU_S_QH_OBL:
14832 case OPC_MULEU_S_QH_OBR:
14833 case OPC_MULQ_RS_QH:
14834 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14835 break;
14836 default: /* Invalid */
14837 MIPS_INVAL("MASK ADDU.OB");
14838 gen_reserved_instruction(ctx);
14839 break;
14841 break;
14842 case OPC_CMPU_EQ_OB_DSP:
14843 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
14844 switch (op2) {
14845 case OPC_PRECR_SRA_QH_PW:
14846 case OPC_PRECR_SRA_R_QH_PW:
14847 /* Return value is rt. */
14848 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14849 break;
14850 case OPC_PRECR_OB_QH:
14851 case OPC_PRECRQ_OB_QH:
14852 case OPC_PRECRQ_PW_L:
14853 case OPC_PRECRQ_QH_PW:
14854 case OPC_PRECRQ_RS_QH_PW:
14855 case OPC_PRECRQU_S_OB_QH:
14856 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14857 break;
14858 case OPC_CMPU_EQ_OB:
14859 case OPC_CMPU_LT_OB:
14860 case OPC_CMPU_LE_OB:
14861 case OPC_CMP_EQ_QH:
14862 case OPC_CMP_LT_QH:
14863 case OPC_CMP_LE_QH:
14864 case OPC_CMP_EQ_PW:
14865 case OPC_CMP_LT_PW:
14866 case OPC_CMP_LE_PW:
14867 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
14868 break;
14869 case OPC_CMPGDU_EQ_OB:
14870 case OPC_CMPGDU_LT_OB:
14871 case OPC_CMPGDU_LE_OB:
14872 case OPC_CMPGU_EQ_OB:
14873 case OPC_CMPGU_LT_OB:
14874 case OPC_CMPGU_LE_OB:
14875 case OPC_PACKRL_PW:
14876 case OPC_PICK_OB:
14877 case OPC_PICK_PW:
14878 case OPC_PICK_QH:
14879 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
14880 break;
14881 default: /* Invalid */
14882 MIPS_INVAL("MASK CMPU_EQ.OB");
14883 gen_reserved_instruction(ctx);
14884 break;
14886 break;
14887 case OPC_DAPPEND_DSP:
14888 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
14889 break;
14890 case OPC_DEXTR_W_DSP:
14891 op2 = MASK_DEXTR_W(ctx->opcode);
14892 switch (op2) {
14893 case OPC_DEXTP:
14894 case OPC_DEXTPDP:
14895 case OPC_DEXTPDPV:
14896 case OPC_DEXTPV:
14897 case OPC_DEXTR_L:
14898 case OPC_DEXTR_R_L:
14899 case OPC_DEXTR_RS_L:
14900 case OPC_DEXTR_W:
14901 case OPC_DEXTR_R_W:
14902 case OPC_DEXTR_RS_W:
14903 case OPC_DEXTR_S_H:
14904 case OPC_DEXTRV_L:
14905 case OPC_DEXTRV_R_L:
14906 case OPC_DEXTRV_RS_L:
14907 case OPC_DEXTRV_S_H:
14908 case OPC_DEXTRV_W:
14909 case OPC_DEXTRV_R_W:
14910 case OPC_DEXTRV_RS_W:
14911 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
14912 break;
14913 case OPC_DMTHLIP:
14914 case OPC_DSHILO:
14915 case OPC_DSHILOV:
14916 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
14917 break;
14918 default: /* Invalid */
14919 MIPS_INVAL("MASK EXTR.W");
14920 gen_reserved_instruction(ctx);
14921 break;
14923 break;
14924 case OPC_DPAQ_W_QH_DSP:
14925 op2 = MASK_DPAQ_W_QH(ctx->opcode);
14926 switch (op2) {
14927 case OPC_DPAU_H_OBL:
14928 case OPC_DPAU_H_OBR:
14929 case OPC_DPSU_H_OBL:
14930 case OPC_DPSU_H_OBR:
14931 case OPC_DPA_W_QH:
14932 case OPC_DPAQ_S_W_QH:
14933 case OPC_DPS_W_QH:
14934 case OPC_DPSQ_S_W_QH:
14935 case OPC_MULSAQ_S_W_QH:
14936 case OPC_DPAQ_SA_L_PW:
14937 case OPC_DPSQ_SA_L_PW:
14938 case OPC_MULSAQ_S_L_PW:
14939 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14940 break;
14941 case OPC_MAQ_S_W_QHLL:
14942 case OPC_MAQ_S_W_QHLR:
14943 case OPC_MAQ_S_W_QHRL:
14944 case OPC_MAQ_S_W_QHRR:
14945 case OPC_MAQ_SA_W_QHLL:
14946 case OPC_MAQ_SA_W_QHLR:
14947 case OPC_MAQ_SA_W_QHRL:
14948 case OPC_MAQ_SA_W_QHRR:
14949 case OPC_MAQ_S_L_PWL:
14950 case OPC_MAQ_S_L_PWR:
14951 case OPC_DMADD:
14952 case OPC_DMADDU:
14953 case OPC_DMSUB:
14954 case OPC_DMSUBU:
14955 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14956 break;
14957 default: /* Invalid */
14958 MIPS_INVAL("MASK DPAQ.W.QH");
14959 gen_reserved_instruction(ctx);
14960 break;
14962 break;
14963 case OPC_DINSV_DSP:
14964 op2 = MASK_INSV(ctx->opcode);
14965 switch (op2) {
14966 case OPC_DINSV:
14968 TCGv t0, t1;
14970 check_dsp(ctx);
14972 if (rt == 0) {
14973 break;
14976 t0 = tcg_temp_new();
14977 t1 = tcg_temp_new();
14979 gen_load_gpr(t0, rt);
14980 gen_load_gpr(t1, rs);
14982 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
14984 tcg_temp_free(t0);
14985 tcg_temp_free(t1);
14986 break;
14988 default: /* Invalid */
14989 MIPS_INVAL("MASK DINSV");
14990 gen_reserved_instruction(ctx);
14991 break;
14993 break;
14994 case OPC_SHLL_OB_DSP:
14995 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14996 break;
14997 #endif
14998 default: /* Invalid */
14999 MIPS_INVAL("special3_legacy");
15000 gen_reserved_instruction(ctx);
15001 break;
15006 #if defined(TARGET_MIPS64)
15008 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
15010 uint32_t opc = MASK_MMI(ctx->opcode);
15011 int rs = extract32(ctx->opcode, 21, 5);
15012 int rt = extract32(ctx->opcode, 16, 5);
15013 int rd = extract32(ctx->opcode, 11, 5);
15015 switch (opc) {
15016 case MMI_OPC_MULT1:
15017 case MMI_OPC_MULTU1:
15018 case MMI_OPC_MADD:
15019 case MMI_OPC_MADDU:
15020 case MMI_OPC_MADD1:
15021 case MMI_OPC_MADDU1:
15022 gen_mul_txx9(ctx, opc, rd, rs, rt);
15023 break;
15024 case MMI_OPC_DIV1:
15025 case MMI_OPC_DIVU1:
15026 gen_div1_tx79(ctx, opc, rs, rt);
15027 break;
15028 default:
15029 MIPS_INVAL("TX79 MMI class");
15030 gen_reserved_instruction(ctx);
15031 break;
15035 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
15037 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
15041 * The TX79-specific instruction Store Quadword
15043 * +--------+-------+-------+------------------------+
15044 * | 011111 | base | rt | offset | SQ
15045 * +--------+-------+-------+------------------------+
15046 * 6 5 5 16
15048 * has the same opcode as the Read Hardware Register instruction
15050 * +--------+-------+-------+-------+-------+--------+
15051 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
15052 * +--------+-------+-------+-------+-------+--------+
15053 * 6 5 5 5 5 6
15055 * that is required, trapped and emulated by the Linux kernel. However, all
15056 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
15057 * offset is odd. Therefore all valid SQ instructions can execute normally.
15058 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
15059 * between SQ and RDHWR, as the Linux kernel does.
15061 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
15063 int base = extract32(ctx->opcode, 21, 5);
15064 int rt = extract32(ctx->opcode, 16, 5);
15065 int offset = extract32(ctx->opcode, 0, 16);
15067 #ifdef CONFIG_USER_ONLY
15068 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
15069 uint32_t op2 = extract32(ctx->opcode, 6, 5);
15071 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
15072 int rd = extract32(ctx->opcode, 11, 5);
15074 gen_rdhwr(ctx, rt, rd, 0);
15075 return;
15077 #endif
15079 gen_mmi_sq(ctx, base, rt, offset);
15082 #endif
15084 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
15086 int rs, rt, rd, sa;
15087 uint32_t op1, op2;
15088 int16_t imm;
15090 rs = (ctx->opcode >> 21) & 0x1f;
15091 rt = (ctx->opcode >> 16) & 0x1f;
15092 rd = (ctx->opcode >> 11) & 0x1f;
15093 sa = (ctx->opcode >> 6) & 0x1f;
15094 imm = sextract32(ctx->opcode, 7, 9);
15096 op1 = MASK_SPECIAL3(ctx->opcode);
15099 * EVA loads and stores overlap Loongson 2E instructions decoded by
15100 * decode_opc_special3_legacy(), so be careful to allow their decoding when
15101 * EVA is absent.
15103 if (ctx->eva) {
15104 switch (op1) {
15105 case OPC_LWLE:
15106 case OPC_LWRE:
15107 case OPC_LBUE:
15108 case OPC_LHUE:
15109 case OPC_LBE:
15110 case OPC_LHE:
15111 case OPC_LLE:
15112 case OPC_LWE:
15113 check_cp0_enabled(ctx);
15114 gen_ld(ctx, op1, rt, rs, imm);
15115 return;
15116 case OPC_SWLE:
15117 case OPC_SWRE:
15118 case OPC_SBE:
15119 case OPC_SHE:
15120 case OPC_SWE:
15121 check_cp0_enabled(ctx);
15122 gen_st(ctx, op1, rt, rs, imm);
15123 return;
15124 case OPC_SCE:
15125 check_cp0_enabled(ctx);
15126 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
15127 return;
15128 case OPC_CACHEE:
15129 check_eva(ctx);
15130 check_cp0_enabled(ctx);
15131 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15132 gen_cache_operation(ctx, rt, rs, imm);
15134 return;
15135 case OPC_PREFE:
15136 check_cp0_enabled(ctx);
15137 /* Treat as NOP. */
15138 return;
15142 switch (op1) {
15143 case OPC_EXT:
15144 case OPC_INS:
15145 check_insn(ctx, ISA_MIPS_R2);
15146 gen_bitops(ctx, op1, rt, rs, sa, rd);
15147 break;
15148 case OPC_BSHFL:
15149 op2 = MASK_BSHFL(ctx->opcode);
15150 switch (op2) {
15151 case OPC_ALIGN:
15152 case OPC_ALIGN_1:
15153 case OPC_ALIGN_2:
15154 case OPC_ALIGN_3:
15155 case OPC_BITSWAP:
15156 check_insn(ctx, ISA_MIPS_R6);
15157 decode_opc_special3_r6(env, ctx);
15158 break;
15159 default:
15160 check_insn(ctx, ISA_MIPS_R2);
15161 gen_bshfl(ctx, op2, rt, rd);
15162 break;
15164 break;
15165 #if defined(TARGET_MIPS64)
15166 case OPC_DEXTM:
15167 case OPC_DEXTU:
15168 case OPC_DEXT:
15169 case OPC_DINSM:
15170 case OPC_DINSU:
15171 case OPC_DINS:
15172 check_insn(ctx, ISA_MIPS_R2);
15173 check_mips_64(ctx);
15174 gen_bitops(ctx, op1, rt, rs, sa, rd);
15175 break;
15176 case OPC_DBSHFL:
15177 op2 = MASK_DBSHFL(ctx->opcode);
15178 switch (op2) {
15179 case OPC_DALIGN:
15180 case OPC_DALIGN_1:
15181 case OPC_DALIGN_2:
15182 case OPC_DALIGN_3:
15183 case OPC_DALIGN_4:
15184 case OPC_DALIGN_5:
15185 case OPC_DALIGN_6:
15186 case OPC_DALIGN_7:
15187 case OPC_DBITSWAP:
15188 check_insn(ctx, ISA_MIPS_R6);
15189 decode_opc_special3_r6(env, ctx);
15190 break;
15191 default:
15192 check_insn(ctx, ISA_MIPS_R2);
15193 check_mips_64(ctx);
15194 op2 = MASK_DBSHFL(ctx->opcode);
15195 gen_bshfl(ctx, op2, rt, rd);
15196 break;
15198 break;
15199 #endif
15200 case OPC_RDHWR:
15201 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
15202 break;
15203 case OPC_FORK:
15204 check_mt(ctx);
15206 TCGv t0 = tcg_temp_new();
15207 TCGv t1 = tcg_temp_new();
15209 gen_load_gpr(t0, rt);
15210 gen_load_gpr(t1, rs);
15211 gen_helper_fork(t0, t1);
15212 tcg_temp_free(t0);
15213 tcg_temp_free(t1);
15215 break;
15216 case OPC_YIELD:
15217 check_mt(ctx);
15219 TCGv t0 = tcg_temp_new();
15221 gen_load_gpr(t0, rs);
15222 gen_helper_yield(t0, cpu_env, t0);
15223 gen_store_gpr(t0, rd);
15224 tcg_temp_free(t0);
15226 break;
15227 default:
15228 if (ctx->insn_flags & ISA_MIPS_R6) {
15229 decode_opc_special3_r6(env, ctx);
15230 } else {
15231 decode_opc_special3_legacy(env, ctx);
15236 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
15238 int32_t offset;
15239 int rs, rt, rd, sa;
15240 uint32_t op, op1;
15241 int16_t imm;
15243 op = MASK_OP_MAJOR(ctx->opcode);
15244 rs = (ctx->opcode >> 21) & 0x1f;
15245 rt = (ctx->opcode >> 16) & 0x1f;
15246 rd = (ctx->opcode >> 11) & 0x1f;
15247 sa = (ctx->opcode >> 6) & 0x1f;
15248 imm = (int16_t)ctx->opcode;
15249 switch (op) {
15250 case OPC_SPECIAL:
15251 decode_opc_special(env, ctx);
15252 break;
15253 case OPC_SPECIAL2:
15254 #if defined(TARGET_MIPS64)
15255 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
15256 decode_mmi(env, ctx);
15257 break;
15259 #endif
15260 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
15261 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
15262 gen_arith(ctx, OPC_MUL, rd, rs, rt);
15263 } else {
15264 decode_ase_mxu(ctx, ctx->opcode);
15266 break;
15268 decode_opc_special2_legacy(env, ctx);
15269 break;
15270 case OPC_SPECIAL3:
15271 #if defined(TARGET_MIPS64)
15272 if (ctx->insn_flags & INSN_R5900) {
15273 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
15274 } else {
15275 decode_opc_special3(env, ctx);
15277 #else
15278 decode_opc_special3(env, ctx);
15279 #endif
15280 break;
15281 case OPC_REGIMM:
15282 op1 = MASK_REGIMM(ctx->opcode);
15283 switch (op1) {
15284 case OPC_BLTZL: /* REGIMM branches */
15285 case OPC_BGEZL:
15286 case OPC_BLTZALL:
15287 case OPC_BGEZALL:
15288 check_insn(ctx, ISA_MIPS2);
15289 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15290 /* Fallthrough */
15291 case OPC_BLTZ:
15292 case OPC_BGEZ:
15293 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
15294 break;
15295 case OPC_BLTZAL:
15296 case OPC_BGEZAL:
15297 if (ctx->insn_flags & ISA_MIPS_R6) {
15298 if (rs == 0) {
15299 /* OPC_NAL, OPC_BAL */
15300 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
15301 } else {
15302 gen_reserved_instruction(ctx);
15304 } else {
15305 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
15307 break;
15308 case OPC_TGEI: /* REGIMM traps */
15309 case OPC_TGEIU:
15310 case OPC_TLTI:
15311 case OPC_TLTIU:
15312 case OPC_TEQI:
15314 case OPC_TNEI:
15315 check_insn(ctx, ISA_MIPS2);
15316 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15317 gen_trap(ctx, op1, rs, -1, imm);
15318 break;
15319 case OPC_SIGRIE:
15320 check_insn(ctx, ISA_MIPS_R6);
15321 gen_reserved_instruction(ctx);
15322 break;
15323 case OPC_SYNCI:
15324 check_insn(ctx, ISA_MIPS_R2);
15326 * Break the TB to be able to sync copied instructions
15327 * immediately.
15329 ctx->base.is_jmp = DISAS_STOP;
15330 break;
15331 case OPC_BPOSGE32: /* MIPS DSP branch */
15332 #if defined(TARGET_MIPS64)
15333 case OPC_BPOSGE64:
15334 #endif
15335 check_dsp(ctx);
15336 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
15337 break;
15338 #if defined(TARGET_MIPS64)
15339 case OPC_DAHI:
15340 check_insn(ctx, ISA_MIPS_R6);
15341 check_mips_64(ctx);
15342 if (rs != 0) {
15343 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
15345 break;
15346 case OPC_DATI:
15347 check_insn(ctx, ISA_MIPS_R6);
15348 check_mips_64(ctx);
15349 if (rs != 0) {
15350 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
15352 break;
15353 #endif
15354 default: /* Invalid */
15355 MIPS_INVAL("regimm");
15356 gen_reserved_instruction(ctx);
15357 break;
15359 break;
15360 case OPC_CP0:
15361 check_cp0_enabled(ctx);
15362 op1 = MASK_CP0(ctx->opcode);
15363 switch (op1) {
15364 case OPC_MFC0:
15365 case OPC_MTC0:
15366 case OPC_MFTR:
15367 case OPC_MTTR:
15368 case OPC_MFHC0:
15369 case OPC_MTHC0:
15370 #if defined(TARGET_MIPS64)
15371 case OPC_DMFC0:
15372 case OPC_DMTC0:
15373 #endif
15374 #ifndef CONFIG_USER_ONLY
15375 gen_cp0(env, ctx, op1, rt, rd);
15376 #endif /* !CONFIG_USER_ONLY */
15377 break;
15378 case OPC_C0:
15379 case OPC_C0_1:
15380 case OPC_C0_2:
15381 case OPC_C0_3:
15382 case OPC_C0_4:
15383 case OPC_C0_5:
15384 case OPC_C0_6:
15385 case OPC_C0_7:
15386 case OPC_C0_8:
15387 case OPC_C0_9:
15388 case OPC_C0_A:
15389 case OPC_C0_B:
15390 case OPC_C0_C:
15391 case OPC_C0_D:
15392 case OPC_C0_E:
15393 case OPC_C0_F:
15394 #ifndef CONFIG_USER_ONLY
15395 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
15396 #endif /* !CONFIG_USER_ONLY */
15397 break;
15398 case OPC_MFMC0:
15399 #ifndef CONFIG_USER_ONLY
15401 uint32_t op2;
15402 TCGv t0 = tcg_temp_new();
15404 op2 = MASK_MFMC0(ctx->opcode);
15405 switch (op2) {
15406 case OPC_DMT:
15407 check_cp0_mt(ctx);
15408 gen_helper_dmt(t0);
15409 gen_store_gpr(t0, rt);
15410 break;
15411 case OPC_EMT:
15412 check_cp0_mt(ctx);
15413 gen_helper_emt(t0);
15414 gen_store_gpr(t0, rt);
15415 break;
15416 case OPC_DVPE:
15417 check_cp0_mt(ctx);
15418 gen_helper_dvpe(t0, cpu_env);
15419 gen_store_gpr(t0, rt);
15420 break;
15421 case OPC_EVPE:
15422 check_cp0_mt(ctx);
15423 gen_helper_evpe(t0, cpu_env);
15424 gen_store_gpr(t0, rt);
15425 break;
15426 case OPC_DVP:
15427 check_insn(ctx, ISA_MIPS_R6);
15428 if (ctx->vp) {
15429 gen_helper_dvp(t0, cpu_env);
15430 gen_store_gpr(t0, rt);
15432 break;
15433 case OPC_EVP:
15434 check_insn(ctx, ISA_MIPS_R6);
15435 if (ctx->vp) {
15436 gen_helper_evp(t0, cpu_env);
15437 gen_store_gpr(t0, rt);
15439 break;
15440 case OPC_DI:
15441 check_insn(ctx, ISA_MIPS_R2);
15442 save_cpu_state(ctx, 1);
15443 gen_helper_di(t0, cpu_env);
15444 gen_store_gpr(t0, rt);
15446 * Stop translation as we may have switched
15447 * the execution mode.
15449 ctx->base.is_jmp = DISAS_STOP;
15450 break;
15451 case OPC_EI:
15452 check_insn(ctx, ISA_MIPS_R2);
15453 save_cpu_state(ctx, 1);
15454 gen_helper_ei(t0, cpu_env);
15455 gen_store_gpr(t0, rt);
15457 * DISAS_STOP isn't sufficient, we need to ensure we break
15458 * out of translated code to check for pending interrupts.
15460 gen_save_pc(ctx->base.pc_next + 4);
15461 ctx->base.is_jmp = DISAS_EXIT;
15462 break;
15463 default: /* Invalid */
15464 MIPS_INVAL("mfmc0");
15465 gen_reserved_instruction(ctx);
15466 break;
15468 tcg_temp_free(t0);
15470 #endif /* !CONFIG_USER_ONLY */
15471 break;
15472 case OPC_RDPGPR:
15473 check_insn(ctx, ISA_MIPS_R2);
15474 gen_load_srsgpr(rt, rd);
15475 break;
15476 case OPC_WRPGPR:
15477 check_insn(ctx, ISA_MIPS_R2);
15478 gen_store_srsgpr(rt, rd);
15479 break;
15480 default:
15481 MIPS_INVAL("cp0");
15482 gen_reserved_instruction(ctx);
15483 break;
15485 break;
15486 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
15487 if (ctx->insn_flags & ISA_MIPS_R6) {
15488 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
15489 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15490 } else {
15491 /* OPC_ADDI */
15492 /* Arithmetic with immediate opcode */
15493 gen_arith_imm(ctx, op, rt, rs, imm);
15495 break;
15496 case OPC_ADDIU:
15497 gen_arith_imm(ctx, op, rt, rs, imm);
15498 break;
15499 case OPC_SLTI: /* Set on less than with immediate opcode */
15500 case OPC_SLTIU:
15501 gen_slt_imm(ctx, op, rt, rs, imm);
15502 break;
15503 case OPC_ANDI: /* Arithmetic with immediate opcode */
15504 case OPC_LUI: /* OPC_AUI */
15505 case OPC_ORI:
15506 case OPC_XORI:
15507 gen_logic_imm(ctx, op, rt, rs, imm);
15508 break;
15509 case OPC_J: /* Jump */
15510 case OPC_JAL:
15511 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15512 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
15513 break;
15514 /* Branch */
15515 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
15516 if (ctx->insn_flags & ISA_MIPS_R6) {
15517 if (rt == 0) {
15518 gen_reserved_instruction(ctx);
15519 break;
15521 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
15522 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15523 } else {
15524 /* OPC_BLEZL */
15525 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15527 break;
15528 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
15529 if (ctx->insn_flags & ISA_MIPS_R6) {
15530 if (rt == 0) {
15531 gen_reserved_instruction(ctx);
15532 break;
15534 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
15535 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15536 } else {
15537 /* OPC_BGTZL */
15538 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15540 break;
15541 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
15542 if (rt == 0) {
15543 /* OPC_BLEZ */
15544 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15545 } else {
15546 check_insn(ctx, ISA_MIPS_R6);
15547 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
15548 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15550 break;
15551 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
15552 if (rt == 0) {
15553 /* OPC_BGTZ */
15554 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15555 } else {
15556 check_insn(ctx, ISA_MIPS_R6);
15557 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
15558 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15560 break;
15561 case OPC_BEQL:
15562 case OPC_BNEL:
15563 check_insn(ctx, ISA_MIPS2);
15564 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15565 /* Fallthrough */
15566 case OPC_BEQ:
15567 case OPC_BNE:
15568 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15569 break;
15570 case OPC_LL: /* Load and stores */
15571 check_insn(ctx, ISA_MIPS2);
15572 if (ctx->insn_flags & INSN_R5900) {
15573 check_insn_opc_user_only(ctx, INSN_R5900);
15575 /* Fallthrough */
15576 case OPC_LWL:
15577 case OPC_LWR:
15578 case OPC_LB:
15579 case OPC_LH:
15580 case OPC_LW:
15581 case OPC_LWPC:
15582 case OPC_LBU:
15583 case OPC_LHU:
15584 gen_ld(ctx, op, rt, rs, imm);
15585 break;
15586 case OPC_SWL:
15587 case OPC_SWR:
15588 case OPC_SB:
15589 case OPC_SH:
15590 case OPC_SW:
15591 gen_st(ctx, op, rt, rs, imm);
15592 break;
15593 case OPC_SC:
15594 check_insn(ctx, ISA_MIPS2);
15595 if (ctx->insn_flags & INSN_R5900) {
15596 check_insn_opc_user_only(ctx, INSN_R5900);
15598 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
15599 break;
15600 case OPC_CACHE:
15601 check_cp0_enabled(ctx);
15602 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
15603 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15604 gen_cache_operation(ctx, rt, rs, imm);
15606 /* Treat as NOP. */
15607 break;
15608 case OPC_PREF:
15609 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 | INSN_R5900);
15610 /* Treat as NOP. */
15611 break;
15613 /* Floating point (COP1). */
15614 case OPC_LWC1:
15615 case OPC_LDC1:
15616 case OPC_SWC1:
15617 case OPC_SDC1:
15618 gen_cop1_ldst(ctx, op, rt, rs, imm);
15619 break;
15621 case OPC_CP1:
15622 op1 = MASK_CP1(ctx->opcode);
15624 switch (op1) {
15625 case OPC_MFHC1:
15626 case OPC_MTHC1:
15627 check_cp1_enabled(ctx);
15628 check_insn(ctx, ISA_MIPS_R2);
15629 /* fall through */
15630 case OPC_MFC1:
15631 case OPC_CFC1:
15632 case OPC_MTC1:
15633 case OPC_CTC1:
15634 check_cp1_enabled(ctx);
15635 gen_cp1(ctx, op1, rt, rd);
15636 break;
15637 #if defined(TARGET_MIPS64)
15638 case OPC_DMFC1:
15639 case OPC_DMTC1:
15640 check_cp1_enabled(ctx);
15641 check_insn(ctx, ISA_MIPS3);
15642 check_mips_64(ctx);
15643 gen_cp1(ctx, op1, rt, rd);
15644 break;
15645 #endif
15646 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
15647 check_cp1_enabled(ctx);
15648 if (ctx->insn_flags & ISA_MIPS_R6) {
15649 /* OPC_BC1EQZ */
15650 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
15651 rt, imm << 2, 4);
15652 } else {
15653 /* OPC_BC1ANY2 */
15654 check_cop1x(ctx);
15655 check_insn(ctx, ASE_MIPS3D);
15656 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
15657 (rt >> 2) & 0x7, imm << 2);
15659 break;
15660 case OPC_BC1NEZ:
15661 check_cp1_enabled(ctx);
15662 check_insn(ctx, ISA_MIPS_R6);
15663 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
15664 rt, imm << 2, 4);
15665 break;
15666 case OPC_BC1ANY4:
15667 check_cp1_enabled(ctx);
15668 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15669 check_cop1x(ctx);
15670 check_insn(ctx, ASE_MIPS3D);
15671 /* fall through */
15672 case OPC_BC1:
15673 check_cp1_enabled(ctx);
15674 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15675 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
15676 (rt >> 2) & 0x7, imm << 2);
15677 break;
15678 case OPC_PS_FMT:
15679 check_ps(ctx);
15680 /* fall through */
15681 case OPC_S_FMT:
15682 case OPC_D_FMT:
15683 check_cp1_enabled(ctx);
15684 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
15685 (imm >> 8) & 0x7);
15686 break;
15687 case OPC_W_FMT:
15688 case OPC_L_FMT:
15690 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
15691 check_cp1_enabled(ctx);
15692 if (ctx->insn_flags & ISA_MIPS_R6) {
15693 switch (r6_op) {
15694 case R6_OPC_CMP_AF_S:
15695 case R6_OPC_CMP_UN_S:
15696 case R6_OPC_CMP_EQ_S:
15697 case R6_OPC_CMP_UEQ_S:
15698 case R6_OPC_CMP_LT_S:
15699 case R6_OPC_CMP_ULT_S:
15700 case R6_OPC_CMP_LE_S:
15701 case R6_OPC_CMP_ULE_S:
15702 case R6_OPC_CMP_SAF_S:
15703 case R6_OPC_CMP_SUN_S:
15704 case R6_OPC_CMP_SEQ_S:
15705 case R6_OPC_CMP_SEUQ_S:
15706 case R6_OPC_CMP_SLT_S:
15707 case R6_OPC_CMP_SULT_S:
15708 case R6_OPC_CMP_SLE_S:
15709 case R6_OPC_CMP_SULE_S:
15710 case R6_OPC_CMP_OR_S:
15711 case R6_OPC_CMP_UNE_S:
15712 case R6_OPC_CMP_NE_S:
15713 case R6_OPC_CMP_SOR_S:
15714 case R6_OPC_CMP_SUNE_S:
15715 case R6_OPC_CMP_SNE_S:
15716 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
15717 break;
15718 case R6_OPC_CMP_AF_D:
15719 case R6_OPC_CMP_UN_D:
15720 case R6_OPC_CMP_EQ_D:
15721 case R6_OPC_CMP_UEQ_D:
15722 case R6_OPC_CMP_LT_D:
15723 case R6_OPC_CMP_ULT_D:
15724 case R6_OPC_CMP_LE_D:
15725 case R6_OPC_CMP_ULE_D:
15726 case R6_OPC_CMP_SAF_D:
15727 case R6_OPC_CMP_SUN_D:
15728 case R6_OPC_CMP_SEQ_D:
15729 case R6_OPC_CMP_SEUQ_D:
15730 case R6_OPC_CMP_SLT_D:
15731 case R6_OPC_CMP_SULT_D:
15732 case R6_OPC_CMP_SLE_D:
15733 case R6_OPC_CMP_SULE_D:
15734 case R6_OPC_CMP_OR_D:
15735 case R6_OPC_CMP_UNE_D:
15736 case R6_OPC_CMP_NE_D:
15737 case R6_OPC_CMP_SOR_D:
15738 case R6_OPC_CMP_SUNE_D:
15739 case R6_OPC_CMP_SNE_D:
15740 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
15741 break;
15742 default:
15743 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
15744 rt, rd, sa, (imm >> 8) & 0x7);
15746 break;
15748 } else {
15749 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
15750 (imm >> 8) & 0x7);
15752 break;
15754 default:
15755 MIPS_INVAL("cp1");
15756 gen_reserved_instruction(ctx);
15757 break;
15759 break;
15761 /* Compact branches [R6] and COP2 [non-R6] */
15762 case OPC_BC: /* OPC_LWC2 */
15763 case OPC_BALC: /* OPC_SWC2 */
15764 if (ctx->insn_flags & ISA_MIPS_R6) {
15765 /* OPC_BC, OPC_BALC */
15766 gen_compute_compact_branch(ctx, op, 0, 0,
15767 sextract32(ctx->opcode << 2, 0, 28));
15768 } else if (ctx->insn_flags & ASE_LEXT) {
15769 gen_loongson_lswc2(ctx, rt, rs, rd);
15770 } else {
15771 /* OPC_LWC2, OPC_SWC2 */
15772 /* COP2: Not implemented. */
15773 generate_exception_err(ctx, EXCP_CpU, 2);
15775 break;
15776 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
15777 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
15778 if (ctx->insn_flags & ISA_MIPS_R6) {
15779 if (rs != 0) {
15780 /* OPC_BEQZC, OPC_BNEZC */
15781 gen_compute_compact_branch(ctx, op, rs, 0,
15782 sextract32(ctx->opcode << 2, 0, 23));
15783 } else {
15784 /* OPC_JIC, OPC_JIALC */
15785 gen_compute_compact_branch(ctx, op, 0, rt, imm);
15787 } else if (ctx->insn_flags & ASE_LEXT) {
15788 gen_loongson_lsdc2(ctx, rt, rs, rd);
15789 } else {
15790 /* OPC_LWC2, OPC_SWC2 */
15791 /* COP2: Not implemented. */
15792 generate_exception_err(ctx, EXCP_CpU, 2);
15794 break;
15795 case OPC_CP2:
15796 check_insn(ctx, ASE_LMMI);
15797 /* Note that these instructions use different fields. */
15798 gen_loongson_multimedia(ctx, sa, rd, rt);
15799 break;
15801 case OPC_CP3:
15802 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15803 check_cp1_enabled(ctx);
15804 op1 = MASK_CP3(ctx->opcode);
15805 switch (op1) {
15806 case OPC_LUXC1:
15807 case OPC_SUXC1:
15808 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
15809 /* Fallthrough */
15810 case OPC_LWXC1:
15811 case OPC_LDXC1:
15812 case OPC_SWXC1:
15813 case OPC_SDXC1:
15814 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
15815 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
15816 break;
15817 case OPC_PREFX:
15818 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
15819 /* Treat as NOP. */
15820 break;
15821 case OPC_ALNV_PS:
15822 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
15823 /* Fallthrough */
15824 case OPC_MADD_S:
15825 case OPC_MADD_D:
15826 case OPC_MADD_PS:
15827 case OPC_MSUB_S:
15828 case OPC_MSUB_D:
15829 case OPC_MSUB_PS:
15830 case OPC_NMADD_S:
15831 case OPC_NMADD_D:
15832 case OPC_NMADD_PS:
15833 case OPC_NMSUB_S:
15834 case OPC_NMSUB_D:
15835 case OPC_NMSUB_PS:
15836 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
15837 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
15838 break;
15839 default:
15840 MIPS_INVAL("cp3");
15841 gen_reserved_instruction(ctx);
15842 break;
15844 } else {
15845 generate_exception_err(ctx, EXCP_CpU, 1);
15847 break;
15849 #if defined(TARGET_MIPS64)
15850 /* MIPS64 opcodes */
15851 case OPC_LLD:
15852 if (ctx->insn_flags & INSN_R5900) {
15853 check_insn_opc_user_only(ctx, INSN_R5900);
15855 /* fall through */
15856 case OPC_LDL:
15857 case OPC_LDR:
15858 case OPC_LWU:
15859 case OPC_LD:
15860 check_insn(ctx, ISA_MIPS3);
15861 check_mips_64(ctx);
15862 gen_ld(ctx, op, rt, rs, imm);
15863 break;
15864 case OPC_SDL:
15865 case OPC_SDR:
15866 case OPC_SD:
15867 check_insn(ctx, ISA_MIPS3);
15868 check_mips_64(ctx);
15869 gen_st(ctx, op, rt, rs, imm);
15870 break;
15871 case OPC_SCD:
15872 check_insn(ctx, ISA_MIPS3);
15873 if (ctx->insn_flags & INSN_R5900) {
15874 check_insn_opc_user_only(ctx, INSN_R5900);
15876 check_mips_64(ctx);
15877 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
15878 break;
15879 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
15880 if (ctx->insn_flags & ISA_MIPS_R6) {
15881 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
15882 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15883 } else {
15884 /* OPC_DADDI */
15885 check_insn(ctx, ISA_MIPS3);
15886 check_mips_64(ctx);
15887 gen_arith_imm(ctx, op, rt, rs, imm);
15889 break;
15890 case OPC_DADDIU:
15891 check_insn(ctx, ISA_MIPS3);
15892 check_mips_64(ctx);
15893 gen_arith_imm(ctx, op, rt, rs, imm);
15894 break;
15895 #else
15896 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15897 if (ctx->insn_flags & ISA_MIPS_R6) {
15898 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15899 } else {
15900 MIPS_INVAL("major opcode");
15901 gen_reserved_instruction(ctx);
15903 break;
15904 #endif
15905 case OPC_DAUI: /* OPC_JALX */
15906 if (ctx->insn_flags & ISA_MIPS_R6) {
15907 #if defined(TARGET_MIPS64)
15908 /* OPC_DAUI */
15909 check_mips_64(ctx);
15910 if (rs == 0) {
15911 generate_exception(ctx, EXCP_RI);
15912 } else if (rt != 0) {
15913 TCGv t0 = tcg_temp_new();
15914 gen_load_gpr(t0, rs);
15915 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
15916 tcg_temp_free(t0);
15918 #else
15919 gen_reserved_instruction(ctx);
15920 MIPS_INVAL("major opcode");
15921 #endif
15922 } else {
15923 /* OPC_JALX */
15924 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
15925 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15926 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
15928 break;
15929 case OPC_MDMX:
15930 /* MDMX: Not implemented. */
15931 break;
15932 case OPC_PCREL:
15933 check_insn(ctx, ISA_MIPS_R6);
15934 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
15935 break;
15936 default: /* Invalid */
15937 MIPS_INVAL("major opcode");
15938 return false;
15940 return true;
15943 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
15945 /* make sure instructions are on a word boundary */
15946 if (ctx->base.pc_next & 0x3) {
15947 env->CP0_BadVAddr = ctx->base.pc_next;
15948 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
15949 return;
15952 /* Handle blikely not taken case */
15953 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
15954 TCGLabel *l1 = gen_new_label();
15956 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
15957 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
15958 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
15959 gen_set_label(l1);
15962 /* Transition to the auto-generated decoder. */
15964 /* Vendor specific extensions */
15965 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
15966 return;
15968 if (cpu_supports_isa(env, INSN_VR54XX) && decode_ext_vr54xx(ctx, ctx->opcode)) {
15969 return;
15972 /* ISA extensions */
15973 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
15974 return;
15977 /* ISA (from latest to oldest) */
15978 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
15979 return;
15982 if (decode_opc_legacy(env, ctx)) {
15983 return;
15986 gen_reserved_instruction(ctx);
15989 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
15991 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15992 CPUMIPSState *env = cs->env_ptr;
15994 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
15995 ctx->saved_pc = -1;
15996 ctx->insn_flags = env->insn_flags;
15997 ctx->CP0_Config1 = env->CP0_Config1;
15998 ctx->CP0_Config2 = env->CP0_Config2;
15999 ctx->CP0_Config3 = env->CP0_Config3;
16000 ctx->CP0_Config5 = env->CP0_Config5;
16001 ctx->btarget = 0;
16002 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
16003 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
16004 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
16005 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
16006 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
16007 ctx->PAMask = env->PAMask;
16008 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
16009 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
16010 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
16011 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
16012 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
16013 /* Restore delay slot state from the tb context. */
16014 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
16015 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
16016 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
16017 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
16018 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
16019 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
16020 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
16021 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
16022 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
16023 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
16024 restore_cpu_state(env, ctx);
16025 #ifdef CONFIG_USER_ONLY
16026 ctx->mem_idx = MIPS_HFLAG_UM;
16027 #else
16028 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
16029 #endif
16030 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
16031 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
16033 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
16034 ctx->hflags);
16037 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
16041 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
16043 DisasContext *ctx = container_of(dcbase, DisasContext, base);
16045 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
16046 ctx->btarget);
16049 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
16051 CPUMIPSState *env = cs->env_ptr;
16052 DisasContext *ctx = container_of(dcbase, DisasContext, base);
16053 int insn_bytes;
16054 int is_slot;
16056 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
16057 if (ctx->insn_flags & ISA_NANOMIPS32) {
16058 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
16059 insn_bytes = decode_isa_nanomips(env, ctx);
16060 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
16061 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
16062 insn_bytes = 4;
16063 decode_opc(env, ctx);
16064 } else if (ctx->insn_flags & ASE_MICROMIPS) {
16065 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
16066 insn_bytes = decode_isa_micromips(env, ctx);
16067 } else if (ctx->insn_flags & ASE_MIPS16) {
16068 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
16069 insn_bytes = decode_ase_mips16e(env, ctx);
16070 } else {
16071 gen_reserved_instruction(ctx);
16072 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
16073 return;
16076 if (ctx->hflags & MIPS_HFLAG_BMASK) {
16077 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
16078 MIPS_HFLAG_FBNSLOT))) {
16080 * Force to generate branch as there is neither delay nor
16081 * forbidden slot.
16083 is_slot = 1;
16085 if ((ctx->hflags & MIPS_HFLAG_M16) &&
16086 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
16088 * Force to generate branch as microMIPS R6 doesn't restrict
16089 * branches in the forbidden slot.
16091 is_slot = 1;
16094 if (is_slot) {
16095 gen_branch(ctx, insn_bytes);
16097 ctx->base.pc_next += insn_bytes;
16099 if (ctx->base.is_jmp != DISAS_NEXT) {
16100 return;
16103 * Execute a branch and its delay slot as a single instruction.
16104 * This is what GDB expects and is consistent with what the
16105 * hardware does (e.g. if a delay slot instruction faults, the
16106 * reported PC is the PC of the branch).
16108 if (ctx->base.singlestep_enabled &&
16109 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
16110 ctx->base.is_jmp = DISAS_TOO_MANY;
16112 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
16113 ctx->base.is_jmp = DISAS_TOO_MANY;
16117 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
16119 DisasContext *ctx = container_of(dcbase, DisasContext, base);
16121 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
16122 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
16123 gen_helper_raise_exception_debug(cpu_env);
16124 } else {
16125 switch (ctx->base.is_jmp) {
16126 case DISAS_STOP:
16127 gen_save_pc(ctx->base.pc_next);
16128 tcg_gen_lookup_and_goto_ptr();
16129 break;
16130 case DISAS_NEXT:
16131 case DISAS_TOO_MANY:
16132 save_cpu_state(ctx, 0);
16133 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16134 break;
16135 case DISAS_EXIT:
16136 tcg_gen_exit_tb(NULL, 0);
16137 break;
16138 case DISAS_NORETURN:
16139 break;
16140 default:
16141 g_assert_not_reached();
16146 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
16148 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
16149 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
16152 static const TranslatorOps mips_tr_ops = {
16153 .init_disas_context = mips_tr_init_disas_context,
16154 .tb_start = mips_tr_tb_start,
16155 .insn_start = mips_tr_insn_start,
16156 .translate_insn = mips_tr_translate_insn,
16157 .tb_stop = mips_tr_tb_stop,
16158 .disas_log = mips_tr_disas_log,
16161 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
16163 DisasContext ctx;
16165 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
16168 void mips_tcg_init(void)
16170 int i;
16172 cpu_gpr[0] = NULL;
16173 for (i = 1; i < 32; i++)
16174 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
16175 offsetof(CPUMIPSState,
16176 active_tc.gpr[i]),
16177 regnames[i]);
16178 #if defined(TARGET_MIPS64)
16179 cpu_gpr_hi[0] = NULL;
16181 for (unsigned i = 1; i < 32; i++) {
16182 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
16184 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
16185 offsetof(CPUMIPSState,
16186 active_tc.gpr_hi[i]),
16187 rname);
16189 #endif /* !TARGET_MIPS64 */
16190 for (i = 0; i < 32; i++) {
16191 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
16193 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
16195 msa_translate_init();
16196 cpu_PC = tcg_global_mem_new(cpu_env,
16197 offsetof(CPUMIPSState, active_tc.PC), "PC");
16198 for (i = 0; i < MIPS_DSP_ACC; i++) {
16199 cpu_HI[i] = tcg_global_mem_new(cpu_env,
16200 offsetof(CPUMIPSState, active_tc.HI[i]),
16201 regnames_HI[i]);
16202 cpu_LO[i] = tcg_global_mem_new(cpu_env,
16203 offsetof(CPUMIPSState, active_tc.LO[i]),
16204 regnames_LO[i]);
16206 cpu_dspctrl = tcg_global_mem_new(cpu_env,
16207 offsetof(CPUMIPSState,
16208 active_tc.DSPControl),
16209 "DSPControl");
16210 bcond = tcg_global_mem_new(cpu_env,
16211 offsetof(CPUMIPSState, bcond), "bcond");
16212 btarget = tcg_global_mem_new(cpu_env,
16213 offsetof(CPUMIPSState, btarget), "btarget");
16214 hflags = tcg_global_mem_new_i32(cpu_env,
16215 offsetof(CPUMIPSState, hflags), "hflags");
16217 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
16218 offsetof(CPUMIPSState, active_fpu.fcr0),
16219 "fcr0");
16220 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
16221 offsetof(CPUMIPSState, active_fpu.fcr31),
16222 "fcr31");
16223 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
16224 "lladdr");
16225 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
16226 "llval");
16228 if (TARGET_LONG_BITS == 32) {
16229 mxu_translate_init();
16233 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
16234 target_ulong *data)
16236 env->active_tc.PC = data[0];
16237 env->hflags &= ~MIPS_HFLAG_BMASK;
16238 env->hflags |= data[1];
16239 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
16240 case MIPS_HFLAG_BR:
16241 break;
16242 case MIPS_HFLAG_BC:
16243 case MIPS_HFLAG_BL:
16244 case MIPS_HFLAG_B:
16245 env->btarget = data[2];
16246 break;