accel/tcg: Remove TranslatorOps.breakpoint_check
[qemu/ar7.git] / target / mips / tcg / translate.c
blob5b03545f099a650a1546cefedff44e5e6b758b02
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 /* Multiplication variants of the vr54xx. */
298 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
300 enum {
301 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
302 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
303 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
304 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
305 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
306 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
308 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
309 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
310 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
311 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
312 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
313 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
314 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
317 /* REGIMM (rt field) opcodes */
318 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
320 enum {
321 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
322 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
323 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
324 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
325 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
326 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
327 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
328 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
329 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
330 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
331 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
332 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
333 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
334 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
335 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
336 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
338 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
339 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
342 /* Special2 opcodes */
343 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
345 enum {
346 /* Multiply & xxx operations */
347 OPC_MADD = 0x00 | OPC_SPECIAL2,
348 OPC_MADDU = 0x01 | OPC_SPECIAL2,
349 OPC_MUL = 0x02 | OPC_SPECIAL2,
350 OPC_MSUB = 0x04 | OPC_SPECIAL2,
351 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
352 /* Loongson 2F */
353 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
354 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
355 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
356 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
357 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
358 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
359 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
360 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
361 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
362 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
363 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
364 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
365 /* Misc */
366 OPC_CLZ = 0x20 | OPC_SPECIAL2,
367 OPC_CLO = 0x21 | OPC_SPECIAL2,
368 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
369 OPC_DCLO = 0x25 | OPC_SPECIAL2,
370 /* Special */
371 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
374 /* Special3 opcodes */
375 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
377 enum {
378 OPC_EXT = 0x00 | OPC_SPECIAL3,
379 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
380 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
381 OPC_DEXT = 0x03 | OPC_SPECIAL3,
382 OPC_INS = 0x04 | OPC_SPECIAL3,
383 OPC_DINSM = 0x05 | OPC_SPECIAL3,
384 OPC_DINSU = 0x06 | OPC_SPECIAL3,
385 OPC_DINS = 0x07 | OPC_SPECIAL3,
386 OPC_FORK = 0x08 | OPC_SPECIAL3,
387 OPC_YIELD = 0x09 | OPC_SPECIAL3,
388 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
389 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
390 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
391 OPC_GINV = 0x3D | OPC_SPECIAL3,
393 /* Loongson 2E */
394 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
395 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
396 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
397 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
398 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
399 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
400 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
401 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
402 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
403 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
404 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
405 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
407 /* MIPS DSP Load */
408 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
409 /* MIPS DSP Arithmetic */
410 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
411 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
412 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
413 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
414 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
415 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
417 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
418 /* MIPS DSP GPR-Based Shift Sub-class */
419 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
420 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
421 /* MIPS DSP Multiply Sub-class insns */
422 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
423 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
424 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
425 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
426 /* DSP Bit/Manipulation Sub-class */
427 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
428 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
429 /* MIPS DSP Append Sub-class */
430 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
431 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
432 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
433 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
434 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
436 /* EVA */
437 OPC_LWLE = 0x19 | OPC_SPECIAL3,
438 OPC_LWRE = 0x1A | OPC_SPECIAL3,
439 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
440 OPC_SBE = 0x1C | OPC_SPECIAL3,
441 OPC_SHE = 0x1D | OPC_SPECIAL3,
442 OPC_SCE = 0x1E | OPC_SPECIAL3,
443 OPC_SWE = 0x1F | OPC_SPECIAL3,
444 OPC_SWLE = 0x21 | OPC_SPECIAL3,
445 OPC_SWRE = 0x22 | OPC_SPECIAL3,
446 OPC_PREFE = 0x23 | OPC_SPECIAL3,
447 OPC_LBUE = 0x28 | OPC_SPECIAL3,
448 OPC_LHUE = 0x29 | OPC_SPECIAL3,
449 OPC_LBE = 0x2C | OPC_SPECIAL3,
450 OPC_LHE = 0x2D | OPC_SPECIAL3,
451 OPC_LLE = 0x2E | OPC_SPECIAL3,
452 OPC_LWE = 0x2F | OPC_SPECIAL3,
454 /* R6 */
455 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
456 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
457 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
458 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
459 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
460 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
463 /* Loongson EXT load/store quad word opcodes */
464 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
465 enum {
466 OPC_GSLQ = 0x0020 | OPC_LWC2,
467 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
468 OPC_GSSHFL = OPC_LWC2,
469 OPC_GSSQ = 0x0020 | OPC_SWC2,
470 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
471 OPC_GSSHFS = OPC_SWC2,
474 /* Loongson EXT shifted load/store opcodes */
475 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
476 enum {
477 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
478 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
479 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
480 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
481 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
482 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
483 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
484 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
487 /* Loongson EXT LDC2/SDC2 opcodes */
488 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
490 enum {
491 OPC_GSLBX = 0x0 | OPC_LDC2,
492 OPC_GSLHX = 0x1 | OPC_LDC2,
493 OPC_GSLWX = 0x2 | OPC_LDC2,
494 OPC_GSLDX = 0x3 | OPC_LDC2,
495 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
496 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
497 OPC_GSSBX = 0x0 | OPC_SDC2,
498 OPC_GSSHX = 0x1 | OPC_SDC2,
499 OPC_GSSWX = 0x2 | OPC_SDC2,
500 OPC_GSSDX = 0x3 | OPC_SDC2,
501 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
502 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
505 /* BSHFL opcodes */
506 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
508 enum {
509 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
510 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
511 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
512 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
513 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
514 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
515 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
516 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
519 /* DBSHFL opcodes */
520 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
522 enum {
523 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
524 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
525 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
526 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
527 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
528 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
529 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
530 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
531 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
532 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
533 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
536 /* MIPS DSP REGIMM opcodes */
537 enum {
538 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
539 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
542 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
543 /* MIPS DSP Load */
544 enum {
545 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
546 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
547 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
548 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
551 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
552 enum {
553 /* MIPS DSP Arithmetic Sub-class */
554 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
555 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
558 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
559 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
560 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
561 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
562 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
563 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
564 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
565 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
566 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
567 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
568 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
569 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
570 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
571 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
572 /* MIPS DSP Multiply Sub-class insns */
573 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
574 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
575 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
576 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
577 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
578 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
581 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
582 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583 enum {
584 /* MIPS DSP Arithmetic Sub-class */
585 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
586 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
587 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
588 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
589 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
590 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
591 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
592 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
593 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
594 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
595 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
596 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
597 /* MIPS DSP Multiply Sub-class insns */
598 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
599 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
600 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
601 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
604 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
605 enum {
606 /* MIPS DSP Arithmetic Sub-class */
607 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
608 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
614 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
616 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
617 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
618 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
619 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
620 /* DSP Bit/Manipulation Sub-class */
621 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
622 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
623 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
624 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
625 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
628 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
629 enum {
630 /* MIPS DSP Arithmetic Sub-class */
631 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
638 /* DSP Compare-Pick Sub-class */
639 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
646 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
647 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
648 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
649 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
650 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
651 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
652 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
653 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
656 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657 enum {
658 /* MIPS DSP GPR-Based Shift Sub-class */
659 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
673 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
674 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
675 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
676 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
677 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
678 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
679 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
680 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
683 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
684 enum {
685 /* MIPS DSP Multiply Sub-class insns */
686 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
695 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
696 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
698 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
699 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
700 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
701 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
702 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
703 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
704 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
705 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
706 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
707 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
710 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
711 enum {
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
716 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
717 enum {
718 /* MIPS DSP Append Sub-class */
719 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
720 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
721 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
724 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
725 enum {
726 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
727 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
728 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
731 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
732 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
733 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
734 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
735 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
736 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
737 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
738 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
739 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
740 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
741 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
742 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
743 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
746 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
747 enum {
748 /* MIPS DSP Arithmetic Sub-class */
749 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
762 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
763 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
765 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
766 /* DSP Bit/Manipulation Sub-class */
767 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
768 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
769 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
770 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
771 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
772 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
775 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
776 enum {
777 /* MIPS DSP Multiply Sub-class insns */
778 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
779 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
780 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
781 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
782 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
783 /* MIPS DSP Arithmetic Sub-class */
784 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
785 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
787 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
788 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
789 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
790 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
791 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
792 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
793 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
794 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
795 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
797 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
798 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
799 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
800 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
801 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
802 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
803 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
804 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
807 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
808 enum {
809 /* DSP Compare-Pick Sub-class */
810 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
826 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
829 /* MIPS DSP Arithmetic Sub-class */
830 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
831 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
832 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
833 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
834 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
835 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
836 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
837 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
840 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
841 enum {
842 /* DSP Append Sub-class */
843 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
844 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
845 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
846 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
849 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
850 enum {
851 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
852 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
853 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
865 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
866 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
867 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
868 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
869 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
870 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
871 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
872 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
875 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
876 enum {
877 /* DSP Bit/Manipulation Sub-class */
878 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
881 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
882 enum {
883 /* MIPS DSP Multiply Sub-class insns */
884 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
902 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
903 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
904 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
905 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
906 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
907 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
908 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
909 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
912 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
913 enum {
914 /* MIPS DSP GPR-Based Shift Sub-class */
915 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
933 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
934 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
935 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
936 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
937 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
938 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
939 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
940 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
943 /* Coprocessor 0 (rs field) */
944 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
946 enum {
947 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
948 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
949 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
950 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
951 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
952 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
953 OPC_MFTR = (0x08 << 21) | OPC_CP0,
954 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
955 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
956 OPC_MTTR = (0x0C << 21) | OPC_CP0,
957 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
958 OPC_C0 = (0x10 << 21) | OPC_CP0,
959 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
960 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
961 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
962 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
963 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
964 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
965 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
966 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
967 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
968 OPC_C0_A = (0x1A << 21) | OPC_CP0,
969 OPC_C0_B = (0x1B << 21) | OPC_CP0,
970 OPC_C0_C = (0x1C << 21) | OPC_CP0,
971 OPC_C0_D = (0x1D << 21) | OPC_CP0,
972 OPC_C0_E = (0x1E << 21) | OPC_CP0,
973 OPC_C0_F = (0x1F << 21) | OPC_CP0,
976 /* MFMC0 opcodes */
977 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
979 enum {
980 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
981 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
982 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
983 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
984 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
985 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
986 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
987 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
990 /* Coprocessor 0 (with rs == C0) */
991 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
993 enum {
994 OPC_TLBR = 0x01 | OPC_C0,
995 OPC_TLBWI = 0x02 | OPC_C0,
996 OPC_TLBINV = 0x03 | OPC_C0,
997 OPC_TLBINVF = 0x04 | OPC_C0,
998 OPC_TLBWR = 0x06 | OPC_C0,
999 OPC_TLBP = 0x08 | OPC_C0,
1000 OPC_RFE = 0x10 | OPC_C0,
1001 OPC_ERET = 0x18 | OPC_C0,
1002 OPC_DERET = 0x1F | OPC_C0,
1003 OPC_WAIT = 0x20 | OPC_C0,
1006 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1008 enum {
1009 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1010 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1011 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1012 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1013 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1014 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1015 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1016 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1017 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1018 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1019 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1022 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1024 enum {
1025 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1026 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1027 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1028 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1029 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1030 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1031 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1032 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1034 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1035 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1036 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1037 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1038 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1039 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1040 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1041 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1043 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1044 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1045 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1046 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1047 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1048 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1049 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1050 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1052 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1053 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1054 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1055 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1056 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1057 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1058 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1059 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1061 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1062 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1063 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1064 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1065 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1066 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1068 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1069 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1070 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1071 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1072 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1073 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1075 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1076 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1077 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1078 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1079 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1080 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1082 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1083 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1084 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1085 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1086 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1087 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1089 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1090 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1091 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1092 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1093 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1094 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1096 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1097 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1098 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1099 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1100 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1101 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1103 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1104 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1105 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1106 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1107 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1108 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1110 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1111 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1112 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1113 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1114 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1115 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1119 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1121 enum {
1122 OPC_LWXC1 = 0x00 | OPC_CP3,
1123 OPC_LDXC1 = 0x01 | OPC_CP3,
1124 OPC_LUXC1 = 0x05 | OPC_CP3,
1125 OPC_SWXC1 = 0x08 | OPC_CP3,
1126 OPC_SDXC1 = 0x09 | OPC_CP3,
1127 OPC_SUXC1 = 0x0D | OPC_CP3,
1128 OPC_PREFX = 0x0F | OPC_CP3,
1129 OPC_ALNV_PS = 0x1E | OPC_CP3,
1130 OPC_MADD_S = 0x20 | OPC_CP3,
1131 OPC_MADD_D = 0x21 | OPC_CP3,
1132 OPC_MADD_PS = 0x26 | OPC_CP3,
1133 OPC_MSUB_S = 0x28 | OPC_CP3,
1134 OPC_MSUB_D = 0x29 | OPC_CP3,
1135 OPC_MSUB_PS = 0x2E | OPC_CP3,
1136 OPC_NMADD_S = 0x30 | OPC_CP3,
1137 OPC_NMADD_D = 0x31 | OPC_CP3,
1138 OPC_NMADD_PS = 0x36 | OPC_CP3,
1139 OPC_NMSUB_S = 0x38 | OPC_CP3,
1140 OPC_NMSUB_D = 0x39 | OPC_CP3,
1141 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1145 * MMI (MultiMedia Instruction) encodings
1146 * ======================================
1148 * MMI instructions encoding table keys:
1150 * * This code is reserved for future use. An attempt to execute it
1151 * causes a Reserved Instruction exception.
1152 * % This code indicates an instruction class. The instruction word
1153 * must be further decoded by examining additional tables that show
1154 * the values for other instruction fields.
1155 * # This code is reserved for the unsupported instructions DMULT,
1156 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1157 * to execute it causes a Reserved Instruction exception.
1159 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1161 * 31 26 0
1162 * +--------+----------------------------------------+
1163 * | opcode | |
1164 * +--------+----------------------------------------+
1166 * opcode bits 28..26
1167 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1168 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1169 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1170 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1171 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1172 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1173 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1174 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1175 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1176 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1177 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1180 enum {
1181 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1182 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1186 * MMI instructions with opcode field = MMI:
1188 * 31 26 5 0
1189 * +--------+-------------------------------+--------+
1190 * | MMI | |function|
1191 * +--------+-------------------------------+--------+
1193 * function bits 2..0
1194 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1195 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1196 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1197 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1198 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1199 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1200 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1201 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1202 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1203 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1204 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1207 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1208 enum {
1209 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1210 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1211 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1212 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1213 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1214 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1215 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1216 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1219 /* global register indices */
1220 TCGv cpu_gpr[32], cpu_PC;
1222 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1223 * and the upper halves in cpu_gpr_hi[].
1225 TCGv_i64 cpu_gpr_hi[32];
1226 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1227 static TCGv cpu_dspctrl, btarget;
1228 TCGv bcond;
1229 static TCGv cpu_lladdr, cpu_llval;
1230 static TCGv_i32 hflags;
1231 TCGv_i32 fpu_fcr0, fpu_fcr31;
1232 TCGv_i64 fpu_f64[32];
1234 #include "exec/gen-icount.h"
1236 #define gen_helper_0e0i(name, arg) do { \
1237 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1238 gen_helper_##name(cpu_env, helper_tmp); \
1239 tcg_temp_free_i32(helper_tmp); \
1240 } while (0)
1242 #define gen_helper_0e1i(name, arg1, arg2) do { \
1243 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1244 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1245 tcg_temp_free_i32(helper_tmp); \
1246 } while (0)
1248 #define gen_helper_1e0i(name, ret, arg1) do { \
1249 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1250 gen_helper_##name(ret, cpu_env, helper_tmp); \
1251 tcg_temp_free_i32(helper_tmp); \
1252 } while (0)
1254 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1255 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1256 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1257 tcg_temp_free_i32(helper_tmp); \
1258 } while (0)
1260 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1261 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1262 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1263 tcg_temp_free_i32(helper_tmp); \
1264 } while (0)
1266 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1267 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1268 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1269 tcg_temp_free_i32(helper_tmp); \
1270 } while (0)
1272 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1273 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1274 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1275 tcg_temp_free_i32(helper_tmp); \
1276 } while (0)
1278 #define DISAS_STOP DISAS_TARGET_0
1279 #define DISAS_EXIT DISAS_TARGET_1
1281 static const char regnames_HI[][4] = {
1282 "HI0", "HI1", "HI2", "HI3",
1285 static const char regnames_LO[][4] = {
1286 "LO0", "LO1", "LO2", "LO3",
1289 /* General purpose registers moves. */
1290 void gen_load_gpr(TCGv t, int reg)
1292 if (reg == 0) {
1293 tcg_gen_movi_tl(t, 0);
1294 } else {
1295 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1299 void gen_store_gpr(TCGv t, int reg)
1301 if (reg != 0) {
1302 tcg_gen_mov_tl(cpu_gpr[reg], t);
1306 #if defined(TARGET_MIPS64)
1307 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1309 if (reg == 0) {
1310 tcg_gen_movi_i64(t, 0);
1311 } else {
1312 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1316 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1318 if (reg != 0) {
1319 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1322 #endif /* TARGET_MIPS64 */
1324 /* Moves to/from shadow registers. */
1325 static inline void gen_load_srsgpr(int from, int to)
1327 TCGv t0 = tcg_temp_new();
1329 if (from == 0) {
1330 tcg_gen_movi_tl(t0, 0);
1331 } else {
1332 TCGv_i32 t2 = tcg_temp_new_i32();
1333 TCGv_ptr addr = tcg_temp_new_ptr();
1335 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1336 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1337 tcg_gen_andi_i32(t2, t2, 0xf);
1338 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1339 tcg_gen_ext_i32_ptr(addr, t2);
1340 tcg_gen_add_ptr(addr, cpu_env, addr);
1342 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1343 tcg_temp_free_ptr(addr);
1344 tcg_temp_free_i32(t2);
1346 gen_store_gpr(t0, to);
1347 tcg_temp_free(t0);
1350 static inline void gen_store_srsgpr(int from, int to)
1352 if (to != 0) {
1353 TCGv t0 = tcg_temp_new();
1354 TCGv_i32 t2 = tcg_temp_new_i32();
1355 TCGv_ptr addr = tcg_temp_new_ptr();
1357 gen_load_gpr(t0, from);
1358 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1359 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1360 tcg_gen_andi_i32(t2, t2, 0xf);
1361 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1362 tcg_gen_ext_i32_ptr(addr, t2);
1363 tcg_gen_add_ptr(addr, cpu_env, addr);
1365 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1366 tcg_temp_free_ptr(addr);
1367 tcg_temp_free_i32(t2);
1368 tcg_temp_free(t0);
1372 /* Tests */
1373 static inline void gen_save_pc(target_ulong pc)
1375 tcg_gen_movi_tl(cpu_PC, pc);
1378 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1380 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1381 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1382 gen_save_pc(ctx->base.pc_next);
1383 ctx->saved_pc = ctx->base.pc_next;
1385 if (ctx->hflags != ctx->saved_hflags) {
1386 tcg_gen_movi_i32(hflags, ctx->hflags);
1387 ctx->saved_hflags = ctx->hflags;
1388 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1389 case MIPS_HFLAG_BR:
1390 break;
1391 case MIPS_HFLAG_BC:
1392 case MIPS_HFLAG_BL:
1393 case MIPS_HFLAG_B:
1394 tcg_gen_movi_tl(btarget, ctx->btarget);
1395 break;
1400 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1402 ctx->saved_hflags = ctx->hflags;
1403 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1404 case MIPS_HFLAG_BR:
1405 break;
1406 case MIPS_HFLAG_BC:
1407 case MIPS_HFLAG_BL:
1408 case MIPS_HFLAG_B:
1409 ctx->btarget = env->btarget;
1410 break;
1414 void generate_exception_err(DisasContext *ctx, int excp, int err)
1416 TCGv_i32 texcp = tcg_const_i32(excp);
1417 TCGv_i32 terr = tcg_const_i32(err);
1418 save_cpu_state(ctx, 1);
1419 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1420 tcg_temp_free_i32(terr);
1421 tcg_temp_free_i32(texcp);
1422 ctx->base.is_jmp = DISAS_NORETURN;
1425 void generate_exception(DisasContext *ctx, int excp)
1427 gen_helper_0e0i(raise_exception, excp);
1430 void generate_exception_end(DisasContext *ctx, int excp)
1432 generate_exception_err(ctx, excp, 0);
1435 void gen_reserved_instruction(DisasContext *ctx)
1437 generate_exception_end(ctx, EXCP_RI);
1440 /* Floating point register moves. */
1441 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1443 if (ctx->hflags & MIPS_HFLAG_FRE) {
1444 generate_exception(ctx, EXCP_RI);
1446 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1449 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1451 TCGv_i64 t64;
1452 if (ctx->hflags & MIPS_HFLAG_FRE) {
1453 generate_exception(ctx, EXCP_RI);
1455 t64 = tcg_temp_new_i64();
1456 tcg_gen_extu_i32_i64(t64, t);
1457 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1458 tcg_temp_free_i64(t64);
1461 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1463 if (ctx->hflags & MIPS_HFLAG_F64) {
1464 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1465 } else {
1466 gen_load_fpr32(ctx, t, reg | 1);
1470 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1472 if (ctx->hflags & MIPS_HFLAG_F64) {
1473 TCGv_i64 t64 = tcg_temp_new_i64();
1474 tcg_gen_extu_i32_i64(t64, t);
1475 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1476 tcg_temp_free_i64(t64);
1477 } else {
1478 gen_store_fpr32(ctx, t, reg | 1);
1482 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1484 if (ctx->hflags & MIPS_HFLAG_F64) {
1485 tcg_gen_mov_i64(t, fpu_f64[reg]);
1486 } else {
1487 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1491 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1493 if (ctx->hflags & MIPS_HFLAG_F64) {
1494 tcg_gen_mov_i64(fpu_f64[reg], t);
1495 } else {
1496 TCGv_i64 t0;
1497 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1498 t0 = tcg_temp_new_i64();
1499 tcg_gen_shri_i64(t0, t, 32);
1500 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1501 tcg_temp_free_i64(t0);
1505 int get_fp_bit(int cc)
1507 if (cc) {
1508 return 24 + cc;
1509 } else {
1510 return 23;
1514 /* Addresses computation */
1515 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1517 tcg_gen_add_tl(ret, arg0, arg1);
1519 #if defined(TARGET_MIPS64)
1520 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1521 tcg_gen_ext32s_i64(ret, ret);
1523 #endif
1526 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1527 target_long ofs)
1529 tcg_gen_addi_tl(ret, base, ofs);
1531 #if defined(TARGET_MIPS64)
1532 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1533 tcg_gen_ext32s_i64(ret, ret);
1535 #endif
1538 /* Addresses computation (translation time) */
1539 static target_long addr_add(DisasContext *ctx, target_long base,
1540 target_long offset)
1542 target_long sum = base + offset;
1544 #if defined(TARGET_MIPS64)
1545 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1546 sum = (int32_t)sum;
1548 #endif
1549 return sum;
1552 /* Sign-extract the low 32-bits to a target_long. */
1553 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1555 #if defined(TARGET_MIPS64)
1556 tcg_gen_ext32s_i64(ret, arg);
1557 #else
1558 tcg_gen_extrl_i64_i32(ret, arg);
1559 #endif
1562 /* Sign-extract the high 32-bits to a target_long. */
1563 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1565 #if defined(TARGET_MIPS64)
1566 tcg_gen_sari_i64(ret, arg, 32);
1567 #else
1568 tcg_gen_extrh_i64_i32(ret, arg);
1569 #endif
1572 bool check_cp0_enabled(DisasContext *ctx)
1574 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1575 generate_exception_end(ctx, EXCP_CpU);
1576 return false;
1578 return true;
1581 void check_cp1_enabled(DisasContext *ctx)
1583 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1584 generate_exception_err(ctx, EXCP_CpU, 1);
1589 * Verify that the processor is running with COP1X instructions enabled.
1590 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1591 * opcode tables.
1593 void check_cop1x(DisasContext *ctx)
1595 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1596 gen_reserved_instruction(ctx);
1601 * Verify that the processor is running with 64-bit floating-point
1602 * operations enabled.
1604 void check_cp1_64bitmode(DisasContext *ctx)
1606 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
1607 gen_reserved_instruction(ctx);
1612 * Verify if floating point register is valid; an operation is not defined
1613 * if bit 0 of any register specification is set and the FR bit in the
1614 * Status register equals zero, since the register numbers specify an
1615 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1616 * in the Status register equals one, both even and odd register numbers
1617 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1619 * Multiple 64 bit wide registers can be checked by calling
1620 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1622 void check_cp1_registers(DisasContext *ctx, int regs)
1624 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1625 gen_reserved_instruction(ctx);
1630 * Verify that the processor is running with DSP instructions enabled.
1631 * This is enabled by CP0 Status register MX(24) bit.
1633 static inline void check_dsp(DisasContext *ctx)
1635 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1636 if (ctx->insn_flags & ASE_DSP) {
1637 generate_exception_end(ctx, EXCP_DSPDIS);
1638 } else {
1639 gen_reserved_instruction(ctx);
1644 static inline void check_dsp_r2(DisasContext *ctx)
1646 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
1647 if (ctx->insn_flags & ASE_DSP) {
1648 generate_exception_end(ctx, EXCP_DSPDIS);
1649 } else {
1650 gen_reserved_instruction(ctx);
1655 static inline void check_dsp_r3(DisasContext *ctx)
1657 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
1658 if (ctx->insn_flags & ASE_DSP) {
1659 generate_exception_end(ctx, EXCP_DSPDIS);
1660 } else {
1661 gen_reserved_instruction(ctx);
1667 * This code generates a "reserved instruction" exception if the
1668 * CPU does not support the instruction set corresponding to flags.
1670 void check_insn(DisasContext *ctx, uint64_t flags)
1672 if (unlikely(!(ctx->insn_flags & flags))) {
1673 gen_reserved_instruction(ctx);
1678 * This code generates a "reserved instruction" exception if the
1679 * CPU has corresponding flag set which indicates that the instruction
1680 * has been removed.
1682 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
1684 if (unlikely(ctx->insn_flags & flags)) {
1685 gen_reserved_instruction(ctx);
1690 * The Linux kernel traps certain reserved instruction exceptions to
1691 * emulate the corresponding instructions. QEMU is the kernel in user
1692 * mode, so those traps are emulated by accepting the instructions.
1694 * A reserved instruction exception is generated for flagged CPUs if
1695 * QEMU runs in system mode.
1697 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1699 #ifndef CONFIG_USER_ONLY
1700 check_insn_opc_removed(ctx, flags);
1701 #endif
1705 * This code generates a "reserved instruction" exception if the
1706 * CPU does not support 64-bit paired-single (PS) floating point data type.
1708 static inline void check_ps(DisasContext *ctx)
1710 if (unlikely(!ctx->ps)) {
1711 generate_exception(ctx, EXCP_RI);
1713 check_cp1_64bitmode(ctx);
1717 * This code generates a "reserved instruction" exception if cpu is not
1718 * 64-bit or 64-bit instructions are not enabled.
1720 void check_mips_64(DisasContext *ctx)
1722 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
1723 gen_reserved_instruction(ctx);
1727 #ifndef CONFIG_USER_ONLY
1728 static inline void check_mvh(DisasContext *ctx)
1730 if (unlikely(!ctx->mvh)) {
1731 generate_exception(ctx, EXCP_RI);
1734 #endif
1737 * This code generates a "reserved instruction" exception if the
1738 * Config5 XNP bit is set.
1740 static inline void check_xnp(DisasContext *ctx)
1742 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1743 gen_reserved_instruction(ctx);
1747 #ifndef CONFIG_USER_ONLY
1749 * This code generates a "reserved instruction" exception if the
1750 * Config3 PW bit is NOT set.
1752 static inline void check_pw(DisasContext *ctx)
1754 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
1755 gen_reserved_instruction(ctx);
1758 #endif
1761 * This code generates a "reserved instruction" exception if the
1762 * Config3 MT bit is NOT set.
1764 static inline void check_mt(DisasContext *ctx)
1766 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1767 gen_reserved_instruction(ctx);
1771 #ifndef CONFIG_USER_ONLY
1773 * This code generates a "coprocessor unusable" exception if CP0 is not
1774 * available, and, if that is not the case, generates a "reserved instruction"
1775 * exception if the Config5 MT bit is NOT set. This is needed for availability
1776 * control of some of MT ASE instructions.
1778 static inline void check_cp0_mt(DisasContext *ctx)
1780 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1781 generate_exception_end(ctx, EXCP_CpU);
1782 } else {
1783 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1784 gen_reserved_instruction(ctx);
1788 #endif
1791 * This code generates a "reserved instruction" exception if the
1792 * Config5 NMS bit is set.
1794 static inline void check_nms(DisasContext *ctx)
1796 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1797 gen_reserved_instruction(ctx);
1802 * This code generates a "reserved instruction" exception if the
1803 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1804 * Config2 TL, and Config5 L2C are unset.
1806 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1808 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1809 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1810 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1811 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1812 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1813 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
1814 gen_reserved_instruction(ctx);
1819 * This code generates a "reserved instruction" exception if the
1820 * Config5 EVA bit is NOT set.
1822 static inline void check_eva(DisasContext *ctx)
1824 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
1825 gen_reserved_instruction(ctx);
1831 * Define small wrappers for gen_load_fpr* so that we have a uniform
1832 * calling interface for 32 and 64-bit FPRs. No sense in changing
1833 * all callers for gen_load_fpr32 when we need the CTX parameter for
1834 * this one use.
1836 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1837 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1838 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1839 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1840 int ft, int fs, int cc) \
1842 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1843 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
1844 switch (ifmt) { \
1845 case FMT_PS: \
1846 check_ps(ctx); \
1847 break; \
1848 case FMT_D: \
1849 if (abs) { \
1850 check_cop1x(ctx); \
1852 check_cp1_registers(ctx, fs | ft); \
1853 break; \
1854 case FMT_S: \
1855 if (abs) { \
1856 check_cop1x(ctx); \
1858 break; \
1860 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1861 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
1862 switch (n) { \
1863 case 0: \
1864 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1865 break; \
1866 case 1: \
1867 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1868 break; \
1869 case 2: \
1870 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1871 break; \
1872 case 3: \
1873 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1874 break; \
1875 case 4: \
1876 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1877 break; \
1878 case 5: \
1879 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1880 break; \
1881 case 6: \
1882 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1883 break; \
1884 case 7: \
1885 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1886 break; \
1887 case 8: \
1888 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1889 break; \
1890 case 9: \
1891 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1892 break; \
1893 case 10: \
1894 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1895 break; \
1896 case 11: \
1897 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1898 break; \
1899 case 12: \
1900 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1901 break; \
1902 case 13: \
1903 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1904 break; \
1905 case 14: \
1906 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1907 break; \
1908 case 15: \
1909 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1910 break; \
1911 default: \
1912 abort(); \
1914 tcg_temp_free_i##bits(fp0); \
1915 tcg_temp_free_i##bits(fp1); \
1918 FOP_CONDS(, 0, d, FMT_D, 64)
1919 FOP_CONDS(abs, 1, d, FMT_D, 64)
1920 FOP_CONDS(, 0, s, FMT_S, 32)
1921 FOP_CONDS(abs, 1, s, FMT_S, 32)
1922 FOP_CONDS(, 0, ps, FMT_PS, 64)
1923 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1924 #undef FOP_CONDS
1926 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1927 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
1928 int ft, int fs, int fd) \
1930 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1931 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1932 if (ifmt == FMT_D) { \
1933 check_cp1_registers(ctx, fs | ft | fd); \
1935 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1936 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1937 switch (n) { \
1938 case 0: \
1939 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1940 break; \
1941 case 1: \
1942 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1943 break; \
1944 case 2: \
1945 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1946 break; \
1947 case 3: \
1948 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1949 break; \
1950 case 4: \
1951 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1952 break; \
1953 case 5: \
1954 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1955 break; \
1956 case 6: \
1957 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1958 break; \
1959 case 7: \
1960 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1961 break; \
1962 case 8: \
1963 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1964 break; \
1965 case 9: \
1966 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1967 break; \
1968 case 10: \
1969 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1970 break; \
1971 case 11: \
1972 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1973 break; \
1974 case 12: \
1975 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1976 break; \
1977 case 13: \
1978 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1979 break; \
1980 case 14: \
1981 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1982 break; \
1983 case 15: \
1984 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1985 break; \
1986 case 17: \
1987 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1988 break; \
1989 case 18: \
1990 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1991 break; \
1992 case 19: \
1993 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1994 break; \
1995 case 25: \
1996 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1997 break; \
1998 case 26: \
1999 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2000 break; \
2001 case 27: \
2002 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2003 break; \
2004 default: \
2005 abort(); \
2007 STORE; \
2008 tcg_temp_free_i ## bits(fp0); \
2009 tcg_temp_free_i ## bits(fp1); \
2012 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2013 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2014 #undef FOP_CONDNS
2015 #undef gen_ldcmp_fpr32
2016 #undef gen_ldcmp_fpr64
2018 /* load/store instructions. */
2019 #ifdef CONFIG_USER_ONLY
2020 #define OP_LD_ATOMIC(insn, fname) \
2021 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2022 DisasContext *ctx) \
2024 TCGv t0 = tcg_temp_new(); \
2025 tcg_gen_mov_tl(t0, arg1); \
2026 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2027 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2028 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2029 tcg_temp_free(t0); \
2031 #else
2032 #define OP_LD_ATOMIC(insn, fname) \
2033 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2034 DisasContext *ctx) \
2036 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2038 #endif
2039 OP_LD_ATOMIC(ll, ld32s);
2040 #if defined(TARGET_MIPS64)
2041 OP_LD_ATOMIC(lld, ld64);
2042 #endif
2043 #undef OP_LD_ATOMIC
2045 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
2047 if (base == 0) {
2048 tcg_gen_movi_tl(addr, offset);
2049 } else if (offset == 0) {
2050 gen_load_gpr(addr, base);
2051 } else {
2052 tcg_gen_movi_tl(addr, offset);
2053 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2057 static target_ulong pc_relative_pc(DisasContext *ctx)
2059 target_ulong pc = ctx->base.pc_next;
2061 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2062 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2064 pc -= branch_bytes;
2067 pc &= ~(target_ulong)3;
2068 return pc;
2071 /* Load */
2072 static void gen_ld(DisasContext *ctx, uint32_t opc,
2073 int rt, int base, int offset)
2075 TCGv t0, t1, t2;
2076 int mem_idx = ctx->mem_idx;
2078 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2079 INSN_LOONGSON3A)) {
2081 * Loongson CPU uses a load to zero register for prefetch.
2082 * We emulate it as a NOP. On other CPU we must perform the
2083 * actual memory access.
2085 return;
2088 t0 = tcg_temp_new();
2089 gen_base_offset_addr(ctx, t0, base, offset);
2091 switch (opc) {
2092 #if defined(TARGET_MIPS64)
2093 case OPC_LWU:
2094 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2095 ctx->default_tcg_memop_mask);
2096 gen_store_gpr(t0, rt);
2097 break;
2098 case OPC_LD:
2099 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2100 ctx->default_tcg_memop_mask);
2101 gen_store_gpr(t0, rt);
2102 break;
2103 case OPC_LLD:
2104 case R6_OPC_LLD:
2105 op_ld_lld(t0, t0, mem_idx, ctx);
2106 gen_store_gpr(t0, rt);
2107 break;
2108 case OPC_LDL:
2109 t1 = tcg_temp_new();
2111 * Do a byte access to possibly trigger a page
2112 * fault with the unaligned address.
2114 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2115 tcg_gen_andi_tl(t1, t0, 7);
2116 #ifndef TARGET_WORDS_BIGENDIAN
2117 tcg_gen_xori_tl(t1, t1, 7);
2118 #endif
2119 tcg_gen_shli_tl(t1, t1, 3);
2120 tcg_gen_andi_tl(t0, t0, ~7);
2121 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2122 tcg_gen_shl_tl(t0, t0, t1);
2123 t2 = tcg_const_tl(-1);
2124 tcg_gen_shl_tl(t2, t2, t1);
2125 gen_load_gpr(t1, rt);
2126 tcg_gen_andc_tl(t1, t1, t2);
2127 tcg_temp_free(t2);
2128 tcg_gen_or_tl(t0, t0, t1);
2129 tcg_temp_free(t1);
2130 gen_store_gpr(t0, rt);
2131 break;
2132 case OPC_LDR:
2133 t1 = tcg_temp_new();
2135 * Do a byte access to possibly trigger a page
2136 * fault with the unaligned address.
2138 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2139 tcg_gen_andi_tl(t1, t0, 7);
2140 #ifdef TARGET_WORDS_BIGENDIAN
2141 tcg_gen_xori_tl(t1, t1, 7);
2142 #endif
2143 tcg_gen_shli_tl(t1, t1, 3);
2144 tcg_gen_andi_tl(t0, t0, ~7);
2145 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2146 tcg_gen_shr_tl(t0, t0, t1);
2147 tcg_gen_xori_tl(t1, t1, 63);
2148 t2 = tcg_const_tl(0xfffffffffffffffeull);
2149 tcg_gen_shl_tl(t2, t2, t1);
2150 gen_load_gpr(t1, rt);
2151 tcg_gen_and_tl(t1, t1, t2);
2152 tcg_temp_free(t2);
2153 tcg_gen_or_tl(t0, t0, t1);
2154 tcg_temp_free(t1);
2155 gen_store_gpr(t0, rt);
2156 break;
2157 case OPC_LDPC:
2158 t1 = tcg_const_tl(pc_relative_pc(ctx));
2159 gen_op_addr_add(ctx, t0, t0, t1);
2160 tcg_temp_free(t1);
2161 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2162 gen_store_gpr(t0, rt);
2163 break;
2164 #endif
2165 case OPC_LWPC:
2166 t1 = tcg_const_tl(pc_relative_pc(ctx));
2167 gen_op_addr_add(ctx, t0, t0, t1);
2168 tcg_temp_free(t1);
2169 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2170 gen_store_gpr(t0, rt);
2171 break;
2172 case OPC_LWE:
2173 mem_idx = MIPS_HFLAG_UM;
2174 /* fall through */
2175 case OPC_LW:
2176 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2177 ctx->default_tcg_memop_mask);
2178 gen_store_gpr(t0, rt);
2179 break;
2180 case OPC_LHE:
2181 mem_idx = MIPS_HFLAG_UM;
2182 /* fall through */
2183 case OPC_LH:
2184 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2185 ctx->default_tcg_memop_mask);
2186 gen_store_gpr(t0, rt);
2187 break;
2188 case OPC_LHUE:
2189 mem_idx = MIPS_HFLAG_UM;
2190 /* fall through */
2191 case OPC_LHU:
2192 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2193 ctx->default_tcg_memop_mask);
2194 gen_store_gpr(t0, rt);
2195 break;
2196 case OPC_LBE:
2197 mem_idx = MIPS_HFLAG_UM;
2198 /* fall through */
2199 case OPC_LB:
2200 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2201 gen_store_gpr(t0, rt);
2202 break;
2203 case OPC_LBUE:
2204 mem_idx = MIPS_HFLAG_UM;
2205 /* fall through */
2206 case OPC_LBU:
2207 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2208 gen_store_gpr(t0, rt);
2209 break;
2210 case OPC_LWLE:
2211 mem_idx = MIPS_HFLAG_UM;
2212 /* fall through */
2213 case OPC_LWL:
2214 t1 = tcg_temp_new();
2216 * Do a byte access to possibly trigger a page
2217 * fault with the unaligned address.
2219 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2220 tcg_gen_andi_tl(t1, t0, 3);
2221 #ifndef TARGET_WORDS_BIGENDIAN
2222 tcg_gen_xori_tl(t1, t1, 3);
2223 #endif
2224 tcg_gen_shli_tl(t1, t1, 3);
2225 tcg_gen_andi_tl(t0, t0, ~3);
2226 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2227 tcg_gen_shl_tl(t0, t0, t1);
2228 t2 = tcg_const_tl(-1);
2229 tcg_gen_shl_tl(t2, t2, t1);
2230 gen_load_gpr(t1, rt);
2231 tcg_gen_andc_tl(t1, t1, t2);
2232 tcg_temp_free(t2);
2233 tcg_gen_or_tl(t0, t0, t1);
2234 tcg_temp_free(t1);
2235 tcg_gen_ext32s_tl(t0, t0);
2236 gen_store_gpr(t0, rt);
2237 break;
2238 case OPC_LWRE:
2239 mem_idx = MIPS_HFLAG_UM;
2240 /* fall through */
2241 case OPC_LWR:
2242 t1 = tcg_temp_new();
2244 * Do a byte access to possibly trigger a page
2245 * fault with the unaligned address.
2247 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2248 tcg_gen_andi_tl(t1, t0, 3);
2249 #ifdef TARGET_WORDS_BIGENDIAN
2250 tcg_gen_xori_tl(t1, t1, 3);
2251 #endif
2252 tcg_gen_shli_tl(t1, t1, 3);
2253 tcg_gen_andi_tl(t0, t0, ~3);
2254 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2255 tcg_gen_shr_tl(t0, t0, t1);
2256 tcg_gen_xori_tl(t1, t1, 31);
2257 t2 = tcg_const_tl(0xfffffffeull);
2258 tcg_gen_shl_tl(t2, t2, t1);
2259 gen_load_gpr(t1, rt);
2260 tcg_gen_and_tl(t1, t1, t2);
2261 tcg_temp_free(t2);
2262 tcg_gen_or_tl(t0, t0, t1);
2263 tcg_temp_free(t1);
2264 tcg_gen_ext32s_tl(t0, t0);
2265 gen_store_gpr(t0, rt);
2266 break;
2267 case OPC_LLE:
2268 mem_idx = MIPS_HFLAG_UM;
2269 /* fall through */
2270 case OPC_LL:
2271 case R6_OPC_LL:
2272 op_ld_ll(t0, t0, mem_idx, ctx);
2273 gen_store_gpr(t0, rt);
2274 break;
2276 tcg_temp_free(t0);
2279 /* Store */
2280 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2281 int base, int offset)
2283 TCGv t0 = tcg_temp_new();
2284 TCGv t1 = tcg_temp_new();
2285 int mem_idx = ctx->mem_idx;
2287 gen_base_offset_addr(ctx, t0, base, offset);
2288 gen_load_gpr(t1, rt);
2289 switch (opc) {
2290 #if defined(TARGET_MIPS64)
2291 case OPC_SD:
2292 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2293 ctx->default_tcg_memop_mask);
2294 break;
2295 case OPC_SDL:
2296 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2297 break;
2298 case OPC_SDR:
2299 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2300 break;
2301 #endif
2302 case OPC_SWE:
2303 mem_idx = MIPS_HFLAG_UM;
2304 /* fall through */
2305 case OPC_SW:
2306 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2307 ctx->default_tcg_memop_mask);
2308 break;
2309 case OPC_SHE:
2310 mem_idx = MIPS_HFLAG_UM;
2311 /* fall through */
2312 case OPC_SH:
2313 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2314 ctx->default_tcg_memop_mask);
2315 break;
2316 case OPC_SBE:
2317 mem_idx = MIPS_HFLAG_UM;
2318 /* fall through */
2319 case OPC_SB:
2320 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2321 break;
2322 case OPC_SWLE:
2323 mem_idx = MIPS_HFLAG_UM;
2324 /* fall through */
2325 case OPC_SWL:
2326 gen_helper_0e2i(swl, t1, t0, mem_idx);
2327 break;
2328 case OPC_SWRE:
2329 mem_idx = MIPS_HFLAG_UM;
2330 /* fall through */
2331 case OPC_SWR:
2332 gen_helper_0e2i(swr, t1, t0, mem_idx);
2333 break;
2335 tcg_temp_free(t0);
2336 tcg_temp_free(t1);
2340 /* Store conditional */
2341 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2342 MemOp tcg_mo, bool eva)
2344 TCGv addr, t0, val;
2345 TCGLabel *l1 = gen_new_label();
2346 TCGLabel *done = gen_new_label();
2348 t0 = tcg_temp_new();
2349 addr = tcg_temp_new();
2350 /* compare the address against that of the preceding LL */
2351 gen_base_offset_addr(ctx, addr, base, offset);
2352 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2353 tcg_temp_free(addr);
2354 tcg_gen_movi_tl(t0, 0);
2355 gen_store_gpr(t0, rt);
2356 tcg_gen_br(done);
2358 gen_set_label(l1);
2359 /* generate cmpxchg */
2360 val = tcg_temp_new();
2361 gen_load_gpr(val, rt);
2362 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2363 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2364 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2365 gen_store_gpr(t0, rt);
2366 tcg_temp_free(val);
2368 gen_set_label(done);
2369 tcg_temp_free(t0);
2372 /* Load and store */
2373 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2374 TCGv t0)
2377 * Don't do NOP if destination is zero: we must perform the actual
2378 * memory access.
2380 switch (opc) {
2381 case OPC_LWC1:
2383 TCGv_i32 fp0 = tcg_temp_new_i32();
2384 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2385 ctx->default_tcg_memop_mask);
2386 gen_store_fpr32(ctx, fp0, ft);
2387 tcg_temp_free_i32(fp0);
2389 break;
2390 case OPC_SWC1:
2392 TCGv_i32 fp0 = tcg_temp_new_i32();
2393 gen_load_fpr32(ctx, fp0, ft);
2394 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2395 ctx->default_tcg_memop_mask);
2396 tcg_temp_free_i32(fp0);
2398 break;
2399 case OPC_LDC1:
2401 TCGv_i64 fp0 = tcg_temp_new_i64();
2402 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2403 ctx->default_tcg_memop_mask);
2404 gen_store_fpr64(ctx, fp0, ft);
2405 tcg_temp_free_i64(fp0);
2407 break;
2408 case OPC_SDC1:
2410 TCGv_i64 fp0 = tcg_temp_new_i64();
2411 gen_load_fpr64(ctx, fp0, ft);
2412 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2413 ctx->default_tcg_memop_mask);
2414 tcg_temp_free_i64(fp0);
2416 break;
2417 default:
2418 MIPS_INVAL("flt_ldst");
2419 gen_reserved_instruction(ctx);
2420 break;
2424 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2425 int rs, int16_t imm)
2427 TCGv t0 = tcg_temp_new();
2429 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2430 check_cp1_enabled(ctx);
2431 switch (op) {
2432 case OPC_LDC1:
2433 case OPC_SDC1:
2434 check_insn(ctx, ISA_MIPS2);
2435 /* Fallthrough */
2436 default:
2437 gen_base_offset_addr(ctx, t0, rs, imm);
2438 gen_flt_ldst(ctx, op, rt, t0);
2440 } else {
2441 generate_exception_err(ctx, EXCP_CpU, 1);
2443 tcg_temp_free(t0);
2446 /* Arithmetic with immediate operand */
2447 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2448 int rt, int rs, int imm)
2450 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2452 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2454 * If no destination, treat it as a NOP.
2455 * For addi, we must generate the overflow exception when needed.
2457 return;
2459 switch (opc) {
2460 case OPC_ADDI:
2462 TCGv t0 = tcg_temp_local_new();
2463 TCGv t1 = tcg_temp_new();
2464 TCGv t2 = tcg_temp_new();
2465 TCGLabel *l1 = gen_new_label();
2467 gen_load_gpr(t1, rs);
2468 tcg_gen_addi_tl(t0, t1, uimm);
2469 tcg_gen_ext32s_tl(t0, t0);
2471 tcg_gen_xori_tl(t1, t1, ~uimm);
2472 tcg_gen_xori_tl(t2, t0, uimm);
2473 tcg_gen_and_tl(t1, t1, t2);
2474 tcg_temp_free(t2);
2475 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2476 tcg_temp_free(t1);
2477 /* operands of same sign, result different sign */
2478 generate_exception(ctx, EXCP_OVERFLOW);
2479 gen_set_label(l1);
2480 tcg_gen_ext32s_tl(t0, t0);
2481 gen_store_gpr(t0, rt);
2482 tcg_temp_free(t0);
2484 break;
2485 case OPC_ADDIU:
2486 if (rs != 0) {
2487 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2488 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2489 } else {
2490 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2492 break;
2493 #if defined(TARGET_MIPS64)
2494 case OPC_DADDI:
2496 TCGv t0 = tcg_temp_local_new();
2497 TCGv t1 = tcg_temp_new();
2498 TCGv t2 = tcg_temp_new();
2499 TCGLabel *l1 = gen_new_label();
2501 gen_load_gpr(t1, rs);
2502 tcg_gen_addi_tl(t0, t1, uimm);
2504 tcg_gen_xori_tl(t1, t1, ~uimm);
2505 tcg_gen_xori_tl(t2, t0, uimm);
2506 tcg_gen_and_tl(t1, t1, t2);
2507 tcg_temp_free(t2);
2508 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2509 tcg_temp_free(t1);
2510 /* operands of same sign, result different sign */
2511 generate_exception(ctx, EXCP_OVERFLOW);
2512 gen_set_label(l1);
2513 gen_store_gpr(t0, rt);
2514 tcg_temp_free(t0);
2516 break;
2517 case OPC_DADDIU:
2518 if (rs != 0) {
2519 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2520 } else {
2521 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2523 break;
2524 #endif
2528 /* Logic with immediate operand */
2529 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2530 int rt, int rs, int16_t imm)
2532 target_ulong uimm;
2534 if (rt == 0) {
2535 /* If no destination, treat it as a NOP. */
2536 return;
2538 uimm = (uint16_t)imm;
2539 switch (opc) {
2540 case OPC_ANDI:
2541 if (likely(rs != 0)) {
2542 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2543 } else {
2544 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2546 break;
2547 case OPC_ORI:
2548 if (rs != 0) {
2549 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2550 } else {
2551 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2553 break;
2554 case OPC_XORI:
2555 if (likely(rs != 0)) {
2556 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2557 } else {
2558 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2560 break;
2561 case OPC_LUI:
2562 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2563 /* OPC_AUI */
2564 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2565 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2566 } else {
2567 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2569 break;
2571 default:
2572 break;
2576 /* Set on less than with immediate operand */
2577 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2578 int rt, int rs, int16_t imm)
2580 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2581 TCGv t0;
2583 if (rt == 0) {
2584 /* If no destination, treat it as a NOP. */
2585 return;
2587 t0 = tcg_temp_new();
2588 gen_load_gpr(t0, rs);
2589 switch (opc) {
2590 case OPC_SLTI:
2591 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2592 break;
2593 case OPC_SLTIU:
2594 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2595 break;
2597 tcg_temp_free(t0);
2600 /* Shifts with immediate operand */
2601 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2602 int rt, int rs, int16_t imm)
2604 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2605 TCGv t0;
2607 if (rt == 0) {
2608 /* If no destination, treat it as a NOP. */
2609 return;
2612 t0 = tcg_temp_new();
2613 gen_load_gpr(t0, rs);
2614 switch (opc) {
2615 case OPC_SLL:
2616 tcg_gen_shli_tl(t0, t0, uimm);
2617 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2618 break;
2619 case OPC_SRA:
2620 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2621 break;
2622 case OPC_SRL:
2623 if (uimm != 0) {
2624 tcg_gen_ext32u_tl(t0, t0);
2625 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2626 } else {
2627 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2629 break;
2630 case OPC_ROTR:
2631 if (uimm != 0) {
2632 TCGv_i32 t1 = tcg_temp_new_i32();
2634 tcg_gen_trunc_tl_i32(t1, t0);
2635 tcg_gen_rotri_i32(t1, t1, uimm);
2636 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2637 tcg_temp_free_i32(t1);
2638 } else {
2639 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2641 break;
2642 #if defined(TARGET_MIPS64)
2643 case OPC_DSLL:
2644 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2645 break;
2646 case OPC_DSRA:
2647 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2648 break;
2649 case OPC_DSRL:
2650 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2651 break;
2652 case OPC_DROTR:
2653 if (uimm != 0) {
2654 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2655 } else {
2656 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2658 break;
2659 case OPC_DSLL32:
2660 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2661 break;
2662 case OPC_DSRA32:
2663 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2664 break;
2665 case OPC_DSRL32:
2666 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2667 break;
2668 case OPC_DROTR32:
2669 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2670 break;
2671 #endif
2673 tcg_temp_free(t0);
2676 /* Arithmetic */
2677 static void gen_arith(DisasContext *ctx, uint32_t opc,
2678 int rd, int rs, int rt)
2680 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2681 && opc != OPC_DADD && opc != OPC_DSUB) {
2683 * If no destination, treat it as a NOP.
2684 * For add & sub, we must generate the overflow exception when needed.
2686 return;
2689 switch (opc) {
2690 case OPC_ADD:
2692 TCGv t0 = tcg_temp_local_new();
2693 TCGv t1 = tcg_temp_new();
2694 TCGv t2 = tcg_temp_new();
2695 TCGLabel *l1 = gen_new_label();
2697 gen_load_gpr(t1, rs);
2698 gen_load_gpr(t2, rt);
2699 tcg_gen_add_tl(t0, t1, t2);
2700 tcg_gen_ext32s_tl(t0, t0);
2701 tcg_gen_xor_tl(t1, t1, t2);
2702 tcg_gen_xor_tl(t2, t0, t2);
2703 tcg_gen_andc_tl(t1, t2, t1);
2704 tcg_temp_free(t2);
2705 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2706 tcg_temp_free(t1);
2707 /* operands of same sign, result different sign */
2708 generate_exception(ctx, EXCP_OVERFLOW);
2709 gen_set_label(l1);
2710 gen_store_gpr(t0, rd);
2711 tcg_temp_free(t0);
2713 break;
2714 case OPC_ADDU:
2715 if (rs != 0 && rt != 0) {
2716 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2717 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2718 } else if (rs == 0 && rt != 0) {
2719 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2720 } else if (rs != 0 && rt == 0) {
2721 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2722 } else {
2723 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2725 break;
2726 case OPC_SUB:
2728 TCGv t0 = tcg_temp_local_new();
2729 TCGv t1 = tcg_temp_new();
2730 TCGv t2 = tcg_temp_new();
2731 TCGLabel *l1 = gen_new_label();
2733 gen_load_gpr(t1, rs);
2734 gen_load_gpr(t2, rt);
2735 tcg_gen_sub_tl(t0, t1, t2);
2736 tcg_gen_ext32s_tl(t0, t0);
2737 tcg_gen_xor_tl(t2, t1, t2);
2738 tcg_gen_xor_tl(t1, t0, t1);
2739 tcg_gen_and_tl(t1, t1, t2);
2740 tcg_temp_free(t2);
2741 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2742 tcg_temp_free(t1);
2744 * operands of different sign, first operand and the result
2745 * of different sign
2747 generate_exception(ctx, EXCP_OVERFLOW);
2748 gen_set_label(l1);
2749 gen_store_gpr(t0, rd);
2750 tcg_temp_free(t0);
2752 break;
2753 case OPC_SUBU:
2754 if (rs != 0 && rt != 0) {
2755 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2756 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2757 } else if (rs == 0 && rt != 0) {
2758 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2759 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2760 } else if (rs != 0 && rt == 0) {
2761 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2762 } else {
2763 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2765 break;
2766 #if defined(TARGET_MIPS64)
2767 case OPC_DADD:
2769 TCGv t0 = tcg_temp_local_new();
2770 TCGv t1 = tcg_temp_new();
2771 TCGv t2 = tcg_temp_new();
2772 TCGLabel *l1 = gen_new_label();
2774 gen_load_gpr(t1, rs);
2775 gen_load_gpr(t2, rt);
2776 tcg_gen_add_tl(t0, t1, t2);
2777 tcg_gen_xor_tl(t1, t1, t2);
2778 tcg_gen_xor_tl(t2, t0, t2);
2779 tcg_gen_andc_tl(t1, t2, t1);
2780 tcg_temp_free(t2);
2781 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2782 tcg_temp_free(t1);
2783 /* operands of same sign, result different sign */
2784 generate_exception(ctx, EXCP_OVERFLOW);
2785 gen_set_label(l1);
2786 gen_store_gpr(t0, rd);
2787 tcg_temp_free(t0);
2789 break;
2790 case OPC_DADDU:
2791 if (rs != 0 && rt != 0) {
2792 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2793 } else if (rs == 0 && rt != 0) {
2794 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2795 } else if (rs != 0 && rt == 0) {
2796 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2797 } else {
2798 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2800 break;
2801 case OPC_DSUB:
2803 TCGv t0 = tcg_temp_local_new();
2804 TCGv t1 = tcg_temp_new();
2805 TCGv t2 = tcg_temp_new();
2806 TCGLabel *l1 = gen_new_label();
2808 gen_load_gpr(t1, rs);
2809 gen_load_gpr(t2, rt);
2810 tcg_gen_sub_tl(t0, t1, t2);
2811 tcg_gen_xor_tl(t2, t1, t2);
2812 tcg_gen_xor_tl(t1, t0, t1);
2813 tcg_gen_and_tl(t1, t1, t2);
2814 tcg_temp_free(t2);
2815 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2816 tcg_temp_free(t1);
2818 * Operands of different sign, first operand and result different
2819 * sign.
2821 generate_exception(ctx, EXCP_OVERFLOW);
2822 gen_set_label(l1);
2823 gen_store_gpr(t0, rd);
2824 tcg_temp_free(t0);
2826 break;
2827 case OPC_DSUBU:
2828 if (rs != 0 && rt != 0) {
2829 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2830 } else if (rs == 0 && rt != 0) {
2831 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2832 } else if (rs != 0 && rt == 0) {
2833 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2834 } else {
2835 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2837 break;
2838 #endif
2839 case OPC_MUL:
2840 if (likely(rs != 0 && rt != 0)) {
2841 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2842 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2843 } else {
2844 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2846 break;
2850 /* Conditional move */
2851 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2852 int rd, int rs, int rt)
2854 TCGv t0, t1, t2;
2856 if (rd == 0) {
2857 /* If no destination, treat it as a NOP. */
2858 return;
2861 t0 = tcg_temp_new();
2862 gen_load_gpr(t0, rt);
2863 t1 = tcg_const_tl(0);
2864 t2 = tcg_temp_new();
2865 gen_load_gpr(t2, rs);
2866 switch (opc) {
2867 case OPC_MOVN:
2868 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2869 break;
2870 case OPC_MOVZ:
2871 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2872 break;
2873 case OPC_SELNEZ:
2874 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2875 break;
2876 case OPC_SELEQZ:
2877 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2878 break;
2880 tcg_temp_free(t2);
2881 tcg_temp_free(t1);
2882 tcg_temp_free(t0);
2885 /* Logic */
2886 static void gen_logic(DisasContext *ctx, uint32_t opc,
2887 int rd, int rs, int rt)
2889 if (rd == 0) {
2890 /* If no destination, treat it as a NOP. */
2891 return;
2894 switch (opc) {
2895 case OPC_AND:
2896 if (likely(rs != 0 && rt != 0)) {
2897 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2898 } else {
2899 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2901 break;
2902 case OPC_NOR:
2903 if (rs != 0 && rt != 0) {
2904 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2905 } else if (rs == 0 && rt != 0) {
2906 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2907 } else if (rs != 0 && rt == 0) {
2908 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2909 } else {
2910 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2912 break;
2913 case OPC_OR:
2914 if (likely(rs != 0 && rt != 0)) {
2915 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2916 } else if (rs == 0 && rt != 0) {
2917 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2918 } else if (rs != 0 && rt == 0) {
2919 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2920 } else {
2921 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2923 break;
2924 case OPC_XOR:
2925 if (likely(rs != 0 && rt != 0)) {
2926 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2927 } else if (rs == 0 && rt != 0) {
2928 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2929 } else if (rs != 0 && rt == 0) {
2930 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2931 } else {
2932 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2934 break;
2938 /* Set on lower than */
2939 static void gen_slt(DisasContext *ctx, uint32_t opc,
2940 int rd, int rs, int rt)
2942 TCGv t0, t1;
2944 if (rd == 0) {
2945 /* If no destination, treat it as a NOP. */
2946 return;
2949 t0 = tcg_temp_new();
2950 t1 = tcg_temp_new();
2951 gen_load_gpr(t0, rs);
2952 gen_load_gpr(t1, rt);
2953 switch (opc) {
2954 case OPC_SLT:
2955 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2956 break;
2957 case OPC_SLTU:
2958 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2959 break;
2961 tcg_temp_free(t0);
2962 tcg_temp_free(t1);
2965 /* Shifts */
2966 static void gen_shift(DisasContext *ctx, uint32_t opc,
2967 int rd, int rs, int rt)
2969 TCGv t0, t1;
2971 if (rd == 0) {
2973 * If no destination, treat it as a NOP.
2974 * For add & sub, we must generate the overflow exception when needed.
2976 return;
2979 t0 = tcg_temp_new();
2980 t1 = tcg_temp_new();
2981 gen_load_gpr(t0, rs);
2982 gen_load_gpr(t1, rt);
2983 switch (opc) {
2984 case OPC_SLLV:
2985 tcg_gen_andi_tl(t0, t0, 0x1f);
2986 tcg_gen_shl_tl(t0, t1, t0);
2987 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2988 break;
2989 case OPC_SRAV:
2990 tcg_gen_andi_tl(t0, t0, 0x1f);
2991 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2992 break;
2993 case OPC_SRLV:
2994 tcg_gen_ext32u_tl(t1, t1);
2995 tcg_gen_andi_tl(t0, t0, 0x1f);
2996 tcg_gen_shr_tl(t0, t1, t0);
2997 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2998 break;
2999 case OPC_ROTRV:
3001 TCGv_i32 t2 = tcg_temp_new_i32();
3002 TCGv_i32 t3 = tcg_temp_new_i32();
3004 tcg_gen_trunc_tl_i32(t2, t0);
3005 tcg_gen_trunc_tl_i32(t3, t1);
3006 tcg_gen_andi_i32(t2, t2, 0x1f);
3007 tcg_gen_rotr_i32(t2, t3, t2);
3008 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3009 tcg_temp_free_i32(t2);
3010 tcg_temp_free_i32(t3);
3012 break;
3013 #if defined(TARGET_MIPS64)
3014 case OPC_DSLLV:
3015 tcg_gen_andi_tl(t0, t0, 0x3f);
3016 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3017 break;
3018 case OPC_DSRAV:
3019 tcg_gen_andi_tl(t0, t0, 0x3f);
3020 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3021 break;
3022 case OPC_DSRLV:
3023 tcg_gen_andi_tl(t0, t0, 0x3f);
3024 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3025 break;
3026 case OPC_DROTRV:
3027 tcg_gen_andi_tl(t0, t0, 0x3f);
3028 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3029 break;
3030 #endif
3032 tcg_temp_free(t0);
3033 tcg_temp_free(t1);
3036 /* Arithmetic on HI/LO registers */
3037 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3039 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3040 /* Treat as NOP. */
3041 return;
3044 if (acc != 0) {
3045 check_dsp(ctx);
3048 switch (opc) {
3049 case OPC_MFHI:
3050 #if defined(TARGET_MIPS64)
3051 if (acc != 0) {
3052 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3053 } else
3054 #endif
3056 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3058 break;
3059 case OPC_MFLO:
3060 #if defined(TARGET_MIPS64)
3061 if (acc != 0) {
3062 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3063 } else
3064 #endif
3066 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3068 break;
3069 case OPC_MTHI:
3070 if (reg != 0) {
3071 #if defined(TARGET_MIPS64)
3072 if (acc != 0) {
3073 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3074 } else
3075 #endif
3077 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3079 } else {
3080 tcg_gen_movi_tl(cpu_HI[acc], 0);
3082 break;
3083 case OPC_MTLO:
3084 if (reg != 0) {
3085 #if defined(TARGET_MIPS64)
3086 if (acc != 0) {
3087 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3088 } else
3089 #endif
3091 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3093 } else {
3094 tcg_gen_movi_tl(cpu_LO[acc], 0);
3096 break;
3100 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3101 MemOp memop)
3103 TCGv t0 = tcg_const_tl(addr);
3104 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3105 gen_store_gpr(t0, reg);
3106 tcg_temp_free(t0);
3109 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3110 int rs)
3112 target_long offset;
3113 target_long addr;
3115 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3116 case OPC_ADDIUPC:
3117 if (rs != 0) {
3118 offset = sextract32(ctx->opcode << 2, 0, 21);
3119 addr = addr_add(ctx, pc, offset);
3120 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3122 break;
3123 case R6_OPC_LWPC:
3124 offset = sextract32(ctx->opcode << 2, 0, 21);
3125 addr = addr_add(ctx, pc, offset);
3126 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3127 break;
3128 #if defined(TARGET_MIPS64)
3129 case OPC_LWUPC:
3130 check_mips_64(ctx);
3131 offset = sextract32(ctx->opcode << 2, 0, 21);
3132 addr = addr_add(ctx, pc, offset);
3133 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3134 break;
3135 #endif
3136 default:
3137 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3138 case OPC_AUIPC:
3139 if (rs != 0) {
3140 offset = sextract32(ctx->opcode, 0, 16) << 16;
3141 addr = addr_add(ctx, pc, offset);
3142 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3144 break;
3145 case OPC_ALUIPC:
3146 if (rs != 0) {
3147 offset = sextract32(ctx->opcode, 0, 16) << 16;
3148 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3149 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3151 break;
3152 #if defined(TARGET_MIPS64)
3153 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3154 case R6_OPC_LDPC + (1 << 16):
3155 case R6_OPC_LDPC + (2 << 16):
3156 case R6_OPC_LDPC + (3 << 16):
3157 check_mips_64(ctx);
3158 offset = sextract32(ctx->opcode << 3, 0, 21);
3159 addr = addr_add(ctx, (pc & ~0x7), offset);
3160 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3161 break;
3162 #endif
3163 default:
3164 MIPS_INVAL("OPC_PCREL");
3165 gen_reserved_instruction(ctx);
3166 break;
3168 break;
3172 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3174 TCGv t0, t1;
3176 if (rd == 0) {
3177 /* Treat as NOP. */
3178 return;
3181 t0 = tcg_temp_new();
3182 t1 = tcg_temp_new();
3184 gen_load_gpr(t0, rs);
3185 gen_load_gpr(t1, rt);
3187 switch (opc) {
3188 case R6_OPC_DIV:
3190 TCGv t2 = tcg_temp_new();
3191 TCGv t3 = tcg_temp_new();
3192 tcg_gen_ext32s_tl(t0, t0);
3193 tcg_gen_ext32s_tl(t1, t1);
3194 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3195 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3196 tcg_gen_and_tl(t2, t2, t3);
3197 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3198 tcg_gen_or_tl(t2, t2, t3);
3199 tcg_gen_movi_tl(t3, 0);
3200 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3201 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3202 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3203 tcg_temp_free(t3);
3204 tcg_temp_free(t2);
3206 break;
3207 case R6_OPC_MOD:
3209 TCGv t2 = tcg_temp_new();
3210 TCGv t3 = tcg_temp_new();
3211 tcg_gen_ext32s_tl(t0, t0);
3212 tcg_gen_ext32s_tl(t1, t1);
3213 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3214 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3215 tcg_gen_and_tl(t2, t2, t3);
3216 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3217 tcg_gen_or_tl(t2, t2, t3);
3218 tcg_gen_movi_tl(t3, 0);
3219 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3220 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3221 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3222 tcg_temp_free(t3);
3223 tcg_temp_free(t2);
3225 break;
3226 case R6_OPC_DIVU:
3228 TCGv t2 = tcg_const_tl(0);
3229 TCGv t3 = tcg_const_tl(1);
3230 tcg_gen_ext32u_tl(t0, t0);
3231 tcg_gen_ext32u_tl(t1, t1);
3232 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3233 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3234 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3235 tcg_temp_free(t3);
3236 tcg_temp_free(t2);
3238 break;
3239 case R6_OPC_MODU:
3241 TCGv t2 = tcg_const_tl(0);
3242 TCGv t3 = tcg_const_tl(1);
3243 tcg_gen_ext32u_tl(t0, t0);
3244 tcg_gen_ext32u_tl(t1, t1);
3245 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3246 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3247 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3248 tcg_temp_free(t3);
3249 tcg_temp_free(t2);
3251 break;
3252 case R6_OPC_MUL:
3254 TCGv_i32 t2 = tcg_temp_new_i32();
3255 TCGv_i32 t3 = tcg_temp_new_i32();
3256 tcg_gen_trunc_tl_i32(t2, t0);
3257 tcg_gen_trunc_tl_i32(t3, t1);
3258 tcg_gen_mul_i32(t2, t2, t3);
3259 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3260 tcg_temp_free_i32(t2);
3261 tcg_temp_free_i32(t3);
3263 break;
3264 case R6_OPC_MUH:
3266 TCGv_i32 t2 = tcg_temp_new_i32();
3267 TCGv_i32 t3 = tcg_temp_new_i32();
3268 tcg_gen_trunc_tl_i32(t2, t0);
3269 tcg_gen_trunc_tl_i32(t3, t1);
3270 tcg_gen_muls2_i32(t2, t3, t2, t3);
3271 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3272 tcg_temp_free_i32(t2);
3273 tcg_temp_free_i32(t3);
3275 break;
3276 case R6_OPC_MULU:
3278 TCGv_i32 t2 = tcg_temp_new_i32();
3279 TCGv_i32 t3 = tcg_temp_new_i32();
3280 tcg_gen_trunc_tl_i32(t2, t0);
3281 tcg_gen_trunc_tl_i32(t3, t1);
3282 tcg_gen_mul_i32(t2, t2, t3);
3283 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3284 tcg_temp_free_i32(t2);
3285 tcg_temp_free_i32(t3);
3287 break;
3288 case R6_OPC_MUHU:
3290 TCGv_i32 t2 = tcg_temp_new_i32();
3291 TCGv_i32 t3 = tcg_temp_new_i32();
3292 tcg_gen_trunc_tl_i32(t2, t0);
3293 tcg_gen_trunc_tl_i32(t3, t1);
3294 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3295 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3296 tcg_temp_free_i32(t2);
3297 tcg_temp_free_i32(t3);
3299 break;
3300 #if defined(TARGET_MIPS64)
3301 case R6_OPC_DDIV:
3303 TCGv t2 = tcg_temp_new();
3304 TCGv t3 = tcg_temp_new();
3305 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3306 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3307 tcg_gen_and_tl(t2, t2, t3);
3308 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3309 tcg_gen_or_tl(t2, t2, t3);
3310 tcg_gen_movi_tl(t3, 0);
3311 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3312 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3313 tcg_temp_free(t3);
3314 tcg_temp_free(t2);
3316 break;
3317 case R6_OPC_DMOD:
3319 TCGv t2 = tcg_temp_new();
3320 TCGv t3 = tcg_temp_new();
3321 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3322 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3323 tcg_gen_and_tl(t2, t2, t3);
3324 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3325 tcg_gen_or_tl(t2, t2, t3);
3326 tcg_gen_movi_tl(t3, 0);
3327 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3328 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3329 tcg_temp_free(t3);
3330 tcg_temp_free(t2);
3332 break;
3333 case R6_OPC_DDIVU:
3335 TCGv t2 = tcg_const_tl(0);
3336 TCGv t3 = tcg_const_tl(1);
3337 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3338 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3339 tcg_temp_free(t3);
3340 tcg_temp_free(t2);
3342 break;
3343 case R6_OPC_DMODU:
3345 TCGv t2 = tcg_const_tl(0);
3346 TCGv t3 = tcg_const_tl(1);
3347 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3348 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3349 tcg_temp_free(t3);
3350 tcg_temp_free(t2);
3352 break;
3353 case R6_OPC_DMUL:
3354 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3355 break;
3356 case R6_OPC_DMUH:
3358 TCGv t2 = tcg_temp_new();
3359 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3360 tcg_temp_free(t2);
3362 break;
3363 case R6_OPC_DMULU:
3364 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3365 break;
3366 case R6_OPC_DMUHU:
3368 TCGv t2 = tcg_temp_new();
3369 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3370 tcg_temp_free(t2);
3372 break;
3373 #endif
3374 default:
3375 MIPS_INVAL("r6 mul/div");
3376 gen_reserved_instruction(ctx);
3377 goto out;
3379 out:
3380 tcg_temp_free(t0);
3381 tcg_temp_free(t1);
3384 #if defined(TARGET_MIPS64)
3385 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3387 TCGv t0, t1;
3389 t0 = tcg_temp_new();
3390 t1 = tcg_temp_new();
3392 gen_load_gpr(t0, rs);
3393 gen_load_gpr(t1, rt);
3395 switch (opc) {
3396 case MMI_OPC_DIV1:
3398 TCGv t2 = tcg_temp_new();
3399 TCGv t3 = tcg_temp_new();
3400 tcg_gen_ext32s_tl(t0, t0);
3401 tcg_gen_ext32s_tl(t1, t1);
3402 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3403 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3404 tcg_gen_and_tl(t2, t2, t3);
3405 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3406 tcg_gen_or_tl(t2, t2, t3);
3407 tcg_gen_movi_tl(t3, 0);
3408 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3409 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3410 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3411 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3412 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3413 tcg_temp_free(t3);
3414 tcg_temp_free(t2);
3416 break;
3417 case MMI_OPC_DIVU1:
3419 TCGv t2 = tcg_const_tl(0);
3420 TCGv t3 = tcg_const_tl(1);
3421 tcg_gen_ext32u_tl(t0, t0);
3422 tcg_gen_ext32u_tl(t1, t1);
3423 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3424 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3425 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3426 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3427 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3428 tcg_temp_free(t3);
3429 tcg_temp_free(t2);
3431 break;
3432 default:
3433 MIPS_INVAL("div1 TX79");
3434 gen_reserved_instruction(ctx);
3435 goto out;
3437 out:
3438 tcg_temp_free(t0);
3439 tcg_temp_free(t1);
3441 #endif
3443 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3444 int acc, int rs, int rt)
3446 TCGv t0, t1;
3448 t0 = tcg_temp_new();
3449 t1 = tcg_temp_new();
3451 gen_load_gpr(t0, rs);
3452 gen_load_gpr(t1, rt);
3454 if (acc != 0) {
3455 check_dsp(ctx);
3458 switch (opc) {
3459 case OPC_DIV:
3461 TCGv t2 = tcg_temp_new();
3462 TCGv t3 = tcg_temp_new();
3463 tcg_gen_ext32s_tl(t0, t0);
3464 tcg_gen_ext32s_tl(t1, t1);
3465 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3466 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3467 tcg_gen_and_tl(t2, t2, t3);
3468 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3469 tcg_gen_or_tl(t2, t2, t3);
3470 tcg_gen_movi_tl(t3, 0);
3471 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3472 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3473 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3474 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3475 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3476 tcg_temp_free(t3);
3477 tcg_temp_free(t2);
3479 break;
3480 case OPC_DIVU:
3482 TCGv t2 = tcg_const_tl(0);
3483 TCGv t3 = tcg_const_tl(1);
3484 tcg_gen_ext32u_tl(t0, t0);
3485 tcg_gen_ext32u_tl(t1, t1);
3486 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3487 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3488 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3489 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3490 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3491 tcg_temp_free(t3);
3492 tcg_temp_free(t2);
3494 break;
3495 case OPC_MULT:
3497 TCGv_i32 t2 = tcg_temp_new_i32();
3498 TCGv_i32 t3 = tcg_temp_new_i32();
3499 tcg_gen_trunc_tl_i32(t2, t0);
3500 tcg_gen_trunc_tl_i32(t3, t1);
3501 tcg_gen_muls2_i32(t2, t3, t2, t3);
3502 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3503 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3504 tcg_temp_free_i32(t2);
3505 tcg_temp_free_i32(t3);
3507 break;
3508 case OPC_MULTU:
3510 TCGv_i32 t2 = tcg_temp_new_i32();
3511 TCGv_i32 t3 = tcg_temp_new_i32();
3512 tcg_gen_trunc_tl_i32(t2, t0);
3513 tcg_gen_trunc_tl_i32(t3, t1);
3514 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3515 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3516 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3517 tcg_temp_free_i32(t2);
3518 tcg_temp_free_i32(t3);
3520 break;
3521 #if defined(TARGET_MIPS64)
3522 case OPC_DDIV:
3524 TCGv t2 = tcg_temp_new();
3525 TCGv t3 = tcg_temp_new();
3526 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3527 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3528 tcg_gen_and_tl(t2, t2, t3);
3529 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3530 tcg_gen_or_tl(t2, t2, t3);
3531 tcg_gen_movi_tl(t3, 0);
3532 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3533 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3534 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3535 tcg_temp_free(t3);
3536 tcg_temp_free(t2);
3538 break;
3539 case OPC_DDIVU:
3541 TCGv t2 = tcg_const_tl(0);
3542 TCGv t3 = tcg_const_tl(1);
3543 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3544 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3545 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3546 tcg_temp_free(t3);
3547 tcg_temp_free(t2);
3549 break;
3550 case OPC_DMULT:
3551 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3552 break;
3553 case OPC_DMULTU:
3554 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3555 break;
3556 #endif
3557 case OPC_MADD:
3559 TCGv_i64 t2 = tcg_temp_new_i64();
3560 TCGv_i64 t3 = tcg_temp_new_i64();
3562 tcg_gen_ext_tl_i64(t2, t0);
3563 tcg_gen_ext_tl_i64(t3, t1);
3564 tcg_gen_mul_i64(t2, t2, t3);
3565 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3566 tcg_gen_add_i64(t2, t2, t3);
3567 tcg_temp_free_i64(t3);
3568 gen_move_low32(cpu_LO[acc], t2);
3569 gen_move_high32(cpu_HI[acc], t2);
3570 tcg_temp_free_i64(t2);
3572 break;
3573 case OPC_MADDU:
3575 TCGv_i64 t2 = tcg_temp_new_i64();
3576 TCGv_i64 t3 = tcg_temp_new_i64();
3578 tcg_gen_ext32u_tl(t0, t0);
3579 tcg_gen_ext32u_tl(t1, t1);
3580 tcg_gen_extu_tl_i64(t2, t0);
3581 tcg_gen_extu_tl_i64(t3, t1);
3582 tcg_gen_mul_i64(t2, t2, t3);
3583 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3584 tcg_gen_add_i64(t2, t2, t3);
3585 tcg_temp_free_i64(t3);
3586 gen_move_low32(cpu_LO[acc], t2);
3587 gen_move_high32(cpu_HI[acc], t2);
3588 tcg_temp_free_i64(t2);
3590 break;
3591 case OPC_MSUB:
3593 TCGv_i64 t2 = tcg_temp_new_i64();
3594 TCGv_i64 t3 = tcg_temp_new_i64();
3596 tcg_gen_ext_tl_i64(t2, t0);
3597 tcg_gen_ext_tl_i64(t3, t1);
3598 tcg_gen_mul_i64(t2, t2, t3);
3599 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3600 tcg_gen_sub_i64(t2, t3, t2);
3601 tcg_temp_free_i64(t3);
3602 gen_move_low32(cpu_LO[acc], t2);
3603 gen_move_high32(cpu_HI[acc], t2);
3604 tcg_temp_free_i64(t2);
3606 break;
3607 case OPC_MSUBU:
3609 TCGv_i64 t2 = tcg_temp_new_i64();
3610 TCGv_i64 t3 = tcg_temp_new_i64();
3612 tcg_gen_ext32u_tl(t0, t0);
3613 tcg_gen_ext32u_tl(t1, t1);
3614 tcg_gen_extu_tl_i64(t2, t0);
3615 tcg_gen_extu_tl_i64(t3, t1);
3616 tcg_gen_mul_i64(t2, t2, t3);
3617 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3618 tcg_gen_sub_i64(t2, t3, t2);
3619 tcg_temp_free_i64(t3);
3620 gen_move_low32(cpu_LO[acc], t2);
3621 gen_move_high32(cpu_HI[acc], t2);
3622 tcg_temp_free_i64(t2);
3624 break;
3625 default:
3626 MIPS_INVAL("mul/div");
3627 gen_reserved_instruction(ctx);
3628 goto out;
3630 out:
3631 tcg_temp_free(t0);
3632 tcg_temp_free(t1);
3636 * These MULT[U] and MADD[U] instructions implemented in for example
3637 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
3638 * architectures are special three-operand variants with the syntax
3640 * MULT[U][1] rd, rs, rt
3642 * such that
3644 * (rd, LO, HI) <- rs * rt
3646 * and
3648 * MADD[U][1] rd, rs, rt
3650 * such that
3652 * (rd, LO, HI) <- (LO, HI) + rs * rt
3654 * where the low-order 32-bits of the result is placed into both the
3655 * GPR rd and the special register LO. The high-order 32-bits of the
3656 * result is placed into the special register HI.
3658 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3659 * which is the zero register that always reads as 0.
3661 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3662 int rd, int rs, int rt)
3664 TCGv t0 = tcg_temp_new();
3665 TCGv t1 = tcg_temp_new();
3666 int acc = 0;
3668 gen_load_gpr(t0, rs);
3669 gen_load_gpr(t1, rt);
3671 switch (opc) {
3672 case MMI_OPC_MULT1:
3673 acc = 1;
3674 /* Fall through */
3675 case OPC_MULT:
3677 TCGv_i32 t2 = tcg_temp_new_i32();
3678 TCGv_i32 t3 = tcg_temp_new_i32();
3679 tcg_gen_trunc_tl_i32(t2, t0);
3680 tcg_gen_trunc_tl_i32(t3, t1);
3681 tcg_gen_muls2_i32(t2, t3, t2, t3);
3682 if (rd) {
3683 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3685 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3686 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3687 tcg_temp_free_i32(t2);
3688 tcg_temp_free_i32(t3);
3690 break;
3691 case MMI_OPC_MULTU1:
3692 acc = 1;
3693 /* Fall through */
3694 case OPC_MULTU:
3696 TCGv_i32 t2 = tcg_temp_new_i32();
3697 TCGv_i32 t3 = tcg_temp_new_i32();
3698 tcg_gen_trunc_tl_i32(t2, t0);
3699 tcg_gen_trunc_tl_i32(t3, t1);
3700 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3701 if (rd) {
3702 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3704 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3705 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3706 tcg_temp_free_i32(t2);
3707 tcg_temp_free_i32(t3);
3709 break;
3710 case MMI_OPC_MADD1:
3711 acc = 1;
3712 /* Fall through */
3713 case MMI_OPC_MADD:
3715 TCGv_i64 t2 = tcg_temp_new_i64();
3716 TCGv_i64 t3 = tcg_temp_new_i64();
3718 tcg_gen_ext_tl_i64(t2, t0);
3719 tcg_gen_ext_tl_i64(t3, t1);
3720 tcg_gen_mul_i64(t2, t2, t3);
3721 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3722 tcg_gen_add_i64(t2, t2, t3);
3723 tcg_temp_free_i64(t3);
3724 gen_move_low32(cpu_LO[acc], t2);
3725 gen_move_high32(cpu_HI[acc], t2);
3726 if (rd) {
3727 gen_move_low32(cpu_gpr[rd], t2);
3729 tcg_temp_free_i64(t2);
3731 break;
3732 case MMI_OPC_MADDU1:
3733 acc = 1;
3734 /* Fall through */
3735 case MMI_OPC_MADDU:
3737 TCGv_i64 t2 = tcg_temp_new_i64();
3738 TCGv_i64 t3 = tcg_temp_new_i64();
3740 tcg_gen_ext32u_tl(t0, t0);
3741 tcg_gen_ext32u_tl(t1, t1);
3742 tcg_gen_extu_tl_i64(t2, t0);
3743 tcg_gen_extu_tl_i64(t3, t1);
3744 tcg_gen_mul_i64(t2, t2, t3);
3745 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3746 tcg_gen_add_i64(t2, t2, t3);
3747 tcg_temp_free_i64(t3);
3748 gen_move_low32(cpu_LO[acc], t2);
3749 gen_move_high32(cpu_HI[acc], t2);
3750 if (rd) {
3751 gen_move_low32(cpu_gpr[rd], t2);
3753 tcg_temp_free_i64(t2);
3755 break;
3756 default:
3757 MIPS_INVAL("mul/madd TXx9");
3758 gen_reserved_instruction(ctx);
3759 goto out;
3762 out:
3763 tcg_temp_free(t0);
3764 tcg_temp_free(t1);
3767 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
3768 int rd, int rs, int rt)
3770 TCGv t0 = tcg_temp_new();
3771 TCGv t1 = tcg_temp_new();
3773 gen_load_gpr(t0, rs);
3774 gen_load_gpr(t1, rt);
3776 switch (opc) {
3777 case OPC_VR54XX_MULS:
3778 gen_helper_muls(t0, cpu_env, t0, t1);
3779 break;
3780 case OPC_VR54XX_MULSU:
3781 gen_helper_mulsu(t0, cpu_env, t0, t1);
3782 break;
3783 case OPC_VR54XX_MACC:
3784 gen_helper_macc(t0, cpu_env, t0, t1);
3785 break;
3786 case OPC_VR54XX_MACCU:
3787 gen_helper_maccu(t0, cpu_env, t0, t1);
3788 break;
3789 case OPC_VR54XX_MSAC:
3790 gen_helper_msac(t0, cpu_env, t0, t1);
3791 break;
3792 case OPC_VR54XX_MSACU:
3793 gen_helper_msacu(t0, cpu_env, t0, t1);
3794 break;
3795 case OPC_VR54XX_MULHI:
3796 gen_helper_mulhi(t0, cpu_env, t0, t1);
3797 break;
3798 case OPC_VR54XX_MULHIU:
3799 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3800 break;
3801 case OPC_VR54XX_MULSHI:
3802 gen_helper_mulshi(t0, cpu_env, t0, t1);
3803 break;
3804 case OPC_VR54XX_MULSHIU:
3805 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3806 break;
3807 case OPC_VR54XX_MACCHI:
3808 gen_helper_macchi(t0, cpu_env, t0, t1);
3809 break;
3810 case OPC_VR54XX_MACCHIU:
3811 gen_helper_macchiu(t0, cpu_env, t0, t1);
3812 break;
3813 case OPC_VR54XX_MSACHI:
3814 gen_helper_msachi(t0, cpu_env, t0, t1);
3815 break;
3816 case OPC_VR54XX_MSACHIU:
3817 gen_helper_msachiu(t0, cpu_env, t0, t1);
3818 break;
3819 default:
3820 MIPS_INVAL("mul vr54xx");
3821 gen_reserved_instruction(ctx);
3822 goto out;
3824 gen_store_gpr(t0, rd);
3826 out:
3827 tcg_temp_free(t0);
3828 tcg_temp_free(t1);
3831 static void gen_cl(DisasContext *ctx, uint32_t opc,
3832 int rd, int rs)
3834 TCGv t0;
3836 if (rd == 0) {
3837 /* Treat as NOP. */
3838 return;
3840 t0 = cpu_gpr[rd];
3841 gen_load_gpr(t0, rs);
3843 switch (opc) {
3844 case OPC_CLO:
3845 case R6_OPC_CLO:
3846 #if defined(TARGET_MIPS64)
3847 case OPC_DCLO:
3848 case R6_OPC_DCLO:
3849 #endif
3850 tcg_gen_not_tl(t0, t0);
3851 break;
3854 switch (opc) {
3855 case OPC_CLO:
3856 case R6_OPC_CLO:
3857 case OPC_CLZ:
3858 case R6_OPC_CLZ:
3859 tcg_gen_ext32u_tl(t0, t0);
3860 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3861 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3862 break;
3863 #if defined(TARGET_MIPS64)
3864 case OPC_DCLO:
3865 case R6_OPC_DCLO:
3866 case OPC_DCLZ:
3867 case R6_OPC_DCLZ:
3868 tcg_gen_clzi_i64(t0, t0, 64);
3869 break;
3870 #endif
3874 /* Godson integer instructions */
3875 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3876 int rd, int rs, int rt)
3878 TCGv t0, t1;
3880 if (rd == 0) {
3881 /* Treat as NOP. */
3882 return;
3885 switch (opc) {
3886 case OPC_MULT_G_2E:
3887 case OPC_MULT_G_2F:
3888 case OPC_MULTU_G_2E:
3889 case OPC_MULTU_G_2F:
3890 #if defined(TARGET_MIPS64)
3891 case OPC_DMULT_G_2E:
3892 case OPC_DMULT_G_2F:
3893 case OPC_DMULTU_G_2E:
3894 case OPC_DMULTU_G_2F:
3895 #endif
3896 t0 = tcg_temp_new();
3897 t1 = tcg_temp_new();
3898 break;
3899 default:
3900 t0 = tcg_temp_local_new();
3901 t1 = tcg_temp_local_new();
3902 break;
3905 gen_load_gpr(t0, rs);
3906 gen_load_gpr(t1, rt);
3908 switch (opc) {
3909 case OPC_MULT_G_2E:
3910 case OPC_MULT_G_2F:
3911 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3912 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3913 break;
3914 case OPC_MULTU_G_2E:
3915 case OPC_MULTU_G_2F:
3916 tcg_gen_ext32u_tl(t0, t0);
3917 tcg_gen_ext32u_tl(t1, t1);
3918 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3919 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3920 break;
3921 case OPC_DIV_G_2E:
3922 case OPC_DIV_G_2F:
3924 TCGLabel *l1 = gen_new_label();
3925 TCGLabel *l2 = gen_new_label();
3926 TCGLabel *l3 = gen_new_label();
3927 tcg_gen_ext32s_tl(t0, t0);
3928 tcg_gen_ext32s_tl(t1, t1);
3929 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3930 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3931 tcg_gen_br(l3);
3932 gen_set_label(l1);
3933 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3934 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3935 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3936 tcg_gen_br(l3);
3937 gen_set_label(l2);
3938 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3939 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3940 gen_set_label(l3);
3942 break;
3943 case OPC_DIVU_G_2E:
3944 case OPC_DIVU_G_2F:
3946 TCGLabel *l1 = gen_new_label();
3947 TCGLabel *l2 = gen_new_label();
3948 tcg_gen_ext32u_tl(t0, t0);
3949 tcg_gen_ext32u_tl(t1, t1);
3950 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3951 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3952 tcg_gen_br(l2);
3953 gen_set_label(l1);
3954 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3955 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3956 gen_set_label(l2);
3958 break;
3959 case OPC_MOD_G_2E:
3960 case OPC_MOD_G_2F:
3962 TCGLabel *l1 = gen_new_label();
3963 TCGLabel *l2 = gen_new_label();
3964 TCGLabel *l3 = gen_new_label();
3965 tcg_gen_ext32u_tl(t0, t0);
3966 tcg_gen_ext32u_tl(t1, t1);
3967 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3968 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3969 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3970 gen_set_label(l1);
3971 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3972 tcg_gen_br(l3);
3973 gen_set_label(l2);
3974 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3975 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3976 gen_set_label(l3);
3978 break;
3979 case OPC_MODU_G_2E:
3980 case OPC_MODU_G_2F:
3982 TCGLabel *l1 = gen_new_label();
3983 TCGLabel *l2 = gen_new_label();
3984 tcg_gen_ext32u_tl(t0, t0);
3985 tcg_gen_ext32u_tl(t1, t1);
3986 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3987 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3988 tcg_gen_br(l2);
3989 gen_set_label(l1);
3990 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3991 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3992 gen_set_label(l2);
3994 break;
3995 #if defined(TARGET_MIPS64)
3996 case OPC_DMULT_G_2E:
3997 case OPC_DMULT_G_2F:
3998 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3999 break;
4000 case OPC_DMULTU_G_2E:
4001 case OPC_DMULTU_G_2F:
4002 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4003 break;
4004 case OPC_DDIV_G_2E:
4005 case OPC_DDIV_G_2F:
4007 TCGLabel *l1 = gen_new_label();
4008 TCGLabel *l2 = gen_new_label();
4009 TCGLabel *l3 = gen_new_label();
4010 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4011 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4012 tcg_gen_br(l3);
4013 gen_set_label(l1);
4014 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4015 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4016 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4017 tcg_gen_br(l3);
4018 gen_set_label(l2);
4019 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4020 gen_set_label(l3);
4022 break;
4023 case OPC_DDIVU_G_2E:
4024 case OPC_DDIVU_G_2F:
4026 TCGLabel *l1 = gen_new_label();
4027 TCGLabel *l2 = gen_new_label();
4028 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4029 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4030 tcg_gen_br(l2);
4031 gen_set_label(l1);
4032 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4033 gen_set_label(l2);
4035 break;
4036 case OPC_DMOD_G_2E:
4037 case OPC_DMOD_G_2F:
4039 TCGLabel *l1 = gen_new_label();
4040 TCGLabel *l2 = gen_new_label();
4041 TCGLabel *l3 = gen_new_label();
4042 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4043 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4044 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4045 gen_set_label(l1);
4046 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4047 tcg_gen_br(l3);
4048 gen_set_label(l2);
4049 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4050 gen_set_label(l3);
4052 break;
4053 case OPC_DMODU_G_2E:
4054 case OPC_DMODU_G_2F:
4056 TCGLabel *l1 = gen_new_label();
4057 TCGLabel *l2 = gen_new_label();
4058 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4059 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4060 tcg_gen_br(l2);
4061 gen_set_label(l1);
4062 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4063 gen_set_label(l2);
4065 break;
4066 #endif
4069 tcg_temp_free(t0);
4070 tcg_temp_free(t1);
4073 /* Loongson multimedia instructions */
4074 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4076 uint32_t opc, shift_max;
4077 TCGv_i64 t0, t1;
4078 TCGCond cond;
4080 opc = MASK_LMMI(ctx->opcode);
4081 switch (opc) {
4082 case OPC_ADD_CP2:
4083 case OPC_SUB_CP2:
4084 case OPC_DADD_CP2:
4085 case OPC_DSUB_CP2:
4086 t0 = tcg_temp_local_new_i64();
4087 t1 = tcg_temp_local_new_i64();
4088 break;
4089 default:
4090 t0 = tcg_temp_new_i64();
4091 t1 = tcg_temp_new_i64();
4092 break;
4095 check_cp1_enabled(ctx);
4096 gen_load_fpr64(ctx, t0, rs);
4097 gen_load_fpr64(ctx, t1, rt);
4099 switch (opc) {
4100 case OPC_PADDSH:
4101 gen_helper_paddsh(t0, t0, t1);
4102 break;
4103 case OPC_PADDUSH:
4104 gen_helper_paddush(t0, t0, t1);
4105 break;
4106 case OPC_PADDH:
4107 gen_helper_paddh(t0, t0, t1);
4108 break;
4109 case OPC_PADDW:
4110 gen_helper_paddw(t0, t0, t1);
4111 break;
4112 case OPC_PADDSB:
4113 gen_helper_paddsb(t0, t0, t1);
4114 break;
4115 case OPC_PADDUSB:
4116 gen_helper_paddusb(t0, t0, t1);
4117 break;
4118 case OPC_PADDB:
4119 gen_helper_paddb(t0, t0, t1);
4120 break;
4122 case OPC_PSUBSH:
4123 gen_helper_psubsh(t0, t0, t1);
4124 break;
4125 case OPC_PSUBUSH:
4126 gen_helper_psubush(t0, t0, t1);
4127 break;
4128 case OPC_PSUBH:
4129 gen_helper_psubh(t0, t0, t1);
4130 break;
4131 case OPC_PSUBW:
4132 gen_helper_psubw(t0, t0, t1);
4133 break;
4134 case OPC_PSUBSB:
4135 gen_helper_psubsb(t0, t0, t1);
4136 break;
4137 case OPC_PSUBUSB:
4138 gen_helper_psubusb(t0, t0, t1);
4139 break;
4140 case OPC_PSUBB:
4141 gen_helper_psubb(t0, t0, t1);
4142 break;
4144 case OPC_PSHUFH:
4145 gen_helper_pshufh(t0, t0, t1);
4146 break;
4147 case OPC_PACKSSWH:
4148 gen_helper_packsswh(t0, t0, t1);
4149 break;
4150 case OPC_PACKSSHB:
4151 gen_helper_packsshb(t0, t0, t1);
4152 break;
4153 case OPC_PACKUSHB:
4154 gen_helper_packushb(t0, t0, t1);
4155 break;
4157 case OPC_PUNPCKLHW:
4158 gen_helper_punpcklhw(t0, t0, t1);
4159 break;
4160 case OPC_PUNPCKHHW:
4161 gen_helper_punpckhhw(t0, t0, t1);
4162 break;
4163 case OPC_PUNPCKLBH:
4164 gen_helper_punpcklbh(t0, t0, t1);
4165 break;
4166 case OPC_PUNPCKHBH:
4167 gen_helper_punpckhbh(t0, t0, t1);
4168 break;
4169 case OPC_PUNPCKLWD:
4170 gen_helper_punpcklwd(t0, t0, t1);
4171 break;
4172 case OPC_PUNPCKHWD:
4173 gen_helper_punpckhwd(t0, t0, t1);
4174 break;
4176 case OPC_PAVGH:
4177 gen_helper_pavgh(t0, t0, t1);
4178 break;
4179 case OPC_PAVGB:
4180 gen_helper_pavgb(t0, t0, t1);
4181 break;
4182 case OPC_PMAXSH:
4183 gen_helper_pmaxsh(t0, t0, t1);
4184 break;
4185 case OPC_PMINSH:
4186 gen_helper_pminsh(t0, t0, t1);
4187 break;
4188 case OPC_PMAXUB:
4189 gen_helper_pmaxub(t0, t0, t1);
4190 break;
4191 case OPC_PMINUB:
4192 gen_helper_pminub(t0, t0, t1);
4193 break;
4195 case OPC_PCMPEQW:
4196 gen_helper_pcmpeqw(t0, t0, t1);
4197 break;
4198 case OPC_PCMPGTW:
4199 gen_helper_pcmpgtw(t0, t0, t1);
4200 break;
4201 case OPC_PCMPEQH:
4202 gen_helper_pcmpeqh(t0, t0, t1);
4203 break;
4204 case OPC_PCMPGTH:
4205 gen_helper_pcmpgth(t0, t0, t1);
4206 break;
4207 case OPC_PCMPEQB:
4208 gen_helper_pcmpeqb(t0, t0, t1);
4209 break;
4210 case OPC_PCMPGTB:
4211 gen_helper_pcmpgtb(t0, t0, t1);
4212 break;
4214 case OPC_PSLLW:
4215 gen_helper_psllw(t0, t0, t1);
4216 break;
4217 case OPC_PSLLH:
4218 gen_helper_psllh(t0, t0, t1);
4219 break;
4220 case OPC_PSRLW:
4221 gen_helper_psrlw(t0, t0, t1);
4222 break;
4223 case OPC_PSRLH:
4224 gen_helper_psrlh(t0, t0, t1);
4225 break;
4226 case OPC_PSRAW:
4227 gen_helper_psraw(t0, t0, t1);
4228 break;
4229 case OPC_PSRAH:
4230 gen_helper_psrah(t0, t0, t1);
4231 break;
4233 case OPC_PMULLH:
4234 gen_helper_pmullh(t0, t0, t1);
4235 break;
4236 case OPC_PMULHH:
4237 gen_helper_pmulhh(t0, t0, t1);
4238 break;
4239 case OPC_PMULHUH:
4240 gen_helper_pmulhuh(t0, t0, t1);
4241 break;
4242 case OPC_PMADDHW:
4243 gen_helper_pmaddhw(t0, t0, t1);
4244 break;
4246 case OPC_PASUBUB:
4247 gen_helper_pasubub(t0, t0, t1);
4248 break;
4249 case OPC_BIADD:
4250 gen_helper_biadd(t0, t0);
4251 break;
4252 case OPC_PMOVMSKB:
4253 gen_helper_pmovmskb(t0, t0);
4254 break;
4256 case OPC_PADDD:
4257 tcg_gen_add_i64(t0, t0, t1);
4258 break;
4259 case OPC_PSUBD:
4260 tcg_gen_sub_i64(t0, t0, t1);
4261 break;
4262 case OPC_XOR_CP2:
4263 tcg_gen_xor_i64(t0, t0, t1);
4264 break;
4265 case OPC_NOR_CP2:
4266 tcg_gen_nor_i64(t0, t0, t1);
4267 break;
4268 case OPC_AND_CP2:
4269 tcg_gen_and_i64(t0, t0, t1);
4270 break;
4271 case OPC_OR_CP2:
4272 tcg_gen_or_i64(t0, t0, t1);
4273 break;
4275 case OPC_PANDN:
4276 tcg_gen_andc_i64(t0, t1, t0);
4277 break;
4279 case OPC_PINSRH_0:
4280 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4281 break;
4282 case OPC_PINSRH_1:
4283 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4284 break;
4285 case OPC_PINSRH_2:
4286 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4287 break;
4288 case OPC_PINSRH_3:
4289 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4290 break;
4292 case OPC_PEXTRH:
4293 tcg_gen_andi_i64(t1, t1, 3);
4294 tcg_gen_shli_i64(t1, t1, 4);
4295 tcg_gen_shr_i64(t0, t0, t1);
4296 tcg_gen_ext16u_i64(t0, t0);
4297 break;
4299 case OPC_ADDU_CP2:
4300 tcg_gen_add_i64(t0, t0, t1);
4301 tcg_gen_ext32s_i64(t0, t0);
4302 break;
4303 case OPC_SUBU_CP2:
4304 tcg_gen_sub_i64(t0, t0, t1);
4305 tcg_gen_ext32s_i64(t0, t0);
4306 break;
4308 case OPC_SLL_CP2:
4309 shift_max = 32;
4310 goto do_shift;
4311 case OPC_SRL_CP2:
4312 shift_max = 32;
4313 goto do_shift;
4314 case OPC_SRA_CP2:
4315 shift_max = 32;
4316 goto do_shift;
4317 case OPC_DSLL_CP2:
4318 shift_max = 64;
4319 goto do_shift;
4320 case OPC_DSRL_CP2:
4321 shift_max = 64;
4322 goto do_shift;
4323 case OPC_DSRA_CP2:
4324 shift_max = 64;
4325 goto do_shift;
4326 do_shift:
4327 /* Make sure shift count isn't TCG undefined behaviour. */
4328 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4330 switch (opc) {
4331 case OPC_SLL_CP2:
4332 case OPC_DSLL_CP2:
4333 tcg_gen_shl_i64(t0, t0, t1);
4334 break;
4335 case OPC_SRA_CP2:
4336 case OPC_DSRA_CP2:
4338 * Since SRA is UndefinedResult without sign-extended inputs,
4339 * we can treat SRA and DSRA the same.
4341 tcg_gen_sar_i64(t0, t0, t1);
4342 break;
4343 case OPC_SRL_CP2:
4344 /* We want to shift in zeros for SRL; zero-extend first. */
4345 tcg_gen_ext32u_i64(t0, t0);
4346 /* FALLTHRU */
4347 case OPC_DSRL_CP2:
4348 tcg_gen_shr_i64(t0, t0, t1);
4349 break;
4352 if (shift_max == 32) {
4353 tcg_gen_ext32s_i64(t0, t0);
4356 /* Shifts larger than MAX produce zero. */
4357 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4358 tcg_gen_neg_i64(t1, t1);
4359 tcg_gen_and_i64(t0, t0, t1);
4360 break;
4362 case OPC_ADD_CP2:
4363 case OPC_DADD_CP2:
4365 TCGv_i64 t2 = tcg_temp_new_i64();
4366 TCGLabel *lab = gen_new_label();
4368 tcg_gen_mov_i64(t2, t0);
4369 tcg_gen_add_i64(t0, t1, t2);
4370 if (opc == OPC_ADD_CP2) {
4371 tcg_gen_ext32s_i64(t0, t0);
4373 tcg_gen_xor_i64(t1, t1, t2);
4374 tcg_gen_xor_i64(t2, t2, t0);
4375 tcg_gen_andc_i64(t1, t2, t1);
4376 tcg_temp_free_i64(t2);
4377 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4378 generate_exception(ctx, EXCP_OVERFLOW);
4379 gen_set_label(lab);
4380 break;
4383 case OPC_SUB_CP2:
4384 case OPC_DSUB_CP2:
4386 TCGv_i64 t2 = tcg_temp_new_i64();
4387 TCGLabel *lab = gen_new_label();
4389 tcg_gen_mov_i64(t2, t0);
4390 tcg_gen_sub_i64(t0, t1, t2);
4391 if (opc == OPC_SUB_CP2) {
4392 tcg_gen_ext32s_i64(t0, t0);
4394 tcg_gen_xor_i64(t1, t1, t2);
4395 tcg_gen_xor_i64(t2, t2, t0);
4396 tcg_gen_and_i64(t1, t1, t2);
4397 tcg_temp_free_i64(t2);
4398 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4399 generate_exception(ctx, EXCP_OVERFLOW);
4400 gen_set_label(lab);
4401 break;
4404 case OPC_PMULUW:
4405 tcg_gen_ext32u_i64(t0, t0);
4406 tcg_gen_ext32u_i64(t1, t1);
4407 tcg_gen_mul_i64(t0, t0, t1);
4408 break;
4410 case OPC_SEQU_CP2:
4411 case OPC_SEQ_CP2:
4412 cond = TCG_COND_EQ;
4413 goto do_cc_cond;
4414 break;
4415 case OPC_SLTU_CP2:
4416 cond = TCG_COND_LTU;
4417 goto do_cc_cond;
4418 break;
4419 case OPC_SLT_CP2:
4420 cond = TCG_COND_LT;
4421 goto do_cc_cond;
4422 break;
4423 case OPC_SLEU_CP2:
4424 cond = TCG_COND_LEU;
4425 goto do_cc_cond;
4426 break;
4427 case OPC_SLE_CP2:
4428 cond = TCG_COND_LE;
4429 do_cc_cond:
4431 int cc = (ctx->opcode >> 8) & 0x7;
4432 TCGv_i64 t64 = tcg_temp_new_i64();
4433 TCGv_i32 t32 = tcg_temp_new_i32();
4435 tcg_gen_setcond_i64(cond, t64, t0, t1);
4436 tcg_gen_extrl_i64_i32(t32, t64);
4437 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4438 get_fp_bit(cc), 1);
4440 tcg_temp_free_i32(t32);
4441 tcg_temp_free_i64(t64);
4443 goto no_rd;
4444 break;
4445 default:
4446 MIPS_INVAL("loongson_cp2");
4447 gen_reserved_instruction(ctx);
4448 return;
4451 gen_store_fpr64(ctx, t0, rd);
4453 no_rd:
4454 tcg_temp_free_i64(t0);
4455 tcg_temp_free_i64(t1);
4458 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4459 int rs, int rd)
4461 TCGv t0, t1, t2;
4462 TCGv_i32 fp0;
4463 #if defined(TARGET_MIPS64)
4464 int lsq_rt1 = ctx->opcode & 0x1f;
4465 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4466 #endif
4467 int shf_offset = sextract32(ctx->opcode, 6, 8);
4469 t0 = tcg_temp_new();
4471 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4472 #if defined(TARGET_MIPS64)
4473 case OPC_GSLQ:
4474 t1 = tcg_temp_new();
4475 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4476 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4477 ctx->default_tcg_memop_mask);
4478 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4479 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4480 ctx->default_tcg_memop_mask);
4481 gen_store_gpr(t1, rt);
4482 gen_store_gpr(t0, lsq_rt1);
4483 tcg_temp_free(t1);
4484 break;
4485 case OPC_GSLQC1:
4486 check_cp1_enabled(ctx);
4487 t1 = tcg_temp_new();
4488 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4489 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4490 ctx->default_tcg_memop_mask);
4491 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4492 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4493 ctx->default_tcg_memop_mask);
4494 gen_store_fpr64(ctx, t1, rt);
4495 gen_store_fpr64(ctx, t0, lsq_rt1);
4496 tcg_temp_free(t1);
4497 break;
4498 case OPC_GSSQ:
4499 t1 = tcg_temp_new();
4500 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4501 gen_load_gpr(t1, rt);
4502 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4503 ctx->default_tcg_memop_mask);
4504 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4505 gen_load_gpr(t1, lsq_rt1);
4506 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4507 ctx->default_tcg_memop_mask);
4508 tcg_temp_free(t1);
4509 break;
4510 case OPC_GSSQC1:
4511 check_cp1_enabled(ctx);
4512 t1 = tcg_temp_new();
4513 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4514 gen_load_fpr64(ctx, t1, rt);
4515 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4516 ctx->default_tcg_memop_mask);
4517 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4518 gen_load_fpr64(ctx, t1, lsq_rt1);
4519 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4520 ctx->default_tcg_memop_mask);
4521 tcg_temp_free(t1);
4522 break;
4523 #endif
4524 case OPC_GSSHFL:
4525 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4526 case OPC_GSLWLC1:
4527 check_cp1_enabled(ctx);
4528 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4529 t1 = tcg_temp_new();
4530 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4531 tcg_gen_andi_tl(t1, t0, 3);
4532 #ifndef TARGET_WORDS_BIGENDIAN
4533 tcg_gen_xori_tl(t1, t1, 3);
4534 #endif
4535 tcg_gen_shli_tl(t1, t1, 3);
4536 tcg_gen_andi_tl(t0, t0, ~3);
4537 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4538 tcg_gen_shl_tl(t0, t0, t1);
4539 t2 = tcg_const_tl(-1);
4540 tcg_gen_shl_tl(t2, t2, t1);
4541 fp0 = tcg_temp_new_i32();
4542 gen_load_fpr32(ctx, fp0, rt);
4543 tcg_gen_ext_i32_tl(t1, fp0);
4544 tcg_gen_andc_tl(t1, t1, t2);
4545 tcg_temp_free(t2);
4546 tcg_gen_or_tl(t0, t0, t1);
4547 tcg_temp_free(t1);
4548 #if defined(TARGET_MIPS64)
4549 tcg_gen_extrl_i64_i32(fp0, t0);
4550 #else
4551 tcg_gen_ext32s_tl(fp0, t0);
4552 #endif
4553 gen_store_fpr32(ctx, fp0, rt);
4554 tcg_temp_free_i32(fp0);
4555 break;
4556 case OPC_GSLWRC1:
4557 check_cp1_enabled(ctx);
4558 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4559 t1 = tcg_temp_new();
4560 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4561 tcg_gen_andi_tl(t1, t0, 3);
4562 #ifdef TARGET_WORDS_BIGENDIAN
4563 tcg_gen_xori_tl(t1, t1, 3);
4564 #endif
4565 tcg_gen_shli_tl(t1, t1, 3);
4566 tcg_gen_andi_tl(t0, t0, ~3);
4567 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4568 tcg_gen_shr_tl(t0, t0, t1);
4569 tcg_gen_xori_tl(t1, t1, 31);
4570 t2 = tcg_const_tl(0xfffffffeull);
4571 tcg_gen_shl_tl(t2, t2, t1);
4572 fp0 = tcg_temp_new_i32();
4573 gen_load_fpr32(ctx, fp0, rt);
4574 tcg_gen_ext_i32_tl(t1, fp0);
4575 tcg_gen_and_tl(t1, t1, t2);
4576 tcg_temp_free(t2);
4577 tcg_gen_or_tl(t0, t0, t1);
4578 tcg_temp_free(t1);
4579 #if defined(TARGET_MIPS64)
4580 tcg_gen_extrl_i64_i32(fp0, t0);
4581 #else
4582 tcg_gen_ext32s_tl(fp0, t0);
4583 #endif
4584 gen_store_fpr32(ctx, fp0, rt);
4585 tcg_temp_free_i32(fp0);
4586 break;
4587 #if defined(TARGET_MIPS64)
4588 case OPC_GSLDLC1:
4589 check_cp1_enabled(ctx);
4590 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4591 t1 = tcg_temp_new();
4592 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4593 tcg_gen_andi_tl(t1, t0, 7);
4594 #ifndef TARGET_WORDS_BIGENDIAN
4595 tcg_gen_xori_tl(t1, t1, 7);
4596 #endif
4597 tcg_gen_shli_tl(t1, t1, 3);
4598 tcg_gen_andi_tl(t0, t0, ~7);
4599 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4600 tcg_gen_shl_tl(t0, t0, t1);
4601 t2 = tcg_const_tl(-1);
4602 tcg_gen_shl_tl(t2, t2, t1);
4603 gen_load_fpr64(ctx, t1, rt);
4604 tcg_gen_andc_tl(t1, t1, t2);
4605 tcg_temp_free(t2);
4606 tcg_gen_or_tl(t0, t0, t1);
4607 tcg_temp_free(t1);
4608 gen_store_fpr64(ctx, t0, rt);
4609 break;
4610 case OPC_GSLDRC1:
4611 check_cp1_enabled(ctx);
4612 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4613 t1 = tcg_temp_new();
4614 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4615 tcg_gen_andi_tl(t1, t0, 7);
4616 #ifdef TARGET_WORDS_BIGENDIAN
4617 tcg_gen_xori_tl(t1, t1, 7);
4618 #endif
4619 tcg_gen_shli_tl(t1, t1, 3);
4620 tcg_gen_andi_tl(t0, t0, ~7);
4621 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4622 tcg_gen_shr_tl(t0, t0, t1);
4623 tcg_gen_xori_tl(t1, t1, 63);
4624 t2 = tcg_const_tl(0xfffffffffffffffeull);
4625 tcg_gen_shl_tl(t2, t2, t1);
4626 gen_load_fpr64(ctx, t1, rt);
4627 tcg_gen_and_tl(t1, t1, t2);
4628 tcg_temp_free(t2);
4629 tcg_gen_or_tl(t0, t0, t1);
4630 tcg_temp_free(t1);
4631 gen_store_fpr64(ctx, t0, rt);
4632 break;
4633 #endif
4634 default:
4635 MIPS_INVAL("loongson_gsshfl");
4636 gen_reserved_instruction(ctx);
4637 break;
4639 break;
4640 case OPC_GSSHFS:
4641 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4642 case OPC_GSSWLC1:
4643 check_cp1_enabled(ctx);
4644 t1 = tcg_temp_new();
4645 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4646 fp0 = tcg_temp_new_i32();
4647 gen_load_fpr32(ctx, fp0, rt);
4648 tcg_gen_ext_i32_tl(t1, fp0);
4649 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4650 tcg_temp_free_i32(fp0);
4651 tcg_temp_free(t1);
4652 break;
4653 case OPC_GSSWRC1:
4654 check_cp1_enabled(ctx);
4655 t1 = tcg_temp_new();
4656 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4657 fp0 = tcg_temp_new_i32();
4658 gen_load_fpr32(ctx, fp0, rt);
4659 tcg_gen_ext_i32_tl(t1, fp0);
4660 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4661 tcg_temp_free_i32(fp0);
4662 tcg_temp_free(t1);
4663 break;
4664 #if defined(TARGET_MIPS64)
4665 case OPC_GSSDLC1:
4666 check_cp1_enabled(ctx);
4667 t1 = tcg_temp_new();
4668 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4669 gen_load_fpr64(ctx, t1, rt);
4670 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4671 tcg_temp_free(t1);
4672 break;
4673 case OPC_GSSDRC1:
4674 check_cp1_enabled(ctx);
4675 t1 = tcg_temp_new();
4676 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4677 gen_load_fpr64(ctx, t1, rt);
4678 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4679 tcg_temp_free(t1);
4680 break;
4681 #endif
4682 default:
4683 MIPS_INVAL("loongson_gsshfs");
4684 gen_reserved_instruction(ctx);
4685 break;
4687 break;
4688 default:
4689 MIPS_INVAL("loongson_gslsq");
4690 gen_reserved_instruction(ctx);
4691 break;
4693 tcg_temp_free(t0);
4696 /* Loongson EXT LDC2/SDC2 */
4697 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4698 int rs, int rd)
4700 int offset = sextract32(ctx->opcode, 3, 8);
4701 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4702 TCGv t0, t1;
4703 TCGv_i32 fp0;
4705 /* Pre-conditions */
4706 switch (opc) {
4707 case OPC_GSLBX:
4708 case OPC_GSLHX:
4709 case OPC_GSLWX:
4710 case OPC_GSLDX:
4711 /* prefetch, implement as NOP */
4712 if (rt == 0) {
4713 return;
4715 break;
4716 case OPC_GSSBX:
4717 case OPC_GSSHX:
4718 case OPC_GSSWX:
4719 case OPC_GSSDX:
4720 break;
4721 case OPC_GSLWXC1:
4722 #if defined(TARGET_MIPS64)
4723 case OPC_GSLDXC1:
4724 #endif
4725 check_cp1_enabled(ctx);
4726 /* prefetch, implement as NOP */
4727 if (rt == 0) {
4728 return;
4730 break;
4731 case OPC_GSSWXC1:
4732 #if defined(TARGET_MIPS64)
4733 case OPC_GSSDXC1:
4734 #endif
4735 check_cp1_enabled(ctx);
4736 break;
4737 default:
4738 MIPS_INVAL("loongson_lsdc2");
4739 gen_reserved_instruction(ctx);
4740 return;
4741 break;
4744 t0 = tcg_temp_new();
4746 gen_base_offset_addr(ctx, t0, rs, offset);
4747 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4749 switch (opc) {
4750 case OPC_GSLBX:
4751 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4752 gen_store_gpr(t0, rt);
4753 break;
4754 case OPC_GSLHX:
4755 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4756 ctx->default_tcg_memop_mask);
4757 gen_store_gpr(t0, rt);
4758 break;
4759 case OPC_GSLWX:
4760 gen_base_offset_addr(ctx, t0, rs, offset);
4761 if (rd) {
4762 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4764 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4765 ctx->default_tcg_memop_mask);
4766 gen_store_gpr(t0, rt);
4767 break;
4768 #if defined(TARGET_MIPS64)
4769 case OPC_GSLDX:
4770 gen_base_offset_addr(ctx, t0, rs, offset);
4771 if (rd) {
4772 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4774 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4775 ctx->default_tcg_memop_mask);
4776 gen_store_gpr(t0, rt);
4777 break;
4778 #endif
4779 case OPC_GSLWXC1:
4780 check_cp1_enabled(ctx);
4781 gen_base_offset_addr(ctx, t0, rs, offset);
4782 if (rd) {
4783 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4785 fp0 = tcg_temp_new_i32();
4786 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
4787 ctx->default_tcg_memop_mask);
4788 gen_store_fpr32(ctx, fp0, rt);
4789 tcg_temp_free_i32(fp0);
4790 break;
4791 #if defined(TARGET_MIPS64)
4792 case OPC_GSLDXC1:
4793 check_cp1_enabled(ctx);
4794 gen_base_offset_addr(ctx, t0, rs, offset);
4795 if (rd) {
4796 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4798 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4799 ctx->default_tcg_memop_mask);
4800 gen_store_fpr64(ctx, t0, rt);
4801 break;
4802 #endif
4803 case OPC_GSSBX:
4804 t1 = tcg_temp_new();
4805 gen_load_gpr(t1, rt);
4806 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4807 tcg_temp_free(t1);
4808 break;
4809 case OPC_GSSHX:
4810 t1 = tcg_temp_new();
4811 gen_load_gpr(t1, rt);
4812 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
4813 ctx->default_tcg_memop_mask);
4814 tcg_temp_free(t1);
4815 break;
4816 case OPC_GSSWX:
4817 t1 = tcg_temp_new();
4818 gen_load_gpr(t1, rt);
4819 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
4820 ctx->default_tcg_memop_mask);
4821 tcg_temp_free(t1);
4822 break;
4823 #if defined(TARGET_MIPS64)
4824 case OPC_GSSDX:
4825 t1 = tcg_temp_new();
4826 gen_load_gpr(t1, rt);
4827 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4828 ctx->default_tcg_memop_mask);
4829 tcg_temp_free(t1);
4830 break;
4831 #endif
4832 case OPC_GSSWXC1:
4833 fp0 = tcg_temp_new_i32();
4834 gen_load_fpr32(ctx, fp0, rt);
4835 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
4836 ctx->default_tcg_memop_mask);
4837 tcg_temp_free_i32(fp0);
4838 break;
4839 #if defined(TARGET_MIPS64)
4840 case OPC_GSSDXC1:
4841 t1 = tcg_temp_new();
4842 gen_load_fpr64(ctx, t1, rt);
4843 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
4844 ctx->default_tcg_memop_mask);
4845 tcg_temp_free(t1);
4846 break;
4847 #endif
4848 default:
4849 break;
4852 tcg_temp_free(t0);
4855 /* Traps */
4856 static void gen_trap(DisasContext *ctx, uint32_t opc,
4857 int rs, int rt, int16_t imm)
4859 int cond;
4860 TCGv t0 = tcg_temp_new();
4861 TCGv t1 = tcg_temp_new();
4863 cond = 0;
4864 /* Load needed operands */
4865 switch (opc) {
4866 case OPC_TEQ:
4867 case OPC_TGE:
4868 case OPC_TGEU:
4869 case OPC_TLT:
4870 case OPC_TLTU:
4871 case OPC_TNE:
4872 /* Compare two registers */
4873 if (rs != rt) {
4874 gen_load_gpr(t0, rs);
4875 gen_load_gpr(t1, rt);
4876 cond = 1;
4878 break;
4879 case OPC_TEQI:
4880 case OPC_TGEI:
4881 case OPC_TGEIU:
4882 case OPC_TLTI:
4883 case OPC_TLTIU:
4884 case OPC_TNEI:
4885 /* Compare register to immediate */
4886 if (rs != 0 || imm != 0) {
4887 gen_load_gpr(t0, rs);
4888 tcg_gen_movi_tl(t1, (int32_t)imm);
4889 cond = 1;
4891 break;
4893 if (cond == 0) {
4894 switch (opc) {
4895 case OPC_TEQ: /* rs == rs */
4896 case OPC_TEQI: /* r0 == 0 */
4897 case OPC_TGE: /* rs >= rs */
4898 case OPC_TGEI: /* r0 >= 0 */
4899 case OPC_TGEU: /* rs >= rs unsigned */
4900 case OPC_TGEIU: /* r0 >= 0 unsigned */
4901 /* Always trap */
4902 generate_exception_end(ctx, EXCP_TRAP);
4903 break;
4904 case OPC_TLT: /* rs < rs */
4905 case OPC_TLTI: /* r0 < 0 */
4906 case OPC_TLTU: /* rs < rs unsigned */
4907 case OPC_TLTIU: /* r0 < 0 unsigned */
4908 case OPC_TNE: /* rs != rs */
4909 case OPC_TNEI: /* r0 != 0 */
4910 /* Never trap: treat as NOP. */
4911 break;
4913 } else {
4914 TCGLabel *l1 = gen_new_label();
4916 switch (opc) {
4917 case OPC_TEQ:
4918 case OPC_TEQI:
4919 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4920 break;
4921 case OPC_TGE:
4922 case OPC_TGEI:
4923 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4924 break;
4925 case OPC_TGEU:
4926 case OPC_TGEIU:
4927 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4928 break;
4929 case OPC_TLT:
4930 case OPC_TLTI:
4931 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4932 break;
4933 case OPC_TLTU:
4934 case OPC_TLTIU:
4935 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4936 break;
4937 case OPC_TNE:
4938 case OPC_TNEI:
4939 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4940 break;
4942 generate_exception(ctx, EXCP_TRAP);
4943 gen_set_label(l1);
4945 tcg_temp_free(t0);
4946 tcg_temp_free(t1);
4949 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4951 if (translator_use_goto_tb(&ctx->base, dest)) {
4952 tcg_gen_goto_tb(n);
4953 gen_save_pc(dest);
4954 tcg_gen_exit_tb(ctx->base.tb, n);
4955 } else {
4956 gen_save_pc(dest);
4957 if (ctx->base.singlestep_enabled) {
4958 save_cpu_state(ctx, 0);
4959 gen_helper_raise_exception_debug(cpu_env);
4960 } else {
4961 tcg_gen_lookup_and_goto_ptr();
4966 /* Branches (before delay slot) */
4967 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
4968 int insn_bytes,
4969 int rs, int rt, int32_t offset,
4970 int delayslot_size)
4972 target_ulong btgt = -1;
4973 int blink = 0;
4974 int bcond_compute = 0;
4975 TCGv t0 = tcg_temp_new();
4976 TCGv t1 = tcg_temp_new();
4978 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4979 #ifdef MIPS_DEBUG_DISAS
4980 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4981 TARGET_FMT_lx "\n", ctx->base.pc_next);
4982 #endif
4983 gen_reserved_instruction(ctx);
4984 goto out;
4987 /* Load needed operands */
4988 switch (opc) {
4989 case OPC_BEQ:
4990 case OPC_BEQL:
4991 case OPC_BNE:
4992 case OPC_BNEL:
4993 /* Compare two registers */
4994 if (rs != rt) {
4995 gen_load_gpr(t0, rs);
4996 gen_load_gpr(t1, rt);
4997 bcond_compute = 1;
4999 btgt = ctx->base.pc_next + insn_bytes + offset;
5000 break;
5001 case OPC_BGEZ:
5002 case OPC_BGEZAL:
5003 case OPC_BGEZALL:
5004 case OPC_BGEZL:
5005 case OPC_BGTZ:
5006 case OPC_BGTZL:
5007 case OPC_BLEZ:
5008 case OPC_BLEZL:
5009 case OPC_BLTZ:
5010 case OPC_BLTZAL:
5011 case OPC_BLTZALL:
5012 case OPC_BLTZL:
5013 /* Compare to zero */
5014 if (rs != 0) {
5015 gen_load_gpr(t0, rs);
5016 bcond_compute = 1;
5018 btgt = ctx->base.pc_next + insn_bytes + offset;
5019 break;
5020 case OPC_BPOSGE32:
5021 #if defined(TARGET_MIPS64)
5022 case OPC_BPOSGE64:
5023 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5024 #else
5025 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5026 #endif
5027 bcond_compute = 1;
5028 btgt = ctx->base.pc_next + insn_bytes + offset;
5029 break;
5030 case OPC_J:
5031 case OPC_JAL:
5032 case OPC_JALX:
5033 /* Jump to immediate */
5034 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5035 (uint32_t)offset;
5036 break;
5037 case OPC_JR:
5038 case OPC_JALR:
5039 /* Jump to register */
5040 if (offset != 0 && offset != 16) {
5042 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5043 * others are reserved.
5045 MIPS_INVAL("jump hint");
5046 gen_reserved_instruction(ctx);
5047 goto out;
5049 gen_load_gpr(btarget, rs);
5050 break;
5051 default:
5052 MIPS_INVAL("branch/jump");
5053 gen_reserved_instruction(ctx);
5054 goto out;
5056 if (bcond_compute == 0) {
5057 /* No condition to be computed */
5058 switch (opc) {
5059 case OPC_BEQ: /* rx == rx */
5060 case OPC_BEQL: /* rx == rx likely */
5061 case OPC_BGEZ: /* 0 >= 0 */
5062 case OPC_BGEZL: /* 0 >= 0 likely */
5063 case OPC_BLEZ: /* 0 <= 0 */
5064 case OPC_BLEZL: /* 0 <= 0 likely */
5065 /* Always take */
5066 ctx->hflags |= MIPS_HFLAG_B;
5067 break;
5068 case OPC_BGEZAL: /* 0 >= 0 */
5069 case OPC_BGEZALL: /* 0 >= 0 likely */
5070 /* Always take and link */
5071 blink = 31;
5072 ctx->hflags |= MIPS_HFLAG_B;
5073 break;
5074 case OPC_BNE: /* rx != rx */
5075 case OPC_BGTZ: /* 0 > 0 */
5076 case OPC_BLTZ: /* 0 < 0 */
5077 /* Treat as NOP. */
5078 goto out;
5079 case OPC_BLTZAL: /* 0 < 0 */
5081 * Handle as an unconditional branch to get correct delay
5082 * slot checking.
5084 blink = 31;
5085 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5086 ctx->hflags |= MIPS_HFLAG_B;
5087 break;
5088 case OPC_BLTZALL: /* 0 < 0 likely */
5089 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5090 /* Skip the instruction in the delay slot */
5091 ctx->base.pc_next += 4;
5092 goto out;
5093 case OPC_BNEL: /* rx != rx likely */
5094 case OPC_BGTZL: /* 0 > 0 likely */
5095 case OPC_BLTZL: /* 0 < 0 likely */
5096 /* Skip the instruction in the delay slot */
5097 ctx->base.pc_next += 4;
5098 goto out;
5099 case OPC_J:
5100 ctx->hflags |= MIPS_HFLAG_B;
5101 break;
5102 case OPC_JALX:
5103 ctx->hflags |= MIPS_HFLAG_BX;
5104 /* Fallthrough */
5105 case OPC_JAL:
5106 blink = 31;
5107 ctx->hflags |= MIPS_HFLAG_B;
5108 break;
5109 case OPC_JR:
5110 ctx->hflags |= MIPS_HFLAG_BR;
5111 break;
5112 case OPC_JALR:
5113 blink = rt;
5114 ctx->hflags |= MIPS_HFLAG_BR;
5115 break;
5116 default:
5117 MIPS_INVAL("branch/jump");
5118 gen_reserved_instruction(ctx);
5119 goto out;
5121 } else {
5122 switch (opc) {
5123 case OPC_BEQ:
5124 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5125 goto not_likely;
5126 case OPC_BEQL:
5127 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5128 goto likely;
5129 case OPC_BNE:
5130 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5131 goto not_likely;
5132 case OPC_BNEL:
5133 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5134 goto likely;
5135 case OPC_BGEZ:
5136 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5137 goto not_likely;
5138 case OPC_BGEZL:
5139 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5140 goto likely;
5141 case OPC_BGEZAL:
5142 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5143 blink = 31;
5144 goto not_likely;
5145 case OPC_BGEZALL:
5146 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5147 blink = 31;
5148 goto likely;
5149 case OPC_BGTZ:
5150 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5151 goto not_likely;
5152 case OPC_BGTZL:
5153 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5154 goto likely;
5155 case OPC_BLEZ:
5156 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5157 goto not_likely;
5158 case OPC_BLEZL:
5159 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5160 goto likely;
5161 case OPC_BLTZ:
5162 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5163 goto not_likely;
5164 case OPC_BLTZL:
5165 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5166 goto likely;
5167 case OPC_BPOSGE32:
5168 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5169 goto not_likely;
5170 #if defined(TARGET_MIPS64)
5171 case OPC_BPOSGE64:
5172 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5173 goto not_likely;
5174 #endif
5175 case OPC_BLTZAL:
5176 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5177 blink = 31;
5178 not_likely:
5179 ctx->hflags |= MIPS_HFLAG_BC;
5180 break;
5181 case OPC_BLTZALL:
5182 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5183 blink = 31;
5184 likely:
5185 ctx->hflags |= MIPS_HFLAG_BL;
5186 break;
5187 default:
5188 MIPS_INVAL("conditional branch/jump");
5189 gen_reserved_instruction(ctx);
5190 goto out;
5194 ctx->btarget = btgt;
5196 switch (delayslot_size) {
5197 case 2:
5198 ctx->hflags |= MIPS_HFLAG_BDS16;
5199 break;
5200 case 4:
5201 ctx->hflags |= MIPS_HFLAG_BDS32;
5202 break;
5205 if (blink > 0) {
5206 int post_delay = insn_bytes + delayslot_size;
5207 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5209 tcg_gen_movi_tl(cpu_gpr[blink],
5210 ctx->base.pc_next + post_delay + lowbit);
5213 out:
5214 if (insn_bytes == 2) {
5215 ctx->hflags |= MIPS_HFLAG_B16;
5217 tcg_temp_free(t0);
5218 tcg_temp_free(t1);
5222 /* special3 bitfield operations */
5223 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5224 int rs, int lsb, int msb)
5226 TCGv t0 = tcg_temp_new();
5227 TCGv t1 = tcg_temp_new();
5229 gen_load_gpr(t1, rs);
5230 switch (opc) {
5231 case OPC_EXT:
5232 if (lsb + msb > 31) {
5233 goto fail;
5235 if (msb != 31) {
5236 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5237 } else {
5239 * The two checks together imply that lsb == 0,
5240 * so this is a simple sign-extension.
5242 tcg_gen_ext32s_tl(t0, t1);
5244 break;
5245 #if defined(TARGET_MIPS64)
5246 case OPC_DEXTU:
5247 lsb += 32;
5248 goto do_dext;
5249 case OPC_DEXTM:
5250 msb += 32;
5251 goto do_dext;
5252 case OPC_DEXT:
5253 do_dext:
5254 if (lsb + msb > 63) {
5255 goto fail;
5257 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5258 break;
5259 #endif
5260 case OPC_INS:
5261 if (lsb > msb) {
5262 goto fail;
5264 gen_load_gpr(t0, rt);
5265 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5266 tcg_gen_ext32s_tl(t0, t0);
5267 break;
5268 #if defined(TARGET_MIPS64)
5269 case OPC_DINSU:
5270 lsb += 32;
5271 /* FALLTHRU */
5272 case OPC_DINSM:
5273 msb += 32;
5274 /* FALLTHRU */
5275 case OPC_DINS:
5276 if (lsb > msb) {
5277 goto fail;
5279 gen_load_gpr(t0, rt);
5280 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5281 break;
5282 #endif
5283 default:
5284 fail:
5285 MIPS_INVAL("bitops");
5286 gen_reserved_instruction(ctx);
5287 tcg_temp_free(t0);
5288 tcg_temp_free(t1);
5289 return;
5291 gen_store_gpr(t0, rt);
5292 tcg_temp_free(t0);
5293 tcg_temp_free(t1);
5296 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
5298 TCGv t0;
5300 if (rd == 0) {
5301 /* If no destination, treat it as a NOP. */
5302 return;
5305 t0 = tcg_temp_new();
5306 gen_load_gpr(t0, rt);
5307 switch (op2) {
5308 case OPC_WSBH:
5310 TCGv t1 = tcg_temp_new();
5311 TCGv t2 = tcg_const_tl(0x00FF00FF);
5313 tcg_gen_shri_tl(t1, t0, 8);
5314 tcg_gen_and_tl(t1, t1, t2);
5315 tcg_gen_and_tl(t0, t0, t2);
5316 tcg_gen_shli_tl(t0, t0, 8);
5317 tcg_gen_or_tl(t0, t0, t1);
5318 tcg_temp_free(t2);
5319 tcg_temp_free(t1);
5320 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5322 break;
5323 case OPC_SEB:
5324 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5325 break;
5326 case OPC_SEH:
5327 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5328 break;
5329 #if defined(TARGET_MIPS64)
5330 case OPC_DSBH:
5332 TCGv t1 = tcg_temp_new();
5333 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5335 tcg_gen_shri_tl(t1, t0, 8);
5336 tcg_gen_and_tl(t1, t1, t2);
5337 tcg_gen_and_tl(t0, t0, t2);
5338 tcg_gen_shli_tl(t0, t0, 8);
5339 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5340 tcg_temp_free(t2);
5341 tcg_temp_free(t1);
5343 break;
5344 case OPC_DSHD:
5346 TCGv t1 = tcg_temp_new();
5347 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5349 tcg_gen_shri_tl(t1, t0, 16);
5350 tcg_gen_and_tl(t1, t1, t2);
5351 tcg_gen_and_tl(t0, t0, t2);
5352 tcg_gen_shli_tl(t0, t0, 16);
5353 tcg_gen_or_tl(t0, t0, t1);
5354 tcg_gen_shri_tl(t1, t0, 32);
5355 tcg_gen_shli_tl(t0, t0, 32);
5356 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5357 tcg_temp_free(t2);
5358 tcg_temp_free(t1);
5360 break;
5361 #endif
5362 default:
5363 MIPS_INVAL("bsfhl");
5364 gen_reserved_instruction(ctx);
5365 tcg_temp_free(t0);
5366 return;
5368 tcg_temp_free(t0);
5371 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5372 int rt, int bits)
5374 TCGv t0;
5375 if (rd == 0) {
5376 /* Treat as NOP. */
5377 return;
5379 t0 = tcg_temp_new();
5380 if (bits == 0 || bits == wordsz) {
5381 if (bits == 0) {
5382 gen_load_gpr(t0, rt);
5383 } else {
5384 gen_load_gpr(t0, rs);
5386 switch (wordsz) {
5387 case 32:
5388 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5389 break;
5390 #if defined(TARGET_MIPS64)
5391 case 64:
5392 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5393 break;
5394 #endif
5396 } else {
5397 TCGv t1 = tcg_temp_new();
5398 gen_load_gpr(t0, rt);
5399 gen_load_gpr(t1, rs);
5400 switch (wordsz) {
5401 case 32:
5403 TCGv_i64 t2 = tcg_temp_new_i64();
5404 tcg_gen_concat_tl_i64(t2, t1, t0);
5405 tcg_gen_shri_i64(t2, t2, 32 - bits);
5406 gen_move_low32(cpu_gpr[rd], t2);
5407 tcg_temp_free_i64(t2);
5409 break;
5410 #if defined(TARGET_MIPS64)
5411 case 64:
5412 tcg_gen_shli_tl(t0, t0, bits);
5413 tcg_gen_shri_tl(t1, t1, 64 - bits);
5414 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5415 break;
5416 #endif
5418 tcg_temp_free(t1);
5421 tcg_temp_free(t0);
5424 void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp)
5426 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5429 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5431 TCGv t0;
5432 if (rd == 0) {
5433 /* Treat as NOP. */
5434 return;
5436 t0 = tcg_temp_new();
5437 gen_load_gpr(t0, rt);
5438 switch (opc) {
5439 case OPC_BITSWAP:
5440 gen_helper_bitswap(cpu_gpr[rd], t0);
5441 break;
5442 #if defined(TARGET_MIPS64)
5443 case OPC_DBITSWAP:
5444 gen_helper_dbitswap(cpu_gpr[rd], t0);
5445 break;
5446 #endif
5448 tcg_temp_free(t0);
5451 #ifndef CONFIG_USER_ONLY
5452 /* CP0 (MMU and control) */
5453 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5455 TCGv_i64 t0 = tcg_temp_new_i64();
5456 TCGv_i64 t1 = tcg_temp_new_i64();
5458 tcg_gen_ext_tl_i64(t0, arg);
5459 tcg_gen_ld_i64(t1, cpu_env, off);
5460 #if defined(TARGET_MIPS64)
5461 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5462 #else
5463 tcg_gen_concat32_i64(t1, t1, t0);
5464 #endif
5465 tcg_gen_st_i64(t1, cpu_env, off);
5466 tcg_temp_free_i64(t1);
5467 tcg_temp_free_i64(t0);
5470 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5472 TCGv_i64 t0 = tcg_temp_new_i64();
5473 TCGv_i64 t1 = tcg_temp_new_i64();
5475 tcg_gen_ext_tl_i64(t0, arg);
5476 tcg_gen_ld_i64(t1, cpu_env, off);
5477 tcg_gen_concat32_i64(t1, t1, t0);
5478 tcg_gen_st_i64(t1, cpu_env, off);
5479 tcg_temp_free_i64(t1);
5480 tcg_temp_free_i64(t0);
5483 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5485 TCGv_i64 t0 = tcg_temp_new_i64();
5487 tcg_gen_ld_i64(t0, cpu_env, off);
5488 #if defined(TARGET_MIPS64)
5489 tcg_gen_shri_i64(t0, t0, 30);
5490 #else
5491 tcg_gen_shri_i64(t0, t0, 32);
5492 #endif
5493 gen_move_low32(arg, t0);
5494 tcg_temp_free_i64(t0);
5497 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5499 TCGv_i64 t0 = tcg_temp_new_i64();
5501 tcg_gen_ld_i64(t0, cpu_env, off);
5502 tcg_gen_shri_i64(t0, t0, 32 + shift);
5503 gen_move_low32(arg, t0);
5504 tcg_temp_free_i64(t0);
5507 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
5509 TCGv_i32 t0 = tcg_temp_new_i32();
5511 tcg_gen_ld_i32(t0, cpu_env, off);
5512 tcg_gen_ext_i32_tl(arg, t0);
5513 tcg_temp_free_i32(t0);
5516 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
5518 tcg_gen_ld_tl(arg, cpu_env, off);
5519 tcg_gen_ext32s_tl(arg, arg);
5522 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
5524 TCGv_i32 t0 = tcg_temp_new_i32();
5526 tcg_gen_trunc_tl_i32(t0, arg);
5527 tcg_gen_st_i32(t0, cpu_env, off);
5528 tcg_temp_free_i32(t0);
5531 #define CP0_CHECK(c) \
5532 do { \
5533 if (!(c)) { \
5534 goto cp0_unimplemented; \
5536 } while (0)
5538 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5540 const char *register_name = "invalid";
5542 switch (reg) {
5543 case CP0_REGISTER_02:
5544 switch (sel) {
5545 case 0:
5546 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5547 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5548 register_name = "EntryLo0";
5549 break;
5550 default:
5551 goto cp0_unimplemented;
5553 break;
5554 case CP0_REGISTER_03:
5555 switch (sel) {
5556 case CP0_REG03__ENTRYLO1:
5557 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5558 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5559 register_name = "EntryLo1";
5560 break;
5561 default:
5562 goto cp0_unimplemented;
5564 break;
5565 case CP0_REGISTER_09:
5566 switch (sel) {
5567 case CP0_REG09__SAAR:
5568 CP0_CHECK(ctx->saar);
5569 gen_helper_mfhc0_saar(arg, cpu_env);
5570 register_name = "SAAR";
5571 break;
5572 default:
5573 goto cp0_unimplemented;
5575 break;
5576 case CP0_REGISTER_17:
5577 switch (sel) {
5578 case CP0_REG17__LLADDR:
5579 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5580 ctx->CP0_LLAddr_shift);
5581 register_name = "LLAddr";
5582 break;
5583 case CP0_REG17__MAAR:
5584 CP0_CHECK(ctx->mrp);
5585 gen_helper_mfhc0_maar(arg, cpu_env);
5586 register_name = "MAAR";
5587 break;
5588 default:
5589 goto cp0_unimplemented;
5591 break;
5592 case CP0_REGISTER_19:
5593 switch (sel) {
5594 case CP0_REG19__WATCHHI0:
5595 case CP0_REG19__WATCHHI1:
5596 case CP0_REG19__WATCHHI2:
5597 case CP0_REG19__WATCHHI3:
5598 case CP0_REG19__WATCHHI4:
5599 case CP0_REG19__WATCHHI5:
5600 case CP0_REG19__WATCHHI6:
5601 case CP0_REG19__WATCHHI7:
5602 /* upper 32 bits are only available when Config5MI != 0 */
5603 CP0_CHECK(ctx->mi);
5604 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5605 register_name = "WatchHi";
5606 break;
5607 default:
5608 goto cp0_unimplemented;
5610 break;
5611 case CP0_REGISTER_28:
5612 switch (sel) {
5613 case 0:
5614 case 2:
5615 case 4:
5616 case 6:
5617 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5618 register_name = "TagLo";
5619 break;
5620 default:
5621 goto cp0_unimplemented;
5623 break;
5624 default:
5625 goto cp0_unimplemented;
5627 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5628 return;
5630 cp0_unimplemented:
5631 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
5632 register_name, reg, sel);
5633 tcg_gen_movi_tl(arg, 0);
5636 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5638 const char *register_name = "invalid";
5639 uint64_t mask = ctx->PAMask >> 36;
5641 switch (reg) {
5642 case CP0_REGISTER_02:
5643 switch (sel) {
5644 case 0:
5645 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5646 tcg_gen_andi_tl(arg, arg, mask);
5647 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5648 register_name = "EntryLo0";
5649 break;
5650 default:
5651 goto cp0_unimplemented;
5653 break;
5654 case CP0_REGISTER_03:
5655 switch (sel) {
5656 case CP0_REG03__ENTRYLO1:
5657 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5658 tcg_gen_andi_tl(arg, arg, mask);
5659 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5660 register_name = "EntryLo1";
5661 break;
5662 default:
5663 goto cp0_unimplemented;
5665 break;
5666 case CP0_REGISTER_09:
5667 switch (sel) {
5668 case CP0_REG09__SAAR:
5669 CP0_CHECK(ctx->saar);
5670 gen_helper_mthc0_saar(cpu_env, arg);
5671 register_name = "SAAR";
5672 break;
5673 default:
5674 goto cp0_unimplemented;
5676 break;
5677 case CP0_REGISTER_17:
5678 switch (sel) {
5679 case CP0_REG17__LLADDR:
5681 * LLAddr is read-only (the only exception is bit 0 if LLB is
5682 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5683 * relevant for modern MIPS cores supporting MTHC0, therefore
5684 * treating MTHC0 to LLAddr as NOP.
5686 register_name = "LLAddr";
5687 break;
5688 case CP0_REG17__MAAR:
5689 CP0_CHECK(ctx->mrp);
5690 gen_helper_mthc0_maar(cpu_env, arg);
5691 register_name = "MAAR";
5692 break;
5693 default:
5694 goto cp0_unimplemented;
5696 break;
5697 case CP0_REGISTER_19:
5698 switch (sel) {
5699 case CP0_REG19__WATCHHI0:
5700 case CP0_REG19__WATCHHI1:
5701 case CP0_REG19__WATCHHI2:
5702 case CP0_REG19__WATCHHI3:
5703 case CP0_REG19__WATCHHI4:
5704 case CP0_REG19__WATCHHI5:
5705 case CP0_REG19__WATCHHI6:
5706 case CP0_REG19__WATCHHI7:
5707 /* upper 32 bits are only available when Config5MI != 0 */
5708 CP0_CHECK(ctx->mi);
5709 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5710 register_name = "WatchHi";
5711 break;
5712 default:
5713 goto cp0_unimplemented;
5715 break;
5716 case CP0_REGISTER_28:
5717 switch (sel) {
5718 case 0:
5719 case 2:
5720 case 4:
5721 case 6:
5722 tcg_gen_andi_tl(arg, arg, mask);
5723 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5724 register_name = "TagLo";
5725 break;
5726 default:
5727 goto cp0_unimplemented;
5729 break;
5730 default:
5731 goto cp0_unimplemented;
5733 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5734 return;
5736 cp0_unimplemented:
5737 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5738 register_name, reg, sel);
5741 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5743 if (ctx->insn_flags & ISA_MIPS_R6) {
5744 tcg_gen_movi_tl(arg, 0);
5745 } else {
5746 tcg_gen_movi_tl(arg, ~0);
5750 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5752 const char *register_name = "invalid";
5754 if (sel != 0) {
5755 check_insn(ctx, ISA_MIPS_R1);
5758 switch (reg) {
5759 case CP0_REGISTER_00:
5760 switch (sel) {
5761 case CP0_REG00__INDEX:
5762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5763 register_name = "Index";
5764 break;
5765 case CP0_REG00__MVPCONTROL:
5766 CP0_CHECK(ctx->insn_flags & ASE_MT);
5767 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5768 register_name = "MVPControl";
5769 break;
5770 case CP0_REG00__MVPCONF0:
5771 CP0_CHECK(ctx->insn_flags & ASE_MT);
5772 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5773 register_name = "MVPConf0";
5774 break;
5775 case CP0_REG00__MVPCONF1:
5776 CP0_CHECK(ctx->insn_flags & ASE_MT);
5777 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5778 register_name = "MVPConf1";
5779 break;
5780 case CP0_REG00__VPCONTROL:
5781 CP0_CHECK(ctx->vp);
5782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5783 register_name = "VPControl";
5784 break;
5785 default:
5786 goto cp0_unimplemented;
5788 break;
5789 case CP0_REGISTER_01:
5790 switch (sel) {
5791 case CP0_REG01__RANDOM:
5792 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
5793 gen_helper_mfc0_random(arg, cpu_env);
5794 register_name = "Random";
5795 break;
5796 case CP0_REG01__VPECONTROL:
5797 CP0_CHECK(ctx->insn_flags & ASE_MT);
5798 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5799 register_name = "VPEControl";
5800 break;
5801 case CP0_REG01__VPECONF0:
5802 CP0_CHECK(ctx->insn_flags & ASE_MT);
5803 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5804 register_name = "VPEConf0";
5805 break;
5806 case CP0_REG01__VPECONF1:
5807 CP0_CHECK(ctx->insn_flags & ASE_MT);
5808 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5809 register_name = "VPEConf1";
5810 break;
5811 case CP0_REG01__YQMASK:
5812 CP0_CHECK(ctx->insn_flags & ASE_MT);
5813 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5814 register_name = "YQMask";
5815 break;
5816 case CP0_REG01__VPESCHEDULE:
5817 CP0_CHECK(ctx->insn_flags & ASE_MT);
5818 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5819 register_name = "VPESchedule";
5820 break;
5821 case CP0_REG01__VPESCHEFBACK:
5822 CP0_CHECK(ctx->insn_flags & ASE_MT);
5823 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5824 register_name = "VPEScheFBack";
5825 break;
5826 case CP0_REG01__VPEOPT:
5827 CP0_CHECK(ctx->insn_flags & ASE_MT);
5828 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5829 register_name = "VPEOpt";
5830 break;
5831 default:
5832 goto cp0_unimplemented;
5834 break;
5835 case CP0_REGISTER_02:
5836 switch (sel) {
5837 case CP0_REG02__ENTRYLO0:
5839 TCGv_i64 tmp = tcg_temp_new_i64();
5840 tcg_gen_ld_i64(tmp, cpu_env,
5841 offsetof(CPUMIPSState, CP0_EntryLo0));
5842 #if defined(TARGET_MIPS64)
5843 if (ctx->rxi) {
5844 /* Move RI/XI fields to bits 31:30 */
5845 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5846 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5848 #endif
5849 gen_move_low32(arg, tmp);
5850 tcg_temp_free_i64(tmp);
5852 register_name = "EntryLo0";
5853 break;
5854 case CP0_REG02__TCSTATUS:
5855 CP0_CHECK(ctx->insn_flags & ASE_MT);
5856 gen_helper_mfc0_tcstatus(arg, cpu_env);
5857 register_name = "TCStatus";
5858 break;
5859 case CP0_REG02__TCBIND:
5860 CP0_CHECK(ctx->insn_flags & ASE_MT);
5861 gen_helper_mfc0_tcbind(arg, cpu_env);
5862 register_name = "TCBind";
5863 break;
5864 case CP0_REG02__TCRESTART:
5865 CP0_CHECK(ctx->insn_flags & ASE_MT);
5866 gen_helper_mfc0_tcrestart(arg, cpu_env);
5867 register_name = "TCRestart";
5868 break;
5869 case CP0_REG02__TCHALT:
5870 CP0_CHECK(ctx->insn_flags & ASE_MT);
5871 gen_helper_mfc0_tchalt(arg, cpu_env);
5872 register_name = "TCHalt";
5873 break;
5874 case CP0_REG02__TCCONTEXT:
5875 CP0_CHECK(ctx->insn_flags & ASE_MT);
5876 gen_helper_mfc0_tccontext(arg, cpu_env);
5877 register_name = "TCContext";
5878 break;
5879 case CP0_REG02__TCSCHEDULE:
5880 CP0_CHECK(ctx->insn_flags & ASE_MT);
5881 gen_helper_mfc0_tcschedule(arg, cpu_env);
5882 register_name = "TCSchedule";
5883 break;
5884 case CP0_REG02__TCSCHEFBACK:
5885 CP0_CHECK(ctx->insn_flags & ASE_MT);
5886 gen_helper_mfc0_tcschefback(arg, cpu_env);
5887 register_name = "TCScheFBack";
5888 break;
5889 default:
5890 goto cp0_unimplemented;
5892 break;
5893 case CP0_REGISTER_03:
5894 switch (sel) {
5895 case CP0_REG03__ENTRYLO1:
5897 TCGv_i64 tmp = tcg_temp_new_i64();
5898 tcg_gen_ld_i64(tmp, cpu_env,
5899 offsetof(CPUMIPSState, CP0_EntryLo1));
5900 #if defined(TARGET_MIPS64)
5901 if (ctx->rxi) {
5902 /* Move RI/XI fields to bits 31:30 */
5903 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5904 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5906 #endif
5907 gen_move_low32(arg, tmp);
5908 tcg_temp_free_i64(tmp);
5910 register_name = "EntryLo1";
5911 break;
5912 case CP0_REG03__GLOBALNUM:
5913 CP0_CHECK(ctx->vp);
5914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5915 register_name = "GlobalNumber";
5916 break;
5917 default:
5918 goto cp0_unimplemented;
5920 break;
5921 case CP0_REGISTER_04:
5922 switch (sel) {
5923 case CP0_REG04__CONTEXT:
5924 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5925 tcg_gen_ext32s_tl(arg, arg);
5926 register_name = "Context";
5927 break;
5928 case CP0_REG04__CONTEXTCONFIG:
5929 /* SmartMIPS ASE */
5930 /* gen_helper_mfc0_contextconfig(arg); */
5931 register_name = "ContextConfig";
5932 goto cp0_unimplemented;
5933 case CP0_REG04__USERLOCAL:
5934 CP0_CHECK(ctx->ulri);
5935 tcg_gen_ld_tl(arg, cpu_env,
5936 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5937 tcg_gen_ext32s_tl(arg, arg);
5938 register_name = "UserLocal";
5939 break;
5940 case CP0_REG04__MMID:
5941 CP0_CHECK(ctx->mi);
5942 gen_helper_mtc0_memorymapid(cpu_env, arg);
5943 register_name = "MMID";
5944 break;
5945 default:
5946 goto cp0_unimplemented;
5948 break;
5949 case CP0_REGISTER_05:
5950 switch (sel) {
5951 case CP0_REG05__PAGEMASK:
5952 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5953 register_name = "PageMask";
5954 break;
5955 case CP0_REG05__PAGEGRAIN:
5956 check_insn(ctx, ISA_MIPS_R2);
5957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5958 register_name = "PageGrain";
5959 break;
5960 case CP0_REG05__SEGCTL0:
5961 CP0_CHECK(ctx->sc);
5962 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5963 tcg_gen_ext32s_tl(arg, arg);
5964 register_name = "SegCtl0";
5965 break;
5966 case CP0_REG05__SEGCTL1:
5967 CP0_CHECK(ctx->sc);
5968 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5969 tcg_gen_ext32s_tl(arg, arg);
5970 register_name = "SegCtl1";
5971 break;
5972 case CP0_REG05__SEGCTL2:
5973 CP0_CHECK(ctx->sc);
5974 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5975 tcg_gen_ext32s_tl(arg, arg);
5976 register_name = "SegCtl2";
5977 break;
5978 case CP0_REG05__PWBASE:
5979 check_pw(ctx);
5980 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
5981 register_name = "PWBase";
5982 break;
5983 case CP0_REG05__PWFIELD:
5984 check_pw(ctx);
5985 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
5986 register_name = "PWField";
5987 break;
5988 case CP0_REG05__PWSIZE:
5989 check_pw(ctx);
5990 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
5991 register_name = "PWSize";
5992 break;
5993 default:
5994 goto cp0_unimplemented;
5996 break;
5997 case CP0_REGISTER_06:
5998 switch (sel) {
5999 case CP0_REG06__WIRED:
6000 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6001 register_name = "Wired";
6002 break;
6003 case CP0_REG06__SRSCONF0:
6004 check_insn(ctx, ISA_MIPS_R2);
6005 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6006 register_name = "SRSConf0";
6007 break;
6008 case CP0_REG06__SRSCONF1:
6009 check_insn(ctx, ISA_MIPS_R2);
6010 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6011 register_name = "SRSConf1";
6012 break;
6013 case CP0_REG06__SRSCONF2:
6014 check_insn(ctx, ISA_MIPS_R2);
6015 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6016 register_name = "SRSConf2";
6017 break;
6018 case CP0_REG06__SRSCONF3:
6019 check_insn(ctx, ISA_MIPS_R2);
6020 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6021 register_name = "SRSConf3";
6022 break;
6023 case CP0_REG06__SRSCONF4:
6024 check_insn(ctx, ISA_MIPS_R2);
6025 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6026 register_name = "SRSConf4";
6027 break;
6028 case CP0_REG06__PWCTL:
6029 check_pw(ctx);
6030 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6031 register_name = "PWCtl";
6032 break;
6033 default:
6034 goto cp0_unimplemented;
6036 break;
6037 case CP0_REGISTER_07:
6038 switch (sel) {
6039 case CP0_REG07__HWRENA:
6040 check_insn(ctx, ISA_MIPS_R2);
6041 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6042 register_name = "HWREna";
6043 break;
6044 default:
6045 goto cp0_unimplemented;
6047 break;
6048 case CP0_REGISTER_08:
6049 switch (sel) {
6050 case CP0_REG08__BADVADDR:
6051 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6052 tcg_gen_ext32s_tl(arg, arg);
6053 register_name = "BadVAddr";
6054 break;
6055 case CP0_REG08__BADINSTR:
6056 CP0_CHECK(ctx->bi);
6057 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6058 register_name = "BadInstr";
6059 break;
6060 case CP0_REG08__BADINSTRP:
6061 CP0_CHECK(ctx->bp);
6062 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6063 register_name = "BadInstrP";
6064 break;
6065 case CP0_REG08__BADINSTRX:
6066 CP0_CHECK(ctx->bi);
6067 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6068 tcg_gen_andi_tl(arg, arg, ~0xffff);
6069 register_name = "BadInstrX";
6070 break;
6071 default:
6072 goto cp0_unimplemented;
6074 break;
6075 case CP0_REGISTER_09:
6076 switch (sel) {
6077 case CP0_REG09__COUNT:
6078 /* Mark as an IO operation because we read the time. */
6079 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6080 gen_io_start();
6082 gen_helper_mfc0_count(arg, cpu_env);
6084 * Break the TB to be able to take timer interrupts immediately
6085 * after reading count. DISAS_STOP isn't sufficient, we need to
6086 * ensure we break completely out of translated code.
6088 gen_save_pc(ctx->base.pc_next + 4);
6089 ctx->base.is_jmp = DISAS_EXIT;
6090 register_name = "Count";
6091 break;
6092 case CP0_REG09__SAARI:
6093 CP0_CHECK(ctx->saar);
6094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
6095 register_name = "SAARI";
6096 break;
6097 case CP0_REG09__SAAR:
6098 CP0_CHECK(ctx->saar);
6099 gen_helper_mfc0_saar(arg, cpu_env);
6100 register_name = "SAAR";
6101 break;
6102 default:
6103 goto cp0_unimplemented;
6105 break;
6106 case CP0_REGISTER_10:
6107 switch (sel) {
6108 case CP0_REG10__ENTRYHI:
6109 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6110 tcg_gen_ext32s_tl(arg, arg);
6111 register_name = "EntryHi";
6112 break;
6113 default:
6114 goto cp0_unimplemented;
6116 break;
6117 case CP0_REGISTER_11:
6118 switch (sel) {
6119 case CP0_REG11__COMPARE:
6120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6121 register_name = "Compare";
6122 break;
6123 /* 6,7 are implementation dependent */
6124 default:
6125 goto cp0_unimplemented;
6127 break;
6128 case CP0_REGISTER_12:
6129 switch (sel) {
6130 case CP0_REG12__STATUS:
6131 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6132 register_name = "Status";
6133 break;
6134 case CP0_REG12__INTCTL:
6135 check_insn(ctx, ISA_MIPS_R2);
6136 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6137 register_name = "IntCtl";
6138 break;
6139 case CP0_REG12__SRSCTL:
6140 check_insn(ctx, ISA_MIPS_R2);
6141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6142 register_name = "SRSCtl";
6143 break;
6144 case CP0_REG12__SRSMAP:
6145 check_insn(ctx, ISA_MIPS_R2);
6146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6147 register_name = "SRSMap";
6148 break;
6149 default:
6150 goto cp0_unimplemented;
6152 break;
6153 case CP0_REGISTER_13:
6154 switch (sel) {
6155 case CP0_REG13__CAUSE:
6156 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6157 register_name = "Cause";
6158 break;
6159 default:
6160 goto cp0_unimplemented;
6162 break;
6163 case CP0_REGISTER_14:
6164 switch (sel) {
6165 case CP0_REG14__EPC:
6166 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6167 tcg_gen_ext32s_tl(arg, arg);
6168 register_name = "EPC";
6169 break;
6170 default:
6171 goto cp0_unimplemented;
6173 break;
6174 case CP0_REGISTER_15:
6175 switch (sel) {
6176 case CP0_REG15__PRID:
6177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6178 register_name = "PRid";
6179 break;
6180 case CP0_REG15__EBASE:
6181 check_insn(ctx, ISA_MIPS_R2);
6182 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6183 tcg_gen_ext32s_tl(arg, arg);
6184 register_name = "EBase";
6185 break;
6186 case CP0_REG15__CMGCRBASE:
6187 check_insn(ctx, ISA_MIPS_R2);
6188 CP0_CHECK(ctx->cmgcr);
6189 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6190 tcg_gen_ext32s_tl(arg, arg);
6191 register_name = "CMGCRBase";
6192 break;
6193 default:
6194 goto cp0_unimplemented;
6196 break;
6197 case CP0_REGISTER_16:
6198 switch (sel) {
6199 case CP0_REG16__CONFIG:
6200 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6201 register_name = "Config";
6202 break;
6203 case CP0_REG16__CONFIG1:
6204 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6205 register_name = "Config1";
6206 break;
6207 case CP0_REG16__CONFIG2:
6208 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6209 register_name = "Config2";
6210 break;
6211 case CP0_REG16__CONFIG3:
6212 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6213 register_name = "Config3";
6214 break;
6215 case CP0_REG16__CONFIG4:
6216 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6217 register_name = "Config4";
6218 break;
6219 case CP0_REG16__CONFIG5:
6220 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6221 register_name = "Config5";
6222 break;
6223 /* 6,7 are implementation dependent */
6224 case CP0_REG16__CONFIG6:
6225 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6226 register_name = "Config6";
6227 break;
6228 case CP0_REG16__CONFIG7:
6229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6230 register_name = "Config7";
6231 break;
6232 default:
6233 goto cp0_unimplemented;
6235 break;
6236 case CP0_REGISTER_17:
6237 switch (sel) {
6238 case CP0_REG17__LLADDR:
6239 gen_helper_mfc0_lladdr(arg, cpu_env);
6240 register_name = "LLAddr";
6241 break;
6242 case CP0_REG17__MAAR:
6243 CP0_CHECK(ctx->mrp);
6244 gen_helper_mfc0_maar(arg, cpu_env);
6245 register_name = "MAAR";
6246 break;
6247 case CP0_REG17__MAARI:
6248 CP0_CHECK(ctx->mrp);
6249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6250 register_name = "MAARI";
6251 break;
6252 default:
6253 goto cp0_unimplemented;
6255 break;
6256 case CP0_REGISTER_18:
6257 switch (sel) {
6258 case CP0_REG18__WATCHLO0:
6259 case CP0_REG18__WATCHLO1:
6260 case CP0_REG18__WATCHLO2:
6261 case CP0_REG18__WATCHLO3:
6262 case CP0_REG18__WATCHLO4:
6263 case CP0_REG18__WATCHLO5:
6264 case CP0_REG18__WATCHLO6:
6265 case CP0_REG18__WATCHLO7:
6266 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6267 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6268 register_name = "WatchLo";
6269 break;
6270 default:
6271 goto cp0_unimplemented;
6273 break;
6274 case CP0_REGISTER_19:
6275 switch (sel) {
6276 case CP0_REG19__WATCHHI0:
6277 case CP0_REG19__WATCHHI1:
6278 case CP0_REG19__WATCHHI2:
6279 case CP0_REG19__WATCHHI3:
6280 case CP0_REG19__WATCHHI4:
6281 case CP0_REG19__WATCHHI5:
6282 case CP0_REG19__WATCHHI6:
6283 case CP0_REG19__WATCHHI7:
6284 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6285 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6286 register_name = "WatchHi";
6287 break;
6288 default:
6289 goto cp0_unimplemented;
6291 break;
6292 case CP0_REGISTER_20:
6293 switch (sel) {
6294 case CP0_REG20__XCONTEXT:
6295 #if defined(TARGET_MIPS64)
6296 check_insn(ctx, ISA_MIPS3);
6297 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6298 tcg_gen_ext32s_tl(arg, arg);
6299 register_name = "XContext";
6300 break;
6301 #endif
6302 default:
6303 goto cp0_unimplemented;
6305 break;
6306 case CP0_REGISTER_21:
6307 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6308 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6309 switch (sel) {
6310 case 0:
6311 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6312 register_name = "Framemask";
6313 break;
6314 default:
6315 goto cp0_unimplemented;
6317 break;
6318 case CP0_REGISTER_22:
6319 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6320 register_name = "'Diagnostic"; /* implementation dependent */
6321 break;
6322 case CP0_REGISTER_23:
6323 switch (sel) {
6324 case CP0_REG23__DEBUG:
6325 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6326 register_name = "Debug";
6327 break;
6328 case CP0_REG23__TRACECONTROL:
6329 /* PDtrace support */
6330 /* gen_helper_mfc0_tracecontrol(arg); */
6331 register_name = "TraceControl";
6332 goto cp0_unimplemented;
6333 case CP0_REG23__TRACECONTROL2:
6334 /* PDtrace support */
6335 /* gen_helper_mfc0_tracecontrol2(arg); */
6336 register_name = "TraceControl2";
6337 goto cp0_unimplemented;
6338 case CP0_REG23__USERTRACEDATA1:
6339 /* PDtrace support */
6340 /* gen_helper_mfc0_usertracedata1(arg);*/
6341 register_name = "UserTraceData1";
6342 goto cp0_unimplemented;
6343 case CP0_REG23__TRACEIBPC:
6344 /* PDtrace support */
6345 /* gen_helper_mfc0_traceibpc(arg); */
6346 register_name = "TraceIBPC";
6347 goto cp0_unimplemented;
6348 case CP0_REG23__TRACEDBPC:
6349 /* PDtrace support */
6350 /* gen_helper_mfc0_tracedbpc(arg); */
6351 register_name = "TraceDBPC";
6352 goto cp0_unimplemented;
6353 default:
6354 goto cp0_unimplemented;
6356 break;
6357 case CP0_REGISTER_24:
6358 switch (sel) {
6359 case CP0_REG24__DEPC:
6360 /* EJTAG support */
6361 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6362 tcg_gen_ext32s_tl(arg, arg);
6363 register_name = "DEPC";
6364 break;
6365 default:
6366 goto cp0_unimplemented;
6368 break;
6369 case CP0_REGISTER_25:
6370 switch (sel) {
6371 case CP0_REG25__PERFCTL0:
6372 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6373 register_name = "Performance0";
6374 break;
6375 case CP0_REG25__PERFCNT0:
6376 /* gen_helper_mfc0_performance1(arg); */
6377 register_name = "Performance1";
6378 goto cp0_unimplemented;
6379 case CP0_REG25__PERFCTL1:
6380 /* gen_helper_mfc0_performance2(arg); */
6381 register_name = "Performance2";
6382 goto cp0_unimplemented;
6383 case CP0_REG25__PERFCNT1:
6384 /* gen_helper_mfc0_performance3(arg); */
6385 register_name = "Performance3";
6386 goto cp0_unimplemented;
6387 case CP0_REG25__PERFCTL2:
6388 /* gen_helper_mfc0_performance4(arg); */
6389 register_name = "Performance4";
6390 goto cp0_unimplemented;
6391 case CP0_REG25__PERFCNT2:
6392 /* gen_helper_mfc0_performance5(arg); */
6393 register_name = "Performance5";
6394 goto cp0_unimplemented;
6395 case CP0_REG25__PERFCTL3:
6396 /* gen_helper_mfc0_performance6(arg); */
6397 register_name = "Performance6";
6398 goto cp0_unimplemented;
6399 case CP0_REG25__PERFCNT3:
6400 /* gen_helper_mfc0_performance7(arg); */
6401 register_name = "Performance7";
6402 goto cp0_unimplemented;
6403 default:
6404 goto cp0_unimplemented;
6406 break;
6407 case CP0_REGISTER_26:
6408 switch (sel) {
6409 case CP0_REG26__ERRCTL:
6410 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6411 register_name = "ErrCtl";
6412 break;
6413 default:
6414 goto cp0_unimplemented;
6416 break;
6417 case CP0_REGISTER_27:
6418 switch (sel) {
6419 case CP0_REG27__CACHERR:
6420 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6421 register_name = "CacheErr";
6422 break;
6423 default:
6424 goto cp0_unimplemented;
6426 break;
6427 case CP0_REGISTER_28:
6428 switch (sel) {
6429 case CP0_REG28__TAGLO:
6430 case CP0_REG28__TAGLO1:
6431 case CP0_REG28__TAGLO2:
6432 case CP0_REG28__TAGLO3:
6434 TCGv_i64 tmp = tcg_temp_new_i64();
6435 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6436 gen_move_low32(arg, tmp);
6437 tcg_temp_free_i64(tmp);
6439 register_name = "TagLo";
6440 break;
6441 case CP0_REG28__DATALO:
6442 case CP0_REG28__DATALO1:
6443 case CP0_REG28__DATALO2:
6444 case CP0_REG28__DATALO3:
6445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6446 register_name = "DataLo";
6447 break;
6448 default:
6449 goto cp0_unimplemented;
6451 break;
6452 case CP0_REGISTER_29:
6453 switch (sel) {
6454 case CP0_REG29__TAGHI:
6455 case CP0_REG29__TAGHI1:
6456 case CP0_REG29__TAGHI2:
6457 case CP0_REG29__TAGHI3:
6458 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6459 register_name = "TagHi";
6460 break;
6461 case CP0_REG29__DATAHI:
6462 case CP0_REG29__DATAHI1:
6463 case CP0_REG29__DATAHI2:
6464 case CP0_REG29__DATAHI3:
6465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6466 register_name = "DataHi";
6467 break;
6468 default:
6469 goto cp0_unimplemented;
6471 break;
6472 case CP0_REGISTER_30:
6473 switch (sel) {
6474 case CP0_REG30__ERROREPC:
6475 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6476 tcg_gen_ext32s_tl(arg, arg);
6477 register_name = "ErrorEPC";
6478 break;
6479 default:
6480 goto cp0_unimplemented;
6482 break;
6483 case CP0_REGISTER_31:
6484 switch (sel) {
6485 case CP0_REG31__DESAVE:
6486 /* EJTAG support */
6487 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6488 register_name = "DESAVE";
6489 break;
6490 case CP0_REG31__KSCRATCH1:
6491 case CP0_REG31__KSCRATCH2:
6492 case CP0_REG31__KSCRATCH3:
6493 case CP0_REG31__KSCRATCH4:
6494 case CP0_REG31__KSCRATCH5:
6495 case CP0_REG31__KSCRATCH6:
6496 CP0_CHECK(ctx->kscrexist & (1 << sel));
6497 tcg_gen_ld_tl(arg, cpu_env,
6498 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
6499 tcg_gen_ext32s_tl(arg, arg);
6500 register_name = "KScratch";
6501 break;
6502 default:
6503 goto cp0_unimplemented;
6505 break;
6506 default:
6507 goto cp0_unimplemented;
6509 trace_mips_translate_c0("mfc0", register_name, reg, sel);
6510 return;
6512 cp0_unimplemented:
6513 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6514 register_name, reg, sel);
6515 gen_mfc0_unimplemented(ctx, arg);
6518 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6520 const char *register_name = "invalid";
6522 if (sel != 0) {
6523 check_insn(ctx, ISA_MIPS_R1);
6526 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6527 gen_io_start();
6530 switch (reg) {
6531 case CP0_REGISTER_00:
6532 switch (sel) {
6533 case CP0_REG00__INDEX:
6534 gen_helper_mtc0_index(cpu_env, arg);
6535 register_name = "Index";
6536 break;
6537 case CP0_REG00__MVPCONTROL:
6538 CP0_CHECK(ctx->insn_flags & ASE_MT);
6539 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6540 register_name = "MVPControl";
6541 break;
6542 case CP0_REG00__MVPCONF0:
6543 CP0_CHECK(ctx->insn_flags & ASE_MT);
6544 /* ignored */
6545 register_name = "MVPConf0";
6546 break;
6547 case CP0_REG00__MVPCONF1:
6548 CP0_CHECK(ctx->insn_flags & ASE_MT);
6549 /* ignored */
6550 register_name = "MVPConf1";
6551 break;
6552 case CP0_REG00__VPCONTROL:
6553 CP0_CHECK(ctx->vp);
6554 /* ignored */
6555 register_name = "VPControl";
6556 break;
6557 default:
6558 goto cp0_unimplemented;
6560 break;
6561 case CP0_REGISTER_01:
6562 switch (sel) {
6563 case CP0_REG01__RANDOM:
6564 /* ignored */
6565 register_name = "Random";
6566 break;
6567 case CP0_REG01__VPECONTROL:
6568 CP0_CHECK(ctx->insn_flags & ASE_MT);
6569 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6570 register_name = "VPEControl";
6571 break;
6572 case CP0_REG01__VPECONF0:
6573 CP0_CHECK(ctx->insn_flags & ASE_MT);
6574 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6575 register_name = "VPEConf0";
6576 break;
6577 case CP0_REG01__VPECONF1:
6578 CP0_CHECK(ctx->insn_flags & ASE_MT);
6579 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6580 register_name = "VPEConf1";
6581 break;
6582 case CP0_REG01__YQMASK:
6583 CP0_CHECK(ctx->insn_flags & ASE_MT);
6584 gen_helper_mtc0_yqmask(cpu_env, arg);
6585 register_name = "YQMask";
6586 break;
6587 case CP0_REG01__VPESCHEDULE:
6588 CP0_CHECK(ctx->insn_flags & ASE_MT);
6589 tcg_gen_st_tl(arg, cpu_env,
6590 offsetof(CPUMIPSState, CP0_VPESchedule));
6591 register_name = "VPESchedule";
6592 break;
6593 case CP0_REG01__VPESCHEFBACK:
6594 CP0_CHECK(ctx->insn_flags & ASE_MT);
6595 tcg_gen_st_tl(arg, cpu_env,
6596 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6597 register_name = "VPEScheFBack";
6598 break;
6599 case CP0_REG01__VPEOPT:
6600 CP0_CHECK(ctx->insn_flags & ASE_MT);
6601 gen_helper_mtc0_vpeopt(cpu_env, arg);
6602 register_name = "VPEOpt";
6603 break;
6604 default:
6605 goto cp0_unimplemented;
6607 break;
6608 case CP0_REGISTER_02:
6609 switch (sel) {
6610 case CP0_REG02__ENTRYLO0:
6611 gen_helper_mtc0_entrylo0(cpu_env, arg);
6612 register_name = "EntryLo0";
6613 break;
6614 case CP0_REG02__TCSTATUS:
6615 CP0_CHECK(ctx->insn_flags & ASE_MT);
6616 gen_helper_mtc0_tcstatus(cpu_env, arg);
6617 register_name = "TCStatus";
6618 break;
6619 case CP0_REG02__TCBIND:
6620 CP0_CHECK(ctx->insn_flags & ASE_MT);
6621 gen_helper_mtc0_tcbind(cpu_env, arg);
6622 register_name = "TCBind";
6623 break;
6624 case CP0_REG02__TCRESTART:
6625 CP0_CHECK(ctx->insn_flags & ASE_MT);
6626 gen_helper_mtc0_tcrestart(cpu_env, arg);
6627 register_name = "TCRestart";
6628 break;
6629 case CP0_REG02__TCHALT:
6630 CP0_CHECK(ctx->insn_flags & ASE_MT);
6631 gen_helper_mtc0_tchalt(cpu_env, arg);
6632 register_name = "TCHalt";
6633 break;
6634 case CP0_REG02__TCCONTEXT:
6635 CP0_CHECK(ctx->insn_flags & ASE_MT);
6636 gen_helper_mtc0_tccontext(cpu_env, arg);
6637 register_name = "TCContext";
6638 break;
6639 case CP0_REG02__TCSCHEDULE:
6640 CP0_CHECK(ctx->insn_flags & ASE_MT);
6641 gen_helper_mtc0_tcschedule(cpu_env, arg);
6642 register_name = "TCSchedule";
6643 break;
6644 case CP0_REG02__TCSCHEFBACK:
6645 CP0_CHECK(ctx->insn_flags & ASE_MT);
6646 gen_helper_mtc0_tcschefback(cpu_env, arg);
6647 register_name = "TCScheFBack";
6648 break;
6649 default:
6650 goto cp0_unimplemented;
6652 break;
6653 case CP0_REGISTER_03:
6654 switch (sel) {
6655 case CP0_REG03__ENTRYLO1:
6656 gen_helper_mtc0_entrylo1(cpu_env, arg);
6657 register_name = "EntryLo1";
6658 break;
6659 case CP0_REG03__GLOBALNUM:
6660 CP0_CHECK(ctx->vp);
6661 /* ignored */
6662 register_name = "GlobalNumber";
6663 break;
6664 default:
6665 goto cp0_unimplemented;
6667 break;
6668 case CP0_REGISTER_04:
6669 switch (sel) {
6670 case CP0_REG04__CONTEXT:
6671 gen_helper_mtc0_context(cpu_env, arg);
6672 register_name = "Context";
6673 break;
6674 case CP0_REG04__CONTEXTCONFIG:
6675 /* SmartMIPS ASE */
6676 /* gen_helper_mtc0_contextconfig(arg); */
6677 register_name = "ContextConfig";
6678 goto cp0_unimplemented;
6679 case CP0_REG04__USERLOCAL:
6680 CP0_CHECK(ctx->ulri);
6681 tcg_gen_st_tl(arg, cpu_env,
6682 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6683 register_name = "UserLocal";
6684 break;
6685 case CP0_REG04__MMID:
6686 CP0_CHECK(ctx->mi);
6687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6688 register_name = "MMID";
6689 break;
6690 default:
6691 goto cp0_unimplemented;
6693 break;
6694 case CP0_REGISTER_05:
6695 switch (sel) {
6696 case CP0_REG05__PAGEMASK:
6697 gen_helper_mtc0_pagemask(cpu_env, arg);
6698 register_name = "PageMask";
6699 break;
6700 case CP0_REG05__PAGEGRAIN:
6701 check_insn(ctx, ISA_MIPS_R2);
6702 gen_helper_mtc0_pagegrain(cpu_env, arg);
6703 register_name = "PageGrain";
6704 ctx->base.is_jmp = DISAS_STOP;
6705 break;
6706 case CP0_REG05__SEGCTL0:
6707 CP0_CHECK(ctx->sc);
6708 gen_helper_mtc0_segctl0(cpu_env, arg);
6709 register_name = "SegCtl0";
6710 break;
6711 case CP0_REG05__SEGCTL1:
6712 CP0_CHECK(ctx->sc);
6713 gen_helper_mtc0_segctl1(cpu_env, arg);
6714 register_name = "SegCtl1";
6715 break;
6716 case CP0_REG05__SEGCTL2:
6717 CP0_CHECK(ctx->sc);
6718 gen_helper_mtc0_segctl2(cpu_env, arg);
6719 register_name = "SegCtl2";
6720 break;
6721 case CP0_REG05__PWBASE:
6722 check_pw(ctx);
6723 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6724 register_name = "PWBase";
6725 break;
6726 case CP0_REG05__PWFIELD:
6727 check_pw(ctx);
6728 gen_helper_mtc0_pwfield(cpu_env, arg);
6729 register_name = "PWField";
6730 break;
6731 case CP0_REG05__PWSIZE:
6732 check_pw(ctx);
6733 gen_helper_mtc0_pwsize(cpu_env, arg);
6734 register_name = "PWSize";
6735 break;
6736 default:
6737 goto cp0_unimplemented;
6739 break;
6740 case CP0_REGISTER_06:
6741 switch (sel) {
6742 case CP0_REG06__WIRED:
6743 gen_helper_mtc0_wired(cpu_env, arg);
6744 register_name = "Wired";
6745 break;
6746 case CP0_REG06__SRSCONF0:
6747 check_insn(ctx, ISA_MIPS_R2);
6748 gen_helper_mtc0_srsconf0(cpu_env, arg);
6749 register_name = "SRSConf0";
6750 break;
6751 case CP0_REG06__SRSCONF1:
6752 check_insn(ctx, ISA_MIPS_R2);
6753 gen_helper_mtc0_srsconf1(cpu_env, arg);
6754 register_name = "SRSConf1";
6755 break;
6756 case CP0_REG06__SRSCONF2:
6757 check_insn(ctx, ISA_MIPS_R2);
6758 gen_helper_mtc0_srsconf2(cpu_env, arg);
6759 register_name = "SRSConf2";
6760 break;
6761 case CP0_REG06__SRSCONF3:
6762 check_insn(ctx, ISA_MIPS_R2);
6763 gen_helper_mtc0_srsconf3(cpu_env, arg);
6764 register_name = "SRSConf3";
6765 break;
6766 case CP0_REG06__SRSCONF4:
6767 check_insn(ctx, ISA_MIPS_R2);
6768 gen_helper_mtc0_srsconf4(cpu_env, arg);
6769 register_name = "SRSConf4";
6770 break;
6771 case CP0_REG06__PWCTL:
6772 check_pw(ctx);
6773 gen_helper_mtc0_pwctl(cpu_env, arg);
6774 register_name = "PWCtl";
6775 break;
6776 default:
6777 goto cp0_unimplemented;
6779 break;
6780 case CP0_REGISTER_07:
6781 switch (sel) {
6782 case CP0_REG07__HWRENA:
6783 check_insn(ctx, ISA_MIPS_R2);
6784 gen_helper_mtc0_hwrena(cpu_env, arg);
6785 ctx->base.is_jmp = DISAS_STOP;
6786 register_name = "HWREna";
6787 break;
6788 default:
6789 goto cp0_unimplemented;
6791 break;
6792 case CP0_REGISTER_08:
6793 switch (sel) {
6794 case CP0_REG08__BADVADDR:
6795 /* ignored */
6796 register_name = "BadVAddr";
6797 break;
6798 case CP0_REG08__BADINSTR:
6799 /* ignored */
6800 register_name = "BadInstr";
6801 break;
6802 case CP0_REG08__BADINSTRP:
6803 /* ignored */
6804 register_name = "BadInstrP";
6805 break;
6806 case CP0_REG08__BADINSTRX:
6807 /* ignored */
6808 register_name = "BadInstrX";
6809 break;
6810 default:
6811 goto cp0_unimplemented;
6813 break;
6814 case CP0_REGISTER_09:
6815 switch (sel) {
6816 case CP0_REG09__COUNT:
6817 gen_helper_mtc0_count(cpu_env, arg);
6818 register_name = "Count";
6819 break;
6820 case CP0_REG09__SAARI:
6821 CP0_CHECK(ctx->saar);
6822 gen_helper_mtc0_saari(cpu_env, arg);
6823 register_name = "SAARI";
6824 break;
6825 case CP0_REG09__SAAR:
6826 CP0_CHECK(ctx->saar);
6827 gen_helper_mtc0_saar(cpu_env, arg);
6828 register_name = "SAAR";
6829 break;
6830 default:
6831 goto cp0_unimplemented;
6833 break;
6834 case CP0_REGISTER_10:
6835 switch (sel) {
6836 case CP0_REG10__ENTRYHI:
6837 gen_helper_mtc0_entryhi(cpu_env, arg);
6838 register_name = "EntryHi";
6839 break;
6840 default:
6841 goto cp0_unimplemented;
6843 break;
6844 case CP0_REGISTER_11:
6845 switch (sel) {
6846 case CP0_REG11__COMPARE:
6847 gen_helper_mtc0_compare(cpu_env, arg);
6848 register_name = "Compare";
6849 break;
6850 /* 6,7 are implementation dependent */
6851 default:
6852 goto cp0_unimplemented;
6854 break;
6855 case CP0_REGISTER_12:
6856 switch (sel) {
6857 case CP0_REG12__STATUS:
6858 save_cpu_state(ctx, 1);
6859 gen_helper_mtc0_status(cpu_env, arg);
6860 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6861 gen_save_pc(ctx->base.pc_next + 4);
6862 ctx->base.is_jmp = DISAS_EXIT;
6863 register_name = "Status";
6864 break;
6865 case CP0_REG12__INTCTL:
6866 check_insn(ctx, ISA_MIPS_R2);
6867 gen_helper_mtc0_intctl(cpu_env, arg);
6868 /* Stop translation as we may have switched the execution mode */
6869 ctx->base.is_jmp = DISAS_STOP;
6870 register_name = "IntCtl";
6871 break;
6872 case CP0_REG12__SRSCTL:
6873 check_insn(ctx, ISA_MIPS_R2);
6874 gen_helper_mtc0_srsctl(cpu_env, arg);
6875 /* Stop translation as we may have switched the execution mode */
6876 ctx->base.is_jmp = DISAS_STOP;
6877 register_name = "SRSCtl";
6878 break;
6879 case CP0_REG12__SRSMAP:
6880 check_insn(ctx, ISA_MIPS_R2);
6881 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6882 /* Stop translation as we may have switched the execution mode */
6883 ctx->base.is_jmp = DISAS_STOP;
6884 register_name = "SRSMap";
6885 break;
6886 default:
6887 goto cp0_unimplemented;
6889 break;
6890 case CP0_REGISTER_13:
6891 switch (sel) {
6892 case CP0_REG13__CAUSE:
6893 save_cpu_state(ctx, 1);
6894 gen_helper_mtc0_cause(cpu_env, arg);
6896 * Stop translation as we may have triggered an interrupt.
6897 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6898 * translated code to check for pending interrupts.
6900 gen_save_pc(ctx->base.pc_next + 4);
6901 ctx->base.is_jmp = DISAS_EXIT;
6902 register_name = "Cause";
6903 break;
6904 default:
6905 goto cp0_unimplemented;
6907 break;
6908 case CP0_REGISTER_14:
6909 switch (sel) {
6910 case CP0_REG14__EPC:
6911 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6912 register_name = "EPC";
6913 break;
6914 default:
6915 goto cp0_unimplemented;
6917 break;
6918 case CP0_REGISTER_15:
6919 switch (sel) {
6920 case CP0_REG15__PRID:
6921 /* ignored */
6922 register_name = "PRid";
6923 break;
6924 case CP0_REG15__EBASE:
6925 check_insn(ctx, ISA_MIPS_R2);
6926 gen_helper_mtc0_ebase(cpu_env, arg);
6927 register_name = "EBase";
6928 break;
6929 default:
6930 goto cp0_unimplemented;
6932 break;
6933 case CP0_REGISTER_16:
6934 switch (sel) {
6935 case CP0_REG16__CONFIG:
6936 gen_helper_mtc0_config0(cpu_env, arg);
6937 register_name = "Config";
6938 /* Stop translation as we may have switched the execution mode */
6939 ctx->base.is_jmp = DISAS_STOP;
6940 break;
6941 case CP0_REG16__CONFIG1:
6942 /* ignored, read only */
6943 register_name = "Config1";
6944 break;
6945 case CP0_REG16__CONFIG2:
6946 gen_helper_mtc0_config2(cpu_env, arg);
6947 register_name = "Config2";
6948 /* Stop translation as we may have switched the execution mode */
6949 ctx->base.is_jmp = DISAS_STOP;
6950 break;
6951 case CP0_REG16__CONFIG3:
6952 gen_helper_mtc0_config3(cpu_env, arg);
6953 register_name = "Config3";
6954 /* Stop translation as we may have switched the execution mode */
6955 ctx->base.is_jmp = DISAS_STOP;
6956 break;
6957 case CP0_REG16__CONFIG4:
6958 gen_helper_mtc0_config4(cpu_env, arg);
6959 register_name = "Config4";
6960 ctx->base.is_jmp = DISAS_STOP;
6961 break;
6962 case CP0_REG16__CONFIG5:
6963 gen_helper_mtc0_config5(cpu_env, arg);
6964 register_name = "Config5";
6965 /* Stop translation as we may have switched the execution mode */
6966 ctx->base.is_jmp = DISAS_STOP;
6967 break;
6968 /* 6,7 are implementation dependent */
6969 case CP0_REG16__CONFIG6:
6970 /* ignored */
6971 register_name = "Config6";
6972 break;
6973 case CP0_REG16__CONFIG7:
6974 /* ignored */
6975 register_name = "Config7";
6976 break;
6977 default:
6978 register_name = "Invalid config selector";
6979 goto cp0_unimplemented;
6981 break;
6982 case CP0_REGISTER_17:
6983 switch (sel) {
6984 case CP0_REG17__LLADDR:
6985 gen_helper_mtc0_lladdr(cpu_env, arg);
6986 register_name = "LLAddr";
6987 break;
6988 case CP0_REG17__MAAR:
6989 CP0_CHECK(ctx->mrp);
6990 gen_helper_mtc0_maar(cpu_env, arg);
6991 register_name = "MAAR";
6992 break;
6993 case CP0_REG17__MAARI:
6994 CP0_CHECK(ctx->mrp);
6995 gen_helper_mtc0_maari(cpu_env, arg);
6996 register_name = "MAARI";
6997 break;
6998 default:
6999 goto cp0_unimplemented;
7001 break;
7002 case CP0_REGISTER_18:
7003 switch (sel) {
7004 case CP0_REG18__WATCHLO0:
7005 case CP0_REG18__WATCHLO1:
7006 case CP0_REG18__WATCHLO2:
7007 case CP0_REG18__WATCHLO3:
7008 case CP0_REG18__WATCHLO4:
7009 case CP0_REG18__WATCHLO5:
7010 case CP0_REG18__WATCHLO6:
7011 case CP0_REG18__WATCHLO7:
7012 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7013 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7014 register_name = "WatchLo";
7015 break;
7016 default:
7017 goto cp0_unimplemented;
7019 break;
7020 case CP0_REGISTER_19:
7021 switch (sel) {
7022 case CP0_REG19__WATCHHI0:
7023 case CP0_REG19__WATCHHI1:
7024 case CP0_REG19__WATCHHI2:
7025 case CP0_REG19__WATCHHI3:
7026 case CP0_REG19__WATCHHI4:
7027 case CP0_REG19__WATCHHI5:
7028 case CP0_REG19__WATCHHI6:
7029 case CP0_REG19__WATCHHI7:
7030 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7031 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7032 register_name = "WatchHi";
7033 break;
7034 default:
7035 goto cp0_unimplemented;
7037 break;
7038 case CP0_REGISTER_20:
7039 switch (sel) {
7040 case CP0_REG20__XCONTEXT:
7041 #if defined(TARGET_MIPS64)
7042 check_insn(ctx, ISA_MIPS3);
7043 gen_helper_mtc0_xcontext(cpu_env, arg);
7044 register_name = "XContext";
7045 break;
7046 #endif
7047 default:
7048 goto cp0_unimplemented;
7050 break;
7051 case CP0_REGISTER_21:
7052 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7053 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7054 switch (sel) {
7055 case 0:
7056 gen_helper_mtc0_framemask(cpu_env, arg);
7057 register_name = "Framemask";
7058 break;
7059 default:
7060 goto cp0_unimplemented;
7062 break;
7063 case CP0_REGISTER_22:
7064 /* ignored */
7065 register_name = "Diagnostic"; /* implementation dependent */
7066 break;
7067 case CP0_REGISTER_23:
7068 switch (sel) {
7069 case CP0_REG23__DEBUG:
7070 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7071 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7072 gen_save_pc(ctx->base.pc_next + 4);
7073 ctx->base.is_jmp = DISAS_EXIT;
7074 register_name = "Debug";
7075 break;
7076 case CP0_REG23__TRACECONTROL:
7077 /* PDtrace support */
7078 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
7079 register_name = "TraceControl";
7080 /* Stop translation as we may have switched the execution mode */
7081 ctx->base.is_jmp = DISAS_STOP;
7082 goto cp0_unimplemented;
7083 case CP0_REG23__TRACECONTROL2:
7084 /* PDtrace support */
7085 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
7086 register_name = "TraceControl2";
7087 /* Stop translation as we may have switched the execution mode */
7088 ctx->base.is_jmp = DISAS_STOP;
7089 goto cp0_unimplemented;
7090 case CP0_REG23__USERTRACEDATA1:
7091 /* Stop translation as we may have switched the execution mode */
7092 ctx->base.is_jmp = DISAS_STOP;
7093 /* PDtrace support */
7094 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
7095 register_name = "UserTraceData";
7096 /* Stop translation as we may have switched the execution mode */
7097 ctx->base.is_jmp = DISAS_STOP;
7098 goto cp0_unimplemented;
7099 case CP0_REG23__TRACEIBPC:
7100 /* PDtrace support */
7101 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
7102 /* Stop translation as we may have switched the execution mode */
7103 ctx->base.is_jmp = DISAS_STOP;
7104 register_name = "TraceIBPC";
7105 goto cp0_unimplemented;
7106 case CP0_REG23__TRACEDBPC:
7107 /* PDtrace support */
7108 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
7109 /* Stop translation as we may have switched the execution mode */
7110 ctx->base.is_jmp = DISAS_STOP;
7111 register_name = "TraceDBPC";
7112 goto cp0_unimplemented;
7113 default:
7114 goto cp0_unimplemented;
7116 break;
7117 case CP0_REGISTER_24:
7118 switch (sel) {
7119 case CP0_REG24__DEPC:
7120 /* EJTAG support */
7121 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7122 register_name = "DEPC";
7123 break;
7124 default:
7125 goto cp0_unimplemented;
7127 break;
7128 case CP0_REGISTER_25:
7129 switch (sel) {
7130 case CP0_REG25__PERFCTL0:
7131 gen_helper_mtc0_performance0(cpu_env, arg);
7132 register_name = "Performance0";
7133 break;
7134 case CP0_REG25__PERFCNT0:
7135 /* gen_helper_mtc0_performance1(arg); */
7136 register_name = "Performance1";
7137 goto cp0_unimplemented;
7138 case CP0_REG25__PERFCTL1:
7139 /* gen_helper_mtc0_performance2(arg); */
7140 register_name = "Performance2";
7141 goto cp0_unimplemented;
7142 case CP0_REG25__PERFCNT1:
7143 /* gen_helper_mtc0_performance3(arg); */
7144 register_name = "Performance3";
7145 goto cp0_unimplemented;
7146 case CP0_REG25__PERFCTL2:
7147 /* gen_helper_mtc0_performance4(arg); */
7148 register_name = "Performance4";
7149 goto cp0_unimplemented;
7150 case CP0_REG25__PERFCNT2:
7151 /* gen_helper_mtc0_performance5(arg); */
7152 register_name = "Performance5";
7153 goto cp0_unimplemented;
7154 case CP0_REG25__PERFCTL3:
7155 /* gen_helper_mtc0_performance6(arg); */
7156 register_name = "Performance6";
7157 goto cp0_unimplemented;
7158 case CP0_REG25__PERFCNT3:
7159 /* gen_helper_mtc0_performance7(arg); */
7160 register_name = "Performance7";
7161 goto cp0_unimplemented;
7162 default:
7163 goto cp0_unimplemented;
7165 break;
7166 case CP0_REGISTER_26:
7167 switch (sel) {
7168 case CP0_REG26__ERRCTL:
7169 gen_helper_mtc0_errctl(cpu_env, arg);
7170 ctx->base.is_jmp = DISAS_STOP;
7171 register_name = "ErrCtl";
7172 break;
7173 default:
7174 goto cp0_unimplemented;
7176 break;
7177 case CP0_REGISTER_27:
7178 switch (sel) {
7179 case CP0_REG27__CACHERR:
7180 /* ignored */
7181 register_name = "CacheErr";
7182 break;
7183 default:
7184 goto cp0_unimplemented;
7186 break;
7187 case CP0_REGISTER_28:
7188 switch (sel) {
7189 case CP0_REG28__TAGLO:
7190 case CP0_REG28__TAGLO1:
7191 case CP0_REG28__TAGLO2:
7192 case CP0_REG28__TAGLO3:
7193 gen_helper_mtc0_taglo(cpu_env, arg);
7194 register_name = "TagLo";
7195 break;
7196 case CP0_REG28__DATALO:
7197 case CP0_REG28__DATALO1:
7198 case CP0_REG28__DATALO2:
7199 case CP0_REG28__DATALO3:
7200 gen_helper_mtc0_datalo(cpu_env, arg);
7201 register_name = "DataLo";
7202 break;
7203 default:
7204 goto cp0_unimplemented;
7206 break;
7207 case CP0_REGISTER_29:
7208 switch (sel) {
7209 case CP0_REG29__TAGHI:
7210 case CP0_REG29__TAGHI1:
7211 case CP0_REG29__TAGHI2:
7212 case CP0_REG29__TAGHI3:
7213 gen_helper_mtc0_taghi(cpu_env, arg);
7214 register_name = "TagHi";
7215 break;
7216 case CP0_REG29__DATAHI:
7217 case CP0_REG29__DATAHI1:
7218 case CP0_REG29__DATAHI2:
7219 case CP0_REG29__DATAHI3:
7220 gen_helper_mtc0_datahi(cpu_env, arg);
7221 register_name = "DataHi";
7222 break;
7223 default:
7224 register_name = "invalid sel";
7225 goto cp0_unimplemented;
7227 break;
7228 case CP0_REGISTER_30:
7229 switch (sel) {
7230 case CP0_REG30__ERROREPC:
7231 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7232 register_name = "ErrorEPC";
7233 break;
7234 default:
7235 goto cp0_unimplemented;
7237 break;
7238 case CP0_REGISTER_31:
7239 switch (sel) {
7240 case CP0_REG31__DESAVE:
7241 /* EJTAG support */
7242 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7243 register_name = "DESAVE";
7244 break;
7245 case CP0_REG31__KSCRATCH1:
7246 case CP0_REG31__KSCRATCH2:
7247 case CP0_REG31__KSCRATCH3:
7248 case CP0_REG31__KSCRATCH4:
7249 case CP0_REG31__KSCRATCH5:
7250 case CP0_REG31__KSCRATCH6:
7251 CP0_CHECK(ctx->kscrexist & (1 << sel));
7252 tcg_gen_st_tl(arg, cpu_env,
7253 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7254 register_name = "KScratch";
7255 break;
7256 default:
7257 goto cp0_unimplemented;
7259 break;
7260 default:
7261 goto cp0_unimplemented;
7263 trace_mips_translate_c0("mtc0", register_name, reg, sel);
7265 /* For simplicity assume that all writes can cause interrupts. */
7266 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7268 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7269 * translated code to check for pending interrupts.
7271 gen_save_pc(ctx->base.pc_next + 4);
7272 ctx->base.is_jmp = DISAS_EXIT;
7274 return;
7276 cp0_unimplemented:
7277 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7278 register_name, reg, sel);
7281 #if defined(TARGET_MIPS64)
7282 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7284 const char *register_name = "invalid";
7286 if (sel != 0) {
7287 check_insn(ctx, ISA_MIPS_R1);
7290 switch (reg) {
7291 case CP0_REGISTER_00:
7292 switch (sel) {
7293 case CP0_REG00__INDEX:
7294 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7295 register_name = "Index";
7296 break;
7297 case CP0_REG00__MVPCONTROL:
7298 CP0_CHECK(ctx->insn_flags & ASE_MT);
7299 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7300 register_name = "MVPControl";
7301 break;
7302 case CP0_REG00__MVPCONF0:
7303 CP0_CHECK(ctx->insn_flags & ASE_MT);
7304 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7305 register_name = "MVPConf0";
7306 break;
7307 case CP0_REG00__MVPCONF1:
7308 CP0_CHECK(ctx->insn_flags & ASE_MT);
7309 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7310 register_name = "MVPConf1";
7311 break;
7312 case CP0_REG00__VPCONTROL:
7313 CP0_CHECK(ctx->vp);
7314 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7315 register_name = "VPControl";
7316 break;
7317 default:
7318 goto cp0_unimplemented;
7320 break;
7321 case CP0_REGISTER_01:
7322 switch (sel) {
7323 case CP0_REG01__RANDOM:
7324 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7325 gen_helper_mfc0_random(arg, cpu_env);
7326 register_name = "Random";
7327 break;
7328 case CP0_REG01__VPECONTROL:
7329 CP0_CHECK(ctx->insn_flags & ASE_MT);
7330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7331 register_name = "VPEControl";
7332 break;
7333 case CP0_REG01__VPECONF0:
7334 CP0_CHECK(ctx->insn_flags & ASE_MT);
7335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7336 register_name = "VPEConf0";
7337 break;
7338 case CP0_REG01__VPECONF1:
7339 CP0_CHECK(ctx->insn_flags & ASE_MT);
7340 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7341 register_name = "VPEConf1";
7342 break;
7343 case CP0_REG01__YQMASK:
7344 CP0_CHECK(ctx->insn_flags & ASE_MT);
7345 tcg_gen_ld_tl(arg, cpu_env,
7346 offsetof(CPUMIPSState, CP0_YQMask));
7347 register_name = "YQMask";
7348 break;
7349 case CP0_REG01__VPESCHEDULE:
7350 CP0_CHECK(ctx->insn_flags & ASE_MT);
7351 tcg_gen_ld_tl(arg, cpu_env,
7352 offsetof(CPUMIPSState, CP0_VPESchedule));
7353 register_name = "VPESchedule";
7354 break;
7355 case CP0_REG01__VPESCHEFBACK:
7356 CP0_CHECK(ctx->insn_flags & ASE_MT);
7357 tcg_gen_ld_tl(arg, cpu_env,
7358 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7359 register_name = "VPEScheFBack";
7360 break;
7361 case CP0_REG01__VPEOPT:
7362 CP0_CHECK(ctx->insn_flags & ASE_MT);
7363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7364 register_name = "VPEOpt";
7365 break;
7366 default:
7367 goto cp0_unimplemented;
7369 break;
7370 case CP0_REGISTER_02:
7371 switch (sel) {
7372 case CP0_REG02__ENTRYLO0:
7373 tcg_gen_ld_tl(arg, cpu_env,
7374 offsetof(CPUMIPSState, CP0_EntryLo0));
7375 register_name = "EntryLo0";
7376 break;
7377 case CP0_REG02__TCSTATUS:
7378 CP0_CHECK(ctx->insn_flags & ASE_MT);
7379 gen_helper_mfc0_tcstatus(arg, cpu_env);
7380 register_name = "TCStatus";
7381 break;
7382 case CP0_REG02__TCBIND:
7383 CP0_CHECK(ctx->insn_flags & ASE_MT);
7384 gen_helper_mfc0_tcbind(arg, cpu_env);
7385 register_name = "TCBind";
7386 break;
7387 case CP0_REG02__TCRESTART:
7388 CP0_CHECK(ctx->insn_flags & ASE_MT);
7389 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7390 register_name = "TCRestart";
7391 break;
7392 case CP0_REG02__TCHALT:
7393 CP0_CHECK(ctx->insn_flags & ASE_MT);
7394 gen_helper_dmfc0_tchalt(arg, cpu_env);
7395 register_name = "TCHalt";
7396 break;
7397 case CP0_REG02__TCCONTEXT:
7398 CP0_CHECK(ctx->insn_flags & ASE_MT);
7399 gen_helper_dmfc0_tccontext(arg, cpu_env);
7400 register_name = "TCContext";
7401 break;
7402 case CP0_REG02__TCSCHEDULE:
7403 CP0_CHECK(ctx->insn_flags & ASE_MT);
7404 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7405 register_name = "TCSchedule";
7406 break;
7407 case CP0_REG02__TCSCHEFBACK:
7408 CP0_CHECK(ctx->insn_flags & ASE_MT);
7409 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7410 register_name = "TCScheFBack";
7411 break;
7412 default:
7413 goto cp0_unimplemented;
7415 break;
7416 case CP0_REGISTER_03:
7417 switch (sel) {
7418 case CP0_REG03__ENTRYLO1:
7419 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7420 register_name = "EntryLo1";
7421 break;
7422 case CP0_REG03__GLOBALNUM:
7423 CP0_CHECK(ctx->vp);
7424 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7425 register_name = "GlobalNumber";
7426 break;
7427 default:
7428 goto cp0_unimplemented;
7430 break;
7431 case CP0_REGISTER_04:
7432 switch (sel) {
7433 case CP0_REG04__CONTEXT:
7434 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7435 register_name = "Context";
7436 break;
7437 case CP0_REG04__CONTEXTCONFIG:
7438 /* SmartMIPS ASE */
7439 /* gen_helper_dmfc0_contextconfig(arg); */
7440 register_name = "ContextConfig";
7441 goto cp0_unimplemented;
7442 case CP0_REG04__USERLOCAL:
7443 CP0_CHECK(ctx->ulri);
7444 tcg_gen_ld_tl(arg, cpu_env,
7445 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7446 register_name = "UserLocal";
7447 break;
7448 case CP0_REG04__MMID:
7449 CP0_CHECK(ctx->mi);
7450 gen_helper_mtc0_memorymapid(cpu_env, arg);
7451 register_name = "MMID";
7452 break;
7453 default:
7454 goto cp0_unimplemented;
7456 break;
7457 case CP0_REGISTER_05:
7458 switch (sel) {
7459 case CP0_REG05__PAGEMASK:
7460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7461 register_name = "PageMask";
7462 break;
7463 case CP0_REG05__PAGEGRAIN:
7464 check_insn(ctx, ISA_MIPS_R2);
7465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7466 register_name = "PageGrain";
7467 break;
7468 case CP0_REG05__SEGCTL0:
7469 CP0_CHECK(ctx->sc);
7470 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7471 register_name = "SegCtl0";
7472 break;
7473 case CP0_REG05__SEGCTL1:
7474 CP0_CHECK(ctx->sc);
7475 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7476 register_name = "SegCtl1";
7477 break;
7478 case CP0_REG05__SEGCTL2:
7479 CP0_CHECK(ctx->sc);
7480 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7481 register_name = "SegCtl2";
7482 break;
7483 case CP0_REG05__PWBASE:
7484 check_pw(ctx);
7485 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7486 register_name = "PWBase";
7487 break;
7488 case CP0_REG05__PWFIELD:
7489 check_pw(ctx);
7490 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7491 register_name = "PWField";
7492 break;
7493 case CP0_REG05__PWSIZE:
7494 check_pw(ctx);
7495 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7496 register_name = "PWSize";
7497 break;
7498 default:
7499 goto cp0_unimplemented;
7501 break;
7502 case CP0_REGISTER_06:
7503 switch (sel) {
7504 case CP0_REG06__WIRED:
7505 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7506 register_name = "Wired";
7507 break;
7508 case CP0_REG06__SRSCONF0:
7509 check_insn(ctx, ISA_MIPS_R2);
7510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7511 register_name = "SRSConf0";
7512 break;
7513 case CP0_REG06__SRSCONF1:
7514 check_insn(ctx, ISA_MIPS_R2);
7515 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7516 register_name = "SRSConf1";
7517 break;
7518 case CP0_REG06__SRSCONF2:
7519 check_insn(ctx, ISA_MIPS_R2);
7520 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7521 register_name = "SRSConf2";
7522 break;
7523 case CP0_REG06__SRSCONF3:
7524 check_insn(ctx, ISA_MIPS_R2);
7525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7526 register_name = "SRSConf3";
7527 break;
7528 case CP0_REG06__SRSCONF4:
7529 check_insn(ctx, ISA_MIPS_R2);
7530 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7531 register_name = "SRSConf4";
7532 break;
7533 case CP0_REG06__PWCTL:
7534 check_pw(ctx);
7535 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7536 register_name = "PWCtl";
7537 break;
7538 default:
7539 goto cp0_unimplemented;
7541 break;
7542 case CP0_REGISTER_07:
7543 switch (sel) {
7544 case CP0_REG07__HWRENA:
7545 check_insn(ctx, ISA_MIPS_R2);
7546 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7547 register_name = "HWREna";
7548 break;
7549 default:
7550 goto cp0_unimplemented;
7552 break;
7553 case CP0_REGISTER_08:
7554 switch (sel) {
7555 case CP0_REG08__BADVADDR:
7556 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7557 register_name = "BadVAddr";
7558 break;
7559 case CP0_REG08__BADINSTR:
7560 CP0_CHECK(ctx->bi);
7561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7562 register_name = "BadInstr";
7563 break;
7564 case CP0_REG08__BADINSTRP:
7565 CP0_CHECK(ctx->bp);
7566 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7567 register_name = "BadInstrP";
7568 break;
7569 case CP0_REG08__BADINSTRX:
7570 CP0_CHECK(ctx->bi);
7571 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7572 tcg_gen_andi_tl(arg, arg, ~0xffff);
7573 register_name = "BadInstrX";
7574 break;
7575 default:
7576 goto cp0_unimplemented;
7578 break;
7579 case CP0_REGISTER_09:
7580 switch (sel) {
7581 case CP0_REG09__COUNT:
7582 /* Mark as an IO operation because we read the time. */
7583 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7584 gen_io_start();
7586 gen_helper_mfc0_count(arg, cpu_env);
7588 * Break the TB to be able to take timer interrupts immediately
7589 * after reading count. DISAS_STOP isn't sufficient, we need to
7590 * ensure we break completely out of translated code.
7592 gen_save_pc(ctx->base.pc_next + 4);
7593 ctx->base.is_jmp = DISAS_EXIT;
7594 register_name = "Count";
7595 break;
7596 case CP0_REG09__SAARI:
7597 CP0_CHECK(ctx->saar);
7598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7599 register_name = "SAARI";
7600 break;
7601 case CP0_REG09__SAAR:
7602 CP0_CHECK(ctx->saar);
7603 gen_helper_dmfc0_saar(arg, cpu_env);
7604 register_name = "SAAR";
7605 break;
7606 default:
7607 goto cp0_unimplemented;
7609 break;
7610 case CP0_REGISTER_10:
7611 switch (sel) {
7612 case CP0_REG10__ENTRYHI:
7613 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7614 register_name = "EntryHi";
7615 break;
7616 default:
7617 goto cp0_unimplemented;
7619 break;
7620 case CP0_REGISTER_11:
7621 switch (sel) {
7622 case CP0_REG11__COMPARE:
7623 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7624 register_name = "Compare";
7625 break;
7626 /* 6,7 are implementation dependent */
7627 default:
7628 goto cp0_unimplemented;
7630 break;
7631 case CP0_REGISTER_12:
7632 switch (sel) {
7633 case CP0_REG12__STATUS:
7634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7635 register_name = "Status";
7636 break;
7637 case CP0_REG12__INTCTL:
7638 check_insn(ctx, ISA_MIPS_R2);
7639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7640 register_name = "IntCtl";
7641 break;
7642 case CP0_REG12__SRSCTL:
7643 check_insn(ctx, ISA_MIPS_R2);
7644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7645 register_name = "SRSCtl";
7646 break;
7647 case CP0_REG12__SRSMAP:
7648 check_insn(ctx, ISA_MIPS_R2);
7649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7650 register_name = "SRSMap";
7651 break;
7652 default:
7653 goto cp0_unimplemented;
7655 break;
7656 case CP0_REGISTER_13:
7657 switch (sel) {
7658 case CP0_REG13__CAUSE:
7659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7660 register_name = "Cause";
7661 break;
7662 default:
7663 goto cp0_unimplemented;
7665 break;
7666 case CP0_REGISTER_14:
7667 switch (sel) {
7668 case CP0_REG14__EPC:
7669 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7670 register_name = "EPC";
7671 break;
7672 default:
7673 goto cp0_unimplemented;
7675 break;
7676 case CP0_REGISTER_15:
7677 switch (sel) {
7678 case CP0_REG15__PRID:
7679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7680 register_name = "PRid";
7681 break;
7682 case CP0_REG15__EBASE:
7683 check_insn(ctx, ISA_MIPS_R2);
7684 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7685 register_name = "EBase";
7686 break;
7687 case CP0_REG15__CMGCRBASE:
7688 check_insn(ctx, ISA_MIPS_R2);
7689 CP0_CHECK(ctx->cmgcr);
7690 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7691 register_name = "CMGCRBase";
7692 break;
7693 default:
7694 goto cp0_unimplemented;
7696 break;
7697 case CP0_REGISTER_16:
7698 switch (sel) {
7699 case CP0_REG16__CONFIG:
7700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7701 register_name = "Config";
7702 break;
7703 case CP0_REG16__CONFIG1:
7704 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7705 register_name = "Config1";
7706 break;
7707 case CP0_REG16__CONFIG2:
7708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7709 register_name = "Config2";
7710 break;
7711 case CP0_REG16__CONFIG3:
7712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7713 register_name = "Config3";
7714 break;
7715 case CP0_REG16__CONFIG4:
7716 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7717 register_name = "Config4";
7718 break;
7719 case CP0_REG16__CONFIG5:
7720 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7721 register_name = "Config5";
7722 break;
7723 /* 6,7 are implementation dependent */
7724 case CP0_REG16__CONFIG6:
7725 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7726 register_name = "Config6";
7727 break;
7728 case CP0_REG16__CONFIG7:
7729 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7730 register_name = "Config7";
7731 break;
7732 default:
7733 goto cp0_unimplemented;
7735 break;
7736 case CP0_REGISTER_17:
7737 switch (sel) {
7738 case CP0_REG17__LLADDR:
7739 gen_helper_dmfc0_lladdr(arg, cpu_env);
7740 register_name = "LLAddr";
7741 break;
7742 case CP0_REG17__MAAR:
7743 CP0_CHECK(ctx->mrp);
7744 gen_helper_dmfc0_maar(arg, cpu_env);
7745 register_name = "MAAR";
7746 break;
7747 case CP0_REG17__MAARI:
7748 CP0_CHECK(ctx->mrp);
7749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7750 register_name = "MAARI";
7751 break;
7752 default:
7753 goto cp0_unimplemented;
7755 break;
7756 case CP0_REGISTER_18:
7757 switch (sel) {
7758 case CP0_REG18__WATCHLO0:
7759 case CP0_REG18__WATCHLO1:
7760 case CP0_REG18__WATCHLO2:
7761 case CP0_REG18__WATCHLO3:
7762 case CP0_REG18__WATCHLO4:
7763 case CP0_REG18__WATCHLO5:
7764 case CP0_REG18__WATCHLO6:
7765 case CP0_REG18__WATCHLO7:
7766 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7767 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7768 register_name = "WatchLo";
7769 break;
7770 default:
7771 goto cp0_unimplemented;
7773 break;
7774 case CP0_REGISTER_19:
7775 switch (sel) {
7776 case CP0_REG19__WATCHHI0:
7777 case CP0_REG19__WATCHHI1:
7778 case CP0_REG19__WATCHHI2:
7779 case CP0_REG19__WATCHHI3:
7780 case CP0_REG19__WATCHHI4:
7781 case CP0_REG19__WATCHHI5:
7782 case CP0_REG19__WATCHHI6:
7783 case CP0_REG19__WATCHHI7:
7784 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7785 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
7786 register_name = "WatchHi";
7787 break;
7788 default:
7789 goto cp0_unimplemented;
7791 break;
7792 case CP0_REGISTER_20:
7793 switch (sel) {
7794 case CP0_REG20__XCONTEXT:
7795 check_insn(ctx, ISA_MIPS3);
7796 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7797 register_name = "XContext";
7798 break;
7799 default:
7800 goto cp0_unimplemented;
7802 break;
7803 case CP0_REGISTER_21:
7804 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7805 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7806 switch (sel) {
7807 case 0:
7808 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7809 register_name = "Framemask";
7810 break;
7811 default:
7812 goto cp0_unimplemented;
7814 break;
7815 case CP0_REGISTER_22:
7816 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7817 register_name = "'Diagnostic"; /* implementation dependent */
7818 break;
7819 case CP0_REGISTER_23:
7820 switch (sel) {
7821 case CP0_REG23__DEBUG:
7822 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7823 register_name = "Debug";
7824 break;
7825 case CP0_REG23__TRACECONTROL:
7826 /* PDtrace support */
7827 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
7828 register_name = "TraceControl";
7829 goto cp0_unimplemented;
7830 case CP0_REG23__TRACECONTROL2:
7831 /* PDtrace support */
7832 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
7833 register_name = "TraceControl2";
7834 goto cp0_unimplemented;
7835 case CP0_REG23__USERTRACEDATA1:
7836 /* PDtrace support */
7837 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
7838 register_name = "UserTraceData1";
7839 goto cp0_unimplemented;
7840 case CP0_REG23__TRACEIBPC:
7841 /* PDtrace support */
7842 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
7843 register_name = "TraceIBPC";
7844 goto cp0_unimplemented;
7845 case CP0_REG23__TRACEDBPC:
7846 /* PDtrace support */
7847 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
7848 register_name = "TraceDBPC";
7849 goto cp0_unimplemented;
7850 default:
7851 goto cp0_unimplemented;
7853 break;
7854 case CP0_REGISTER_24:
7855 switch (sel) {
7856 case CP0_REG24__DEPC:
7857 /* EJTAG support */
7858 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7859 register_name = "DEPC";
7860 break;
7861 default:
7862 goto cp0_unimplemented;
7864 break;
7865 case CP0_REGISTER_25:
7866 switch (sel) {
7867 case CP0_REG25__PERFCTL0:
7868 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7869 register_name = "Performance0";
7870 break;
7871 case CP0_REG25__PERFCNT0:
7872 /* gen_helper_dmfc0_performance1(arg); */
7873 register_name = "Performance1";
7874 goto cp0_unimplemented;
7875 case CP0_REG25__PERFCTL1:
7876 /* gen_helper_dmfc0_performance2(arg); */
7877 register_name = "Performance2";
7878 goto cp0_unimplemented;
7879 case CP0_REG25__PERFCNT1:
7880 /* gen_helper_dmfc0_performance3(arg); */
7881 register_name = "Performance3";
7882 goto cp0_unimplemented;
7883 case CP0_REG25__PERFCTL2:
7884 /* gen_helper_dmfc0_performance4(arg); */
7885 register_name = "Performance4";
7886 goto cp0_unimplemented;
7887 case CP0_REG25__PERFCNT2:
7888 /* gen_helper_dmfc0_performance5(arg); */
7889 register_name = "Performance5";
7890 goto cp0_unimplemented;
7891 case CP0_REG25__PERFCTL3:
7892 /* gen_helper_dmfc0_performance6(arg); */
7893 register_name = "Performance6";
7894 goto cp0_unimplemented;
7895 case CP0_REG25__PERFCNT3:
7896 /* gen_helper_dmfc0_performance7(arg); */
7897 register_name = "Performance7";
7898 goto cp0_unimplemented;
7899 default:
7900 goto cp0_unimplemented;
7902 break;
7903 case CP0_REGISTER_26:
7904 switch (sel) {
7905 case CP0_REG26__ERRCTL:
7906 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7907 register_name = "ErrCtl";
7908 break;
7909 default:
7910 goto cp0_unimplemented;
7912 break;
7913 case CP0_REGISTER_27:
7914 switch (sel) {
7915 /* ignored */
7916 case CP0_REG27__CACHERR:
7917 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7918 register_name = "CacheErr";
7919 break;
7920 default:
7921 goto cp0_unimplemented;
7923 break;
7924 case CP0_REGISTER_28:
7925 switch (sel) {
7926 case CP0_REG28__TAGLO:
7927 case CP0_REG28__TAGLO1:
7928 case CP0_REG28__TAGLO2:
7929 case CP0_REG28__TAGLO3:
7930 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7931 register_name = "TagLo";
7932 break;
7933 case CP0_REG28__DATALO:
7934 case CP0_REG28__DATALO1:
7935 case CP0_REG28__DATALO2:
7936 case CP0_REG28__DATALO3:
7937 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7938 register_name = "DataLo";
7939 break;
7940 default:
7941 goto cp0_unimplemented;
7943 break;
7944 case CP0_REGISTER_29:
7945 switch (sel) {
7946 case CP0_REG29__TAGHI:
7947 case CP0_REG29__TAGHI1:
7948 case CP0_REG29__TAGHI2:
7949 case CP0_REG29__TAGHI3:
7950 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7951 register_name = "TagHi";
7952 break;
7953 case CP0_REG29__DATAHI:
7954 case CP0_REG29__DATAHI1:
7955 case CP0_REG29__DATAHI2:
7956 case CP0_REG29__DATAHI3:
7957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7958 register_name = "DataHi";
7959 break;
7960 default:
7961 goto cp0_unimplemented;
7963 break;
7964 case CP0_REGISTER_30:
7965 switch (sel) {
7966 case CP0_REG30__ERROREPC:
7967 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7968 register_name = "ErrorEPC";
7969 break;
7970 default:
7971 goto cp0_unimplemented;
7973 break;
7974 case CP0_REGISTER_31:
7975 switch (sel) {
7976 case CP0_REG31__DESAVE:
7977 /* EJTAG support */
7978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7979 register_name = "DESAVE";
7980 break;
7981 case CP0_REG31__KSCRATCH1:
7982 case CP0_REG31__KSCRATCH2:
7983 case CP0_REG31__KSCRATCH3:
7984 case CP0_REG31__KSCRATCH4:
7985 case CP0_REG31__KSCRATCH5:
7986 case CP0_REG31__KSCRATCH6:
7987 CP0_CHECK(ctx->kscrexist & (1 << sel));
7988 tcg_gen_ld_tl(arg, cpu_env,
7989 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7990 register_name = "KScratch";
7991 break;
7992 default:
7993 goto cp0_unimplemented;
7995 break;
7996 default:
7997 goto cp0_unimplemented;
7999 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8000 return;
8002 cp0_unimplemented:
8003 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8004 register_name, reg, sel);
8005 gen_mfc0_unimplemented(ctx, arg);
8008 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8010 const char *register_name = "invalid";
8012 if (sel != 0) {
8013 check_insn(ctx, ISA_MIPS_R1);
8016 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8017 gen_io_start();
8020 switch (reg) {
8021 case CP0_REGISTER_00:
8022 switch (sel) {
8023 case CP0_REG00__INDEX:
8024 gen_helper_mtc0_index(cpu_env, arg);
8025 register_name = "Index";
8026 break;
8027 case CP0_REG00__MVPCONTROL:
8028 CP0_CHECK(ctx->insn_flags & ASE_MT);
8029 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8030 register_name = "MVPControl";
8031 break;
8032 case CP0_REG00__MVPCONF0:
8033 CP0_CHECK(ctx->insn_flags & ASE_MT);
8034 /* ignored */
8035 register_name = "MVPConf0";
8036 break;
8037 case CP0_REG00__MVPCONF1:
8038 CP0_CHECK(ctx->insn_flags & ASE_MT);
8039 /* ignored */
8040 register_name = "MVPConf1";
8041 break;
8042 case CP0_REG00__VPCONTROL:
8043 CP0_CHECK(ctx->vp);
8044 /* ignored */
8045 register_name = "VPControl";
8046 break;
8047 default:
8048 goto cp0_unimplemented;
8050 break;
8051 case CP0_REGISTER_01:
8052 switch (sel) {
8053 case CP0_REG01__RANDOM:
8054 /* ignored */
8055 register_name = "Random";
8056 break;
8057 case CP0_REG01__VPECONTROL:
8058 CP0_CHECK(ctx->insn_flags & ASE_MT);
8059 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8060 register_name = "VPEControl";
8061 break;
8062 case CP0_REG01__VPECONF0:
8063 CP0_CHECK(ctx->insn_flags & ASE_MT);
8064 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8065 register_name = "VPEConf0";
8066 break;
8067 case CP0_REG01__VPECONF1:
8068 CP0_CHECK(ctx->insn_flags & ASE_MT);
8069 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8070 register_name = "VPEConf1";
8071 break;
8072 case CP0_REG01__YQMASK:
8073 CP0_CHECK(ctx->insn_flags & ASE_MT);
8074 gen_helper_mtc0_yqmask(cpu_env, arg);
8075 register_name = "YQMask";
8076 break;
8077 case CP0_REG01__VPESCHEDULE:
8078 CP0_CHECK(ctx->insn_flags & ASE_MT);
8079 tcg_gen_st_tl(arg, cpu_env,
8080 offsetof(CPUMIPSState, CP0_VPESchedule));
8081 register_name = "VPESchedule";
8082 break;
8083 case CP0_REG01__VPESCHEFBACK:
8084 CP0_CHECK(ctx->insn_flags & ASE_MT);
8085 tcg_gen_st_tl(arg, cpu_env,
8086 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8087 register_name = "VPEScheFBack";
8088 break;
8089 case CP0_REG01__VPEOPT:
8090 CP0_CHECK(ctx->insn_flags & ASE_MT);
8091 gen_helper_mtc0_vpeopt(cpu_env, arg);
8092 register_name = "VPEOpt";
8093 break;
8094 default:
8095 goto cp0_unimplemented;
8097 break;
8098 case CP0_REGISTER_02:
8099 switch (sel) {
8100 case CP0_REG02__ENTRYLO0:
8101 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8102 register_name = "EntryLo0";
8103 break;
8104 case CP0_REG02__TCSTATUS:
8105 CP0_CHECK(ctx->insn_flags & ASE_MT);
8106 gen_helper_mtc0_tcstatus(cpu_env, arg);
8107 register_name = "TCStatus";
8108 break;
8109 case CP0_REG02__TCBIND:
8110 CP0_CHECK(ctx->insn_flags & ASE_MT);
8111 gen_helper_mtc0_tcbind(cpu_env, arg);
8112 register_name = "TCBind";
8113 break;
8114 case CP0_REG02__TCRESTART:
8115 CP0_CHECK(ctx->insn_flags & ASE_MT);
8116 gen_helper_mtc0_tcrestart(cpu_env, arg);
8117 register_name = "TCRestart";
8118 break;
8119 case CP0_REG02__TCHALT:
8120 CP0_CHECK(ctx->insn_flags & ASE_MT);
8121 gen_helper_mtc0_tchalt(cpu_env, arg);
8122 register_name = "TCHalt";
8123 break;
8124 case CP0_REG02__TCCONTEXT:
8125 CP0_CHECK(ctx->insn_flags & ASE_MT);
8126 gen_helper_mtc0_tccontext(cpu_env, arg);
8127 register_name = "TCContext";
8128 break;
8129 case CP0_REG02__TCSCHEDULE:
8130 CP0_CHECK(ctx->insn_flags & ASE_MT);
8131 gen_helper_mtc0_tcschedule(cpu_env, arg);
8132 register_name = "TCSchedule";
8133 break;
8134 case CP0_REG02__TCSCHEFBACK:
8135 CP0_CHECK(ctx->insn_flags & ASE_MT);
8136 gen_helper_mtc0_tcschefback(cpu_env, arg);
8137 register_name = "TCScheFBack";
8138 break;
8139 default:
8140 goto cp0_unimplemented;
8142 break;
8143 case CP0_REGISTER_03:
8144 switch (sel) {
8145 case CP0_REG03__ENTRYLO1:
8146 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8147 register_name = "EntryLo1";
8148 break;
8149 case CP0_REG03__GLOBALNUM:
8150 CP0_CHECK(ctx->vp);
8151 /* ignored */
8152 register_name = "GlobalNumber";
8153 break;
8154 default:
8155 goto cp0_unimplemented;
8157 break;
8158 case CP0_REGISTER_04:
8159 switch (sel) {
8160 case CP0_REG04__CONTEXT:
8161 gen_helper_mtc0_context(cpu_env, arg);
8162 register_name = "Context";
8163 break;
8164 case CP0_REG04__CONTEXTCONFIG:
8165 /* SmartMIPS ASE */
8166 /* gen_helper_dmtc0_contextconfig(arg); */
8167 register_name = "ContextConfig";
8168 goto cp0_unimplemented;
8169 case CP0_REG04__USERLOCAL:
8170 CP0_CHECK(ctx->ulri);
8171 tcg_gen_st_tl(arg, cpu_env,
8172 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8173 register_name = "UserLocal";
8174 break;
8175 case CP0_REG04__MMID:
8176 CP0_CHECK(ctx->mi);
8177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8178 register_name = "MMID";
8179 break;
8180 default:
8181 goto cp0_unimplemented;
8183 break;
8184 case CP0_REGISTER_05:
8185 switch (sel) {
8186 case CP0_REG05__PAGEMASK:
8187 gen_helper_mtc0_pagemask(cpu_env, arg);
8188 register_name = "PageMask";
8189 break;
8190 case CP0_REG05__PAGEGRAIN:
8191 check_insn(ctx, ISA_MIPS_R2);
8192 gen_helper_mtc0_pagegrain(cpu_env, arg);
8193 register_name = "PageGrain";
8194 break;
8195 case CP0_REG05__SEGCTL0:
8196 CP0_CHECK(ctx->sc);
8197 gen_helper_mtc0_segctl0(cpu_env, arg);
8198 register_name = "SegCtl0";
8199 break;
8200 case CP0_REG05__SEGCTL1:
8201 CP0_CHECK(ctx->sc);
8202 gen_helper_mtc0_segctl1(cpu_env, arg);
8203 register_name = "SegCtl1";
8204 break;
8205 case CP0_REG05__SEGCTL2:
8206 CP0_CHECK(ctx->sc);
8207 gen_helper_mtc0_segctl2(cpu_env, arg);
8208 register_name = "SegCtl2";
8209 break;
8210 case CP0_REG05__PWBASE:
8211 check_pw(ctx);
8212 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8213 register_name = "PWBase";
8214 break;
8215 case CP0_REG05__PWFIELD:
8216 check_pw(ctx);
8217 gen_helper_mtc0_pwfield(cpu_env, arg);
8218 register_name = "PWField";
8219 break;
8220 case CP0_REG05__PWSIZE:
8221 check_pw(ctx);
8222 gen_helper_mtc0_pwsize(cpu_env, arg);
8223 register_name = "PWSize";
8224 break;
8225 default:
8226 goto cp0_unimplemented;
8228 break;
8229 case CP0_REGISTER_06:
8230 switch (sel) {
8231 case CP0_REG06__WIRED:
8232 gen_helper_mtc0_wired(cpu_env, arg);
8233 register_name = "Wired";
8234 break;
8235 case CP0_REG06__SRSCONF0:
8236 check_insn(ctx, ISA_MIPS_R2);
8237 gen_helper_mtc0_srsconf0(cpu_env, arg);
8238 register_name = "SRSConf0";
8239 break;
8240 case CP0_REG06__SRSCONF1:
8241 check_insn(ctx, ISA_MIPS_R2);
8242 gen_helper_mtc0_srsconf1(cpu_env, arg);
8243 register_name = "SRSConf1";
8244 break;
8245 case CP0_REG06__SRSCONF2:
8246 check_insn(ctx, ISA_MIPS_R2);
8247 gen_helper_mtc0_srsconf2(cpu_env, arg);
8248 register_name = "SRSConf2";
8249 break;
8250 case CP0_REG06__SRSCONF3:
8251 check_insn(ctx, ISA_MIPS_R2);
8252 gen_helper_mtc0_srsconf3(cpu_env, arg);
8253 register_name = "SRSConf3";
8254 break;
8255 case CP0_REG06__SRSCONF4:
8256 check_insn(ctx, ISA_MIPS_R2);
8257 gen_helper_mtc0_srsconf4(cpu_env, arg);
8258 register_name = "SRSConf4";
8259 break;
8260 case CP0_REG06__PWCTL:
8261 check_pw(ctx);
8262 gen_helper_mtc0_pwctl(cpu_env, arg);
8263 register_name = "PWCtl";
8264 break;
8265 default:
8266 goto cp0_unimplemented;
8268 break;
8269 case CP0_REGISTER_07:
8270 switch (sel) {
8271 case CP0_REG07__HWRENA:
8272 check_insn(ctx, ISA_MIPS_R2);
8273 gen_helper_mtc0_hwrena(cpu_env, arg);
8274 ctx->base.is_jmp = DISAS_STOP;
8275 register_name = "HWREna";
8276 break;
8277 default:
8278 goto cp0_unimplemented;
8280 break;
8281 case CP0_REGISTER_08:
8282 switch (sel) {
8283 case CP0_REG08__BADVADDR:
8284 /* ignored */
8285 register_name = "BadVAddr";
8286 break;
8287 case CP0_REG08__BADINSTR:
8288 /* ignored */
8289 register_name = "BadInstr";
8290 break;
8291 case CP0_REG08__BADINSTRP:
8292 /* ignored */
8293 register_name = "BadInstrP";
8294 break;
8295 case CP0_REG08__BADINSTRX:
8296 /* ignored */
8297 register_name = "BadInstrX";
8298 break;
8299 default:
8300 goto cp0_unimplemented;
8302 break;
8303 case CP0_REGISTER_09:
8304 switch (sel) {
8305 case CP0_REG09__COUNT:
8306 gen_helper_mtc0_count(cpu_env, arg);
8307 register_name = "Count";
8308 break;
8309 case CP0_REG09__SAARI:
8310 CP0_CHECK(ctx->saar);
8311 gen_helper_mtc0_saari(cpu_env, arg);
8312 register_name = "SAARI";
8313 break;
8314 case CP0_REG09__SAAR:
8315 CP0_CHECK(ctx->saar);
8316 gen_helper_mtc0_saar(cpu_env, arg);
8317 register_name = "SAAR";
8318 break;
8319 default:
8320 goto cp0_unimplemented;
8322 /* Stop translation as we may have switched the execution mode */
8323 ctx->base.is_jmp = DISAS_STOP;
8324 break;
8325 case CP0_REGISTER_10:
8326 switch (sel) {
8327 case CP0_REG10__ENTRYHI:
8328 gen_helper_mtc0_entryhi(cpu_env, arg);
8329 register_name = "EntryHi";
8330 break;
8331 default:
8332 goto cp0_unimplemented;
8334 break;
8335 case CP0_REGISTER_11:
8336 switch (sel) {
8337 case CP0_REG11__COMPARE:
8338 gen_helper_mtc0_compare(cpu_env, arg);
8339 register_name = "Compare";
8340 break;
8341 /* 6,7 are implementation dependent */
8342 default:
8343 goto cp0_unimplemented;
8345 /* Stop translation as we may have switched the execution mode */
8346 ctx->base.is_jmp = DISAS_STOP;
8347 break;
8348 case CP0_REGISTER_12:
8349 switch (sel) {
8350 case CP0_REG12__STATUS:
8351 save_cpu_state(ctx, 1);
8352 gen_helper_mtc0_status(cpu_env, arg);
8353 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8354 gen_save_pc(ctx->base.pc_next + 4);
8355 ctx->base.is_jmp = DISAS_EXIT;
8356 register_name = "Status";
8357 break;
8358 case CP0_REG12__INTCTL:
8359 check_insn(ctx, ISA_MIPS_R2);
8360 gen_helper_mtc0_intctl(cpu_env, arg);
8361 /* Stop translation as we may have switched the execution mode */
8362 ctx->base.is_jmp = DISAS_STOP;
8363 register_name = "IntCtl";
8364 break;
8365 case CP0_REG12__SRSCTL:
8366 check_insn(ctx, ISA_MIPS_R2);
8367 gen_helper_mtc0_srsctl(cpu_env, arg);
8368 /* Stop translation as we may have switched the execution mode */
8369 ctx->base.is_jmp = DISAS_STOP;
8370 register_name = "SRSCtl";
8371 break;
8372 case CP0_REG12__SRSMAP:
8373 check_insn(ctx, ISA_MIPS_R2);
8374 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8375 /* Stop translation as we may have switched the execution mode */
8376 ctx->base.is_jmp = DISAS_STOP;
8377 register_name = "SRSMap";
8378 break;
8379 default:
8380 goto cp0_unimplemented;
8382 break;
8383 case CP0_REGISTER_13:
8384 switch (sel) {
8385 case CP0_REG13__CAUSE:
8386 save_cpu_state(ctx, 1);
8387 gen_helper_mtc0_cause(cpu_env, arg);
8389 * Stop translation as we may have triggered an interrupt.
8390 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8391 * translated code to check for pending interrupts.
8393 gen_save_pc(ctx->base.pc_next + 4);
8394 ctx->base.is_jmp = DISAS_EXIT;
8395 register_name = "Cause";
8396 break;
8397 default:
8398 goto cp0_unimplemented;
8400 break;
8401 case CP0_REGISTER_14:
8402 switch (sel) {
8403 case CP0_REG14__EPC:
8404 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8405 register_name = "EPC";
8406 break;
8407 default:
8408 goto cp0_unimplemented;
8410 break;
8411 case CP0_REGISTER_15:
8412 switch (sel) {
8413 case CP0_REG15__PRID:
8414 /* ignored */
8415 register_name = "PRid";
8416 break;
8417 case CP0_REG15__EBASE:
8418 check_insn(ctx, ISA_MIPS_R2);
8419 gen_helper_mtc0_ebase(cpu_env, arg);
8420 register_name = "EBase";
8421 break;
8422 default:
8423 goto cp0_unimplemented;
8425 break;
8426 case CP0_REGISTER_16:
8427 switch (sel) {
8428 case CP0_REG16__CONFIG:
8429 gen_helper_mtc0_config0(cpu_env, arg);
8430 register_name = "Config";
8431 /* Stop translation as we may have switched the execution mode */
8432 ctx->base.is_jmp = DISAS_STOP;
8433 break;
8434 case CP0_REG16__CONFIG1:
8435 /* ignored, read only */
8436 register_name = "Config1";
8437 break;
8438 case CP0_REG16__CONFIG2:
8439 gen_helper_mtc0_config2(cpu_env, arg);
8440 register_name = "Config2";
8441 /* Stop translation as we may have switched the execution mode */
8442 ctx->base.is_jmp = DISAS_STOP;
8443 break;
8444 case CP0_REG16__CONFIG3:
8445 gen_helper_mtc0_config3(cpu_env, arg);
8446 register_name = "Config3";
8447 /* Stop translation as we may have switched the execution mode */
8448 ctx->base.is_jmp = DISAS_STOP;
8449 break;
8450 case CP0_REG16__CONFIG4:
8451 /* currently ignored */
8452 register_name = "Config4";
8453 break;
8454 case CP0_REG16__CONFIG5:
8455 gen_helper_mtc0_config5(cpu_env, arg);
8456 register_name = "Config5";
8457 /* Stop translation as we may have switched the execution mode */
8458 ctx->base.is_jmp = DISAS_STOP;
8459 break;
8460 /* 6,7 are implementation dependent */
8461 default:
8462 register_name = "Invalid config selector";
8463 goto cp0_unimplemented;
8465 break;
8466 case CP0_REGISTER_17:
8467 switch (sel) {
8468 case CP0_REG17__LLADDR:
8469 gen_helper_mtc0_lladdr(cpu_env, arg);
8470 register_name = "LLAddr";
8471 break;
8472 case CP0_REG17__MAAR:
8473 CP0_CHECK(ctx->mrp);
8474 gen_helper_mtc0_maar(cpu_env, arg);
8475 register_name = "MAAR";
8476 break;
8477 case CP0_REG17__MAARI:
8478 CP0_CHECK(ctx->mrp);
8479 gen_helper_mtc0_maari(cpu_env, arg);
8480 register_name = "MAARI";
8481 break;
8482 default:
8483 goto cp0_unimplemented;
8485 break;
8486 case CP0_REGISTER_18:
8487 switch (sel) {
8488 case CP0_REG18__WATCHLO0:
8489 case CP0_REG18__WATCHLO1:
8490 case CP0_REG18__WATCHLO2:
8491 case CP0_REG18__WATCHLO3:
8492 case CP0_REG18__WATCHLO4:
8493 case CP0_REG18__WATCHLO5:
8494 case CP0_REG18__WATCHLO6:
8495 case CP0_REG18__WATCHLO7:
8496 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8497 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8498 register_name = "WatchLo";
8499 break;
8500 default:
8501 goto cp0_unimplemented;
8503 break;
8504 case CP0_REGISTER_19:
8505 switch (sel) {
8506 case CP0_REG19__WATCHHI0:
8507 case CP0_REG19__WATCHHI1:
8508 case CP0_REG19__WATCHHI2:
8509 case CP0_REG19__WATCHHI3:
8510 case CP0_REG19__WATCHHI4:
8511 case CP0_REG19__WATCHHI5:
8512 case CP0_REG19__WATCHHI6:
8513 case CP0_REG19__WATCHHI7:
8514 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8515 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8516 register_name = "WatchHi";
8517 break;
8518 default:
8519 goto cp0_unimplemented;
8521 break;
8522 case CP0_REGISTER_20:
8523 switch (sel) {
8524 case CP0_REG20__XCONTEXT:
8525 check_insn(ctx, ISA_MIPS3);
8526 gen_helper_mtc0_xcontext(cpu_env, arg);
8527 register_name = "XContext";
8528 break;
8529 default:
8530 goto cp0_unimplemented;
8532 break;
8533 case CP0_REGISTER_21:
8534 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8535 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8536 switch (sel) {
8537 case 0:
8538 gen_helper_mtc0_framemask(cpu_env, arg);
8539 register_name = "Framemask";
8540 break;
8541 default:
8542 goto cp0_unimplemented;
8544 break;
8545 case CP0_REGISTER_22:
8546 /* ignored */
8547 register_name = "Diagnostic"; /* implementation dependent */
8548 break;
8549 case CP0_REGISTER_23:
8550 switch (sel) {
8551 case CP0_REG23__DEBUG:
8552 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8553 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8554 gen_save_pc(ctx->base.pc_next + 4);
8555 ctx->base.is_jmp = DISAS_EXIT;
8556 register_name = "Debug";
8557 break;
8558 case CP0_REG23__TRACECONTROL:
8559 /* PDtrace support */
8560 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8561 /* Stop translation as we may have switched the execution mode */
8562 ctx->base.is_jmp = DISAS_STOP;
8563 register_name = "TraceControl";
8564 goto cp0_unimplemented;
8565 case CP0_REG23__TRACECONTROL2:
8566 /* PDtrace support */
8567 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8568 /* Stop translation as we may have switched the execution mode */
8569 ctx->base.is_jmp = DISAS_STOP;
8570 register_name = "TraceControl2";
8571 goto cp0_unimplemented;
8572 case CP0_REG23__USERTRACEDATA1:
8573 /* PDtrace support */
8574 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8575 /* Stop translation as we may have switched the execution mode */
8576 ctx->base.is_jmp = DISAS_STOP;
8577 register_name = "UserTraceData1";
8578 goto cp0_unimplemented;
8579 case CP0_REG23__TRACEIBPC:
8580 /* PDtrace support */
8581 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8582 /* Stop translation as we may have switched the execution mode */
8583 ctx->base.is_jmp = DISAS_STOP;
8584 register_name = "TraceIBPC";
8585 goto cp0_unimplemented;
8586 case CP0_REG23__TRACEDBPC:
8587 /* PDtrace support */
8588 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8589 /* Stop translation as we may have switched the execution mode */
8590 ctx->base.is_jmp = DISAS_STOP;
8591 register_name = "TraceDBPC";
8592 goto cp0_unimplemented;
8593 default:
8594 goto cp0_unimplemented;
8596 break;
8597 case CP0_REGISTER_24:
8598 switch (sel) {
8599 case CP0_REG24__DEPC:
8600 /* EJTAG support */
8601 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8602 register_name = "DEPC";
8603 break;
8604 default:
8605 goto cp0_unimplemented;
8607 break;
8608 case CP0_REGISTER_25:
8609 switch (sel) {
8610 case CP0_REG25__PERFCTL0:
8611 gen_helper_mtc0_performance0(cpu_env, arg);
8612 register_name = "Performance0";
8613 break;
8614 case CP0_REG25__PERFCNT0:
8615 /* gen_helper_mtc0_performance1(cpu_env, arg); */
8616 register_name = "Performance1";
8617 goto cp0_unimplemented;
8618 case CP0_REG25__PERFCTL1:
8619 /* gen_helper_mtc0_performance2(cpu_env, arg); */
8620 register_name = "Performance2";
8621 goto cp0_unimplemented;
8622 case CP0_REG25__PERFCNT1:
8623 /* gen_helper_mtc0_performance3(cpu_env, arg); */
8624 register_name = "Performance3";
8625 goto cp0_unimplemented;
8626 case CP0_REG25__PERFCTL2:
8627 /* gen_helper_mtc0_performance4(cpu_env, arg); */
8628 register_name = "Performance4";
8629 goto cp0_unimplemented;
8630 case CP0_REG25__PERFCNT2:
8631 /* gen_helper_mtc0_performance5(cpu_env, arg); */
8632 register_name = "Performance5";
8633 goto cp0_unimplemented;
8634 case CP0_REG25__PERFCTL3:
8635 /* gen_helper_mtc0_performance6(cpu_env, arg); */
8636 register_name = "Performance6";
8637 goto cp0_unimplemented;
8638 case CP0_REG25__PERFCNT3:
8639 /* gen_helper_mtc0_performance7(cpu_env, arg); */
8640 register_name = "Performance7";
8641 goto cp0_unimplemented;
8642 default:
8643 goto cp0_unimplemented;
8645 break;
8646 case CP0_REGISTER_26:
8647 switch (sel) {
8648 case CP0_REG26__ERRCTL:
8649 gen_helper_mtc0_errctl(cpu_env, arg);
8650 ctx->base.is_jmp = DISAS_STOP;
8651 register_name = "ErrCtl";
8652 break;
8653 default:
8654 goto cp0_unimplemented;
8656 break;
8657 case CP0_REGISTER_27:
8658 switch (sel) {
8659 case CP0_REG27__CACHERR:
8660 /* ignored */
8661 register_name = "CacheErr";
8662 break;
8663 default:
8664 goto cp0_unimplemented;
8666 break;
8667 case CP0_REGISTER_28:
8668 switch (sel) {
8669 case CP0_REG28__TAGLO:
8670 case CP0_REG28__TAGLO1:
8671 case CP0_REG28__TAGLO2:
8672 case CP0_REG28__TAGLO3:
8673 gen_helper_mtc0_taglo(cpu_env, arg);
8674 register_name = "TagLo";
8675 break;
8676 case CP0_REG28__DATALO:
8677 case CP0_REG28__DATALO1:
8678 case CP0_REG28__DATALO2:
8679 case CP0_REG28__DATALO3:
8680 gen_helper_mtc0_datalo(cpu_env, arg);
8681 register_name = "DataLo";
8682 break;
8683 default:
8684 goto cp0_unimplemented;
8686 break;
8687 case CP0_REGISTER_29:
8688 switch (sel) {
8689 case CP0_REG29__TAGHI:
8690 case CP0_REG29__TAGHI1:
8691 case CP0_REG29__TAGHI2:
8692 case CP0_REG29__TAGHI3:
8693 gen_helper_mtc0_taghi(cpu_env, arg);
8694 register_name = "TagHi";
8695 break;
8696 case CP0_REG29__DATAHI:
8697 case CP0_REG29__DATAHI1:
8698 case CP0_REG29__DATAHI2:
8699 case CP0_REG29__DATAHI3:
8700 gen_helper_mtc0_datahi(cpu_env, arg);
8701 register_name = "DataHi";
8702 break;
8703 default:
8704 register_name = "invalid sel";
8705 goto cp0_unimplemented;
8707 break;
8708 case CP0_REGISTER_30:
8709 switch (sel) {
8710 case CP0_REG30__ERROREPC:
8711 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8712 register_name = "ErrorEPC";
8713 break;
8714 default:
8715 goto cp0_unimplemented;
8717 break;
8718 case CP0_REGISTER_31:
8719 switch (sel) {
8720 case CP0_REG31__DESAVE:
8721 /* EJTAG support */
8722 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8723 register_name = "DESAVE";
8724 break;
8725 case CP0_REG31__KSCRATCH1:
8726 case CP0_REG31__KSCRATCH2:
8727 case CP0_REG31__KSCRATCH3:
8728 case CP0_REG31__KSCRATCH4:
8729 case CP0_REG31__KSCRATCH5:
8730 case CP0_REG31__KSCRATCH6:
8731 CP0_CHECK(ctx->kscrexist & (1 << sel));
8732 tcg_gen_st_tl(arg, cpu_env,
8733 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8734 register_name = "KScratch";
8735 break;
8736 default:
8737 goto cp0_unimplemented;
8739 break;
8740 default:
8741 goto cp0_unimplemented;
8743 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
8745 /* For simplicity assume that all writes can cause interrupts. */
8746 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8748 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8749 * translated code to check for pending interrupts.
8751 gen_save_pc(ctx->base.pc_next + 4);
8752 ctx->base.is_jmp = DISAS_EXIT;
8754 return;
8756 cp0_unimplemented:
8757 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8758 register_name, reg, sel);
8760 #endif /* TARGET_MIPS64 */
8762 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8763 int u, int sel, int h)
8765 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8766 TCGv t0 = tcg_temp_local_new();
8768 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8769 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8770 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8771 tcg_gen_movi_tl(t0, -1);
8772 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8773 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8774 tcg_gen_movi_tl(t0, -1);
8775 } else if (u == 0) {
8776 switch (rt) {
8777 case 1:
8778 switch (sel) {
8779 case 1:
8780 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8781 break;
8782 case 2:
8783 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8784 break;
8785 default:
8786 goto die;
8787 break;
8789 break;
8790 case 2:
8791 switch (sel) {
8792 case 1:
8793 gen_helper_mftc0_tcstatus(t0, cpu_env);
8794 break;
8795 case 2:
8796 gen_helper_mftc0_tcbind(t0, cpu_env);
8797 break;
8798 case 3:
8799 gen_helper_mftc0_tcrestart(t0, cpu_env);
8800 break;
8801 case 4:
8802 gen_helper_mftc0_tchalt(t0, cpu_env);
8803 break;
8804 case 5:
8805 gen_helper_mftc0_tccontext(t0, cpu_env);
8806 break;
8807 case 6:
8808 gen_helper_mftc0_tcschedule(t0, cpu_env);
8809 break;
8810 case 7:
8811 gen_helper_mftc0_tcschefback(t0, cpu_env);
8812 break;
8813 default:
8814 gen_mfc0(ctx, t0, rt, sel);
8815 break;
8817 break;
8818 case 10:
8819 switch (sel) {
8820 case 0:
8821 gen_helper_mftc0_entryhi(t0, cpu_env);
8822 break;
8823 default:
8824 gen_mfc0(ctx, t0, rt, sel);
8825 break;
8827 break;
8828 case 12:
8829 switch (sel) {
8830 case 0:
8831 gen_helper_mftc0_status(t0, cpu_env);
8832 break;
8833 default:
8834 gen_mfc0(ctx, t0, rt, sel);
8835 break;
8837 break;
8838 case 13:
8839 switch (sel) {
8840 case 0:
8841 gen_helper_mftc0_cause(t0, cpu_env);
8842 break;
8843 default:
8844 goto die;
8845 break;
8847 break;
8848 case 14:
8849 switch (sel) {
8850 case 0:
8851 gen_helper_mftc0_epc(t0, cpu_env);
8852 break;
8853 default:
8854 goto die;
8855 break;
8857 break;
8858 case 15:
8859 switch (sel) {
8860 case 1:
8861 gen_helper_mftc0_ebase(t0, cpu_env);
8862 break;
8863 default:
8864 goto die;
8865 break;
8867 break;
8868 case 16:
8869 switch (sel) {
8870 case 0:
8871 case 1:
8872 case 2:
8873 case 3:
8874 case 4:
8875 case 5:
8876 case 6:
8877 case 7:
8878 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
8879 break;
8880 default:
8881 goto die;
8882 break;
8884 break;
8885 case 23:
8886 switch (sel) {
8887 case 0:
8888 gen_helper_mftc0_debug(t0, cpu_env);
8889 break;
8890 default:
8891 gen_mfc0(ctx, t0, rt, sel);
8892 break;
8894 break;
8895 default:
8896 gen_mfc0(ctx, t0, rt, sel);
8898 } else {
8899 switch (sel) {
8900 /* GPR registers. */
8901 case 0:
8902 gen_helper_1e0i(mftgpr, t0, rt);
8903 break;
8904 /* Auxiliary CPU registers */
8905 case 1:
8906 switch (rt) {
8907 case 0:
8908 gen_helper_1e0i(mftlo, t0, 0);
8909 break;
8910 case 1:
8911 gen_helper_1e0i(mfthi, t0, 0);
8912 break;
8913 case 2:
8914 gen_helper_1e0i(mftacx, t0, 0);
8915 break;
8916 case 4:
8917 gen_helper_1e0i(mftlo, t0, 1);
8918 break;
8919 case 5:
8920 gen_helper_1e0i(mfthi, t0, 1);
8921 break;
8922 case 6:
8923 gen_helper_1e0i(mftacx, t0, 1);
8924 break;
8925 case 8:
8926 gen_helper_1e0i(mftlo, t0, 2);
8927 break;
8928 case 9:
8929 gen_helper_1e0i(mfthi, t0, 2);
8930 break;
8931 case 10:
8932 gen_helper_1e0i(mftacx, t0, 2);
8933 break;
8934 case 12:
8935 gen_helper_1e0i(mftlo, t0, 3);
8936 break;
8937 case 13:
8938 gen_helper_1e0i(mfthi, t0, 3);
8939 break;
8940 case 14:
8941 gen_helper_1e0i(mftacx, t0, 3);
8942 break;
8943 case 16:
8944 gen_helper_mftdsp(t0, cpu_env);
8945 break;
8946 default:
8947 goto die;
8949 break;
8950 /* Floating point (COP1). */
8951 case 2:
8952 /* XXX: For now we support only a single FPU context. */
8953 if (h == 0) {
8954 TCGv_i32 fp0 = tcg_temp_new_i32();
8956 gen_load_fpr32(ctx, fp0, rt);
8957 tcg_gen_ext_i32_tl(t0, fp0);
8958 tcg_temp_free_i32(fp0);
8959 } else {
8960 TCGv_i32 fp0 = tcg_temp_new_i32();
8962 gen_load_fpr32h(ctx, fp0, rt);
8963 tcg_gen_ext_i32_tl(t0, fp0);
8964 tcg_temp_free_i32(fp0);
8966 break;
8967 case 3:
8968 /* XXX: For now we support only a single FPU context. */
8969 gen_helper_1e0i(cfc1, t0, rt);
8970 break;
8971 /* COP2: Not implemented. */
8972 case 4:
8973 case 5:
8974 /* fall through */
8975 default:
8976 goto die;
8979 trace_mips_translate_tr("mftr", rt, u, sel, h);
8980 gen_store_gpr(t0, rd);
8981 tcg_temp_free(t0);
8982 return;
8984 die:
8985 tcg_temp_free(t0);
8986 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
8987 gen_reserved_instruction(ctx);
8990 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
8991 int u, int sel, int h)
8993 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8994 TCGv t0 = tcg_temp_local_new();
8996 gen_load_gpr(t0, rt);
8997 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8998 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8999 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9000 /* NOP */
9002 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9003 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9004 /* NOP */
9006 } else if (u == 0) {
9007 switch (rd) {
9008 case 1:
9009 switch (sel) {
9010 case 1:
9011 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9012 break;
9013 case 2:
9014 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9015 break;
9016 default:
9017 goto die;
9018 break;
9020 break;
9021 case 2:
9022 switch (sel) {
9023 case 1:
9024 gen_helper_mttc0_tcstatus(cpu_env, t0);
9025 break;
9026 case 2:
9027 gen_helper_mttc0_tcbind(cpu_env, t0);
9028 break;
9029 case 3:
9030 gen_helper_mttc0_tcrestart(cpu_env, t0);
9031 break;
9032 case 4:
9033 gen_helper_mttc0_tchalt(cpu_env, t0);
9034 break;
9035 case 5:
9036 gen_helper_mttc0_tccontext(cpu_env, t0);
9037 break;
9038 case 6:
9039 gen_helper_mttc0_tcschedule(cpu_env, t0);
9040 break;
9041 case 7:
9042 gen_helper_mttc0_tcschefback(cpu_env, t0);
9043 break;
9044 default:
9045 gen_mtc0(ctx, t0, rd, sel);
9046 break;
9048 break;
9049 case 10:
9050 switch (sel) {
9051 case 0:
9052 gen_helper_mttc0_entryhi(cpu_env, t0);
9053 break;
9054 default:
9055 gen_mtc0(ctx, t0, rd, sel);
9056 break;
9058 break;
9059 case 12:
9060 switch (sel) {
9061 case 0:
9062 gen_helper_mttc0_status(cpu_env, t0);
9063 break;
9064 default:
9065 gen_mtc0(ctx, t0, rd, sel);
9066 break;
9068 break;
9069 case 13:
9070 switch (sel) {
9071 case 0:
9072 gen_helper_mttc0_cause(cpu_env, t0);
9073 break;
9074 default:
9075 goto die;
9076 break;
9078 break;
9079 case 15:
9080 switch (sel) {
9081 case 1:
9082 gen_helper_mttc0_ebase(cpu_env, t0);
9083 break;
9084 default:
9085 goto die;
9086 break;
9088 break;
9089 case 23:
9090 switch (sel) {
9091 case 0:
9092 gen_helper_mttc0_debug(cpu_env, t0);
9093 break;
9094 default:
9095 gen_mtc0(ctx, t0, rd, sel);
9096 break;
9098 break;
9099 default:
9100 gen_mtc0(ctx, t0, rd, sel);
9102 } else {
9103 switch (sel) {
9104 /* GPR registers. */
9105 case 0:
9106 gen_helper_0e1i(mttgpr, t0, rd);
9107 break;
9108 /* Auxiliary CPU registers */
9109 case 1:
9110 switch (rd) {
9111 case 0:
9112 gen_helper_0e1i(mttlo, t0, 0);
9113 break;
9114 case 1:
9115 gen_helper_0e1i(mtthi, t0, 0);
9116 break;
9117 case 2:
9118 gen_helper_0e1i(mttacx, t0, 0);
9119 break;
9120 case 4:
9121 gen_helper_0e1i(mttlo, t0, 1);
9122 break;
9123 case 5:
9124 gen_helper_0e1i(mtthi, t0, 1);
9125 break;
9126 case 6:
9127 gen_helper_0e1i(mttacx, t0, 1);
9128 break;
9129 case 8:
9130 gen_helper_0e1i(mttlo, t0, 2);
9131 break;
9132 case 9:
9133 gen_helper_0e1i(mtthi, t0, 2);
9134 break;
9135 case 10:
9136 gen_helper_0e1i(mttacx, t0, 2);
9137 break;
9138 case 12:
9139 gen_helper_0e1i(mttlo, t0, 3);
9140 break;
9141 case 13:
9142 gen_helper_0e1i(mtthi, t0, 3);
9143 break;
9144 case 14:
9145 gen_helper_0e1i(mttacx, t0, 3);
9146 break;
9147 case 16:
9148 gen_helper_mttdsp(cpu_env, t0);
9149 break;
9150 default:
9151 goto die;
9153 break;
9154 /* Floating point (COP1). */
9155 case 2:
9156 /* XXX: For now we support only a single FPU context. */
9157 if (h == 0) {
9158 TCGv_i32 fp0 = tcg_temp_new_i32();
9160 tcg_gen_trunc_tl_i32(fp0, t0);
9161 gen_store_fpr32(ctx, fp0, rd);
9162 tcg_temp_free_i32(fp0);
9163 } else {
9164 TCGv_i32 fp0 = tcg_temp_new_i32();
9166 tcg_gen_trunc_tl_i32(fp0, t0);
9167 gen_store_fpr32h(ctx, fp0, rd);
9168 tcg_temp_free_i32(fp0);
9170 break;
9171 case 3:
9172 /* XXX: For now we support only a single FPU context. */
9174 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9176 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9177 tcg_temp_free_i32(fs_tmp);
9179 /* Stop translation as we may have changed hflags */
9180 ctx->base.is_jmp = DISAS_STOP;
9181 break;
9182 /* COP2: Not implemented. */
9183 case 4:
9184 case 5:
9185 /* fall through */
9186 default:
9187 goto die;
9190 trace_mips_translate_tr("mttr", rd, u, sel, h);
9191 tcg_temp_free(t0);
9192 return;
9194 die:
9195 tcg_temp_free(t0);
9196 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9197 gen_reserved_instruction(ctx);
9200 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9201 int rt, int rd)
9203 const char *opn = "ldst";
9205 check_cp0_enabled(ctx);
9206 switch (opc) {
9207 case OPC_MFC0:
9208 if (rt == 0) {
9209 /* Treat as NOP. */
9210 return;
9212 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9213 opn = "mfc0";
9214 break;
9215 case OPC_MTC0:
9217 TCGv t0 = tcg_temp_new();
9219 gen_load_gpr(t0, rt);
9220 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9221 tcg_temp_free(t0);
9223 opn = "mtc0";
9224 break;
9225 #if defined(TARGET_MIPS64)
9226 case OPC_DMFC0:
9227 check_insn(ctx, ISA_MIPS3);
9228 if (rt == 0) {
9229 /* Treat as NOP. */
9230 return;
9232 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9233 opn = "dmfc0";
9234 break;
9235 case OPC_DMTC0:
9236 check_insn(ctx, ISA_MIPS3);
9238 TCGv t0 = tcg_temp_new();
9240 gen_load_gpr(t0, rt);
9241 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9242 tcg_temp_free(t0);
9244 opn = "dmtc0";
9245 break;
9246 #endif
9247 case OPC_MFHC0:
9248 check_mvh(ctx);
9249 if (rt == 0) {
9250 /* Treat as NOP. */
9251 return;
9253 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9254 opn = "mfhc0";
9255 break;
9256 case OPC_MTHC0:
9257 check_mvh(ctx);
9259 TCGv t0 = tcg_temp_new();
9260 gen_load_gpr(t0, rt);
9261 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9262 tcg_temp_free(t0);
9264 opn = "mthc0";
9265 break;
9266 case OPC_MFTR:
9267 check_cp0_enabled(ctx);
9268 if (rd == 0) {
9269 /* Treat as NOP. */
9270 return;
9272 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9273 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9274 opn = "mftr";
9275 break;
9276 case OPC_MTTR:
9277 check_cp0_enabled(ctx);
9278 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9279 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9280 opn = "mttr";
9281 break;
9282 case OPC_TLBWI:
9283 opn = "tlbwi";
9284 if (!env->tlb->helper_tlbwi) {
9285 goto die;
9287 gen_helper_tlbwi(cpu_env);
9288 break;
9289 case OPC_TLBINV:
9290 opn = "tlbinv";
9291 if (ctx->ie >= 2) {
9292 if (!env->tlb->helper_tlbinv) {
9293 goto die;
9295 gen_helper_tlbinv(cpu_env);
9296 } /* treat as nop if TLBINV not supported */
9297 break;
9298 case OPC_TLBINVF:
9299 opn = "tlbinvf";
9300 if (ctx->ie >= 2) {
9301 if (!env->tlb->helper_tlbinvf) {
9302 goto die;
9304 gen_helper_tlbinvf(cpu_env);
9305 } /* treat as nop if TLBINV not supported */
9306 break;
9307 case OPC_TLBWR:
9308 opn = "tlbwr";
9309 if (!env->tlb->helper_tlbwr) {
9310 goto die;
9312 gen_helper_tlbwr(cpu_env);
9313 break;
9314 case OPC_TLBP:
9315 opn = "tlbp";
9316 if (!env->tlb->helper_tlbp) {
9317 goto die;
9319 gen_helper_tlbp(cpu_env);
9320 break;
9321 case OPC_TLBR:
9322 opn = "tlbr";
9323 if (!env->tlb->helper_tlbr) {
9324 goto die;
9326 gen_helper_tlbr(cpu_env);
9327 break;
9328 case OPC_ERET: /* OPC_ERETNC */
9329 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9330 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9331 goto die;
9332 } else {
9333 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9334 if (ctx->opcode & (1 << bit_shift)) {
9335 /* OPC_ERETNC */
9336 opn = "eretnc";
9337 check_insn(ctx, ISA_MIPS_R5);
9338 gen_helper_eretnc(cpu_env);
9339 } else {
9340 /* OPC_ERET */
9341 opn = "eret";
9342 check_insn(ctx, ISA_MIPS2);
9343 gen_helper_eret(cpu_env);
9345 ctx->base.is_jmp = DISAS_EXIT;
9347 break;
9348 case OPC_DERET:
9349 opn = "deret";
9350 check_insn(ctx, ISA_MIPS_R1);
9351 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9352 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9353 goto die;
9355 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9356 MIPS_INVAL(opn);
9357 gen_reserved_instruction(ctx);
9358 } else {
9359 gen_helper_deret(cpu_env);
9360 ctx->base.is_jmp = DISAS_EXIT;
9362 break;
9363 case OPC_WAIT:
9364 opn = "wait";
9365 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
9366 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9367 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9368 goto die;
9370 /* If we get an exception, we want to restart at next instruction */
9371 ctx->base.pc_next += 4;
9372 save_cpu_state(ctx, 1);
9373 ctx->base.pc_next -= 4;
9374 gen_helper_wait(cpu_env);
9375 ctx->base.is_jmp = DISAS_NORETURN;
9376 break;
9377 default:
9378 die:
9379 MIPS_INVAL(opn);
9380 gen_reserved_instruction(ctx);
9381 return;
9383 (void)opn; /* avoid a compiler warning */
9385 #endif /* !CONFIG_USER_ONLY */
9387 /* CP1 Branches (before delay slot) */
9388 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9389 int32_t cc, int32_t offset)
9391 target_ulong btarget;
9392 TCGv_i32 t0 = tcg_temp_new_i32();
9394 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9395 gen_reserved_instruction(ctx);
9396 goto out;
9399 if (cc != 0) {
9400 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
9403 btarget = ctx->base.pc_next + 4 + offset;
9405 switch (op) {
9406 case OPC_BC1F:
9407 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9408 tcg_gen_not_i32(t0, t0);
9409 tcg_gen_andi_i32(t0, t0, 1);
9410 tcg_gen_extu_i32_tl(bcond, t0);
9411 goto not_likely;
9412 case OPC_BC1FL:
9413 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9414 tcg_gen_not_i32(t0, t0);
9415 tcg_gen_andi_i32(t0, t0, 1);
9416 tcg_gen_extu_i32_tl(bcond, t0);
9417 goto likely;
9418 case OPC_BC1T:
9419 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9420 tcg_gen_andi_i32(t0, t0, 1);
9421 tcg_gen_extu_i32_tl(bcond, t0);
9422 goto not_likely;
9423 case OPC_BC1TL:
9424 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9425 tcg_gen_andi_i32(t0, t0, 1);
9426 tcg_gen_extu_i32_tl(bcond, t0);
9427 likely:
9428 ctx->hflags |= MIPS_HFLAG_BL;
9429 break;
9430 case OPC_BC1FANY2:
9432 TCGv_i32 t1 = tcg_temp_new_i32();
9433 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9434 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9435 tcg_gen_nand_i32(t0, t0, t1);
9436 tcg_temp_free_i32(t1);
9437 tcg_gen_andi_i32(t0, t0, 1);
9438 tcg_gen_extu_i32_tl(bcond, t0);
9440 goto not_likely;
9441 case OPC_BC1TANY2:
9443 TCGv_i32 t1 = tcg_temp_new_i32();
9444 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9445 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9446 tcg_gen_or_i32(t0, t0, t1);
9447 tcg_temp_free_i32(t1);
9448 tcg_gen_andi_i32(t0, t0, 1);
9449 tcg_gen_extu_i32_tl(bcond, t0);
9451 goto not_likely;
9452 case OPC_BC1FANY4:
9454 TCGv_i32 t1 = tcg_temp_new_i32();
9455 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9456 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9457 tcg_gen_and_i32(t0, t0, t1);
9458 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9459 tcg_gen_and_i32(t0, t0, t1);
9460 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9461 tcg_gen_nand_i32(t0, t0, t1);
9462 tcg_temp_free_i32(t1);
9463 tcg_gen_andi_i32(t0, t0, 1);
9464 tcg_gen_extu_i32_tl(bcond, t0);
9466 goto not_likely;
9467 case OPC_BC1TANY4:
9469 TCGv_i32 t1 = tcg_temp_new_i32();
9470 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9471 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9472 tcg_gen_or_i32(t0, t0, t1);
9473 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9474 tcg_gen_or_i32(t0, t0, t1);
9475 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9476 tcg_gen_or_i32(t0, t0, t1);
9477 tcg_temp_free_i32(t1);
9478 tcg_gen_andi_i32(t0, t0, 1);
9479 tcg_gen_extu_i32_tl(bcond, t0);
9481 not_likely:
9482 ctx->hflags |= MIPS_HFLAG_BC;
9483 break;
9484 default:
9485 MIPS_INVAL("cp1 cond branch");
9486 gen_reserved_instruction(ctx);
9487 goto out;
9489 ctx->btarget = btarget;
9490 ctx->hflags |= MIPS_HFLAG_BDS32;
9491 out:
9492 tcg_temp_free_i32(t0);
9495 /* R6 CP1 Branches */
9496 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9497 int32_t ft, int32_t offset,
9498 int delayslot_size)
9500 target_ulong btarget;
9501 TCGv_i64 t0 = tcg_temp_new_i64();
9503 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9504 #ifdef MIPS_DEBUG_DISAS
9505 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9506 "\n", ctx->base.pc_next);
9507 #endif
9508 gen_reserved_instruction(ctx);
9509 goto out;
9512 gen_load_fpr64(ctx, t0, ft);
9513 tcg_gen_andi_i64(t0, t0, 1);
9515 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9517 switch (op) {
9518 case OPC_BC1EQZ:
9519 tcg_gen_xori_i64(t0, t0, 1);
9520 ctx->hflags |= MIPS_HFLAG_BC;
9521 break;
9522 case OPC_BC1NEZ:
9523 /* t0 already set */
9524 ctx->hflags |= MIPS_HFLAG_BC;
9525 break;
9526 default:
9527 MIPS_INVAL("cp1 cond branch");
9528 gen_reserved_instruction(ctx);
9529 goto out;
9532 tcg_gen_trunc_i64_tl(bcond, t0);
9534 ctx->btarget = btarget;
9536 switch (delayslot_size) {
9537 case 2:
9538 ctx->hflags |= MIPS_HFLAG_BDS16;
9539 break;
9540 case 4:
9541 ctx->hflags |= MIPS_HFLAG_BDS32;
9542 break;
9545 out:
9546 tcg_temp_free_i64(t0);
9549 /* Coprocessor 1 (FPU) */
9551 #define FOP(func, fmt) (((fmt) << 21) | (func))
9553 enum fopcode {
9554 OPC_ADD_S = FOP(0, FMT_S),
9555 OPC_SUB_S = FOP(1, FMT_S),
9556 OPC_MUL_S = FOP(2, FMT_S),
9557 OPC_DIV_S = FOP(3, FMT_S),
9558 OPC_SQRT_S = FOP(4, FMT_S),
9559 OPC_ABS_S = FOP(5, FMT_S),
9560 OPC_MOV_S = FOP(6, FMT_S),
9561 OPC_NEG_S = FOP(7, FMT_S),
9562 OPC_ROUND_L_S = FOP(8, FMT_S),
9563 OPC_TRUNC_L_S = FOP(9, FMT_S),
9564 OPC_CEIL_L_S = FOP(10, FMT_S),
9565 OPC_FLOOR_L_S = FOP(11, FMT_S),
9566 OPC_ROUND_W_S = FOP(12, FMT_S),
9567 OPC_TRUNC_W_S = FOP(13, FMT_S),
9568 OPC_CEIL_W_S = FOP(14, FMT_S),
9569 OPC_FLOOR_W_S = FOP(15, FMT_S),
9570 OPC_SEL_S = FOP(16, FMT_S),
9571 OPC_MOVCF_S = FOP(17, FMT_S),
9572 OPC_MOVZ_S = FOP(18, FMT_S),
9573 OPC_MOVN_S = FOP(19, FMT_S),
9574 OPC_SELEQZ_S = FOP(20, FMT_S),
9575 OPC_RECIP_S = FOP(21, FMT_S),
9576 OPC_RSQRT_S = FOP(22, FMT_S),
9577 OPC_SELNEZ_S = FOP(23, FMT_S),
9578 OPC_MADDF_S = FOP(24, FMT_S),
9579 OPC_MSUBF_S = FOP(25, FMT_S),
9580 OPC_RINT_S = FOP(26, FMT_S),
9581 OPC_CLASS_S = FOP(27, FMT_S),
9582 OPC_MIN_S = FOP(28, FMT_S),
9583 OPC_RECIP2_S = FOP(28, FMT_S),
9584 OPC_MINA_S = FOP(29, FMT_S),
9585 OPC_RECIP1_S = FOP(29, FMT_S),
9586 OPC_MAX_S = FOP(30, FMT_S),
9587 OPC_RSQRT1_S = FOP(30, FMT_S),
9588 OPC_MAXA_S = FOP(31, FMT_S),
9589 OPC_RSQRT2_S = FOP(31, FMT_S),
9590 OPC_CVT_D_S = FOP(33, FMT_S),
9591 OPC_CVT_W_S = FOP(36, FMT_S),
9592 OPC_CVT_L_S = FOP(37, FMT_S),
9593 OPC_CVT_PS_S = FOP(38, FMT_S),
9594 OPC_CMP_F_S = FOP(48, FMT_S),
9595 OPC_CMP_UN_S = FOP(49, FMT_S),
9596 OPC_CMP_EQ_S = FOP(50, FMT_S),
9597 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9598 OPC_CMP_OLT_S = FOP(52, FMT_S),
9599 OPC_CMP_ULT_S = FOP(53, FMT_S),
9600 OPC_CMP_OLE_S = FOP(54, FMT_S),
9601 OPC_CMP_ULE_S = FOP(55, FMT_S),
9602 OPC_CMP_SF_S = FOP(56, FMT_S),
9603 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9604 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9605 OPC_CMP_NGL_S = FOP(59, FMT_S),
9606 OPC_CMP_LT_S = FOP(60, FMT_S),
9607 OPC_CMP_NGE_S = FOP(61, FMT_S),
9608 OPC_CMP_LE_S = FOP(62, FMT_S),
9609 OPC_CMP_NGT_S = FOP(63, FMT_S),
9611 OPC_ADD_D = FOP(0, FMT_D),
9612 OPC_SUB_D = FOP(1, FMT_D),
9613 OPC_MUL_D = FOP(2, FMT_D),
9614 OPC_DIV_D = FOP(3, FMT_D),
9615 OPC_SQRT_D = FOP(4, FMT_D),
9616 OPC_ABS_D = FOP(5, FMT_D),
9617 OPC_MOV_D = FOP(6, FMT_D),
9618 OPC_NEG_D = FOP(7, FMT_D),
9619 OPC_ROUND_L_D = FOP(8, FMT_D),
9620 OPC_TRUNC_L_D = FOP(9, FMT_D),
9621 OPC_CEIL_L_D = FOP(10, FMT_D),
9622 OPC_FLOOR_L_D = FOP(11, FMT_D),
9623 OPC_ROUND_W_D = FOP(12, FMT_D),
9624 OPC_TRUNC_W_D = FOP(13, FMT_D),
9625 OPC_CEIL_W_D = FOP(14, FMT_D),
9626 OPC_FLOOR_W_D = FOP(15, FMT_D),
9627 OPC_SEL_D = FOP(16, FMT_D),
9628 OPC_MOVCF_D = FOP(17, FMT_D),
9629 OPC_MOVZ_D = FOP(18, FMT_D),
9630 OPC_MOVN_D = FOP(19, FMT_D),
9631 OPC_SELEQZ_D = FOP(20, FMT_D),
9632 OPC_RECIP_D = FOP(21, FMT_D),
9633 OPC_RSQRT_D = FOP(22, FMT_D),
9634 OPC_SELNEZ_D = FOP(23, FMT_D),
9635 OPC_MADDF_D = FOP(24, FMT_D),
9636 OPC_MSUBF_D = FOP(25, FMT_D),
9637 OPC_RINT_D = FOP(26, FMT_D),
9638 OPC_CLASS_D = FOP(27, FMT_D),
9639 OPC_MIN_D = FOP(28, FMT_D),
9640 OPC_RECIP2_D = FOP(28, FMT_D),
9641 OPC_MINA_D = FOP(29, FMT_D),
9642 OPC_RECIP1_D = FOP(29, FMT_D),
9643 OPC_MAX_D = FOP(30, FMT_D),
9644 OPC_RSQRT1_D = FOP(30, FMT_D),
9645 OPC_MAXA_D = FOP(31, FMT_D),
9646 OPC_RSQRT2_D = FOP(31, FMT_D),
9647 OPC_CVT_S_D = FOP(32, FMT_D),
9648 OPC_CVT_W_D = FOP(36, FMT_D),
9649 OPC_CVT_L_D = FOP(37, FMT_D),
9650 OPC_CMP_F_D = FOP(48, FMT_D),
9651 OPC_CMP_UN_D = FOP(49, FMT_D),
9652 OPC_CMP_EQ_D = FOP(50, FMT_D),
9653 OPC_CMP_UEQ_D = FOP(51, FMT_D),
9654 OPC_CMP_OLT_D = FOP(52, FMT_D),
9655 OPC_CMP_ULT_D = FOP(53, FMT_D),
9656 OPC_CMP_OLE_D = FOP(54, FMT_D),
9657 OPC_CMP_ULE_D = FOP(55, FMT_D),
9658 OPC_CMP_SF_D = FOP(56, FMT_D),
9659 OPC_CMP_NGLE_D = FOP(57, FMT_D),
9660 OPC_CMP_SEQ_D = FOP(58, FMT_D),
9661 OPC_CMP_NGL_D = FOP(59, FMT_D),
9662 OPC_CMP_LT_D = FOP(60, FMT_D),
9663 OPC_CMP_NGE_D = FOP(61, FMT_D),
9664 OPC_CMP_LE_D = FOP(62, FMT_D),
9665 OPC_CMP_NGT_D = FOP(63, FMT_D),
9667 OPC_CVT_S_W = FOP(32, FMT_W),
9668 OPC_CVT_D_W = FOP(33, FMT_W),
9669 OPC_CVT_S_L = FOP(32, FMT_L),
9670 OPC_CVT_D_L = FOP(33, FMT_L),
9671 OPC_CVT_PS_PW = FOP(38, FMT_W),
9673 OPC_ADD_PS = FOP(0, FMT_PS),
9674 OPC_SUB_PS = FOP(1, FMT_PS),
9675 OPC_MUL_PS = FOP(2, FMT_PS),
9676 OPC_DIV_PS = FOP(3, FMT_PS),
9677 OPC_ABS_PS = FOP(5, FMT_PS),
9678 OPC_MOV_PS = FOP(6, FMT_PS),
9679 OPC_NEG_PS = FOP(7, FMT_PS),
9680 OPC_MOVCF_PS = FOP(17, FMT_PS),
9681 OPC_MOVZ_PS = FOP(18, FMT_PS),
9682 OPC_MOVN_PS = FOP(19, FMT_PS),
9683 OPC_ADDR_PS = FOP(24, FMT_PS),
9684 OPC_MULR_PS = FOP(26, FMT_PS),
9685 OPC_RECIP2_PS = FOP(28, FMT_PS),
9686 OPC_RECIP1_PS = FOP(29, FMT_PS),
9687 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9688 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9690 OPC_CVT_S_PU = FOP(32, FMT_PS),
9691 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9692 OPC_CVT_S_PL = FOP(40, FMT_PS),
9693 OPC_PLL_PS = FOP(44, FMT_PS),
9694 OPC_PLU_PS = FOP(45, FMT_PS),
9695 OPC_PUL_PS = FOP(46, FMT_PS),
9696 OPC_PUU_PS = FOP(47, FMT_PS),
9697 OPC_CMP_F_PS = FOP(48, FMT_PS),
9698 OPC_CMP_UN_PS = FOP(49, FMT_PS),
9699 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
9700 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
9701 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
9702 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
9703 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
9704 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
9705 OPC_CMP_SF_PS = FOP(56, FMT_PS),
9706 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
9707 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
9708 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
9709 OPC_CMP_LT_PS = FOP(60, FMT_PS),
9710 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
9711 OPC_CMP_LE_PS = FOP(62, FMT_PS),
9712 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
9715 enum r6_f_cmp_op {
9716 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9717 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9718 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9719 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9720 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9721 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9722 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9723 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9724 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9725 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9726 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9727 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9728 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9729 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9730 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9731 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9732 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9733 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9734 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9735 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9736 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9737 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9739 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9740 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9741 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9742 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9743 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9744 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9745 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9746 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9747 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9748 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9749 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9750 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9751 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9752 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9753 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9754 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9755 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9756 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9757 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9758 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9759 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9760 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9763 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
9765 TCGv t0 = tcg_temp_new();
9767 switch (opc) {
9768 case OPC_MFC1:
9770 TCGv_i32 fp0 = tcg_temp_new_i32();
9772 gen_load_fpr32(ctx, fp0, fs);
9773 tcg_gen_ext_i32_tl(t0, fp0);
9774 tcg_temp_free_i32(fp0);
9776 gen_store_gpr(t0, rt);
9777 break;
9778 case OPC_MTC1:
9779 gen_load_gpr(t0, rt);
9781 TCGv_i32 fp0 = tcg_temp_new_i32();
9783 tcg_gen_trunc_tl_i32(fp0, t0);
9784 gen_store_fpr32(ctx, fp0, fs);
9785 tcg_temp_free_i32(fp0);
9787 break;
9788 case OPC_CFC1:
9789 gen_helper_1e0i(cfc1, t0, fs);
9790 gen_store_gpr(t0, rt);
9791 break;
9792 case OPC_CTC1:
9793 gen_load_gpr(t0, rt);
9794 save_cpu_state(ctx, 0);
9796 TCGv_i32 fs_tmp = tcg_const_i32(fs);
9798 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9799 tcg_temp_free_i32(fs_tmp);
9801 /* Stop translation as we may have changed hflags */
9802 ctx->base.is_jmp = DISAS_STOP;
9803 break;
9804 #if defined(TARGET_MIPS64)
9805 case OPC_DMFC1:
9806 gen_load_fpr64(ctx, t0, fs);
9807 gen_store_gpr(t0, rt);
9808 break;
9809 case OPC_DMTC1:
9810 gen_load_gpr(t0, rt);
9811 gen_store_fpr64(ctx, t0, fs);
9812 break;
9813 #endif
9814 case OPC_MFHC1:
9816 TCGv_i32 fp0 = tcg_temp_new_i32();
9818 gen_load_fpr32h(ctx, fp0, fs);
9819 tcg_gen_ext_i32_tl(t0, fp0);
9820 tcg_temp_free_i32(fp0);
9822 gen_store_gpr(t0, rt);
9823 break;
9824 case OPC_MTHC1:
9825 gen_load_gpr(t0, rt);
9827 TCGv_i32 fp0 = tcg_temp_new_i32();
9829 tcg_gen_trunc_tl_i32(fp0, t0);
9830 gen_store_fpr32h(ctx, fp0, fs);
9831 tcg_temp_free_i32(fp0);
9833 break;
9834 default:
9835 MIPS_INVAL("cp1 move");
9836 gen_reserved_instruction(ctx);
9837 goto out;
9840 out:
9841 tcg_temp_free(t0);
9844 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
9846 TCGLabel *l1;
9847 TCGCond cond;
9848 TCGv_i32 t0;
9850 if (rd == 0) {
9851 /* Treat as NOP. */
9852 return;
9855 if (tf) {
9856 cond = TCG_COND_EQ;
9857 } else {
9858 cond = TCG_COND_NE;
9861 l1 = gen_new_label();
9862 t0 = tcg_temp_new_i32();
9863 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9864 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9865 tcg_temp_free_i32(t0);
9866 gen_load_gpr(cpu_gpr[rd], rs);
9867 gen_set_label(l1);
9870 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9871 int tf)
9873 int cond;
9874 TCGv_i32 t0 = tcg_temp_new_i32();
9875 TCGLabel *l1 = gen_new_label();
9877 if (tf) {
9878 cond = TCG_COND_EQ;
9879 } else {
9880 cond = TCG_COND_NE;
9883 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9884 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9885 gen_load_fpr32(ctx, t0, fs);
9886 gen_store_fpr32(ctx, t0, fd);
9887 gen_set_label(l1);
9888 tcg_temp_free_i32(t0);
9891 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
9892 int tf)
9894 int cond;
9895 TCGv_i32 t0 = tcg_temp_new_i32();
9896 TCGv_i64 fp0;
9897 TCGLabel *l1 = gen_new_label();
9899 if (tf) {
9900 cond = TCG_COND_EQ;
9901 } else {
9902 cond = TCG_COND_NE;
9905 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9906 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9907 tcg_temp_free_i32(t0);
9908 fp0 = tcg_temp_new_i64();
9909 gen_load_fpr64(ctx, fp0, fs);
9910 gen_store_fpr64(ctx, fp0, fd);
9911 tcg_temp_free_i64(fp0);
9912 gen_set_label(l1);
9915 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9916 int cc, int tf)
9918 int cond;
9919 TCGv_i32 t0 = tcg_temp_new_i32();
9920 TCGLabel *l1 = gen_new_label();
9921 TCGLabel *l2 = gen_new_label();
9923 if (tf) {
9924 cond = TCG_COND_EQ;
9925 } else {
9926 cond = TCG_COND_NE;
9929 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9930 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9931 gen_load_fpr32(ctx, t0, fs);
9932 gen_store_fpr32(ctx, t0, fd);
9933 gen_set_label(l1);
9935 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
9936 tcg_gen_brcondi_i32(cond, t0, 0, l2);
9937 gen_load_fpr32h(ctx, t0, fs);
9938 gen_store_fpr32h(ctx, t0, fd);
9939 tcg_temp_free_i32(t0);
9940 gen_set_label(l2);
9943 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9944 int fs)
9946 TCGv_i32 t1 = tcg_const_i32(0);
9947 TCGv_i32 fp0 = tcg_temp_new_i32();
9948 TCGv_i32 fp1 = tcg_temp_new_i32();
9949 TCGv_i32 fp2 = tcg_temp_new_i32();
9950 gen_load_fpr32(ctx, fp0, fd);
9951 gen_load_fpr32(ctx, fp1, ft);
9952 gen_load_fpr32(ctx, fp2, fs);
9954 switch (op1) {
9955 case OPC_SEL_S:
9956 tcg_gen_andi_i32(fp0, fp0, 1);
9957 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9958 break;
9959 case OPC_SELEQZ_S:
9960 tcg_gen_andi_i32(fp1, fp1, 1);
9961 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9962 break;
9963 case OPC_SELNEZ_S:
9964 tcg_gen_andi_i32(fp1, fp1, 1);
9965 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9966 break;
9967 default:
9968 MIPS_INVAL("gen_sel_s");
9969 gen_reserved_instruction(ctx);
9970 break;
9973 gen_store_fpr32(ctx, fp0, fd);
9974 tcg_temp_free_i32(fp2);
9975 tcg_temp_free_i32(fp1);
9976 tcg_temp_free_i32(fp0);
9977 tcg_temp_free_i32(t1);
9980 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9981 int fs)
9983 TCGv_i64 t1 = tcg_const_i64(0);
9984 TCGv_i64 fp0 = tcg_temp_new_i64();
9985 TCGv_i64 fp1 = tcg_temp_new_i64();
9986 TCGv_i64 fp2 = tcg_temp_new_i64();
9987 gen_load_fpr64(ctx, fp0, fd);
9988 gen_load_fpr64(ctx, fp1, ft);
9989 gen_load_fpr64(ctx, fp2, fs);
9991 switch (op1) {
9992 case OPC_SEL_D:
9993 tcg_gen_andi_i64(fp0, fp0, 1);
9994 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9995 break;
9996 case OPC_SELEQZ_D:
9997 tcg_gen_andi_i64(fp1, fp1, 1);
9998 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9999 break;
10000 case OPC_SELNEZ_D:
10001 tcg_gen_andi_i64(fp1, fp1, 1);
10002 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10003 break;
10004 default:
10005 MIPS_INVAL("gen_sel_d");
10006 gen_reserved_instruction(ctx);
10007 break;
10010 gen_store_fpr64(ctx, fp0, fd);
10011 tcg_temp_free_i64(fp2);
10012 tcg_temp_free_i64(fp1);
10013 tcg_temp_free_i64(fp0);
10014 tcg_temp_free_i64(t1);
10017 static void gen_farith(DisasContext *ctx, enum fopcode op1,
10018 int ft, int fs, int fd, int cc)
10020 uint32_t func = ctx->opcode & 0x3f;
10021 switch (op1) {
10022 case OPC_ADD_S:
10024 TCGv_i32 fp0 = tcg_temp_new_i32();
10025 TCGv_i32 fp1 = tcg_temp_new_i32();
10027 gen_load_fpr32(ctx, fp0, fs);
10028 gen_load_fpr32(ctx, fp1, ft);
10029 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10030 tcg_temp_free_i32(fp1);
10031 gen_store_fpr32(ctx, fp0, fd);
10032 tcg_temp_free_i32(fp0);
10034 break;
10035 case OPC_SUB_S:
10037 TCGv_i32 fp0 = tcg_temp_new_i32();
10038 TCGv_i32 fp1 = tcg_temp_new_i32();
10040 gen_load_fpr32(ctx, fp0, fs);
10041 gen_load_fpr32(ctx, fp1, ft);
10042 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10043 tcg_temp_free_i32(fp1);
10044 gen_store_fpr32(ctx, fp0, fd);
10045 tcg_temp_free_i32(fp0);
10047 break;
10048 case OPC_MUL_S:
10050 TCGv_i32 fp0 = tcg_temp_new_i32();
10051 TCGv_i32 fp1 = tcg_temp_new_i32();
10053 gen_load_fpr32(ctx, fp0, fs);
10054 gen_load_fpr32(ctx, fp1, ft);
10055 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10056 tcg_temp_free_i32(fp1);
10057 gen_store_fpr32(ctx, fp0, fd);
10058 tcg_temp_free_i32(fp0);
10060 break;
10061 case OPC_DIV_S:
10063 TCGv_i32 fp0 = tcg_temp_new_i32();
10064 TCGv_i32 fp1 = tcg_temp_new_i32();
10066 gen_load_fpr32(ctx, fp0, fs);
10067 gen_load_fpr32(ctx, fp1, ft);
10068 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10069 tcg_temp_free_i32(fp1);
10070 gen_store_fpr32(ctx, fp0, fd);
10071 tcg_temp_free_i32(fp0);
10073 break;
10074 case OPC_SQRT_S:
10076 TCGv_i32 fp0 = tcg_temp_new_i32();
10078 gen_load_fpr32(ctx, fp0, fs);
10079 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10080 gen_store_fpr32(ctx, fp0, fd);
10081 tcg_temp_free_i32(fp0);
10083 break;
10084 case OPC_ABS_S:
10086 TCGv_i32 fp0 = tcg_temp_new_i32();
10088 gen_load_fpr32(ctx, fp0, fs);
10089 if (ctx->abs2008) {
10090 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10091 } else {
10092 gen_helper_float_abs_s(fp0, fp0);
10094 gen_store_fpr32(ctx, fp0, fd);
10095 tcg_temp_free_i32(fp0);
10097 break;
10098 case OPC_MOV_S:
10100 TCGv_i32 fp0 = tcg_temp_new_i32();
10102 gen_load_fpr32(ctx, fp0, fs);
10103 gen_store_fpr32(ctx, fp0, fd);
10104 tcg_temp_free_i32(fp0);
10106 break;
10107 case OPC_NEG_S:
10109 TCGv_i32 fp0 = tcg_temp_new_i32();
10111 gen_load_fpr32(ctx, fp0, fs);
10112 if (ctx->abs2008) {
10113 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10114 } else {
10115 gen_helper_float_chs_s(fp0, fp0);
10117 gen_store_fpr32(ctx, fp0, fd);
10118 tcg_temp_free_i32(fp0);
10120 break;
10121 case OPC_ROUND_L_S:
10122 check_cp1_64bitmode(ctx);
10124 TCGv_i32 fp32 = tcg_temp_new_i32();
10125 TCGv_i64 fp64 = tcg_temp_new_i64();
10127 gen_load_fpr32(ctx, fp32, fs);
10128 if (ctx->nan2008) {
10129 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10130 } else {
10131 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10133 tcg_temp_free_i32(fp32);
10134 gen_store_fpr64(ctx, fp64, fd);
10135 tcg_temp_free_i64(fp64);
10137 break;
10138 case OPC_TRUNC_L_S:
10139 check_cp1_64bitmode(ctx);
10141 TCGv_i32 fp32 = tcg_temp_new_i32();
10142 TCGv_i64 fp64 = tcg_temp_new_i64();
10144 gen_load_fpr32(ctx, fp32, fs);
10145 if (ctx->nan2008) {
10146 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10147 } else {
10148 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10150 tcg_temp_free_i32(fp32);
10151 gen_store_fpr64(ctx, fp64, fd);
10152 tcg_temp_free_i64(fp64);
10154 break;
10155 case OPC_CEIL_L_S:
10156 check_cp1_64bitmode(ctx);
10158 TCGv_i32 fp32 = tcg_temp_new_i32();
10159 TCGv_i64 fp64 = tcg_temp_new_i64();
10161 gen_load_fpr32(ctx, fp32, fs);
10162 if (ctx->nan2008) {
10163 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10164 } else {
10165 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10167 tcg_temp_free_i32(fp32);
10168 gen_store_fpr64(ctx, fp64, fd);
10169 tcg_temp_free_i64(fp64);
10171 break;
10172 case OPC_FLOOR_L_S:
10173 check_cp1_64bitmode(ctx);
10175 TCGv_i32 fp32 = tcg_temp_new_i32();
10176 TCGv_i64 fp64 = tcg_temp_new_i64();
10178 gen_load_fpr32(ctx, fp32, fs);
10179 if (ctx->nan2008) {
10180 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10181 } else {
10182 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10184 tcg_temp_free_i32(fp32);
10185 gen_store_fpr64(ctx, fp64, fd);
10186 tcg_temp_free_i64(fp64);
10188 break;
10189 case OPC_ROUND_W_S:
10191 TCGv_i32 fp0 = tcg_temp_new_i32();
10193 gen_load_fpr32(ctx, fp0, fs);
10194 if (ctx->nan2008) {
10195 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10196 } else {
10197 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10199 gen_store_fpr32(ctx, fp0, fd);
10200 tcg_temp_free_i32(fp0);
10202 break;
10203 case OPC_TRUNC_W_S:
10205 TCGv_i32 fp0 = tcg_temp_new_i32();
10207 gen_load_fpr32(ctx, fp0, fs);
10208 if (ctx->nan2008) {
10209 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10210 } else {
10211 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10213 gen_store_fpr32(ctx, fp0, fd);
10214 tcg_temp_free_i32(fp0);
10216 break;
10217 case OPC_CEIL_W_S:
10219 TCGv_i32 fp0 = tcg_temp_new_i32();
10221 gen_load_fpr32(ctx, fp0, fs);
10222 if (ctx->nan2008) {
10223 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10224 } else {
10225 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10227 gen_store_fpr32(ctx, fp0, fd);
10228 tcg_temp_free_i32(fp0);
10230 break;
10231 case OPC_FLOOR_W_S:
10233 TCGv_i32 fp0 = tcg_temp_new_i32();
10235 gen_load_fpr32(ctx, fp0, fs);
10236 if (ctx->nan2008) {
10237 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10238 } else {
10239 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10241 gen_store_fpr32(ctx, fp0, fd);
10242 tcg_temp_free_i32(fp0);
10244 break;
10245 case OPC_SEL_S:
10246 check_insn(ctx, ISA_MIPS_R6);
10247 gen_sel_s(ctx, op1, fd, ft, fs);
10248 break;
10249 case OPC_SELEQZ_S:
10250 check_insn(ctx, ISA_MIPS_R6);
10251 gen_sel_s(ctx, op1, fd, ft, fs);
10252 break;
10253 case OPC_SELNEZ_S:
10254 check_insn(ctx, ISA_MIPS_R6);
10255 gen_sel_s(ctx, op1, fd, ft, fs);
10256 break;
10257 case OPC_MOVCF_S:
10258 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10259 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10260 break;
10261 case OPC_MOVZ_S:
10262 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10264 TCGLabel *l1 = gen_new_label();
10265 TCGv_i32 fp0;
10267 if (ft != 0) {
10268 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10270 fp0 = tcg_temp_new_i32();
10271 gen_load_fpr32(ctx, fp0, fs);
10272 gen_store_fpr32(ctx, fp0, fd);
10273 tcg_temp_free_i32(fp0);
10274 gen_set_label(l1);
10276 break;
10277 case OPC_MOVN_S:
10278 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10280 TCGLabel *l1 = gen_new_label();
10281 TCGv_i32 fp0;
10283 if (ft != 0) {
10284 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10285 fp0 = tcg_temp_new_i32();
10286 gen_load_fpr32(ctx, fp0, fs);
10287 gen_store_fpr32(ctx, fp0, fd);
10288 tcg_temp_free_i32(fp0);
10289 gen_set_label(l1);
10292 break;
10293 case OPC_RECIP_S:
10295 TCGv_i32 fp0 = tcg_temp_new_i32();
10297 gen_load_fpr32(ctx, fp0, fs);
10298 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10299 gen_store_fpr32(ctx, fp0, fd);
10300 tcg_temp_free_i32(fp0);
10302 break;
10303 case OPC_RSQRT_S:
10305 TCGv_i32 fp0 = tcg_temp_new_i32();
10307 gen_load_fpr32(ctx, fp0, fs);
10308 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10309 gen_store_fpr32(ctx, fp0, fd);
10310 tcg_temp_free_i32(fp0);
10312 break;
10313 case OPC_MADDF_S:
10314 check_insn(ctx, ISA_MIPS_R6);
10316 TCGv_i32 fp0 = tcg_temp_new_i32();
10317 TCGv_i32 fp1 = tcg_temp_new_i32();
10318 TCGv_i32 fp2 = tcg_temp_new_i32();
10319 gen_load_fpr32(ctx, fp0, fs);
10320 gen_load_fpr32(ctx, fp1, ft);
10321 gen_load_fpr32(ctx, fp2, fd);
10322 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10323 gen_store_fpr32(ctx, fp2, fd);
10324 tcg_temp_free_i32(fp2);
10325 tcg_temp_free_i32(fp1);
10326 tcg_temp_free_i32(fp0);
10328 break;
10329 case OPC_MSUBF_S:
10330 check_insn(ctx, ISA_MIPS_R6);
10332 TCGv_i32 fp0 = tcg_temp_new_i32();
10333 TCGv_i32 fp1 = tcg_temp_new_i32();
10334 TCGv_i32 fp2 = tcg_temp_new_i32();
10335 gen_load_fpr32(ctx, fp0, fs);
10336 gen_load_fpr32(ctx, fp1, ft);
10337 gen_load_fpr32(ctx, fp2, fd);
10338 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10339 gen_store_fpr32(ctx, fp2, fd);
10340 tcg_temp_free_i32(fp2);
10341 tcg_temp_free_i32(fp1);
10342 tcg_temp_free_i32(fp0);
10344 break;
10345 case OPC_RINT_S:
10346 check_insn(ctx, ISA_MIPS_R6);
10348 TCGv_i32 fp0 = tcg_temp_new_i32();
10349 gen_load_fpr32(ctx, fp0, fs);
10350 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10351 gen_store_fpr32(ctx, fp0, fd);
10352 tcg_temp_free_i32(fp0);
10354 break;
10355 case OPC_CLASS_S:
10356 check_insn(ctx, ISA_MIPS_R6);
10358 TCGv_i32 fp0 = tcg_temp_new_i32();
10359 gen_load_fpr32(ctx, fp0, fs);
10360 gen_helper_float_class_s(fp0, cpu_env, fp0);
10361 gen_store_fpr32(ctx, fp0, fd);
10362 tcg_temp_free_i32(fp0);
10364 break;
10365 case OPC_MIN_S: /* OPC_RECIP2_S */
10366 if (ctx->insn_flags & ISA_MIPS_R6) {
10367 /* OPC_MIN_S */
10368 TCGv_i32 fp0 = tcg_temp_new_i32();
10369 TCGv_i32 fp1 = tcg_temp_new_i32();
10370 TCGv_i32 fp2 = tcg_temp_new_i32();
10371 gen_load_fpr32(ctx, fp0, fs);
10372 gen_load_fpr32(ctx, fp1, ft);
10373 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10374 gen_store_fpr32(ctx, fp2, fd);
10375 tcg_temp_free_i32(fp2);
10376 tcg_temp_free_i32(fp1);
10377 tcg_temp_free_i32(fp0);
10378 } else {
10379 /* OPC_RECIP2_S */
10380 check_cp1_64bitmode(ctx);
10382 TCGv_i32 fp0 = tcg_temp_new_i32();
10383 TCGv_i32 fp1 = tcg_temp_new_i32();
10385 gen_load_fpr32(ctx, fp0, fs);
10386 gen_load_fpr32(ctx, fp1, ft);
10387 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10388 tcg_temp_free_i32(fp1);
10389 gen_store_fpr32(ctx, fp0, fd);
10390 tcg_temp_free_i32(fp0);
10393 break;
10394 case OPC_MINA_S: /* OPC_RECIP1_S */
10395 if (ctx->insn_flags & ISA_MIPS_R6) {
10396 /* OPC_MINA_S */
10397 TCGv_i32 fp0 = tcg_temp_new_i32();
10398 TCGv_i32 fp1 = tcg_temp_new_i32();
10399 TCGv_i32 fp2 = tcg_temp_new_i32();
10400 gen_load_fpr32(ctx, fp0, fs);
10401 gen_load_fpr32(ctx, fp1, ft);
10402 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10403 gen_store_fpr32(ctx, fp2, fd);
10404 tcg_temp_free_i32(fp2);
10405 tcg_temp_free_i32(fp1);
10406 tcg_temp_free_i32(fp0);
10407 } else {
10408 /* OPC_RECIP1_S */
10409 check_cp1_64bitmode(ctx);
10411 TCGv_i32 fp0 = tcg_temp_new_i32();
10413 gen_load_fpr32(ctx, fp0, fs);
10414 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10415 gen_store_fpr32(ctx, fp0, fd);
10416 tcg_temp_free_i32(fp0);
10419 break;
10420 case OPC_MAX_S: /* OPC_RSQRT1_S */
10421 if (ctx->insn_flags & ISA_MIPS_R6) {
10422 /* OPC_MAX_S */
10423 TCGv_i32 fp0 = tcg_temp_new_i32();
10424 TCGv_i32 fp1 = tcg_temp_new_i32();
10425 gen_load_fpr32(ctx, fp0, fs);
10426 gen_load_fpr32(ctx, fp1, ft);
10427 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10428 gen_store_fpr32(ctx, fp1, fd);
10429 tcg_temp_free_i32(fp1);
10430 tcg_temp_free_i32(fp0);
10431 } else {
10432 /* OPC_RSQRT1_S */
10433 check_cp1_64bitmode(ctx);
10435 TCGv_i32 fp0 = tcg_temp_new_i32();
10437 gen_load_fpr32(ctx, fp0, fs);
10438 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10439 gen_store_fpr32(ctx, fp0, fd);
10440 tcg_temp_free_i32(fp0);
10443 break;
10444 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10445 if (ctx->insn_flags & ISA_MIPS_R6) {
10446 /* OPC_MAXA_S */
10447 TCGv_i32 fp0 = tcg_temp_new_i32();
10448 TCGv_i32 fp1 = tcg_temp_new_i32();
10449 gen_load_fpr32(ctx, fp0, fs);
10450 gen_load_fpr32(ctx, fp1, ft);
10451 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10452 gen_store_fpr32(ctx, fp1, fd);
10453 tcg_temp_free_i32(fp1);
10454 tcg_temp_free_i32(fp0);
10455 } else {
10456 /* OPC_RSQRT2_S */
10457 check_cp1_64bitmode(ctx);
10459 TCGv_i32 fp0 = tcg_temp_new_i32();
10460 TCGv_i32 fp1 = tcg_temp_new_i32();
10462 gen_load_fpr32(ctx, fp0, fs);
10463 gen_load_fpr32(ctx, fp1, ft);
10464 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10465 tcg_temp_free_i32(fp1);
10466 gen_store_fpr32(ctx, fp0, fd);
10467 tcg_temp_free_i32(fp0);
10470 break;
10471 case OPC_CVT_D_S:
10472 check_cp1_registers(ctx, fd);
10474 TCGv_i32 fp32 = tcg_temp_new_i32();
10475 TCGv_i64 fp64 = tcg_temp_new_i64();
10477 gen_load_fpr32(ctx, fp32, fs);
10478 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10479 tcg_temp_free_i32(fp32);
10480 gen_store_fpr64(ctx, fp64, fd);
10481 tcg_temp_free_i64(fp64);
10483 break;
10484 case OPC_CVT_W_S:
10486 TCGv_i32 fp0 = tcg_temp_new_i32();
10488 gen_load_fpr32(ctx, fp0, fs);
10489 if (ctx->nan2008) {
10490 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10491 } else {
10492 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10494 gen_store_fpr32(ctx, fp0, fd);
10495 tcg_temp_free_i32(fp0);
10497 break;
10498 case OPC_CVT_L_S:
10499 check_cp1_64bitmode(ctx);
10501 TCGv_i32 fp32 = tcg_temp_new_i32();
10502 TCGv_i64 fp64 = tcg_temp_new_i64();
10504 gen_load_fpr32(ctx, fp32, fs);
10505 if (ctx->nan2008) {
10506 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10507 } else {
10508 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10510 tcg_temp_free_i32(fp32);
10511 gen_store_fpr64(ctx, fp64, fd);
10512 tcg_temp_free_i64(fp64);
10514 break;
10515 case OPC_CVT_PS_S:
10516 check_ps(ctx);
10518 TCGv_i64 fp64 = tcg_temp_new_i64();
10519 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10520 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10522 gen_load_fpr32(ctx, fp32_0, fs);
10523 gen_load_fpr32(ctx, fp32_1, ft);
10524 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10525 tcg_temp_free_i32(fp32_1);
10526 tcg_temp_free_i32(fp32_0);
10527 gen_store_fpr64(ctx, fp64, fd);
10528 tcg_temp_free_i64(fp64);
10530 break;
10531 case OPC_CMP_F_S:
10532 case OPC_CMP_UN_S:
10533 case OPC_CMP_EQ_S:
10534 case OPC_CMP_UEQ_S:
10535 case OPC_CMP_OLT_S:
10536 case OPC_CMP_ULT_S:
10537 case OPC_CMP_OLE_S:
10538 case OPC_CMP_ULE_S:
10539 case OPC_CMP_SF_S:
10540 case OPC_CMP_NGLE_S:
10541 case OPC_CMP_SEQ_S:
10542 case OPC_CMP_NGL_S:
10543 case OPC_CMP_LT_S:
10544 case OPC_CMP_NGE_S:
10545 case OPC_CMP_LE_S:
10546 case OPC_CMP_NGT_S:
10547 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10548 if (ctx->opcode & (1 << 6)) {
10549 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
10550 } else {
10551 gen_cmp_s(ctx, func - 48, ft, fs, cc);
10553 break;
10554 case OPC_ADD_D:
10555 check_cp1_registers(ctx, fs | ft | fd);
10557 TCGv_i64 fp0 = tcg_temp_new_i64();
10558 TCGv_i64 fp1 = tcg_temp_new_i64();
10560 gen_load_fpr64(ctx, fp0, fs);
10561 gen_load_fpr64(ctx, fp1, ft);
10562 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10563 tcg_temp_free_i64(fp1);
10564 gen_store_fpr64(ctx, fp0, fd);
10565 tcg_temp_free_i64(fp0);
10567 break;
10568 case OPC_SUB_D:
10569 check_cp1_registers(ctx, fs | ft | fd);
10571 TCGv_i64 fp0 = tcg_temp_new_i64();
10572 TCGv_i64 fp1 = tcg_temp_new_i64();
10574 gen_load_fpr64(ctx, fp0, fs);
10575 gen_load_fpr64(ctx, fp1, ft);
10576 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10577 tcg_temp_free_i64(fp1);
10578 gen_store_fpr64(ctx, fp0, fd);
10579 tcg_temp_free_i64(fp0);
10581 break;
10582 case OPC_MUL_D:
10583 check_cp1_registers(ctx, fs | ft | fd);
10585 TCGv_i64 fp0 = tcg_temp_new_i64();
10586 TCGv_i64 fp1 = tcg_temp_new_i64();
10588 gen_load_fpr64(ctx, fp0, fs);
10589 gen_load_fpr64(ctx, fp1, ft);
10590 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10591 tcg_temp_free_i64(fp1);
10592 gen_store_fpr64(ctx, fp0, fd);
10593 tcg_temp_free_i64(fp0);
10595 break;
10596 case OPC_DIV_D:
10597 check_cp1_registers(ctx, fs | ft | fd);
10599 TCGv_i64 fp0 = tcg_temp_new_i64();
10600 TCGv_i64 fp1 = tcg_temp_new_i64();
10602 gen_load_fpr64(ctx, fp0, fs);
10603 gen_load_fpr64(ctx, fp1, ft);
10604 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10605 tcg_temp_free_i64(fp1);
10606 gen_store_fpr64(ctx, fp0, fd);
10607 tcg_temp_free_i64(fp0);
10609 break;
10610 case OPC_SQRT_D:
10611 check_cp1_registers(ctx, fs | fd);
10613 TCGv_i64 fp0 = tcg_temp_new_i64();
10615 gen_load_fpr64(ctx, fp0, fs);
10616 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10617 gen_store_fpr64(ctx, fp0, fd);
10618 tcg_temp_free_i64(fp0);
10620 break;
10621 case OPC_ABS_D:
10622 check_cp1_registers(ctx, fs | fd);
10624 TCGv_i64 fp0 = tcg_temp_new_i64();
10626 gen_load_fpr64(ctx, fp0, fs);
10627 if (ctx->abs2008) {
10628 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10629 } else {
10630 gen_helper_float_abs_d(fp0, fp0);
10632 gen_store_fpr64(ctx, fp0, fd);
10633 tcg_temp_free_i64(fp0);
10635 break;
10636 case OPC_MOV_D:
10637 check_cp1_registers(ctx, fs | fd);
10639 TCGv_i64 fp0 = tcg_temp_new_i64();
10641 gen_load_fpr64(ctx, fp0, fs);
10642 gen_store_fpr64(ctx, fp0, fd);
10643 tcg_temp_free_i64(fp0);
10645 break;
10646 case OPC_NEG_D:
10647 check_cp1_registers(ctx, fs | fd);
10649 TCGv_i64 fp0 = tcg_temp_new_i64();
10651 gen_load_fpr64(ctx, fp0, fs);
10652 if (ctx->abs2008) {
10653 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10654 } else {
10655 gen_helper_float_chs_d(fp0, fp0);
10657 gen_store_fpr64(ctx, fp0, fd);
10658 tcg_temp_free_i64(fp0);
10660 break;
10661 case OPC_ROUND_L_D:
10662 check_cp1_64bitmode(ctx);
10664 TCGv_i64 fp0 = tcg_temp_new_i64();
10666 gen_load_fpr64(ctx, fp0, fs);
10667 if (ctx->nan2008) {
10668 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10669 } else {
10670 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10672 gen_store_fpr64(ctx, fp0, fd);
10673 tcg_temp_free_i64(fp0);
10675 break;
10676 case OPC_TRUNC_L_D:
10677 check_cp1_64bitmode(ctx);
10679 TCGv_i64 fp0 = tcg_temp_new_i64();
10681 gen_load_fpr64(ctx, fp0, fs);
10682 if (ctx->nan2008) {
10683 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10684 } else {
10685 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10687 gen_store_fpr64(ctx, fp0, fd);
10688 tcg_temp_free_i64(fp0);
10690 break;
10691 case OPC_CEIL_L_D:
10692 check_cp1_64bitmode(ctx);
10694 TCGv_i64 fp0 = tcg_temp_new_i64();
10696 gen_load_fpr64(ctx, fp0, fs);
10697 if (ctx->nan2008) {
10698 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10699 } else {
10700 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10702 gen_store_fpr64(ctx, fp0, fd);
10703 tcg_temp_free_i64(fp0);
10705 break;
10706 case OPC_FLOOR_L_D:
10707 check_cp1_64bitmode(ctx);
10709 TCGv_i64 fp0 = tcg_temp_new_i64();
10711 gen_load_fpr64(ctx, fp0, fs);
10712 if (ctx->nan2008) {
10713 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10714 } else {
10715 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10717 gen_store_fpr64(ctx, fp0, fd);
10718 tcg_temp_free_i64(fp0);
10720 break;
10721 case OPC_ROUND_W_D:
10722 check_cp1_registers(ctx, fs);
10724 TCGv_i32 fp32 = tcg_temp_new_i32();
10725 TCGv_i64 fp64 = tcg_temp_new_i64();
10727 gen_load_fpr64(ctx, fp64, fs);
10728 if (ctx->nan2008) {
10729 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10730 } else {
10731 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10733 tcg_temp_free_i64(fp64);
10734 gen_store_fpr32(ctx, fp32, fd);
10735 tcg_temp_free_i32(fp32);
10737 break;
10738 case OPC_TRUNC_W_D:
10739 check_cp1_registers(ctx, fs);
10741 TCGv_i32 fp32 = tcg_temp_new_i32();
10742 TCGv_i64 fp64 = tcg_temp_new_i64();
10744 gen_load_fpr64(ctx, fp64, fs);
10745 if (ctx->nan2008) {
10746 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10747 } else {
10748 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10750 tcg_temp_free_i64(fp64);
10751 gen_store_fpr32(ctx, fp32, fd);
10752 tcg_temp_free_i32(fp32);
10754 break;
10755 case OPC_CEIL_W_D:
10756 check_cp1_registers(ctx, fs);
10758 TCGv_i32 fp32 = tcg_temp_new_i32();
10759 TCGv_i64 fp64 = tcg_temp_new_i64();
10761 gen_load_fpr64(ctx, fp64, fs);
10762 if (ctx->nan2008) {
10763 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10764 } else {
10765 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10767 tcg_temp_free_i64(fp64);
10768 gen_store_fpr32(ctx, fp32, fd);
10769 tcg_temp_free_i32(fp32);
10771 break;
10772 case OPC_FLOOR_W_D:
10773 check_cp1_registers(ctx, fs);
10775 TCGv_i32 fp32 = tcg_temp_new_i32();
10776 TCGv_i64 fp64 = tcg_temp_new_i64();
10778 gen_load_fpr64(ctx, fp64, fs);
10779 if (ctx->nan2008) {
10780 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10781 } else {
10782 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10784 tcg_temp_free_i64(fp64);
10785 gen_store_fpr32(ctx, fp32, fd);
10786 tcg_temp_free_i32(fp32);
10788 break;
10789 case OPC_SEL_D:
10790 check_insn(ctx, ISA_MIPS_R6);
10791 gen_sel_d(ctx, op1, fd, ft, fs);
10792 break;
10793 case OPC_SELEQZ_D:
10794 check_insn(ctx, ISA_MIPS_R6);
10795 gen_sel_d(ctx, op1, fd, ft, fs);
10796 break;
10797 case OPC_SELNEZ_D:
10798 check_insn(ctx, ISA_MIPS_R6);
10799 gen_sel_d(ctx, op1, fd, ft, fs);
10800 break;
10801 case OPC_MOVCF_D:
10802 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10803 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10804 break;
10805 case OPC_MOVZ_D:
10806 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10808 TCGLabel *l1 = gen_new_label();
10809 TCGv_i64 fp0;
10811 if (ft != 0) {
10812 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10814 fp0 = tcg_temp_new_i64();
10815 gen_load_fpr64(ctx, fp0, fs);
10816 gen_store_fpr64(ctx, fp0, fd);
10817 tcg_temp_free_i64(fp0);
10818 gen_set_label(l1);
10820 break;
10821 case OPC_MOVN_D:
10822 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10824 TCGLabel *l1 = gen_new_label();
10825 TCGv_i64 fp0;
10827 if (ft != 0) {
10828 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10829 fp0 = tcg_temp_new_i64();
10830 gen_load_fpr64(ctx, fp0, fs);
10831 gen_store_fpr64(ctx, fp0, fd);
10832 tcg_temp_free_i64(fp0);
10833 gen_set_label(l1);
10836 break;
10837 case OPC_RECIP_D:
10838 check_cp1_registers(ctx, fs | fd);
10840 TCGv_i64 fp0 = tcg_temp_new_i64();
10842 gen_load_fpr64(ctx, fp0, fs);
10843 gen_helper_float_recip_d(fp0, cpu_env, fp0);
10844 gen_store_fpr64(ctx, fp0, fd);
10845 tcg_temp_free_i64(fp0);
10847 break;
10848 case OPC_RSQRT_D:
10849 check_cp1_registers(ctx, fs | fd);
10851 TCGv_i64 fp0 = tcg_temp_new_i64();
10853 gen_load_fpr64(ctx, fp0, fs);
10854 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
10855 gen_store_fpr64(ctx, fp0, fd);
10856 tcg_temp_free_i64(fp0);
10858 break;
10859 case OPC_MADDF_D:
10860 check_insn(ctx, ISA_MIPS_R6);
10862 TCGv_i64 fp0 = tcg_temp_new_i64();
10863 TCGv_i64 fp1 = tcg_temp_new_i64();
10864 TCGv_i64 fp2 = tcg_temp_new_i64();
10865 gen_load_fpr64(ctx, fp0, fs);
10866 gen_load_fpr64(ctx, fp1, ft);
10867 gen_load_fpr64(ctx, fp2, fd);
10868 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
10869 gen_store_fpr64(ctx, fp2, fd);
10870 tcg_temp_free_i64(fp2);
10871 tcg_temp_free_i64(fp1);
10872 tcg_temp_free_i64(fp0);
10874 break;
10875 case OPC_MSUBF_D:
10876 check_insn(ctx, ISA_MIPS_R6);
10878 TCGv_i64 fp0 = tcg_temp_new_i64();
10879 TCGv_i64 fp1 = tcg_temp_new_i64();
10880 TCGv_i64 fp2 = tcg_temp_new_i64();
10881 gen_load_fpr64(ctx, fp0, fs);
10882 gen_load_fpr64(ctx, fp1, ft);
10883 gen_load_fpr64(ctx, fp2, fd);
10884 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
10885 gen_store_fpr64(ctx, fp2, fd);
10886 tcg_temp_free_i64(fp2);
10887 tcg_temp_free_i64(fp1);
10888 tcg_temp_free_i64(fp0);
10890 break;
10891 case OPC_RINT_D:
10892 check_insn(ctx, ISA_MIPS_R6);
10894 TCGv_i64 fp0 = tcg_temp_new_i64();
10895 gen_load_fpr64(ctx, fp0, fs);
10896 gen_helper_float_rint_d(fp0, cpu_env, fp0);
10897 gen_store_fpr64(ctx, fp0, fd);
10898 tcg_temp_free_i64(fp0);
10900 break;
10901 case OPC_CLASS_D:
10902 check_insn(ctx, ISA_MIPS_R6);
10904 TCGv_i64 fp0 = tcg_temp_new_i64();
10905 gen_load_fpr64(ctx, fp0, fs);
10906 gen_helper_float_class_d(fp0, cpu_env, fp0);
10907 gen_store_fpr64(ctx, fp0, fd);
10908 tcg_temp_free_i64(fp0);
10910 break;
10911 case OPC_MIN_D: /* OPC_RECIP2_D */
10912 if (ctx->insn_flags & ISA_MIPS_R6) {
10913 /* OPC_MIN_D */
10914 TCGv_i64 fp0 = tcg_temp_new_i64();
10915 TCGv_i64 fp1 = tcg_temp_new_i64();
10916 gen_load_fpr64(ctx, fp0, fs);
10917 gen_load_fpr64(ctx, fp1, ft);
10918 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
10919 gen_store_fpr64(ctx, fp1, fd);
10920 tcg_temp_free_i64(fp1);
10921 tcg_temp_free_i64(fp0);
10922 } else {
10923 /* OPC_RECIP2_D */
10924 check_cp1_64bitmode(ctx);
10926 TCGv_i64 fp0 = tcg_temp_new_i64();
10927 TCGv_i64 fp1 = tcg_temp_new_i64();
10929 gen_load_fpr64(ctx, fp0, fs);
10930 gen_load_fpr64(ctx, fp1, ft);
10931 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
10932 tcg_temp_free_i64(fp1);
10933 gen_store_fpr64(ctx, fp0, fd);
10934 tcg_temp_free_i64(fp0);
10937 break;
10938 case OPC_MINA_D: /* OPC_RECIP1_D */
10939 if (ctx->insn_flags & ISA_MIPS_R6) {
10940 /* OPC_MINA_D */
10941 TCGv_i64 fp0 = tcg_temp_new_i64();
10942 TCGv_i64 fp1 = tcg_temp_new_i64();
10943 gen_load_fpr64(ctx, fp0, fs);
10944 gen_load_fpr64(ctx, fp1, ft);
10945 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
10946 gen_store_fpr64(ctx, fp1, fd);
10947 tcg_temp_free_i64(fp1);
10948 tcg_temp_free_i64(fp0);
10949 } else {
10950 /* OPC_RECIP1_D */
10951 check_cp1_64bitmode(ctx);
10953 TCGv_i64 fp0 = tcg_temp_new_i64();
10955 gen_load_fpr64(ctx, fp0, fs);
10956 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
10957 gen_store_fpr64(ctx, fp0, fd);
10958 tcg_temp_free_i64(fp0);
10961 break;
10962 case OPC_MAX_D: /* OPC_RSQRT1_D */
10963 if (ctx->insn_flags & ISA_MIPS_R6) {
10964 /* OPC_MAX_D */
10965 TCGv_i64 fp0 = tcg_temp_new_i64();
10966 TCGv_i64 fp1 = tcg_temp_new_i64();
10967 gen_load_fpr64(ctx, fp0, fs);
10968 gen_load_fpr64(ctx, fp1, ft);
10969 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
10970 gen_store_fpr64(ctx, fp1, fd);
10971 tcg_temp_free_i64(fp1);
10972 tcg_temp_free_i64(fp0);
10973 } else {
10974 /* OPC_RSQRT1_D */
10975 check_cp1_64bitmode(ctx);
10977 TCGv_i64 fp0 = tcg_temp_new_i64();
10979 gen_load_fpr64(ctx, fp0, fs);
10980 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
10981 gen_store_fpr64(ctx, fp0, fd);
10982 tcg_temp_free_i64(fp0);
10985 break;
10986 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10987 if (ctx->insn_flags & ISA_MIPS_R6) {
10988 /* OPC_MAXA_D */
10989 TCGv_i64 fp0 = tcg_temp_new_i64();
10990 TCGv_i64 fp1 = tcg_temp_new_i64();
10991 gen_load_fpr64(ctx, fp0, fs);
10992 gen_load_fpr64(ctx, fp1, ft);
10993 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10994 gen_store_fpr64(ctx, fp1, fd);
10995 tcg_temp_free_i64(fp1);
10996 tcg_temp_free_i64(fp0);
10997 } else {
10998 /* OPC_RSQRT2_D */
10999 check_cp1_64bitmode(ctx);
11001 TCGv_i64 fp0 = tcg_temp_new_i64();
11002 TCGv_i64 fp1 = tcg_temp_new_i64();
11004 gen_load_fpr64(ctx, fp0, fs);
11005 gen_load_fpr64(ctx, fp1, ft);
11006 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11007 tcg_temp_free_i64(fp1);
11008 gen_store_fpr64(ctx, fp0, fd);
11009 tcg_temp_free_i64(fp0);
11012 break;
11013 case OPC_CMP_F_D:
11014 case OPC_CMP_UN_D:
11015 case OPC_CMP_EQ_D:
11016 case OPC_CMP_UEQ_D:
11017 case OPC_CMP_OLT_D:
11018 case OPC_CMP_ULT_D:
11019 case OPC_CMP_OLE_D:
11020 case OPC_CMP_ULE_D:
11021 case OPC_CMP_SF_D:
11022 case OPC_CMP_NGLE_D:
11023 case OPC_CMP_SEQ_D:
11024 case OPC_CMP_NGL_D:
11025 case OPC_CMP_LT_D:
11026 case OPC_CMP_NGE_D:
11027 case OPC_CMP_LE_D:
11028 case OPC_CMP_NGT_D:
11029 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11030 if (ctx->opcode & (1 << 6)) {
11031 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
11032 } else {
11033 gen_cmp_d(ctx, func - 48, ft, fs, cc);
11035 break;
11036 case OPC_CVT_S_D:
11037 check_cp1_registers(ctx, fs);
11039 TCGv_i32 fp32 = tcg_temp_new_i32();
11040 TCGv_i64 fp64 = tcg_temp_new_i64();
11042 gen_load_fpr64(ctx, fp64, fs);
11043 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11044 tcg_temp_free_i64(fp64);
11045 gen_store_fpr32(ctx, fp32, fd);
11046 tcg_temp_free_i32(fp32);
11048 break;
11049 case OPC_CVT_W_D:
11050 check_cp1_registers(ctx, fs);
11052 TCGv_i32 fp32 = tcg_temp_new_i32();
11053 TCGv_i64 fp64 = tcg_temp_new_i64();
11055 gen_load_fpr64(ctx, fp64, fs);
11056 if (ctx->nan2008) {
11057 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11058 } else {
11059 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11061 tcg_temp_free_i64(fp64);
11062 gen_store_fpr32(ctx, fp32, fd);
11063 tcg_temp_free_i32(fp32);
11065 break;
11066 case OPC_CVT_L_D:
11067 check_cp1_64bitmode(ctx);
11069 TCGv_i64 fp0 = tcg_temp_new_i64();
11071 gen_load_fpr64(ctx, fp0, fs);
11072 if (ctx->nan2008) {
11073 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11074 } else {
11075 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11077 gen_store_fpr64(ctx, fp0, fd);
11078 tcg_temp_free_i64(fp0);
11080 break;
11081 case OPC_CVT_S_W:
11083 TCGv_i32 fp0 = tcg_temp_new_i32();
11085 gen_load_fpr32(ctx, fp0, fs);
11086 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11087 gen_store_fpr32(ctx, fp0, fd);
11088 tcg_temp_free_i32(fp0);
11090 break;
11091 case OPC_CVT_D_W:
11092 check_cp1_registers(ctx, fd);
11094 TCGv_i32 fp32 = tcg_temp_new_i32();
11095 TCGv_i64 fp64 = tcg_temp_new_i64();
11097 gen_load_fpr32(ctx, fp32, fs);
11098 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11099 tcg_temp_free_i32(fp32);
11100 gen_store_fpr64(ctx, fp64, fd);
11101 tcg_temp_free_i64(fp64);
11103 break;
11104 case OPC_CVT_S_L:
11105 check_cp1_64bitmode(ctx);
11107 TCGv_i32 fp32 = tcg_temp_new_i32();
11108 TCGv_i64 fp64 = tcg_temp_new_i64();
11110 gen_load_fpr64(ctx, fp64, fs);
11111 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11112 tcg_temp_free_i64(fp64);
11113 gen_store_fpr32(ctx, fp32, fd);
11114 tcg_temp_free_i32(fp32);
11116 break;
11117 case OPC_CVT_D_L:
11118 check_cp1_64bitmode(ctx);
11120 TCGv_i64 fp0 = tcg_temp_new_i64();
11122 gen_load_fpr64(ctx, fp0, fs);
11123 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11124 gen_store_fpr64(ctx, fp0, fd);
11125 tcg_temp_free_i64(fp0);
11127 break;
11128 case OPC_CVT_PS_PW:
11129 check_ps(ctx);
11131 TCGv_i64 fp0 = tcg_temp_new_i64();
11133 gen_load_fpr64(ctx, fp0, fs);
11134 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11135 gen_store_fpr64(ctx, fp0, fd);
11136 tcg_temp_free_i64(fp0);
11138 break;
11139 case OPC_ADD_PS:
11140 check_ps(ctx);
11142 TCGv_i64 fp0 = tcg_temp_new_i64();
11143 TCGv_i64 fp1 = tcg_temp_new_i64();
11145 gen_load_fpr64(ctx, fp0, fs);
11146 gen_load_fpr64(ctx, fp1, ft);
11147 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11148 tcg_temp_free_i64(fp1);
11149 gen_store_fpr64(ctx, fp0, fd);
11150 tcg_temp_free_i64(fp0);
11152 break;
11153 case OPC_SUB_PS:
11154 check_ps(ctx);
11156 TCGv_i64 fp0 = tcg_temp_new_i64();
11157 TCGv_i64 fp1 = tcg_temp_new_i64();
11159 gen_load_fpr64(ctx, fp0, fs);
11160 gen_load_fpr64(ctx, fp1, ft);
11161 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11162 tcg_temp_free_i64(fp1);
11163 gen_store_fpr64(ctx, fp0, fd);
11164 tcg_temp_free_i64(fp0);
11166 break;
11167 case OPC_MUL_PS:
11168 check_ps(ctx);
11170 TCGv_i64 fp0 = tcg_temp_new_i64();
11171 TCGv_i64 fp1 = tcg_temp_new_i64();
11173 gen_load_fpr64(ctx, fp0, fs);
11174 gen_load_fpr64(ctx, fp1, ft);
11175 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11176 tcg_temp_free_i64(fp1);
11177 gen_store_fpr64(ctx, fp0, fd);
11178 tcg_temp_free_i64(fp0);
11180 break;
11181 case OPC_ABS_PS:
11182 check_ps(ctx);
11184 TCGv_i64 fp0 = tcg_temp_new_i64();
11186 gen_load_fpr64(ctx, fp0, fs);
11187 gen_helper_float_abs_ps(fp0, fp0);
11188 gen_store_fpr64(ctx, fp0, fd);
11189 tcg_temp_free_i64(fp0);
11191 break;
11192 case OPC_MOV_PS:
11193 check_ps(ctx);
11195 TCGv_i64 fp0 = tcg_temp_new_i64();
11197 gen_load_fpr64(ctx, fp0, fs);
11198 gen_store_fpr64(ctx, fp0, fd);
11199 tcg_temp_free_i64(fp0);
11201 break;
11202 case OPC_NEG_PS:
11203 check_ps(ctx);
11205 TCGv_i64 fp0 = tcg_temp_new_i64();
11207 gen_load_fpr64(ctx, fp0, fs);
11208 gen_helper_float_chs_ps(fp0, fp0);
11209 gen_store_fpr64(ctx, fp0, fd);
11210 tcg_temp_free_i64(fp0);
11212 break;
11213 case OPC_MOVCF_PS:
11214 check_ps(ctx);
11215 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11216 break;
11217 case OPC_MOVZ_PS:
11218 check_ps(ctx);
11220 TCGLabel *l1 = gen_new_label();
11221 TCGv_i64 fp0;
11223 if (ft != 0) {
11224 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11226 fp0 = tcg_temp_new_i64();
11227 gen_load_fpr64(ctx, fp0, fs);
11228 gen_store_fpr64(ctx, fp0, fd);
11229 tcg_temp_free_i64(fp0);
11230 gen_set_label(l1);
11232 break;
11233 case OPC_MOVN_PS:
11234 check_ps(ctx);
11236 TCGLabel *l1 = gen_new_label();
11237 TCGv_i64 fp0;
11239 if (ft != 0) {
11240 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11241 fp0 = tcg_temp_new_i64();
11242 gen_load_fpr64(ctx, fp0, fs);
11243 gen_store_fpr64(ctx, fp0, fd);
11244 tcg_temp_free_i64(fp0);
11245 gen_set_label(l1);
11248 break;
11249 case OPC_ADDR_PS:
11250 check_ps(ctx);
11252 TCGv_i64 fp0 = tcg_temp_new_i64();
11253 TCGv_i64 fp1 = tcg_temp_new_i64();
11255 gen_load_fpr64(ctx, fp0, ft);
11256 gen_load_fpr64(ctx, fp1, fs);
11257 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11258 tcg_temp_free_i64(fp1);
11259 gen_store_fpr64(ctx, fp0, fd);
11260 tcg_temp_free_i64(fp0);
11262 break;
11263 case OPC_MULR_PS:
11264 check_ps(ctx);
11266 TCGv_i64 fp0 = tcg_temp_new_i64();
11267 TCGv_i64 fp1 = tcg_temp_new_i64();
11269 gen_load_fpr64(ctx, fp0, ft);
11270 gen_load_fpr64(ctx, fp1, fs);
11271 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11272 tcg_temp_free_i64(fp1);
11273 gen_store_fpr64(ctx, fp0, fd);
11274 tcg_temp_free_i64(fp0);
11276 break;
11277 case OPC_RECIP2_PS:
11278 check_ps(ctx);
11280 TCGv_i64 fp0 = tcg_temp_new_i64();
11281 TCGv_i64 fp1 = tcg_temp_new_i64();
11283 gen_load_fpr64(ctx, fp0, fs);
11284 gen_load_fpr64(ctx, fp1, ft);
11285 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11286 tcg_temp_free_i64(fp1);
11287 gen_store_fpr64(ctx, fp0, fd);
11288 tcg_temp_free_i64(fp0);
11290 break;
11291 case OPC_RECIP1_PS:
11292 check_ps(ctx);
11294 TCGv_i64 fp0 = tcg_temp_new_i64();
11296 gen_load_fpr64(ctx, fp0, fs);
11297 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11298 gen_store_fpr64(ctx, fp0, fd);
11299 tcg_temp_free_i64(fp0);
11301 break;
11302 case OPC_RSQRT1_PS:
11303 check_ps(ctx);
11305 TCGv_i64 fp0 = tcg_temp_new_i64();
11307 gen_load_fpr64(ctx, fp0, fs);
11308 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11309 gen_store_fpr64(ctx, fp0, fd);
11310 tcg_temp_free_i64(fp0);
11312 break;
11313 case OPC_RSQRT2_PS:
11314 check_ps(ctx);
11316 TCGv_i64 fp0 = tcg_temp_new_i64();
11317 TCGv_i64 fp1 = tcg_temp_new_i64();
11319 gen_load_fpr64(ctx, fp0, fs);
11320 gen_load_fpr64(ctx, fp1, ft);
11321 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11322 tcg_temp_free_i64(fp1);
11323 gen_store_fpr64(ctx, fp0, fd);
11324 tcg_temp_free_i64(fp0);
11326 break;
11327 case OPC_CVT_S_PU:
11328 check_cp1_64bitmode(ctx);
11330 TCGv_i32 fp0 = tcg_temp_new_i32();
11332 gen_load_fpr32h(ctx, fp0, fs);
11333 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11334 gen_store_fpr32(ctx, fp0, fd);
11335 tcg_temp_free_i32(fp0);
11337 break;
11338 case OPC_CVT_PW_PS:
11339 check_ps(ctx);
11341 TCGv_i64 fp0 = tcg_temp_new_i64();
11343 gen_load_fpr64(ctx, fp0, fs);
11344 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11345 gen_store_fpr64(ctx, fp0, fd);
11346 tcg_temp_free_i64(fp0);
11348 break;
11349 case OPC_CVT_S_PL:
11350 check_cp1_64bitmode(ctx);
11352 TCGv_i32 fp0 = tcg_temp_new_i32();
11354 gen_load_fpr32(ctx, fp0, fs);
11355 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11356 gen_store_fpr32(ctx, fp0, fd);
11357 tcg_temp_free_i32(fp0);
11359 break;
11360 case OPC_PLL_PS:
11361 check_ps(ctx);
11363 TCGv_i32 fp0 = tcg_temp_new_i32();
11364 TCGv_i32 fp1 = tcg_temp_new_i32();
11366 gen_load_fpr32(ctx, fp0, fs);
11367 gen_load_fpr32(ctx, fp1, ft);
11368 gen_store_fpr32h(ctx, fp0, fd);
11369 gen_store_fpr32(ctx, fp1, fd);
11370 tcg_temp_free_i32(fp0);
11371 tcg_temp_free_i32(fp1);
11373 break;
11374 case OPC_PLU_PS:
11375 check_ps(ctx);
11377 TCGv_i32 fp0 = tcg_temp_new_i32();
11378 TCGv_i32 fp1 = tcg_temp_new_i32();
11380 gen_load_fpr32(ctx, fp0, fs);
11381 gen_load_fpr32h(ctx, fp1, ft);
11382 gen_store_fpr32(ctx, fp1, fd);
11383 gen_store_fpr32h(ctx, fp0, fd);
11384 tcg_temp_free_i32(fp0);
11385 tcg_temp_free_i32(fp1);
11387 break;
11388 case OPC_PUL_PS:
11389 check_ps(ctx);
11391 TCGv_i32 fp0 = tcg_temp_new_i32();
11392 TCGv_i32 fp1 = tcg_temp_new_i32();
11394 gen_load_fpr32h(ctx, fp0, fs);
11395 gen_load_fpr32(ctx, fp1, ft);
11396 gen_store_fpr32(ctx, fp1, fd);
11397 gen_store_fpr32h(ctx, fp0, fd);
11398 tcg_temp_free_i32(fp0);
11399 tcg_temp_free_i32(fp1);
11401 break;
11402 case OPC_PUU_PS:
11403 check_ps(ctx);
11405 TCGv_i32 fp0 = tcg_temp_new_i32();
11406 TCGv_i32 fp1 = tcg_temp_new_i32();
11408 gen_load_fpr32h(ctx, fp0, fs);
11409 gen_load_fpr32h(ctx, fp1, ft);
11410 gen_store_fpr32(ctx, fp1, fd);
11411 gen_store_fpr32h(ctx, fp0, fd);
11412 tcg_temp_free_i32(fp0);
11413 tcg_temp_free_i32(fp1);
11415 break;
11416 case OPC_CMP_F_PS:
11417 case OPC_CMP_UN_PS:
11418 case OPC_CMP_EQ_PS:
11419 case OPC_CMP_UEQ_PS:
11420 case OPC_CMP_OLT_PS:
11421 case OPC_CMP_ULT_PS:
11422 case OPC_CMP_OLE_PS:
11423 case OPC_CMP_ULE_PS:
11424 case OPC_CMP_SF_PS:
11425 case OPC_CMP_NGLE_PS:
11426 case OPC_CMP_SEQ_PS:
11427 case OPC_CMP_NGL_PS:
11428 case OPC_CMP_LT_PS:
11429 case OPC_CMP_NGE_PS:
11430 case OPC_CMP_LE_PS:
11431 case OPC_CMP_NGT_PS:
11432 if (ctx->opcode & (1 << 6)) {
11433 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
11434 } else {
11435 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
11437 break;
11438 default:
11439 MIPS_INVAL("farith");
11440 gen_reserved_instruction(ctx);
11441 return;
11445 /* Coprocessor 3 (FPU) */
11446 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
11447 int fd, int fs, int base, int index)
11449 TCGv t0 = tcg_temp_new();
11451 if (base == 0) {
11452 gen_load_gpr(t0, index);
11453 } else if (index == 0) {
11454 gen_load_gpr(t0, base);
11455 } else {
11456 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11459 * Don't do NOP if destination is zero: we must perform the actual
11460 * memory access.
11462 switch (opc) {
11463 case OPC_LWXC1:
11464 check_cop1x(ctx);
11466 TCGv_i32 fp0 = tcg_temp_new_i32();
11468 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11469 tcg_gen_trunc_tl_i32(fp0, t0);
11470 gen_store_fpr32(ctx, fp0, fd);
11471 tcg_temp_free_i32(fp0);
11473 break;
11474 case OPC_LDXC1:
11475 check_cop1x(ctx);
11476 check_cp1_registers(ctx, fd);
11478 TCGv_i64 fp0 = tcg_temp_new_i64();
11479 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11480 gen_store_fpr64(ctx, fp0, fd);
11481 tcg_temp_free_i64(fp0);
11483 break;
11484 case OPC_LUXC1:
11485 check_cp1_64bitmode(ctx);
11486 tcg_gen_andi_tl(t0, t0, ~0x7);
11488 TCGv_i64 fp0 = tcg_temp_new_i64();
11490 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11491 gen_store_fpr64(ctx, fp0, fd);
11492 tcg_temp_free_i64(fp0);
11494 break;
11495 case OPC_SWXC1:
11496 check_cop1x(ctx);
11498 TCGv_i32 fp0 = tcg_temp_new_i32();
11499 gen_load_fpr32(ctx, fp0, fs);
11500 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11501 tcg_temp_free_i32(fp0);
11503 break;
11504 case OPC_SDXC1:
11505 check_cop1x(ctx);
11506 check_cp1_registers(ctx, fs);
11508 TCGv_i64 fp0 = tcg_temp_new_i64();
11509 gen_load_fpr64(ctx, fp0, fs);
11510 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11511 tcg_temp_free_i64(fp0);
11513 break;
11514 case OPC_SUXC1:
11515 check_cp1_64bitmode(ctx);
11516 tcg_gen_andi_tl(t0, t0, ~0x7);
11518 TCGv_i64 fp0 = tcg_temp_new_i64();
11519 gen_load_fpr64(ctx, fp0, fs);
11520 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11521 tcg_temp_free_i64(fp0);
11523 break;
11525 tcg_temp_free(t0);
11528 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
11529 int fd, int fr, int fs, int ft)
11531 switch (opc) {
11532 case OPC_ALNV_PS:
11533 check_ps(ctx);
11535 TCGv t0 = tcg_temp_local_new();
11536 TCGv_i32 fp = tcg_temp_new_i32();
11537 TCGv_i32 fph = tcg_temp_new_i32();
11538 TCGLabel *l1 = gen_new_label();
11539 TCGLabel *l2 = gen_new_label();
11541 gen_load_gpr(t0, fr);
11542 tcg_gen_andi_tl(t0, t0, 0x7);
11544 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11545 gen_load_fpr32(ctx, fp, fs);
11546 gen_load_fpr32h(ctx, fph, fs);
11547 gen_store_fpr32(ctx, fp, fd);
11548 gen_store_fpr32h(ctx, fph, fd);
11549 tcg_gen_br(l2);
11550 gen_set_label(l1);
11551 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11552 tcg_temp_free(t0);
11553 #ifdef TARGET_WORDS_BIGENDIAN
11554 gen_load_fpr32(ctx, fp, fs);
11555 gen_load_fpr32h(ctx, fph, ft);
11556 gen_store_fpr32h(ctx, fp, fd);
11557 gen_store_fpr32(ctx, fph, fd);
11558 #else
11559 gen_load_fpr32h(ctx, fph, fs);
11560 gen_load_fpr32(ctx, fp, ft);
11561 gen_store_fpr32(ctx, fph, fd);
11562 gen_store_fpr32h(ctx, fp, fd);
11563 #endif
11564 gen_set_label(l2);
11565 tcg_temp_free_i32(fp);
11566 tcg_temp_free_i32(fph);
11568 break;
11569 case OPC_MADD_S:
11570 check_cop1x(ctx);
11572 TCGv_i32 fp0 = tcg_temp_new_i32();
11573 TCGv_i32 fp1 = tcg_temp_new_i32();
11574 TCGv_i32 fp2 = tcg_temp_new_i32();
11576 gen_load_fpr32(ctx, fp0, fs);
11577 gen_load_fpr32(ctx, fp1, ft);
11578 gen_load_fpr32(ctx, fp2, fr);
11579 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11580 tcg_temp_free_i32(fp0);
11581 tcg_temp_free_i32(fp1);
11582 gen_store_fpr32(ctx, fp2, fd);
11583 tcg_temp_free_i32(fp2);
11585 break;
11586 case OPC_MADD_D:
11587 check_cop1x(ctx);
11588 check_cp1_registers(ctx, fd | fs | ft | fr);
11590 TCGv_i64 fp0 = tcg_temp_new_i64();
11591 TCGv_i64 fp1 = tcg_temp_new_i64();
11592 TCGv_i64 fp2 = tcg_temp_new_i64();
11594 gen_load_fpr64(ctx, fp0, fs);
11595 gen_load_fpr64(ctx, fp1, ft);
11596 gen_load_fpr64(ctx, fp2, fr);
11597 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11598 tcg_temp_free_i64(fp0);
11599 tcg_temp_free_i64(fp1);
11600 gen_store_fpr64(ctx, fp2, fd);
11601 tcg_temp_free_i64(fp2);
11603 break;
11604 case OPC_MADD_PS:
11605 check_ps(ctx);
11607 TCGv_i64 fp0 = tcg_temp_new_i64();
11608 TCGv_i64 fp1 = tcg_temp_new_i64();
11609 TCGv_i64 fp2 = tcg_temp_new_i64();
11611 gen_load_fpr64(ctx, fp0, fs);
11612 gen_load_fpr64(ctx, fp1, ft);
11613 gen_load_fpr64(ctx, fp2, fr);
11614 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11615 tcg_temp_free_i64(fp0);
11616 tcg_temp_free_i64(fp1);
11617 gen_store_fpr64(ctx, fp2, fd);
11618 tcg_temp_free_i64(fp2);
11620 break;
11621 case OPC_MSUB_S:
11622 check_cop1x(ctx);
11624 TCGv_i32 fp0 = tcg_temp_new_i32();
11625 TCGv_i32 fp1 = tcg_temp_new_i32();
11626 TCGv_i32 fp2 = tcg_temp_new_i32();
11628 gen_load_fpr32(ctx, fp0, fs);
11629 gen_load_fpr32(ctx, fp1, ft);
11630 gen_load_fpr32(ctx, fp2, fr);
11631 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11632 tcg_temp_free_i32(fp0);
11633 tcg_temp_free_i32(fp1);
11634 gen_store_fpr32(ctx, fp2, fd);
11635 tcg_temp_free_i32(fp2);
11637 break;
11638 case OPC_MSUB_D:
11639 check_cop1x(ctx);
11640 check_cp1_registers(ctx, fd | fs | ft | fr);
11642 TCGv_i64 fp0 = tcg_temp_new_i64();
11643 TCGv_i64 fp1 = tcg_temp_new_i64();
11644 TCGv_i64 fp2 = tcg_temp_new_i64();
11646 gen_load_fpr64(ctx, fp0, fs);
11647 gen_load_fpr64(ctx, fp1, ft);
11648 gen_load_fpr64(ctx, fp2, fr);
11649 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11650 tcg_temp_free_i64(fp0);
11651 tcg_temp_free_i64(fp1);
11652 gen_store_fpr64(ctx, fp2, fd);
11653 tcg_temp_free_i64(fp2);
11655 break;
11656 case OPC_MSUB_PS:
11657 check_ps(ctx);
11659 TCGv_i64 fp0 = tcg_temp_new_i64();
11660 TCGv_i64 fp1 = tcg_temp_new_i64();
11661 TCGv_i64 fp2 = tcg_temp_new_i64();
11663 gen_load_fpr64(ctx, fp0, fs);
11664 gen_load_fpr64(ctx, fp1, ft);
11665 gen_load_fpr64(ctx, fp2, fr);
11666 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11667 tcg_temp_free_i64(fp0);
11668 tcg_temp_free_i64(fp1);
11669 gen_store_fpr64(ctx, fp2, fd);
11670 tcg_temp_free_i64(fp2);
11672 break;
11673 case OPC_NMADD_S:
11674 check_cop1x(ctx);
11676 TCGv_i32 fp0 = tcg_temp_new_i32();
11677 TCGv_i32 fp1 = tcg_temp_new_i32();
11678 TCGv_i32 fp2 = tcg_temp_new_i32();
11680 gen_load_fpr32(ctx, fp0, fs);
11681 gen_load_fpr32(ctx, fp1, ft);
11682 gen_load_fpr32(ctx, fp2, fr);
11683 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11684 tcg_temp_free_i32(fp0);
11685 tcg_temp_free_i32(fp1);
11686 gen_store_fpr32(ctx, fp2, fd);
11687 tcg_temp_free_i32(fp2);
11689 break;
11690 case OPC_NMADD_D:
11691 check_cop1x(ctx);
11692 check_cp1_registers(ctx, fd | fs | ft | fr);
11694 TCGv_i64 fp0 = tcg_temp_new_i64();
11695 TCGv_i64 fp1 = tcg_temp_new_i64();
11696 TCGv_i64 fp2 = tcg_temp_new_i64();
11698 gen_load_fpr64(ctx, fp0, fs);
11699 gen_load_fpr64(ctx, fp1, ft);
11700 gen_load_fpr64(ctx, fp2, fr);
11701 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11702 tcg_temp_free_i64(fp0);
11703 tcg_temp_free_i64(fp1);
11704 gen_store_fpr64(ctx, fp2, fd);
11705 tcg_temp_free_i64(fp2);
11707 break;
11708 case OPC_NMADD_PS:
11709 check_ps(ctx);
11711 TCGv_i64 fp0 = tcg_temp_new_i64();
11712 TCGv_i64 fp1 = tcg_temp_new_i64();
11713 TCGv_i64 fp2 = tcg_temp_new_i64();
11715 gen_load_fpr64(ctx, fp0, fs);
11716 gen_load_fpr64(ctx, fp1, ft);
11717 gen_load_fpr64(ctx, fp2, fr);
11718 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11719 tcg_temp_free_i64(fp0);
11720 tcg_temp_free_i64(fp1);
11721 gen_store_fpr64(ctx, fp2, fd);
11722 tcg_temp_free_i64(fp2);
11724 break;
11725 case OPC_NMSUB_S:
11726 check_cop1x(ctx);
11728 TCGv_i32 fp0 = tcg_temp_new_i32();
11729 TCGv_i32 fp1 = tcg_temp_new_i32();
11730 TCGv_i32 fp2 = tcg_temp_new_i32();
11732 gen_load_fpr32(ctx, fp0, fs);
11733 gen_load_fpr32(ctx, fp1, ft);
11734 gen_load_fpr32(ctx, fp2, fr);
11735 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11736 tcg_temp_free_i32(fp0);
11737 tcg_temp_free_i32(fp1);
11738 gen_store_fpr32(ctx, fp2, fd);
11739 tcg_temp_free_i32(fp2);
11741 break;
11742 case OPC_NMSUB_D:
11743 check_cop1x(ctx);
11744 check_cp1_registers(ctx, fd | fs | ft | fr);
11746 TCGv_i64 fp0 = tcg_temp_new_i64();
11747 TCGv_i64 fp1 = tcg_temp_new_i64();
11748 TCGv_i64 fp2 = tcg_temp_new_i64();
11750 gen_load_fpr64(ctx, fp0, fs);
11751 gen_load_fpr64(ctx, fp1, ft);
11752 gen_load_fpr64(ctx, fp2, fr);
11753 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11754 tcg_temp_free_i64(fp0);
11755 tcg_temp_free_i64(fp1);
11756 gen_store_fpr64(ctx, fp2, fd);
11757 tcg_temp_free_i64(fp2);
11759 break;
11760 case OPC_NMSUB_PS:
11761 check_ps(ctx);
11763 TCGv_i64 fp0 = tcg_temp_new_i64();
11764 TCGv_i64 fp1 = tcg_temp_new_i64();
11765 TCGv_i64 fp2 = tcg_temp_new_i64();
11767 gen_load_fpr64(ctx, fp0, fs);
11768 gen_load_fpr64(ctx, fp1, ft);
11769 gen_load_fpr64(ctx, fp2, fr);
11770 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11771 tcg_temp_free_i64(fp0);
11772 tcg_temp_free_i64(fp1);
11773 gen_store_fpr64(ctx, fp2, fd);
11774 tcg_temp_free_i64(fp2);
11776 break;
11777 default:
11778 MIPS_INVAL("flt3_arith");
11779 gen_reserved_instruction(ctx);
11780 return;
11784 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11786 TCGv t0;
11788 #if !defined(CONFIG_USER_ONLY)
11790 * The Linux kernel will emulate rdhwr if it's not supported natively.
11791 * Therefore only check the ISA in system mode.
11793 check_insn(ctx, ISA_MIPS_R2);
11794 #endif
11795 t0 = tcg_temp_new();
11797 switch (rd) {
11798 case 0:
11799 gen_helper_rdhwr_cpunum(t0, cpu_env);
11800 gen_store_gpr(t0, rt);
11801 break;
11802 case 1:
11803 gen_helper_rdhwr_synci_step(t0, cpu_env);
11804 gen_store_gpr(t0, rt);
11805 break;
11806 case 2:
11807 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11808 gen_io_start();
11810 gen_helper_rdhwr_cc(t0, cpu_env);
11811 gen_store_gpr(t0, rt);
11813 * Break the TB to be able to take timer interrupts immediately
11814 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
11815 * we break completely out of translated code.
11817 gen_save_pc(ctx->base.pc_next + 4);
11818 ctx->base.is_jmp = DISAS_EXIT;
11819 break;
11820 case 3:
11821 gen_helper_rdhwr_ccres(t0, cpu_env);
11822 gen_store_gpr(t0, rt);
11823 break;
11824 case 4:
11825 check_insn(ctx, ISA_MIPS_R6);
11826 if (sel != 0) {
11828 * Performance counter registers are not implemented other than
11829 * control register 0.
11831 generate_exception(ctx, EXCP_RI);
11833 gen_helper_rdhwr_performance(t0, cpu_env);
11834 gen_store_gpr(t0, rt);
11835 break;
11836 case 5:
11837 check_insn(ctx, ISA_MIPS_R6);
11838 gen_helper_rdhwr_xnp(t0, cpu_env);
11839 gen_store_gpr(t0, rt);
11840 break;
11841 case 29:
11842 #if defined(CONFIG_USER_ONLY)
11843 tcg_gen_ld_tl(t0, cpu_env,
11844 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11845 gen_store_gpr(t0, rt);
11846 break;
11847 #else
11848 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11849 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
11850 tcg_gen_ld_tl(t0, cpu_env,
11851 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11852 gen_store_gpr(t0, rt);
11853 } else {
11854 gen_reserved_instruction(ctx);
11856 break;
11857 #endif
11858 default: /* Invalid */
11859 MIPS_INVAL("rdhwr");
11860 gen_reserved_instruction(ctx);
11861 break;
11863 tcg_temp_free(t0);
11866 static inline void clear_branch_hflags(DisasContext *ctx)
11868 ctx->hflags &= ~MIPS_HFLAG_BMASK;
11869 if (ctx->base.is_jmp == DISAS_NEXT) {
11870 save_cpu_state(ctx, 0);
11871 } else {
11873 * It is not safe to save ctx->hflags as hflags may be changed
11874 * in execution time by the instruction in delay / forbidden slot.
11876 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11880 static void gen_branch(DisasContext *ctx, int insn_bytes)
11882 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11883 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
11884 /* Branches completion */
11885 clear_branch_hflags(ctx);
11886 ctx->base.is_jmp = DISAS_NORETURN;
11887 /* FIXME: Need to clear can_do_io. */
11888 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
11889 case MIPS_HFLAG_FBNSLOT:
11890 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
11891 break;
11892 case MIPS_HFLAG_B:
11893 /* unconditional branch */
11894 if (proc_hflags & MIPS_HFLAG_BX) {
11895 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11897 gen_goto_tb(ctx, 0, ctx->btarget);
11898 break;
11899 case MIPS_HFLAG_BL:
11900 /* blikely taken case */
11901 gen_goto_tb(ctx, 0, ctx->btarget);
11902 break;
11903 case MIPS_HFLAG_BC:
11904 /* Conditional branch */
11906 TCGLabel *l1 = gen_new_label();
11908 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11909 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
11910 gen_set_label(l1);
11911 gen_goto_tb(ctx, 0, ctx->btarget);
11913 break;
11914 case MIPS_HFLAG_BR:
11915 /* unconditional branch to register */
11916 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
11917 TCGv t0 = tcg_temp_new();
11918 TCGv_i32 t1 = tcg_temp_new_i32();
11920 tcg_gen_andi_tl(t0, btarget, 0x1);
11921 tcg_gen_trunc_tl_i32(t1, t0);
11922 tcg_temp_free(t0);
11923 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11924 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11925 tcg_gen_or_i32(hflags, hflags, t1);
11926 tcg_temp_free_i32(t1);
11928 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11929 } else {
11930 tcg_gen_mov_tl(cpu_PC, btarget);
11932 if (ctx->base.singlestep_enabled) {
11933 save_cpu_state(ctx, 0);
11934 gen_helper_raise_exception_debug(cpu_env);
11936 tcg_gen_lookup_and_goto_ptr();
11937 break;
11938 default:
11939 LOG_DISAS("unknown branch 0x%x\n", proc_hflags);
11940 gen_reserved_instruction(ctx);
11945 /* Compact Branches */
11946 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11947 int rs, int rt, int32_t offset)
11949 int bcond_compute = 0;
11950 TCGv t0 = tcg_temp_new();
11951 TCGv t1 = tcg_temp_new();
11952 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11954 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11955 #ifdef MIPS_DEBUG_DISAS
11956 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11957 "\n", ctx->base.pc_next);
11958 #endif
11959 gen_reserved_instruction(ctx);
11960 goto out;
11963 /* Load needed operands and calculate btarget */
11964 switch (opc) {
11965 /* compact branch */
11966 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11967 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11968 gen_load_gpr(t0, rs);
11969 gen_load_gpr(t1, rt);
11970 bcond_compute = 1;
11971 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11972 if (rs <= rt && rs == 0) {
11973 /* OPC_BEQZALC, OPC_BNEZALC */
11974 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11976 break;
11977 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11978 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11979 gen_load_gpr(t0, rs);
11980 gen_load_gpr(t1, rt);
11981 bcond_compute = 1;
11982 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11983 break;
11984 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11985 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11986 if (rs == 0 || rs == rt) {
11987 /* OPC_BLEZALC, OPC_BGEZALC */
11988 /* OPC_BGTZALC, OPC_BLTZALC */
11989 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11991 gen_load_gpr(t0, rs);
11992 gen_load_gpr(t1, rt);
11993 bcond_compute = 1;
11994 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11995 break;
11996 case OPC_BC:
11997 case OPC_BALC:
11998 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11999 break;
12000 case OPC_BEQZC:
12001 case OPC_BNEZC:
12002 if (rs != 0) {
12003 /* OPC_BEQZC, OPC_BNEZC */
12004 gen_load_gpr(t0, rs);
12005 bcond_compute = 1;
12006 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12007 } else {
12008 /* OPC_JIC, OPC_JIALC */
12009 TCGv tbase = tcg_temp_new();
12010 TCGv toffset = tcg_temp_new();
12012 gen_load_gpr(tbase, rt);
12013 tcg_gen_movi_tl(toffset, offset);
12014 gen_op_addr_add(ctx, btarget, tbase, toffset);
12015 tcg_temp_free(tbase);
12016 tcg_temp_free(toffset);
12018 break;
12019 default:
12020 MIPS_INVAL("Compact branch/jump");
12021 gen_reserved_instruction(ctx);
12022 goto out;
12025 if (bcond_compute == 0) {
12026 /* Unconditional compact branch */
12027 switch (opc) {
12028 case OPC_JIALC:
12029 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12030 /* Fallthrough */
12031 case OPC_JIC:
12032 ctx->hflags |= MIPS_HFLAG_BR;
12033 break;
12034 case OPC_BALC:
12035 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12036 /* Fallthrough */
12037 case OPC_BC:
12038 ctx->hflags |= MIPS_HFLAG_B;
12039 break;
12040 default:
12041 MIPS_INVAL("Compact branch/jump");
12042 gen_reserved_instruction(ctx);
12043 goto out;
12046 /* Generating branch here as compact branches don't have delay slot */
12047 gen_branch(ctx, 4);
12048 } else {
12049 /* Conditional compact branch */
12050 TCGLabel *fs = gen_new_label();
12051 save_cpu_state(ctx, 0);
12053 switch (opc) {
12054 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12055 if (rs == 0 && rt != 0) {
12056 /* OPC_BLEZALC */
12057 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12058 } else if (rs != 0 && rt != 0 && rs == rt) {
12059 /* OPC_BGEZALC */
12060 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12061 } else {
12062 /* OPC_BGEUC */
12063 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12065 break;
12066 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12067 if (rs == 0 && rt != 0) {
12068 /* OPC_BGTZALC */
12069 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12070 } else if (rs != 0 && rt != 0 && rs == rt) {
12071 /* OPC_BLTZALC */
12072 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12073 } else {
12074 /* OPC_BLTUC */
12075 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12077 break;
12078 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12079 if (rs == 0 && rt != 0) {
12080 /* OPC_BLEZC */
12081 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12082 } else if (rs != 0 && rt != 0 && rs == rt) {
12083 /* OPC_BGEZC */
12084 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12085 } else {
12086 /* OPC_BGEC */
12087 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12089 break;
12090 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12091 if (rs == 0 && rt != 0) {
12092 /* OPC_BGTZC */
12093 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12094 } else if (rs != 0 && rt != 0 && rs == rt) {
12095 /* OPC_BLTZC */
12096 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12097 } else {
12098 /* OPC_BLTC */
12099 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12101 break;
12102 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12103 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12104 if (rs >= rt) {
12105 /* OPC_BOVC, OPC_BNVC */
12106 TCGv t2 = tcg_temp_new();
12107 TCGv t3 = tcg_temp_new();
12108 TCGv t4 = tcg_temp_new();
12109 TCGv input_overflow = tcg_temp_new();
12111 gen_load_gpr(t0, rs);
12112 gen_load_gpr(t1, rt);
12113 tcg_gen_ext32s_tl(t2, t0);
12114 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12115 tcg_gen_ext32s_tl(t3, t1);
12116 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12117 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12119 tcg_gen_add_tl(t4, t2, t3);
12120 tcg_gen_ext32s_tl(t4, t4);
12121 tcg_gen_xor_tl(t2, t2, t3);
12122 tcg_gen_xor_tl(t3, t4, t3);
12123 tcg_gen_andc_tl(t2, t3, t2);
12124 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12125 tcg_gen_or_tl(t4, t4, input_overflow);
12126 if (opc == OPC_BOVC) {
12127 /* OPC_BOVC */
12128 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12129 } else {
12130 /* OPC_BNVC */
12131 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12133 tcg_temp_free(input_overflow);
12134 tcg_temp_free(t4);
12135 tcg_temp_free(t3);
12136 tcg_temp_free(t2);
12137 } else if (rs < rt && rs == 0) {
12138 /* OPC_BEQZALC, OPC_BNEZALC */
12139 if (opc == OPC_BEQZALC) {
12140 /* OPC_BEQZALC */
12141 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12142 } else {
12143 /* OPC_BNEZALC */
12144 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12146 } else {
12147 /* OPC_BEQC, OPC_BNEC */
12148 if (opc == OPC_BEQC) {
12149 /* OPC_BEQC */
12150 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12151 } else {
12152 /* OPC_BNEC */
12153 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12156 break;
12157 case OPC_BEQZC:
12158 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12159 break;
12160 case OPC_BNEZC:
12161 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12162 break;
12163 default:
12164 MIPS_INVAL("Compact conditional branch/jump");
12165 gen_reserved_instruction(ctx);
12166 goto out;
12169 /* Generating branch here as compact branches don't have delay slot */
12170 gen_goto_tb(ctx, 1, ctx->btarget);
12171 gen_set_label(fs);
12173 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12176 out:
12177 tcg_temp_free(t0);
12178 tcg_temp_free(t1);
12181 void gen_addiupc(DisasContext *ctx, int rx, int imm,
12182 int is_64_bit, int extended)
12184 TCGv t0;
12186 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12187 gen_reserved_instruction(ctx);
12188 return;
12191 t0 = tcg_temp_new();
12193 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12194 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12195 if (!is_64_bit) {
12196 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12199 tcg_temp_free(t0);
12202 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12203 int16_t offset)
12205 TCGv_i32 t0 = tcg_const_i32(op);
12206 TCGv t1 = tcg_temp_new();
12207 gen_base_offset_addr(ctx, t1, base, offset);
12208 gen_helper_cache(cpu_env, t1, t0);
12209 tcg_temp_free(t1);
12210 tcg_temp_free_i32(t0);
12213 static inline bool is_uhi(int sdbbp_code)
12215 #ifdef CONFIG_USER_ONLY
12216 return false;
12217 #else
12218 return semihosting_enabled() && sdbbp_code == 1;
12219 #endif
12222 #ifdef CONFIG_USER_ONLY
12223 /* The above should dead-code away any calls to this..*/
12224 static inline void gen_helper_do_semihosting(void *env)
12226 g_assert_not_reached();
12228 #endif
12230 void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
12232 TCGv t0 = tcg_temp_new();
12233 TCGv t1 = tcg_temp_new();
12235 gen_load_gpr(t0, base);
12237 if (index != 0) {
12238 gen_load_gpr(t1, index);
12239 tcg_gen_shli_tl(t1, t1, 2);
12240 gen_op_addr_add(ctx, t0, t1, t0);
12243 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12244 gen_store_gpr(t1, rd);
12246 tcg_temp_free(t0);
12247 tcg_temp_free(t1);
12250 static void gen_sync(int stype)
12252 TCGBar tcg_mo = TCG_BAR_SC;
12254 switch (stype) {
12255 case 0x4: /* SYNC_WMB */
12256 tcg_mo |= TCG_MO_ST_ST;
12257 break;
12258 case 0x10: /* SYNC_MB */
12259 tcg_mo |= TCG_MO_ALL;
12260 break;
12261 case 0x11: /* SYNC_ACQUIRE */
12262 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
12263 break;
12264 case 0x12: /* SYNC_RELEASE */
12265 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
12266 break;
12267 case 0x13: /* SYNC_RMB */
12268 tcg_mo |= TCG_MO_LD_LD;
12269 break;
12270 default:
12271 tcg_mo |= TCG_MO_ALL;
12272 break;
12275 tcg_gen_mb(tcg_mo);
12278 /* ISA extensions (ASEs) */
12280 /* MIPS16 extension to MIPS32 */
12281 #include "mips16e_translate.c.inc"
12283 /* microMIPS extension to MIPS32/MIPS64 */
12286 * Values for microMIPS fmt field. Variable-width, depending on which
12287 * formats the instruction supports.
12289 enum {
12290 FMT_SD_S = 0,
12291 FMT_SD_D = 1,
12293 FMT_SDPS_S = 0,
12294 FMT_SDPS_D = 1,
12295 FMT_SDPS_PS = 2,
12297 FMT_SWL_S = 0,
12298 FMT_SWL_W = 1,
12299 FMT_SWL_L = 2,
12301 FMT_DWL_D = 0,
12302 FMT_DWL_W = 1,
12303 FMT_DWL_L = 2
12306 #include "micromips_translate.c.inc"
12308 #include "nanomips_translate.c.inc"
12310 /* MIPSDSP functions. */
12311 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
12312 int rd, int base, int offset)
12314 TCGv t0;
12316 check_dsp(ctx);
12317 t0 = tcg_temp_new();
12319 if (base == 0) {
12320 gen_load_gpr(t0, offset);
12321 } else if (offset == 0) {
12322 gen_load_gpr(t0, base);
12323 } else {
12324 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
12327 switch (opc) {
12328 case OPC_LBUX:
12329 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
12330 gen_store_gpr(t0, rd);
12331 break;
12332 case OPC_LHX:
12333 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
12334 gen_store_gpr(t0, rd);
12335 break;
12336 case OPC_LWX:
12337 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12338 gen_store_gpr(t0, rd);
12339 break;
12340 #if defined(TARGET_MIPS64)
12341 case OPC_LDX:
12342 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
12343 gen_store_gpr(t0, rd);
12344 break;
12345 #endif
12347 tcg_temp_free(t0);
12350 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
12351 int ret, int v1, int v2)
12353 TCGv v1_t;
12354 TCGv v2_t;
12356 if (ret == 0) {
12357 /* Treat as NOP. */
12358 return;
12361 v1_t = tcg_temp_new();
12362 v2_t = tcg_temp_new();
12364 gen_load_gpr(v1_t, v1);
12365 gen_load_gpr(v2_t, v2);
12367 switch (op1) {
12368 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
12369 case OPC_MULT_G_2E:
12370 check_dsp_r2(ctx);
12371 switch (op2) {
12372 case OPC_ADDUH_QB:
12373 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
12374 break;
12375 case OPC_ADDUH_R_QB:
12376 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12377 break;
12378 case OPC_ADDQH_PH:
12379 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
12380 break;
12381 case OPC_ADDQH_R_PH:
12382 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12383 break;
12384 case OPC_ADDQH_W:
12385 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
12386 break;
12387 case OPC_ADDQH_R_W:
12388 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12389 break;
12390 case OPC_SUBUH_QB:
12391 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
12392 break;
12393 case OPC_SUBUH_R_QB:
12394 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12395 break;
12396 case OPC_SUBQH_PH:
12397 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
12398 break;
12399 case OPC_SUBQH_R_PH:
12400 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12401 break;
12402 case OPC_SUBQH_W:
12403 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
12404 break;
12405 case OPC_SUBQH_R_W:
12406 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12407 break;
12409 break;
12410 case OPC_ABSQ_S_PH_DSP:
12411 switch (op2) {
12412 case OPC_ABSQ_S_QB:
12413 check_dsp_r2(ctx);
12414 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
12415 break;
12416 case OPC_ABSQ_S_PH:
12417 check_dsp(ctx);
12418 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
12419 break;
12420 case OPC_ABSQ_S_W:
12421 check_dsp(ctx);
12422 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
12423 break;
12424 case OPC_PRECEQ_W_PHL:
12425 check_dsp(ctx);
12426 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
12427 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12428 break;
12429 case OPC_PRECEQ_W_PHR:
12430 check_dsp(ctx);
12431 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
12432 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
12433 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12434 break;
12435 case OPC_PRECEQU_PH_QBL:
12436 check_dsp(ctx);
12437 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
12438 break;
12439 case OPC_PRECEQU_PH_QBR:
12440 check_dsp(ctx);
12441 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
12442 break;
12443 case OPC_PRECEQU_PH_QBLA:
12444 check_dsp(ctx);
12445 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
12446 break;
12447 case OPC_PRECEQU_PH_QBRA:
12448 check_dsp(ctx);
12449 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
12450 break;
12451 case OPC_PRECEU_PH_QBL:
12452 check_dsp(ctx);
12453 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
12454 break;
12455 case OPC_PRECEU_PH_QBR:
12456 check_dsp(ctx);
12457 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
12458 break;
12459 case OPC_PRECEU_PH_QBLA:
12460 check_dsp(ctx);
12461 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
12462 break;
12463 case OPC_PRECEU_PH_QBRA:
12464 check_dsp(ctx);
12465 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
12466 break;
12468 break;
12469 case OPC_ADDU_QB_DSP:
12470 switch (op2) {
12471 case OPC_ADDQ_PH:
12472 check_dsp(ctx);
12473 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12474 break;
12475 case OPC_ADDQ_S_PH:
12476 check_dsp(ctx);
12477 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12478 break;
12479 case OPC_ADDQ_S_W:
12480 check_dsp(ctx);
12481 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12482 break;
12483 case OPC_ADDU_QB:
12484 check_dsp(ctx);
12485 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12486 break;
12487 case OPC_ADDU_S_QB:
12488 check_dsp(ctx);
12489 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12490 break;
12491 case OPC_ADDU_PH:
12492 check_dsp_r2(ctx);
12493 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12494 break;
12495 case OPC_ADDU_S_PH:
12496 check_dsp_r2(ctx);
12497 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12498 break;
12499 case OPC_SUBQ_PH:
12500 check_dsp(ctx);
12501 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12502 break;
12503 case OPC_SUBQ_S_PH:
12504 check_dsp(ctx);
12505 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12506 break;
12507 case OPC_SUBQ_S_W:
12508 check_dsp(ctx);
12509 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12510 break;
12511 case OPC_SUBU_QB:
12512 check_dsp(ctx);
12513 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12514 break;
12515 case OPC_SUBU_S_QB:
12516 check_dsp(ctx);
12517 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12518 break;
12519 case OPC_SUBU_PH:
12520 check_dsp_r2(ctx);
12521 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12522 break;
12523 case OPC_SUBU_S_PH:
12524 check_dsp_r2(ctx);
12525 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12526 break;
12527 case OPC_ADDSC:
12528 check_dsp(ctx);
12529 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12530 break;
12531 case OPC_ADDWC:
12532 check_dsp(ctx);
12533 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12534 break;
12535 case OPC_MODSUB:
12536 check_dsp(ctx);
12537 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
12538 break;
12539 case OPC_RADDU_W_QB:
12540 check_dsp(ctx);
12541 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
12542 break;
12544 break;
12545 case OPC_CMPU_EQ_QB_DSP:
12546 switch (op2) {
12547 case OPC_PRECR_QB_PH:
12548 check_dsp_r2(ctx);
12549 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12550 break;
12551 case OPC_PRECRQ_QB_PH:
12552 check_dsp(ctx);
12553 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12554 break;
12555 case OPC_PRECR_SRA_PH_W:
12556 check_dsp_r2(ctx);
12558 TCGv_i32 sa_t = tcg_const_i32(v2);
12559 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
12560 cpu_gpr[ret]);
12561 tcg_temp_free_i32(sa_t);
12562 break;
12564 case OPC_PRECR_SRA_R_PH_W:
12565 check_dsp_r2(ctx);
12567 TCGv_i32 sa_t = tcg_const_i32(v2);
12568 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
12569 cpu_gpr[ret]);
12570 tcg_temp_free_i32(sa_t);
12571 break;
12573 case OPC_PRECRQ_PH_W:
12574 check_dsp(ctx);
12575 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
12576 break;
12577 case OPC_PRECRQ_RS_PH_W:
12578 check_dsp(ctx);
12579 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12580 break;
12581 case OPC_PRECRQU_S_QB_PH:
12582 check_dsp(ctx);
12583 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12584 break;
12586 break;
12587 #ifdef TARGET_MIPS64
12588 case OPC_ABSQ_S_QH_DSP:
12589 switch (op2) {
12590 case OPC_PRECEQ_L_PWL:
12591 check_dsp(ctx);
12592 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
12593 break;
12594 case OPC_PRECEQ_L_PWR:
12595 check_dsp(ctx);
12596 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
12597 break;
12598 case OPC_PRECEQ_PW_QHL:
12599 check_dsp(ctx);
12600 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
12601 break;
12602 case OPC_PRECEQ_PW_QHR:
12603 check_dsp(ctx);
12604 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
12605 break;
12606 case OPC_PRECEQ_PW_QHLA:
12607 check_dsp(ctx);
12608 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
12609 break;
12610 case OPC_PRECEQ_PW_QHRA:
12611 check_dsp(ctx);
12612 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
12613 break;
12614 case OPC_PRECEQU_QH_OBL:
12615 check_dsp(ctx);
12616 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
12617 break;
12618 case OPC_PRECEQU_QH_OBR:
12619 check_dsp(ctx);
12620 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
12621 break;
12622 case OPC_PRECEQU_QH_OBLA:
12623 check_dsp(ctx);
12624 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
12625 break;
12626 case OPC_PRECEQU_QH_OBRA:
12627 check_dsp(ctx);
12628 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
12629 break;
12630 case OPC_PRECEU_QH_OBL:
12631 check_dsp(ctx);
12632 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
12633 break;
12634 case OPC_PRECEU_QH_OBR:
12635 check_dsp(ctx);
12636 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
12637 break;
12638 case OPC_PRECEU_QH_OBLA:
12639 check_dsp(ctx);
12640 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
12641 break;
12642 case OPC_PRECEU_QH_OBRA:
12643 check_dsp(ctx);
12644 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
12645 break;
12646 case OPC_ABSQ_S_OB:
12647 check_dsp_r2(ctx);
12648 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
12649 break;
12650 case OPC_ABSQ_S_PW:
12651 check_dsp(ctx);
12652 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
12653 break;
12654 case OPC_ABSQ_S_QH:
12655 check_dsp(ctx);
12656 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
12657 break;
12659 break;
12660 case OPC_ADDU_OB_DSP:
12661 switch (op2) {
12662 case OPC_RADDU_L_OB:
12663 check_dsp(ctx);
12664 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
12665 break;
12666 case OPC_SUBQ_PW:
12667 check_dsp(ctx);
12668 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12669 break;
12670 case OPC_SUBQ_S_PW:
12671 check_dsp(ctx);
12672 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12673 break;
12674 case OPC_SUBQ_QH:
12675 check_dsp(ctx);
12676 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12677 break;
12678 case OPC_SUBQ_S_QH:
12679 check_dsp(ctx);
12680 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12681 break;
12682 case OPC_SUBU_OB:
12683 check_dsp(ctx);
12684 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12685 break;
12686 case OPC_SUBU_S_OB:
12687 check_dsp(ctx);
12688 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12689 break;
12690 case OPC_SUBU_QH:
12691 check_dsp_r2(ctx);
12692 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12693 break;
12694 case OPC_SUBU_S_QH:
12695 check_dsp_r2(ctx);
12696 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12697 break;
12698 case OPC_SUBUH_OB:
12699 check_dsp_r2(ctx);
12700 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
12701 break;
12702 case OPC_SUBUH_R_OB:
12703 check_dsp_r2(ctx);
12704 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12705 break;
12706 case OPC_ADDQ_PW:
12707 check_dsp(ctx);
12708 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12709 break;
12710 case OPC_ADDQ_S_PW:
12711 check_dsp(ctx);
12712 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12713 break;
12714 case OPC_ADDQ_QH:
12715 check_dsp(ctx);
12716 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12717 break;
12718 case OPC_ADDQ_S_QH:
12719 check_dsp(ctx);
12720 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12721 break;
12722 case OPC_ADDU_OB:
12723 check_dsp(ctx);
12724 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12725 break;
12726 case OPC_ADDU_S_OB:
12727 check_dsp(ctx);
12728 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12729 break;
12730 case OPC_ADDU_QH:
12731 check_dsp_r2(ctx);
12732 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12733 break;
12734 case OPC_ADDU_S_QH:
12735 check_dsp_r2(ctx);
12736 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12737 break;
12738 case OPC_ADDUH_OB:
12739 check_dsp_r2(ctx);
12740 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
12741 break;
12742 case OPC_ADDUH_R_OB:
12743 check_dsp_r2(ctx);
12744 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
12745 break;
12747 break;
12748 case OPC_CMPU_EQ_OB_DSP:
12749 switch (op2) {
12750 case OPC_PRECR_OB_QH:
12751 check_dsp_r2(ctx);
12752 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12753 break;
12754 case OPC_PRECR_SRA_QH_PW:
12755 check_dsp_r2(ctx);
12757 TCGv_i32 ret_t = tcg_const_i32(ret);
12758 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
12759 tcg_temp_free_i32(ret_t);
12760 break;
12762 case OPC_PRECR_SRA_R_QH_PW:
12763 check_dsp_r2(ctx);
12765 TCGv_i32 sa_v = tcg_const_i32(ret);
12766 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
12767 tcg_temp_free_i32(sa_v);
12768 break;
12770 case OPC_PRECRQ_OB_QH:
12771 check_dsp(ctx);
12772 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
12773 break;
12774 case OPC_PRECRQ_PW_L:
12775 check_dsp(ctx);
12776 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
12777 break;
12778 case OPC_PRECRQ_QH_PW:
12779 check_dsp(ctx);
12780 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
12781 break;
12782 case OPC_PRECRQ_RS_QH_PW:
12783 check_dsp(ctx);
12784 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12785 break;
12786 case OPC_PRECRQU_S_OB_QH:
12787 check_dsp(ctx);
12788 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12789 break;
12791 break;
12792 #endif
12795 tcg_temp_free(v1_t);
12796 tcg_temp_free(v2_t);
12799 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
12800 int ret, int v1, int v2)
12802 uint32_t op2;
12803 TCGv t0;
12804 TCGv v1_t;
12805 TCGv v2_t;
12807 if (ret == 0) {
12808 /* Treat as NOP. */
12809 return;
12812 t0 = tcg_temp_new();
12813 v1_t = tcg_temp_new();
12814 v2_t = tcg_temp_new();
12816 tcg_gen_movi_tl(t0, v1);
12817 gen_load_gpr(v1_t, v1);
12818 gen_load_gpr(v2_t, v2);
12820 switch (opc) {
12821 case OPC_SHLL_QB_DSP:
12823 op2 = MASK_SHLL_QB(ctx->opcode);
12824 switch (op2) {
12825 case OPC_SHLL_QB:
12826 check_dsp(ctx);
12827 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
12828 break;
12829 case OPC_SHLLV_QB:
12830 check_dsp(ctx);
12831 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12832 break;
12833 case OPC_SHLL_PH:
12834 check_dsp(ctx);
12835 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
12836 break;
12837 case OPC_SHLLV_PH:
12838 check_dsp(ctx);
12839 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12840 break;
12841 case OPC_SHLL_S_PH:
12842 check_dsp(ctx);
12843 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
12844 break;
12845 case OPC_SHLLV_S_PH:
12846 check_dsp(ctx);
12847 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12848 break;
12849 case OPC_SHLL_S_W:
12850 check_dsp(ctx);
12851 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
12852 break;
12853 case OPC_SHLLV_S_W:
12854 check_dsp(ctx);
12855 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12856 break;
12857 case OPC_SHRL_QB:
12858 check_dsp(ctx);
12859 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
12860 break;
12861 case OPC_SHRLV_QB:
12862 check_dsp(ctx);
12863 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
12864 break;
12865 case OPC_SHRL_PH:
12866 check_dsp_r2(ctx);
12867 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
12868 break;
12869 case OPC_SHRLV_PH:
12870 check_dsp_r2(ctx);
12871 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
12872 break;
12873 case OPC_SHRA_QB:
12874 check_dsp_r2(ctx);
12875 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
12876 break;
12877 case OPC_SHRA_R_QB:
12878 check_dsp_r2(ctx);
12879 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
12880 break;
12881 case OPC_SHRAV_QB:
12882 check_dsp_r2(ctx);
12883 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
12884 break;
12885 case OPC_SHRAV_R_QB:
12886 check_dsp_r2(ctx);
12887 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
12888 break;
12889 case OPC_SHRA_PH:
12890 check_dsp(ctx);
12891 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
12892 break;
12893 case OPC_SHRA_R_PH:
12894 check_dsp(ctx);
12895 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
12896 break;
12897 case OPC_SHRAV_PH:
12898 check_dsp(ctx);
12899 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
12900 break;
12901 case OPC_SHRAV_R_PH:
12902 check_dsp(ctx);
12903 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
12904 break;
12905 case OPC_SHRA_R_W:
12906 check_dsp(ctx);
12907 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
12908 break;
12909 case OPC_SHRAV_R_W:
12910 check_dsp(ctx);
12911 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
12912 break;
12913 default: /* Invalid */
12914 MIPS_INVAL("MASK SHLL.QB");
12915 gen_reserved_instruction(ctx);
12916 break;
12918 break;
12920 #ifdef TARGET_MIPS64
12921 case OPC_SHLL_OB_DSP:
12922 op2 = MASK_SHLL_OB(ctx->opcode);
12923 switch (op2) {
12924 case OPC_SHLL_PW:
12925 check_dsp(ctx);
12926 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
12927 break;
12928 case OPC_SHLLV_PW:
12929 check_dsp(ctx);
12930 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12931 break;
12932 case OPC_SHLL_S_PW:
12933 check_dsp(ctx);
12934 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
12935 break;
12936 case OPC_SHLLV_S_PW:
12937 check_dsp(ctx);
12938 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12939 break;
12940 case OPC_SHLL_OB:
12941 check_dsp(ctx);
12942 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
12943 break;
12944 case OPC_SHLLV_OB:
12945 check_dsp(ctx);
12946 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12947 break;
12948 case OPC_SHLL_QH:
12949 check_dsp(ctx);
12950 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
12951 break;
12952 case OPC_SHLLV_QH:
12953 check_dsp(ctx);
12954 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12955 break;
12956 case OPC_SHLL_S_QH:
12957 check_dsp(ctx);
12958 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
12959 break;
12960 case OPC_SHLLV_S_QH:
12961 check_dsp(ctx);
12962 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
12963 break;
12964 case OPC_SHRA_OB:
12965 check_dsp_r2(ctx);
12966 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
12967 break;
12968 case OPC_SHRAV_OB:
12969 check_dsp_r2(ctx);
12970 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
12971 break;
12972 case OPC_SHRA_R_OB:
12973 check_dsp_r2(ctx);
12974 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
12975 break;
12976 case OPC_SHRAV_R_OB:
12977 check_dsp_r2(ctx);
12978 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
12979 break;
12980 case OPC_SHRA_PW:
12981 check_dsp(ctx);
12982 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
12983 break;
12984 case OPC_SHRAV_PW:
12985 check_dsp(ctx);
12986 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
12987 break;
12988 case OPC_SHRA_R_PW:
12989 check_dsp(ctx);
12990 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
12991 break;
12992 case OPC_SHRAV_R_PW:
12993 check_dsp(ctx);
12994 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
12995 break;
12996 case OPC_SHRA_QH:
12997 check_dsp(ctx);
12998 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
12999 break;
13000 case OPC_SHRAV_QH:
13001 check_dsp(ctx);
13002 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
13003 break;
13004 case OPC_SHRA_R_QH:
13005 check_dsp(ctx);
13006 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
13007 break;
13008 case OPC_SHRAV_R_QH:
13009 check_dsp(ctx);
13010 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
13011 break;
13012 case OPC_SHRL_OB:
13013 check_dsp(ctx);
13014 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
13015 break;
13016 case OPC_SHRLV_OB:
13017 check_dsp(ctx);
13018 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
13019 break;
13020 case OPC_SHRL_QH:
13021 check_dsp_r2(ctx);
13022 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
13023 break;
13024 case OPC_SHRLV_QH:
13025 check_dsp_r2(ctx);
13026 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
13027 break;
13028 default: /* Invalid */
13029 MIPS_INVAL("MASK SHLL.OB");
13030 gen_reserved_instruction(ctx);
13031 break;
13033 break;
13034 #endif
13037 tcg_temp_free(t0);
13038 tcg_temp_free(v1_t);
13039 tcg_temp_free(v2_t);
13042 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
13043 int ret, int v1, int v2, int check_ret)
13045 TCGv_i32 t0;
13046 TCGv v1_t;
13047 TCGv v2_t;
13049 if ((ret == 0) && (check_ret == 1)) {
13050 /* Treat as NOP. */
13051 return;
13054 t0 = tcg_temp_new_i32();
13055 v1_t = tcg_temp_new();
13056 v2_t = tcg_temp_new();
13058 tcg_gen_movi_i32(t0, ret);
13059 gen_load_gpr(v1_t, v1);
13060 gen_load_gpr(v2_t, v2);
13062 switch (op1) {
13064 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13065 * the same mask and op1.
13067 case OPC_MULT_G_2E:
13068 check_dsp_r2(ctx);
13069 switch (op2) {
13070 case OPC_MUL_PH:
13071 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13072 break;
13073 case OPC_MUL_S_PH:
13074 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13075 break;
13076 case OPC_MULQ_S_W:
13077 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13078 break;
13079 case OPC_MULQ_RS_W:
13080 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13081 break;
13083 break;
13084 case OPC_DPA_W_PH_DSP:
13085 switch (op2) {
13086 case OPC_DPAU_H_QBL:
13087 check_dsp(ctx);
13088 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
13089 break;
13090 case OPC_DPAU_H_QBR:
13091 check_dsp(ctx);
13092 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
13093 break;
13094 case OPC_DPSU_H_QBL:
13095 check_dsp(ctx);
13096 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
13097 break;
13098 case OPC_DPSU_H_QBR:
13099 check_dsp(ctx);
13100 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
13101 break;
13102 case OPC_DPA_W_PH:
13103 check_dsp_r2(ctx);
13104 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
13105 break;
13106 case OPC_DPAX_W_PH:
13107 check_dsp_r2(ctx);
13108 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
13109 break;
13110 case OPC_DPAQ_S_W_PH:
13111 check_dsp(ctx);
13112 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13113 break;
13114 case OPC_DPAQX_S_W_PH:
13115 check_dsp_r2(ctx);
13116 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13117 break;
13118 case OPC_DPAQX_SA_W_PH:
13119 check_dsp_r2(ctx);
13120 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13121 break;
13122 case OPC_DPS_W_PH:
13123 check_dsp_r2(ctx);
13124 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
13125 break;
13126 case OPC_DPSX_W_PH:
13127 check_dsp_r2(ctx);
13128 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
13129 break;
13130 case OPC_DPSQ_S_W_PH:
13131 check_dsp(ctx);
13132 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13133 break;
13134 case OPC_DPSQX_S_W_PH:
13135 check_dsp_r2(ctx);
13136 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13137 break;
13138 case OPC_DPSQX_SA_W_PH:
13139 check_dsp_r2(ctx);
13140 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13141 break;
13142 case OPC_MULSAQ_S_W_PH:
13143 check_dsp(ctx);
13144 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13145 break;
13146 case OPC_DPAQ_SA_L_W:
13147 check_dsp(ctx);
13148 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13149 break;
13150 case OPC_DPSQ_SA_L_W:
13151 check_dsp(ctx);
13152 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13153 break;
13154 case OPC_MAQ_S_W_PHL:
13155 check_dsp(ctx);
13156 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
13157 break;
13158 case OPC_MAQ_S_W_PHR:
13159 check_dsp(ctx);
13160 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
13161 break;
13162 case OPC_MAQ_SA_W_PHL:
13163 check_dsp(ctx);
13164 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
13165 break;
13166 case OPC_MAQ_SA_W_PHR:
13167 check_dsp(ctx);
13168 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
13169 break;
13170 case OPC_MULSA_W_PH:
13171 check_dsp_r2(ctx);
13172 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
13173 break;
13175 break;
13176 #ifdef TARGET_MIPS64
13177 case OPC_DPAQ_W_QH_DSP:
13179 int ac = ret & 0x03;
13180 tcg_gen_movi_i32(t0, ac);
13182 switch (op2) {
13183 case OPC_DMADD:
13184 check_dsp(ctx);
13185 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
13186 break;
13187 case OPC_DMADDU:
13188 check_dsp(ctx);
13189 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
13190 break;
13191 case OPC_DMSUB:
13192 check_dsp(ctx);
13193 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
13194 break;
13195 case OPC_DMSUBU:
13196 check_dsp(ctx);
13197 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
13198 break;
13199 case OPC_DPA_W_QH:
13200 check_dsp_r2(ctx);
13201 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
13202 break;
13203 case OPC_DPAQ_S_W_QH:
13204 check_dsp(ctx);
13205 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13206 break;
13207 case OPC_DPAQ_SA_L_PW:
13208 check_dsp(ctx);
13209 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13210 break;
13211 case OPC_DPAU_H_OBL:
13212 check_dsp(ctx);
13213 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
13214 break;
13215 case OPC_DPAU_H_OBR:
13216 check_dsp(ctx);
13217 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
13218 break;
13219 case OPC_DPS_W_QH:
13220 check_dsp_r2(ctx);
13221 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
13222 break;
13223 case OPC_DPSQ_S_W_QH:
13224 check_dsp(ctx);
13225 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13226 break;
13227 case OPC_DPSQ_SA_L_PW:
13228 check_dsp(ctx);
13229 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13230 break;
13231 case OPC_DPSU_H_OBL:
13232 check_dsp(ctx);
13233 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
13234 break;
13235 case OPC_DPSU_H_OBR:
13236 check_dsp(ctx);
13237 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
13238 break;
13239 case OPC_MAQ_S_L_PWL:
13240 check_dsp(ctx);
13241 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
13242 break;
13243 case OPC_MAQ_S_L_PWR:
13244 check_dsp(ctx);
13245 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
13246 break;
13247 case OPC_MAQ_S_W_QHLL:
13248 check_dsp(ctx);
13249 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
13250 break;
13251 case OPC_MAQ_SA_W_QHLL:
13252 check_dsp(ctx);
13253 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
13254 break;
13255 case OPC_MAQ_S_W_QHLR:
13256 check_dsp(ctx);
13257 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
13258 break;
13259 case OPC_MAQ_SA_W_QHLR:
13260 check_dsp(ctx);
13261 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
13262 break;
13263 case OPC_MAQ_S_W_QHRL:
13264 check_dsp(ctx);
13265 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
13266 break;
13267 case OPC_MAQ_SA_W_QHRL:
13268 check_dsp(ctx);
13269 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
13270 break;
13271 case OPC_MAQ_S_W_QHRR:
13272 check_dsp(ctx);
13273 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
13274 break;
13275 case OPC_MAQ_SA_W_QHRR:
13276 check_dsp(ctx);
13277 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
13278 break;
13279 case OPC_MULSAQ_S_L_PW:
13280 check_dsp(ctx);
13281 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
13282 break;
13283 case OPC_MULSAQ_S_W_QH:
13284 check_dsp(ctx);
13285 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13286 break;
13289 break;
13290 #endif
13291 case OPC_ADDU_QB_DSP:
13292 switch (op2) {
13293 case OPC_MULEU_S_PH_QBL:
13294 check_dsp(ctx);
13295 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13296 break;
13297 case OPC_MULEU_S_PH_QBR:
13298 check_dsp(ctx);
13299 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13300 break;
13301 case OPC_MULQ_RS_PH:
13302 check_dsp(ctx);
13303 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13304 break;
13305 case OPC_MULEQ_S_W_PHL:
13306 check_dsp(ctx);
13307 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13308 break;
13309 case OPC_MULEQ_S_W_PHR:
13310 check_dsp(ctx);
13311 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13312 break;
13313 case OPC_MULQ_S_PH:
13314 check_dsp_r2(ctx);
13315 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13316 break;
13318 break;
13319 #ifdef TARGET_MIPS64
13320 case OPC_ADDU_OB_DSP:
13321 switch (op2) {
13322 case OPC_MULEQ_S_PW_QHL:
13323 check_dsp(ctx);
13324 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13325 break;
13326 case OPC_MULEQ_S_PW_QHR:
13327 check_dsp(ctx);
13328 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13329 break;
13330 case OPC_MULEU_S_QH_OBL:
13331 check_dsp(ctx);
13332 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13333 break;
13334 case OPC_MULEU_S_QH_OBR:
13335 check_dsp(ctx);
13336 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13337 break;
13338 case OPC_MULQ_RS_QH:
13339 check_dsp(ctx);
13340 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13341 break;
13343 break;
13344 #endif
13347 tcg_temp_free_i32(t0);
13348 tcg_temp_free(v1_t);
13349 tcg_temp_free(v2_t);
13352 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
13353 int ret, int val)
13355 int16_t imm;
13356 TCGv t0;
13357 TCGv val_t;
13359 if (ret == 0) {
13360 /* Treat as NOP. */
13361 return;
13364 t0 = tcg_temp_new();
13365 val_t = tcg_temp_new();
13366 gen_load_gpr(val_t, val);
13368 switch (op1) {
13369 case OPC_ABSQ_S_PH_DSP:
13370 switch (op2) {
13371 case OPC_BITREV:
13372 check_dsp(ctx);
13373 gen_helper_bitrev(cpu_gpr[ret], val_t);
13374 break;
13375 case OPC_REPL_QB:
13376 check_dsp(ctx);
13378 target_long result;
13379 imm = (ctx->opcode >> 16) & 0xFF;
13380 result = (uint32_t)imm << 24 |
13381 (uint32_t)imm << 16 |
13382 (uint32_t)imm << 8 |
13383 (uint32_t)imm;
13384 result = (int32_t)result;
13385 tcg_gen_movi_tl(cpu_gpr[ret], result);
13387 break;
13388 case OPC_REPLV_QB:
13389 check_dsp(ctx);
13390 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13391 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13392 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13393 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13394 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13395 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13396 break;
13397 case OPC_REPL_PH:
13398 check_dsp(ctx);
13400 imm = (ctx->opcode >> 16) & 0x03FF;
13401 imm = (int16_t)(imm << 6) >> 6;
13402 tcg_gen_movi_tl(cpu_gpr[ret], \
13403 (target_long)((int32_t)imm << 16 | \
13404 (uint16_t)imm));
13406 break;
13407 case OPC_REPLV_PH:
13408 check_dsp(ctx);
13409 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13410 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13411 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13412 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13413 break;
13415 break;
13416 #ifdef TARGET_MIPS64
13417 case OPC_ABSQ_S_QH_DSP:
13418 switch (op2) {
13419 case OPC_REPL_OB:
13420 check_dsp(ctx);
13422 target_long temp;
13424 imm = (ctx->opcode >> 16) & 0xFF;
13425 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
13426 temp = (temp << 16) | temp;
13427 temp = (temp << 32) | temp;
13428 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13429 break;
13431 case OPC_REPL_PW:
13432 check_dsp(ctx);
13434 target_long temp;
13436 imm = (ctx->opcode >> 16) & 0x03FF;
13437 imm = (int16_t)(imm << 6) >> 6;
13438 temp = ((target_long)imm << 32) \
13439 | ((target_long)imm & 0xFFFFFFFF);
13440 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13441 break;
13443 case OPC_REPL_QH:
13444 check_dsp(ctx);
13446 target_long temp;
13448 imm = (ctx->opcode >> 16) & 0x03FF;
13449 imm = (int16_t)(imm << 6) >> 6;
13451 temp = ((uint64_t)(uint16_t)imm << 48) |
13452 ((uint64_t)(uint16_t)imm << 32) |
13453 ((uint64_t)(uint16_t)imm << 16) |
13454 (uint64_t)(uint16_t)imm;
13455 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13456 break;
13458 case OPC_REPLV_OB:
13459 check_dsp(ctx);
13460 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13461 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13462 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13463 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13464 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13465 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13466 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13467 break;
13468 case OPC_REPLV_PW:
13469 check_dsp(ctx);
13470 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
13471 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13472 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13473 break;
13474 case OPC_REPLV_QH:
13475 check_dsp(ctx);
13476 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13477 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13478 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13479 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13480 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13481 break;
13483 break;
13484 #endif
13486 tcg_temp_free(t0);
13487 tcg_temp_free(val_t);
13490 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
13491 uint32_t op1, uint32_t op2,
13492 int ret, int v1, int v2, int check_ret)
13494 TCGv t1;
13495 TCGv v1_t;
13496 TCGv v2_t;
13498 if ((ret == 0) && (check_ret == 1)) {
13499 /* Treat as NOP. */
13500 return;
13503 t1 = tcg_temp_new();
13504 v1_t = tcg_temp_new();
13505 v2_t = tcg_temp_new();
13507 gen_load_gpr(v1_t, v1);
13508 gen_load_gpr(v2_t, v2);
13510 switch (op1) {
13511 case OPC_CMPU_EQ_QB_DSP:
13512 switch (op2) {
13513 case OPC_CMPU_EQ_QB:
13514 check_dsp(ctx);
13515 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
13516 break;
13517 case OPC_CMPU_LT_QB:
13518 check_dsp(ctx);
13519 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
13520 break;
13521 case OPC_CMPU_LE_QB:
13522 check_dsp(ctx);
13523 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
13524 break;
13525 case OPC_CMPGU_EQ_QB:
13526 check_dsp(ctx);
13527 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
13528 break;
13529 case OPC_CMPGU_LT_QB:
13530 check_dsp(ctx);
13531 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
13532 break;
13533 case OPC_CMPGU_LE_QB:
13534 check_dsp(ctx);
13535 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
13536 break;
13537 case OPC_CMPGDU_EQ_QB:
13538 check_dsp_r2(ctx);
13539 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
13540 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13541 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13542 tcg_gen_shli_tl(t1, t1, 24);
13543 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13544 break;
13545 case OPC_CMPGDU_LT_QB:
13546 check_dsp_r2(ctx);
13547 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
13548 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13549 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13550 tcg_gen_shli_tl(t1, t1, 24);
13551 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13552 break;
13553 case OPC_CMPGDU_LE_QB:
13554 check_dsp_r2(ctx);
13555 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
13556 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13557 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13558 tcg_gen_shli_tl(t1, t1, 24);
13559 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13560 break;
13561 case OPC_CMP_EQ_PH:
13562 check_dsp(ctx);
13563 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
13564 break;
13565 case OPC_CMP_LT_PH:
13566 check_dsp(ctx);
13567 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
13568 break;
13569 case OPC_CMP_LE_PH:
13570 check_dsp(ctx);
13571 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
13572 break;
13573 case OPC_PICK_QB:
13574 check_dsp(ctx);
13575 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13576 break;
13577 case OPC_PICK_PH:
13578 check_dsp(ctx);
13579 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13580 break;
13581 case OPC_PACKRL_PH:
13582 check_dsp(ctx);
13583 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
13584 break;
13586 break;
13587 #ifdef TARGET_MIPS64
13588 case OPC_CMPU_EQ_OB_DSP:
13589 switch (op2) {
13590 case OPC_CMP_EQ_PW:
13591 check_dsp(ctx);
13592 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
13593 break;
13594 case OPC_CMP_LT_PW:
13595 check_dsp(ctx);
13596 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
13597 break;
13598 case OPC_CMP_LE_PW:
13599 check_dsp(ctx);
13600 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
13601 break;
13602 case OPC_CMP_EQ_QH:
13603 check_dsp(ctx);
13604 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
13605 break;
13606 case OPC_CMP_LT_QH:
13607 check_dsp(ctx);
13608 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
13609 break;
13610 case OPC_CMP_LE_QH:
13611 check_dsp(ctx);
13612 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
13613 break;
13614 case OPC_CMPGDU_EQ_OB:
13615 check_dsp_r2(ctx);
13616 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13617 break;
13618 case OPC_CMPGDU_LT_OB:
13619 check_dsp_r2(ctx);
13620 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13621 break;
13622 case OPC_CMPGDU_LE_OB:
13623 check_dsp_r2(ctx);
13624 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13625 break;
13626 case OPC_CMPGU_EQ_OB:
13627 check_dsp(ctx);
13628 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
13629 break;
13630 case OPC_CMPGU_LT_OB:
13631 check_dsp(ctx);
13632 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
13633 break;
13634 case OPC_CMPGU_LE_OB:
13635 check_dsp(ctx);
13636 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
13637 break;
13638 case OPC_CMPU_EQ_OB:
13639 check_dsp(ctx);
13640 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
13641 break;
13642 case OPC_CMPU_LT_OB:
13643 check_dsp(ctx);
13644 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
13645 break;
13646 case OPC_CMPU_LE_OB:
13647 check_dsp(ctx);
13648 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
13649 break;
13650 case OPC_PACKRL_PW:
13651 check_dsp(ctx);
13652 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
13653 break;
13654 case OPC_PICK_OB:
13655 check_dsp(ctx);
13656 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13657 break;
13658 case OPC_PICK_PW:
13659 check_dsp(ctx);
13660 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13661 break;
13662 case OPC_PICK_QH:
13663 check_dsp(ctx);
13664 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13665 break;
13667 break;
13668 #endif
13671 tcg_temp_free(t1);
13672 tcg_temp_free(v1_t);
13673 tcg_temp_free(v2_t);
13676 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
13677 uint32_t op1, int rt, int rs, int sa)
13679 TCGv t0;
13681 check_dsp_r2(ctx);
13683 if (rt == 0) {
13684 /* Treat as NOP. */
13685 return;
13688 t0 = tcg_temp_new();
13689 gen_load_gpr(t0, rs);
13691 switch (op1) {
13692 case OPC_APPEND_DSP:
13693 switch (MASK_APPEND(ctx->opcode)) {
13694 case OPC_APPEND:
13695 if (sa != 0) {
13696 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
13698 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
13699 break;
13700 case OPC_PREPEND:
13701 if (sa != 0) {
13702 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
13703 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
13704 tcg_gen_shli_tl(t0, t0, 32 - sa);
13705 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13707 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
13708 break;
13709 case OPC_BALIGN:
13710 sa &= 3;
13711 if (sa != 0 && sa != 2) {
13712 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
13713 tcg_gen_ext32u_tl(t0, t0);
13714 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
13715 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13717 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
13718 break;
13719 default: /* Invalid */
13720 MIPS_INVAL("MASK APPEND");
13721 gen_reserved_instruction(ctx);
13722 break;
13724 break;
13725 #ifdef TARGET_MIPS64
13726 case OPC_DAPPEND_DSP:
13727 switch (MASK_DAPPEND(ctx->opcode)) {
13728 case OPC_DAPPEND:
13729 if (sa != 0) {
13730 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
13732 break;
13733 case OPC_PREPENDD:
13734 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
13735 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
13736 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
13737 break;
13738 case OPC_PREPENDW:
13739 if (sa != 0) {
13740 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
13741 tcg_gen_shli_tl(t0, t0, 64 - sa);
13742 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13744 break;
13745 case OPC_DBALIGN:
13746 sa &= 7;
13747 if (sa != 0 && sa != 2 && sa != 4) {
13748 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
13749 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
13750 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
13752 break;
13753 default: /* Invalid */
13754 MIPS_INVAL("MASK DAPPEND");
13755 gen_reserved_instruction(ctx);
13756 break;
13758 break;
13759 #endif
13761 tcg_temp_free(t0);
13764 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
13765 int ret, int v1, int v2, int check_ret)
13768 TCGv t0;
13769 TCGv t1;
13770 TCGv v1_t;
13771 TCGv v2_t;
13772 int16_t imm;
13774 if ((ret == 0) && (check_ret == 1)) {
13775 /* Treat as NOP. */
13776 return;
13779 t0 = tcg_temp_new();
13780 t1 = tcg_temp_new();
13781 v1_t = tcg_temp_new();
13782 v2_t = tcg_temp_new();
13784 gen_load_gpr(v1_t, v1);
13785 gen_load_gpr(v2_t, v2);
13787 switch (op1) {
13788 case OPC_EXTR_W_DSP:
13789 check_dsp(ctx);
13790 switch (op2) {
13791 case OPC_EXTR_W:
13792 tcg_gen_movi_tl(t0, v2);
13793 tcg_gen_movi_tl(t1, v1);
13794 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
13795 break;
13796 case OPC_EXTR_R_W:
13797 tcg_gen_movi_tl(t0, v2);
13798 tcg_gen_movi_tl(t1, v1);
13799 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
13800 break;
13801 case OPC_EXTR_RS_W:
13802 tcg_gen_movi_tl(t0, v2);
13803 tcg_gen_movi_tl(t1, v1);
13804 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
13805 break;
13806 case OPC_EXTR_S_H:
13807 tcg_gen_movi_tl(t0, v2);
13808 tcg_gen_movi_tl(t1, v1);
13809 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
13810 break;
13811 case OPC_EXTRV_S_H:
13812 tcg_gen_movi_tl(t0, v2);
13813 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
13814 break;
13815 case OPC_EXTRV_W:
13816 tcg_gen_movi_tl(t0, v2);
13817 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13818 break;
13819 case OPC_EXTRV_R_W:
13820 tcg_gen_movi_tl(t0, v2);
13821 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13822 break;
13823 case OPC_EXTRV_RS_W:
13824 tcg_gen_movi_tl(t0, v2);
13825 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13826 break;
13827 case OPC_EXTP:
13828 tcg_gen_movi_tl(t0, v2);
13829 tcg_gen_movi_tl(t1, v1);
13830 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
13831 break;
13832 case OPC_EXTPV:
13833 tcg_gen_movi_tl(t0, v2);
13834 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
13835 break;
13836 case OPC_EXTPDP:
13837 tcg_gen_movi_tl(t0, v2);
13838 tcg_gen_movi_tl(t1, v1);
13839 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
13840 break;
13841 case OPC_EXTPDPV:
13842 tcg_gen_movi_tl(t0, v2);
13843 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
13844 break;
13845 case OPC_SHILO:
13846 imm = (ctx->opcode >> 20) & 0x3F;
13847 tcg_gen_movi_tl(t0, ret);
13848 tcg_gen_movi_tl(t1, imm);
13849 gen_helper_shilo(t0, t1, cpu_env);
13850 break;
13851 case OPC_SHILOV:
13852 tcg_gen_movi_tl(t0, ret);
13853 gen_helper_shilo(t0, v1_t, cpu_env);
13854 break;
13855 case OPC_MTHLIP:
13856 tcg_gen_movi_tl(t0, ret);
13857 gen_helper_mthlip(t0, v1_t, cpu_env);
13858 break;
13859 case OPC_WRDSP:
13860 imm = (ctx->opcode >> 11) & 0x3FF;
13861 tcg_gen_movi_tl(t0, imm);
13862 gen_helper_wrdsp(v1_t, t0, cpu_env);
13863 break;
13864 case OPC_RDDSP:
13865 imm = (ctx->opcode >> 16) & 0x03FF;
13866 tcg_gen_movi_tl(t0, imm);
13867 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
13868 break;
13870 break;
13871 #ifdef TARGET_MIPS64
13872 case OPC_DEXTR_W_DSP:
13873 check_dsp(ctx);
13874 switch (op2) {
13875 case OPC_DMTHLIP:
13876 tcg_gen_movi_tl(t0, ret);
13877 gen_helper_dmthlip(v1_t, t0, cpu_env);
13878 break;
13879 case OPC_DSHILO:
13881 int shift = (ctx->opcode >> 19) & 0x7F;
13882 int ac = (ctx->opcode >> 11) & 0x03;
13883 tcg_gen_movi_tl(t0, shift);
13884 tcg_gen_movi_tl(t1, ac);
13885 gen_helper_dshilo(t0, t1, cpu_env);
13886 break;
13888 case OPC_DSHILOV:
13890 int ac = (ctx->opcode >> 11) & 0x03;
13891 tcg_gen_movi_tl(t0, ac);
13892 gen_helper_dshilo(v1_t, t0, cpu_env);
13893 break;
13895 case OPC_DEXTP:
13896 tcg_gen_movi_tl(t0, v2);
13897 tcg_gen_movi_tl(t1, v1);
13899 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
13900 break;
13901 case OPC_DEXTPV:
13902 tcg_gen_movi_tl(t0, v2);
13903 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
13904 break;
13905 case OPC_DEXTPDP:
13906 tcg_gen_movi_tl(t0, v2);
13907 tcg_gen_movi_tl(t1, v1);
13908 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
13909 break;
13910 case OPC_DEXTPDPV:
13911 tcg_gen_movi_tl(t0, v2);
13912 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
13913 break;
13914 case OPC_DEXTR_L:
13915 tcg_gen_movi_tl(t0, v2);
13916 tcg_gen_movi_tl(t1, v1);
13917 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
13918 break;
13919 case OPC_DEXTR_R_L:
13920 tcg_gen_movi_tl(t0, v2);
13921 tcg_gen_movi_tl(t1, v1);
13922 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
13923 break;
13924 case OPC_DEXTR_RS_L:
13925 tcg_gen_movi_tl(t0, v2);
13926 tcg_gen_movi_tl(t1, v1);
13927 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
13928 break;
13929 case OPC_DEXTR_W:
13930 tcg_gen_movi_tl(t0, v2);
13931 tcg_gen_movi_tl(t1, v1);
13932 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
13933 break;
13934 case OPC_DEXTR_R_W:
13935 tcg_gen_movi_tl(t0, v2);
13936 tcg_gen_movi_tl(t1, v1);
13937 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
13938 break;
13939 case OPC_DEXTR_RS_W:
13940 tcg_gen_movi_tl(t0, v2);
13941 tcg_gen_movi_tl(t1, v1);
13942 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
13943 break;
13944 case OPC_DEXTR_S_H:
13945 tcg_gen_movi_tl(t0, v2);
13946 tcg_gen_movi_tl(t1, v1);
13947 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
13948 break;
13949 case OPC_DEXTRV_S_H:
13950 tcg_gen_movi_tl(t0, v2);
13951 tcg_gen_movi_tl(t1, v1);
13952 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
13953 break;
13954 case OPC_DEXTRV_L:
13955 tcg_gen_movi_tl(t0, v2);
13956 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
13957 break;
13958 case OPC_DEXTRV_R_L:
13959 tcg_gen_movi_tl(t0, v2);
13960 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
13961 break;
13962 case OPC_DEXTRV_RS_L:
13963 tcg_gen_movi_tl(t0, v2);
13964 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
13965 break;
13966 case OPC_DEXTRV_W:
13967 tcg_gen_movi_tl(t0, v2);
13968 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13969 break;
13970 case OPC_DEXTRV_R_W:
13971 tcg_gen_movi_tl(t0, v2);
13972 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13973 break;
13974 case OPC_DEXTRV_RS_W:
13975 tcg_gen_movi_tl(t0, v2);
13976 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
13977 break;
13979 break;
13980 #endif
13983 tcg_temp_free(t0);
13984 tcg_temp_free(t1);
13985 tcg_temp_free(v1_t);
13986 tcg_temp_free(v2_t);
13989 /* End MIPSDSP functions. */
13991 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
13993 int rs, rt, rd, sa;
13994 uint32_t op1, op2;
13996 rs = (ctx->opcode >> 21) & 0x1f;
13997 rt = (ctx->opcode >> 16) & 0x1f;
13998 rd = (ctx->opcode >> 11) & 0x1f;
13999 sa = (ctx->opcode >> 6) & 0x1f;
14001 op1 = MASK_SPECIAL(ctx->opcode);
14002 switch (op1) {
14003 case OPC_MULT:
14004 case OPC_MULTU:
14005 case OPC_DIV:
14006 case OPC_DIVU:
14007 op2 = MASK_R6_MULDIV(ctx->opcode);
14008 switch (op2) {
14009 case R6_OPC_MUL:
14010 case R6_OPC_MUH:
14011 case R6_OPC_MULU:
14012 case R6_OPC_MUHU:
14013 case R6_OPC_DIV:
14014 case R6_OPC_MOD:
14015 case R6_OPC_DIVU:
14016 case R6_OPC_MODU:
14017 gen_r6_muldiv(ctx, op2, rd, rs, rt);
14018 break;
14019 default:
14020 MIPS_INVAL("special_r6 muldiv");
14021 gen_reserved_instruction(ctx);
14022 break;
14024 break;
14025 case OPC_SELEQZ:
14026 case OPC_SELNEZ:
14027 gen_cond_move(ctx, op1, rd, rs, rt);
14028 break;
14029 case R6_OPC_CLO:
14030 case R6_OPC_CLZ:
14031 if (rt == 0 && sa == 1) {
14033 * Major opcode and function field is shared with preR6 MFHI/MTHI.
14034 * We need additionally to check other fields.
14036 gen_cl(ctx, op1, rd, rs);
14037 } else {
14038 gen_reserved_instruction(ctx);
14040 break;
14041 case R6_OPC_SDBBP:
14042 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
14043 gen_helper_do_semihosting(cpu_env);
14044 } else {
14045 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14046 gen_reserved_instruction(ctx);
14047 } else {
14048 generate_exception_end(ctx, EXCP_DBp);
14051 break;
14052 #if defined(TARGET_MIPS64)
14053 case R6_OPC_DCLO:
14054 case R6_OPC_DCLZ:
14055 if (rt == 0 && sa == 1) {
14057 * Major opcode and function field is shared with preR6 MFHI/MTHI.
14058 * We need additionally to check other fields.
14060 check_mips_64(ctx);
14061 gen_cl(ctx, op1, rd, rs);
14062 } else {
14063 gen_reserved_instruction(ctx);
14065 break;
14066 case OPC_DMULT:
14067 case OPC_DMULTU:
14068 case OPC_DDIV:
14069 case OPC_DDIVU:
14071 op2 = MASK_R6_MULDIV(ctx->opcode);
14072 switch (op2) {
14073 case R6_OPC_DMUL:
14074 case R6_OPC_DMUH:
14075 case R6_OPC_DMULU:
14076 case R6_OPC_DMUHU:
14077 case R6_OPC_DDIV:
14078 case R6_OPC_DMOD:
14079 case R6_OPC_DDIVU:
14080 case R6_OPC_DMODU:
14081 check_mips_64(ctx);
14082 gen_r6_muldiv(ctx, op2, rd, rs, rt);
14083 break;
14084 default:
14085 MIPS_INVAL("special_r6 muldiv");
14086 gen_reserved_instruction(ctx);
14087 break;
14089 break;
14090 #endif
14091 default: /* Invalid */
14092 MIPS_INVAL("special_r6");
14093 gen_reserved_instruction(ctx);
14094 break;
14098 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
14100 int rs = extract32(ctx->opcode, 21, 5);
14101 int rt = extract32(ctx->opcode, 16, 5);
14102 int rd = extract32(ctx->opcode, 11, 5);
14103 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
14105 switch (op1) {
14106 case OPC_MOVN: /* Conditional move */
14107 case OPC_MOVZ:
14108 gen_cond_move(ctx, op1, rd, rs, rt);
14109 break;
14110 case OPC_MFHI: /* Move from HI/LO */
14111 case OPC_MFLO:
14112 gen_HILO(ctx, op1, 0, rd);
14113 break;
14114 case OPC_MTHI:
14115 case OPC_MTLO: /* Move to HI/LO */
14116 gen_HILO(ctx, op1, 0, rs);
14117 break;
14118 case OPC_MULT:
14119 case OPC_MULTU:
14120 gen_mul_txx9(ctx, op1, rd, rs, rt);
14121 break;
14122 case OPC_DIV:
14123 case OPC_DIVU:
14124 gen_muldiv(ctx, op1, 0, rs, rt);
14125 break;
14126 #if defined(TARGET_MIPS64)
14127 case OPC_DMULT:
14128 case OPC_DMULTU:
14129 case OPC_DDIV:
14130 case OPC_DDIVU:
14131 check_insn_opc_user_only(ctx, INSN_R5900);
14132 gen_muldiv(ctx, op1, 0, rs, rt);
14133 break;
14134 #endif
14135 case OPC_JR:
14136 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
14137 break;
14138 default: /* Invalid */
14139 MIPS_INVAL("special_tx79");
14140 gen_reserved_instruction(ctx);
14141 break;
14145 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
14147 int rs, rt, rd, sa;
14148 uint32_t op1;
14150 rs = (ctx->opcode >> 21) & 0x1f;
14151 rt = (ctx->opcode >> 16) & 0x1f;
14152 rd = (ctx->opcode >> 11) & 0x1f;
14153 sa = (ctx->opcode >> 6) & 0x1f;
14155 op1 = MASK_SPECIAL(ctx->opcode);
14156 switch (op1) {
14157 case OPC_MOVN: /* Conditional move */
14158 case OPC_MOVZ:
14159 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
14160 INSN_LOONGSON2E | INSN_LOONGSON2F);
14161 gen_cond_move(ctx, op1, rd, rs, rt);
14162 break;
14163 case OPC_MFHI: /* Move from HI/LO */
14164 case OPC_MFLO:
14165 gen_HILO(ctx, op1, rs & 3, rd);
14166 break;
14167 case OPC_MTHI:
14168 case OPC_MTLO: /* Move to HI/LO */
14169 gen_HILO(ctx, op1, rd & 3, rs);
14170 break;
14171 case OPC_MOVCI:
14172 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
14173 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14174 check_cp1_enabled(ctx);
14175 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
14176 (ctx->opcode >> 16) & 1);
14177 } else {
14178 generate_exception_err(ctx, EXCP_CpU, 1);
14180 break;
14181 case OPC_MULT:
14182 case OPC_MULTU:
14183 if (sa) {
14184 check_insn(ctx, INSN_VR54XX);
14185 op1 = MASK_MUL_VR54XX(ctx->opcode);
14186 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
14187 } else {
14188 gen_muldiv(ctx, op1, rd & 3, rs, rt);
14190 break;
14191 case OPC_DIV:
14192 case OPC_DIVU:
14193 gen_muldiv(ctx, op1, 0, rs, rt);
14194 break;
14195 #if defined(TARGET_MIPS64)
14196 case OPC_DMULT:
14197 case OPC_DMULTU:
14198 case OPC_DDIV:
14199 case OPC_DDIVU:
14200 check_insn(ctx, ISA_MIPS3);
14201 check_mips_64(ctx);
14202 gen_muldiv(ctx, op1, 0, rs, rt);
14203 break;
14204 #endif
14205 case OPC_JR:
14206 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
14207 break;
14208 case OPC_SPIM:
14209 #ifdef MIPS_STRICT_STANDARD
14210 MIPS_INVAL("SPIM");
14211 gen_reserved_instruction(ctx);
14212 #else
14213 /* Implemented as RI exception for now. */
14214 MIPS_INVAL("spim (unofficial)");
14215 gen_reserved_instruction(ctx);
14216 #endif
14217 break;
14218 default: /* Invalid */
14219 MIPS_INVAL("special_legacy");
14220 gen_reserved_instruction(ctx);
14221 break;
14225 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
14227 int rs, rt, rd, sa;
14228 uint32_t op1;
14230 rs = (ctx->opcode >> 21) & 0x1f;
14231 rt = (ctx->opcode >> 16) & 0x1f;
14232 rd = (ctx->opcode >> 11) & 0x1f;
14233 sa = (ctx->opcode >> 6) & 0x1f;
14235 op1 = MASK_SPECIAL(ctx->opcode);
14236 switch (op1) {
14237 case OPC_SLL: /* Shift with immediate */
14238 if (sa == 5 && rd == 0 &&
14239 rs == 0 && rt == 0) { /* PAUSE */
14240 if ((ctx->insn_flags & ISA_MIPS_R6) &&
14241 (ctx->hflags & MIPS_HFLAG_BMASK)) {
14242 gen_reserved_instruction(ctx);
14243 break;
14246 /* Fallthrough */
14247 case OPC_SRA:
14248 gen_shift_imm(ctx, op1, rd, rt, sa);
14249 break;
14250 case OPC_SRL:
14251 switch ((ctx->opcode >> 21) & 0x1f) {
14252 case 1:
14253 /* rotr is decoded as srl on non-R2 CPUs */
14254 if (ctx->insn_flags & ISA_MIPS_R2) {
14255 op1 = OPC_ROTR;
14257 /* Fallthrough */
14258 case 0:
14259 gen_shift_imm(ctx, op1, rd, rt, sa);
14260 break;
14261 default:
14262 gen_reserved_instruction(ctx);
14263 break;
14265 break;
14266 case OPC_ADD:
14267 case OPC_ADDU:
14268 case OPC_SUB:
14269 case OPC_SUBU:
14270 gen_arith(ctx, op1, rd, rs, rt);
14271 break;
14272 case OPC_SLLV: /* Shifts */
14273 case OPC_SRAV:
14274 gen_shift(ctx, op1, rd, rs, rt);
14275 break;
14276 case OPC_SRLV:
14277 switch ((ctx->opcode >> 6) & 0x1f) {
14278 case 1:
14279 /* rotrv is decoded as srlv on non-R2 CPUs */
14280 if (ctx->insn_flags & ISA_MIPS_R2) {
14281 op1 = OPC_ROTRV;
14283 /* Fallthrough */
14284 case 0:
14285 gen_shift(ctx, op1, rd, rs, rt);
14286 break;
14287 default:
14288 gen_reserved_instruction(ctx);
14289 break;
14291 break;
14292 case OPC_SLT: /* Set on less than */
14293 case OPC_SLTU:
14294 gen_slt(ctx, op1, rd, rs, rt);
14295 break;
14296 case OPC_AND: /* Logic*/
14297 case OPC_OR:
14298 case OPC_NOR:
14299 case OPC_XOR:
14300 gen_logic(ctx, op1, rd, rs, rt);
14301 break;
14302 case OPC_JALR:
14303 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
14304 break;
14305 case OPC_TGE: /* Traps */
14306 case OPC_TGEU:
14307 case OPC_TLT:
14308 case OPC_TLTU:
14309 case OPC_TEQ:
14310 case OPC_TNE:
14311 check_insn(ctx, ISA_MIPS2);
14312 gen_trap(ctx, op1, rs, rt, -1);
14313 break;
14314 case OPC_PMON:
14315 /* Pmon entry point, also R4010 selsl */
14316 #ifdef MIPS_STRICT_STANDARD
14317 MIPS_INVAL("PMON / selsl");
14318 gen_reserved_instruction(ctx);
14319 #else
14320 gen_helper_0e0i(pmon, sa);
14321 #endif
14322 break;
14323 case OPC_SYSCALL:
14324 generate_exception_end(ctx, EXCP_SYSCALL);
14325 break;
14326 case OPC_BREAK:
14327 generate_exception_end(ctx, EXCP_BREAK);
14328 break;
14329 case OPC_SYNC:
14330 check_insn(ctx, ISA_MIPS2);
14331 gen_sync(extract32(ctx->opcode, 6, 5));
14332 break;
14334 #if defined(TARGET_MIPS64)
14335 /* MIPS64 specific opcodes */
14336 case OPC_DSLL:
14337 case OPC_DSRA:
14338 case OPC_DSLL32:
14339 case OPC_DSRA32:
14340 check_insn(ctx, ISA_MIPS3);
14341 check_mips_64(ctx);
14342 gen_shift_imm(ctx, op1, rd, rt, sa);
14343 break;
14344 case OPC_DSRL:
14345 switch ((ctx->opcode >> 21) & 0x1f) {
14346 case 1:
14347 /* drotr is decoded as dsrl on non-R2 CPUs */
14348 if (ctx->insn_flags & ISA_MIPS_R2) {
14349 op1 = OPC_DROTR;
14351 /* Fallthrough */
14352 case 0:
14353 check_insn(ctx, ISA_MIPS3);
14354 check_mips_64(ctx);
14355 gen_shift_imm(ctx, op1, rd, rt, sa);
14356 break;
14357 default:
14358 gen_reserved_instruction(ctx);
14359 break;
14361 break;
14362 case OPC_DSRL32:
14363 switch ((ctx->opcode >> 21) & 0x1f) {
14364 case 1:
14365 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
14366 if (ctx->insn_flags & ISA_MIPS_R2) {
14367 op1 = OPC_DROTR32;
14369 /* Fallthrough */
14370 case 0:
14371 check_insn(ctx, ISA_MIPS3);
14372 check_mips_64(ctx);
14373 gen_shift_imm(ctx, op1, rd, rt, sa);
14374 break;
14375 default:
14376 gen_reserved_instruction(ctx);
14377 break;
14379 break;
14380 case OPC_DADD:
14381 case OPC_DADDU:
14382 case OPC_DSUB:
14383 case OPC_DSUBU:
14384 check_insn(ctx, ISA_MIPS3);
14385 check_mips_64(ctx);
14386 gen_arith(ctx, op1, rd, rs, rt);
14387 break;
14388 case OPC_DSLLV:
14389 case OPC_DSRAV:
14390 check_insn(ctx, ISA_MIPS3);
14391 check_mips_64(ctx);
14392 gen_shift(ctx, op1, rd, rs, rt);
14393 break;
14394 case OPC_DSRLV:
14395 switch ((ctx->opcode >> 6) & 0x1f) {
14396 case 1:
14397 /* drotrv is decoded as dsrlv on non-R2 CPUs */
14398 if (ctx->insn_flags & ISA_MIPS_R2) {
14399 op1 = OPC_DROTRV;
14401 /* Fallthrough */
14402 case 0:
14403 check_insn(ctx, ISA_MIPS3);
14404 check_mips_64(ctx);
14405 gen_shift(ctx, op1, rd, rs, rt);
14406 break;
14407 default:
14408 gen_reserved_instruction(ctx);
14409 break;
14411 break;
14412 #endif
14413 default:
14414 if (ctx->insn_flags & ISA_MIPS_R6) {
14415 decode_opc_special_r6(env, ctx);
14416 } else if (ctx->insn_flags & INSN_R5900) {
14417 decode_opc_special_tx79(env, ctx);
14418 } else {
14419 decode_opc_special_legacy(env, ctx);
14425 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
14427 int rs, rt, rd;
14428 uint32_t op1;
14430 rs = (ctx->opcode >> 21) & 0x1f;
14431 rt = (ctx->opcode >> 16) & 0x1f;
14432 rd = (ctx->opcode >> 11) & 0x1f;
14434 op1 = MASK_SPECIAL2(ctx->opcode);
14435 switch (op1) {
14436 case OPC_MADD: /* Multiply and add/sub */
14437 case OPC_MADDU:
14438 case OPC_MSUB:
14439 case OPC_MSUBU:
14440 check_insn(ctx, ISA_MIPS_R1);
14441 gen_muldiv(ctx, op1, rd & 3, rs, rt);
14442 break;
14443 case OPC_MUL:
14444 gen_arith(ctx, op1, rd, rs, rt);
14445 break;
14446 case OPC_DIV_G_2F:
14447 case OPC_DIVU_G_2F:
14448 case OPC_MULT_G_2F:
14449 case OPC_MULTU_G_2F:
14450 case OPC_MOD_G_2F:
14451 case OPC_MODU_G_2F:
14452 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
14453 gen_loongson_integer(ctx, op1, rd, rs, rt);
14454 break;
14455 case OPC_CLO:
14456 case OPC_CLZ:
14457 check_insn(ctx, ISA_MIPS_R1);
14458 gen_cl(ctx, op1, rd, rs);
14459 break;
14460 case OPC_SDBBP:
14461 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
14462 gen_helper_do_semihosting(cpu_env);
14463 } else {
14465 * XXX: not clear which exception should be raised
14466 * when in debug mode...
14468 check_insn(ctx, ISA_MIPS_R1);
14469 generate_exception_end(ctx, EXCP_DBp);
14471 break;
14472 #if defined(TARGET_MIPS64)
14473 case OPC_DCLO:
14474 case OPC_DCLZ:
14475 check_insn(ctx, ISA_MIPS_R1);
14476 check_mips_64(ctx);
14477 gen_cl(ctx, op1, rd, rs);
14478 break;
14479 case OPC_DMULT_G_2F:
14480 case OPC_DMULTU_G_2F:
14481 case OPC_DDIV_G_2F:
14482 case OPC_DDIVU_G_2F:
14483 case OPC_DMOD_G_2F:
14484 case OPC_DMODU_G_2F:
14485 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
14486 gen_loongson_integer(ctx, op1, rd, rs, rt);
14487 break;
14488 #endif
14489 default: /* Invalid */
14490 MIPS_INVAL("special2_legacy");
14491 gen_reserved_instruction(ctx);
14492 break;
14496 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
14498 int rs, rt, rd, sa;
14499 uint32_t op1, op2;
14500 int16_t imm;
14502 rs = (ctx->opcode >> 21) & 0x1f;
14503 rt = (ctx->opcode >> 16) & 0x1f;
14504 rd = (ctx->opcode >> 11) & 0x1f;
14505 sa = (ctx->opcode >> 6) & 0x1f;
14506 imm = (int16_t)ctx->opcode >> 7;
14508 op1 = MASK_SPECIAL3(ctx->opcode);
14509 switch (op1) {
14510 case R6_OPC_PREF:
14511 if (rt >= 24) {
14512 /* hint codes 24-31 are reserved and signal RI */
14513 gen_reserved_instruction(ctx);
14515 /* Treat as NOP. */
14516 break;
14517 case R6_OPC_CACHE:
14518 check_cp0_enabled(ctx);
14519 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14520 gen_cache_operation(ctx, rt, rs, imm);
14522 break;
14523 case R6_OPC_SC:
14524 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
14525 break;
14526 case R6_OPC_LL:
14527 gen_ld(ctx, op1, rt, rs, imm);
14528 break;
14529 case OPC_BSHFL:
14531 if (rd == 0) {
14532 /* Treat as NOP. */
14533 break;
14535 op2 = MASK_BSHFL(ctx->opcode);
14536 switch (op2) {
14537 case OPC_ALIGN:
14538 case OPC_ALIGN_1:
14539 case OPC_ALIGN_2:
14540 case OPC_ALIGN_3:
14541 gen_align(ctx, 32, rd, rs, rt, sa & 3);
14542 break;
14543 case OPC_BITSWAP:
14544 gen_bitswap(ctx, op2, rd, rt);
14545 break;
14548 break;
14549 #ifndef CONFIG_USER_ONLY
14550 case OPC_GINV:
14551 if (unlikely(ctx->gi <= 1)) {
14552 gen_reserved_instruction(ctx);
14554 check_cp0_enabled(ctx);
14555 switch ((ctx->opcode >> 6) & 3) {
14556 case 0: /* GINVI */
14557 /* Treat as NOP. */
14558 break;
14559 case 2: /* GINVT */
14560 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
14561 break;
14562 default:
14563 gen_reserved_instruction(ctx);
14564 break;
14566 break;
14567 #endif
14568 #if defined(TARGET_MIPS64)
14569 case R6_OPC_SCD:
14570 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
14571 break;
14572 case R6_OPC_LLD:
14573 gen_ld(ctx, op1, rt, rs, imm);
14574 break;
14575 case OPC_DBSHFL:
14576 check_mips_64(ctx);
14578 if (rd == 0) {
14579 /* Treat as NOP. */
14580 break;
14582 op2 = MASK_DBSHFL(ctx->opcode);
14583 switch (op2) {
14584 case OPC_DALIGN:
14585 case OPC_DALIGN_1:
14586 case OPC_DALIGN_2:
14587 case OPC_DALIGN_3:
14588 case OPC_DALIGN_4:
14589 case OPC_DALIGN_5:
14590 case OPC_DALIGN_6:
14591 case OPC_DALIGN_7:
14592 gen_align(ctx, 64, rd, rs, rt, sa & 7);
14593 break;
14594 case OPC_DBITSWAP:
14595 gen_bitswap(ctx, op2, rd, rt);
14596 break;
14600 break;
14601 #endif
14602 default: /* Invalid */
14603 MIPS_INVAL("special3_r6");
14604 gen_reserved_instruction(ctx);
14605 break;
14609 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
14611 int rs, rt, rd;
14612 uint32_t op1, op2;
14614 rs = (ctx->opcode >> 21) & 0x1f;
14615 rt = (ctx->opcode >> 16) & 0x1f;
14616 rd = (ctx->opcode >> 11) & 0x1f;
14618 op1 = MASK_SPECIAL3(ctx->opcode);
14619 switch (op1) {
14620 case OPC_DIV_G_2E:
14621 case OPC_DIVU_G_2E:
14622 case OPC_MOD_G_2E:
14623 case OPC_MODU_G_2E:
14624 case OPC_MULT_G_2E:
14625 case OPC_MULTU_G_2E:
14627 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14628 * the same mask and op1.
14630 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
14631 op2 = MASK_ADDUH_QB(ctx->opcode);
14632 switch (op2) {
14633 case OPC_ADDUH_QB:
14634 case OPC_ADDUH_R_QB:
14635 case OPC_ADDQH_PH:
14636 case OPC_ADDQH_R_PH:
14637 case OPC_ADDQH_W:
14638 case OPC_ADDQH_R_W:
14639 case OPC_SUBUH_QB:
14640 case OPC_SUBUH_R_QB:
14641 case OPC_SUBQH_PH:
14642 case OPC_SUBQH_R_PH:
14643 case OPC_SUBQH_W:
14644 case OPC_SUBQH_R_W:
14645 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14646 break;
14647 case OPC_MUL_PH:
14648 case OPC_MUL_S_PH:
14649 case OPC_MULQ_S_W:
14650 case OPC_MULQ_RS_W:
14651 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14652 break;
14653 default:
14654 MIPS_INVAL("MASK ADDUH.QB");
14655 gen_reserved_instruction(ctx);
14656 break;
14658 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
14659 gen_loongson_integer(ctx, op1, rd, rs, rt);
14660 } else {
14661 gen_reserved_instruction(ctx);
14663 break;
14664 case OPC_LX_DSP:
14665 op2 = MASK_LX(ctx->opcode);
14666 switch (op2) {
14667 #if defined(TARGET_MIPS64)
14668 case OPC_LDX:
14669 #endif
14670 case OPC_LBUX:
14671 case OPC_LHX:
14672 case OPC_LWX:
14673 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
14674 break;
14675 default: /* Invalid */
14676 MIPS_INVAL("MASK LX");
14677 gen_reserved_instruction(ctx);
14678 break;
14680 break;
14681 case OPC_ABSQ_S_PH_DSP:
14682 op2 = MASK_ABSQ_S_PH(ctx->opcode);
14683 switch (op2) {
14684 case OPC_ABSQ_S_QB:
14685 case OPC_ABSQ_S_PH:
14686 case OPC_ABSQ_S_W:
14687 case OPC_PRECEQ_W_PHL:
14688 case OPC_PRECEQ_W_PHR:
14689 case OPC_PRECEQU_PH_QBL:
14690 case OPC_PRECEQU_PH_QBR:
14691 case OPC_PRECEQU_PH_QBLA:
14692 case OPC_PRECEQU_PH_QBRA:
14693 case OPC_PRECEU_PH_QBL:
14694 case OPC_PRECEU_PH_QBR:
14695 case OPC_PRECEU_PH_QBLA:
14696 case OPC_PRECEU_PH_QBRA:
14697 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14698 break;
14699 case OPC_BITREV:
14700 case OPC_REPL_QB:
14701 case OPC_REPLV_QB:
14702 case OPC_REPL_PH:
14703 case OPC_REPLV_PH:
14704 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
14705 break;
14706 default:
14707 MIPS_INVAL("MASK ABSQ_S.PH");
14708 gen_reserved_instruction(ctx);
14709 break;
14711 break;
14712 case OPC_ADDU_QB_DSP:
14713 op2 = MASK_ADDU_QB(ctx->opcode);
14714 switch (op2) {
14715 case OPC_ADDQ_PH:
14716 case OPC_ADDQ_S_PH:
14717 case OPC_ADDQ_S_W:
14718 case OPC_ADDU_QB:
14719 case OPC_ADDU_S_QB:
14720 case OPC_ADDU_PH:
14721 case OPC_ADDU_S_PH:
14722 case OPC_SUBQ_PH:
14723 case OPC_SUBQ_S_PH:
14724 case OPC_SUBQ_S_W:
14725 case OPC_SUBU_QB:
14726 case OPC_SUBU_S_QB:
14727 case OPC_SUBU_PH:
14728 case OPC_SUBU_S_PH:
14729 case OPC_ADDSC:
14730 case OPC_ADDWC:
14731 case OPC_MODSUB:
14732 case OPC_RADDU_W_QB:
14733 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14734 break;
14735 case OPC_MULEU_S_PH_QBL:
14736 case OPC_MULEU_S_PH_QBR:
14737 case OPC_MULQ_RS_PH:
14738 case OPC_MULEQ_S_W_PHL:
14739 case OPC_MULEQ_S_W_PHR:
14740 case OPC_MULQ_S_PH:
14741 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14742 break;
14743 default: /* Invalid */
14744 MIPS_INVAL("MASK ADDU.QB");
14745 gen_reserved_instruction(ctx);
14746 break;
14749 break;
14750 case OPC_CMPU_EQ_QB_DSP:
14751 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
14752 switch (op2) {
14753 case OPC_PRECR_SRA_PH_W:
14754 case OPC_PRECR_SRA_R_PH_W:
14755 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14756 break;
14757 case OPC_PRECR_QB_PH:
14758 case OPC_PRECRQ_QB_PH:
14759 case OPC_PRECRQ_PH_W:
14760 case OPC_PRECRQ_RS_PH_W:
14761 case OPC_PRECRQU_S_QB_PH:
14762 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14763 break;
14764 case OPC_CMPU_EQ_QB:
14765 case OPC_CMPU_LT_QB:
14766 case OPC_CMPU_LE_QB:
14767 case OPC_CMP_EQ_PH:
14768 case OPC_CMP_LT_PH:
14769 case OPC_CMP_LE_PH:
14770 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
14771 break;
14772 case OPC_CMPGU_EQ_QB:
14773 case OPC_CMPGU_LT_QB:
14774 case OPC_CMPGU_LE_QB:
14775 case OPC_CMPGDU_EQ_QB:
14776 case OPC_CMPGDU_LT_QB:
14777 case OPC_CMPGDU_LE_QB:
14778 case OPC_PICK_QB:
14779 case OPC_PICK_PH:
14780 case OPC_PACKRL_PH:
14781 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
14782 break;
14783 default: /* Invalid */
14784 MIPS_INVAL("MASK CMPU.EQ.QB");
14785 gen_reserved_instruction(ctx);
14786 break;
14788 break;
14789 case OPC_SHLL_QB_DSP:
14790 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14791 break;
14792 case OPC_DPA_W_PH_DSP:
14793 op2 = MASK_DPA_W_PH(ctx->opcode);
14794 switch (op2) {
14795 case OPC_DPAU_H_QBL:
14796 case OPC_DPAU_H_QBR:
14797 case OPC_DPSU_H_QBL:
14798 case OPC_DPSU_H_QBR:
14799 case OPC_DPA_W_PH:
14800 case OPC_DPAX_W_PH:
14801 case OPC_DPAQ_S_W_PH:
14802 case OPC_DPAQX_S_W_PH:
14803 case OPC_DPAQX_SA_W_PH:
14804 case OPC_DPS_W_PH:
14805 case OPC_DPSX_W_PH:
14806 case OPC_DPSQ_S_W_PH:
14807 case OPC_DPSQX_S_W_PH:
14808 case OPC_DPSQX_SA_W_PH:
14809 case OPC_MULSAQ_S_W_PH:
14810 case OPC_DPAQ_SA_L_W:
14811 case OPC_DPSQ_SA_L_W:
14812 case OPC_MAQ_S_W_PHL:
14813 case OPC_MAQ_S_W_PHR:
14814 case OPC_MAQ_SA_W_PHL:
14815 case OPC_MAQ_SA_W_PHR:
14816 case OPC_MULSA_W_PH:
14817 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14818 break;
14819 default: /* Invalid */
14820 MIPS_INVAL("MASK DPAW.PH");
14821 gen_reserved_instruction(ctx);
14822 break;
14824 break;
14825 case OPC_INSV_DSP:
14826 op2 = MASK_INSV(ctx->opcode);
14827 switch (op2) {
14828 case OPC_INSV:
14829 check_dsp(ctx);
14831 TCGv t0, t1;
14833 if (rt == 0) {
14834 break;
14837 t0 = tcg_temp_new();
14838 t1 = tcg_temp_new();
14840 gen_load_gpr(t0, rt);
14841 gen_load_gpr(t1, rs);
14843 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
14845 tcg_temp_free(t0);
14846 tcg_temp_free(t1);
14847 break;
14849 default: /* Invalid */
14850 MIPS_INVAL("MASK INSV");
14851 gen_reserved_instruction(ctx);
14852 break;
14854 break;
14855 case OPC_APPEND_DSP:
14856 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
14857 break;
14858 case OPC_EXTR_W_DSP:
14859 op2 = MASK_EXTR_W(ctx->opcode);
14860 switch (op2) {
14861 case OPC_EXTR_W:
14862 case OPC_EXTR_R_W:
14863 case OPC_EXTR_RS_W:
14864 case OPC_EXTR_S_H:
14865 case OPC_EXTRV_S_H:
14866 case OPC_EXTRV_W:
14867 case OPC_EXTRV_R_W:
14868 case OPC_EXTRV_RS_W:
14869 case OPC_EXTP:
14870 case OPC_EXTPV:
14871 case OPC_EXTPDP:
14872 case OPC_EXTPDPV:
14873 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
14874 break;
14875 case OPC_RDDSP:
14876 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
14877 break;
14878 case OPC_SHILO:
14879 case OPC_SHILOV:
14880 case OPC_MTHLIP:
14881 case OPC_WRDSP:
14882 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
14883 break;
14884 default: /* Invalid */
14885 MIPS_INVAL("MASK EXTR.W");
14886 gen_reserved_instruction(ctx);
14887 break;
14889 break;
14890 #if defined(TARGET_MIPS64)
14891 case OPC_DDIV_G_2E:
14892 case OPC_DDIVU_G_2E:
14893 case OPC_DMULT_G_2E:
14894 case OPC_DMULTU_G_2E:
14895 case OPC_DMOD_G_2E:
14896 case OPC_DMODU_G_2E:
14897 check_insn(ctx, INSN_LOONGSON2E);
14898 gen_loongson_integer(ctx, op1, rd, rs, rt);
14899 break;
14900 case OPC_ABSQ_S_QH_DSP:
14901 op2 = MASK_ABSQ_S_QH(ctx->opcode);
14902 switch (op2) {
14903 case OPC_PRECEQ_L_PWL:
14904 case OPC_PRECEQ_L_PWR:
14905 case OPC_PRECEQ_PW_QHL:
14906 case OPC_PRECEQ_PW_QHR:
14907 case OPC_PRECEQ_PW_QHLA:
14908 case OPC_PRECEQ_PW_QHRA:
14909 case OPC_PRECEQU_QH_OBL:
14910 case OPC_PRECEQU_QH_OBR:
14911 case OPC_PRECEQU_QH_OBLA:
14912 case OPC_PRECEQU_QH_OBRA:
14913 case OPC_PRECEU_QH_OBL:
14914 case OPC_PRECEU_QH_OBR:
14915 case OPC_PRECEU_QH_OBLA:
14916 case OPC_PRECEU_QH_OBRA:
14917 case OPC_ABSQ_S_OB:
14918 case OPC_ABSQ_S_PW:
14919 case OPC_ABSQ_S_QH:
14920 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14921 break;
14922 case OPC_REPL_OB:
14923 case OPC_REPL_PW:
14924 case OPC_REPL_QH:
14925 case OPC_REPLV_OB:
14926 case OPC_REPLV_PW:
14927 case OPC_REPLV_QH:
14928 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
14929 break;
14930 default: /* Invalid */
14931 MIPS_INVAL("MASK ABSQ_S.QH");
14932 gen_reserved_instruction(ctx);
14933 break;
14935 break;
14936 case OPC_ADDU_OB_DSP:
14937 op2 = MASK_ADDU_OB(ctx->opcode);
14938 switch (op2) {
14939 case OPC_RADDU_L_OB:
14940 case OPC_SUBQ_PW:
14941 case OPC_SUBQ_S_PW:
14942 case OPC_SUBQ_QH:
14943 case OPC_SUBQ_S_QH:
14944 case OPC_SUBU_OB:
14945 case OPC_SUBU_S_OB:
14946 case OPC_SUBU_QH:
14947 case OPC_SUBU_S_QH:
14948 case OPC_SUBUH_OB:
14949 case OPC_SUBUH_R_OB:
14950 case OPC_ADDQ_PW:
14951 case OPC_ADDQ_S_PW:
14952 case OPC_ADDQ_QH:
14953 case OPC_ADDQ_S_QH:
14954 case OPC_ADDU_OB:
14955 case OPC_ADDU_S_OB:
14956 case OPC_ADDU_QH:
14957 case OPC_ADDU_S_QH:
14958 case OPC_ADDUH_OB:
14959 case OPC_ADDUH_R_OB:
14960 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14961 break;
14962 case OPC_MULEQ_S_PW_QHL:
14963 case OPC_MULEQ_S_PW_QHR:
14964 case OPC_MULEU_S_QH_OBL:
14965 case OPC_MULEU_S_QH_OBR:
14966 case OPC_MULQ_RS_QH:
14967 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14968 break;
14969 default: /* Invalid */
14970 MIPS_INVAL("MASK ADDU.OB");
14971 gen_reserved_instruction(ctx);
14972 break;
14974 break;
14975 case OPC_CMPU_EQ_OB_DSP:
14976 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
14977 switch (op2) {
14978 case OPC_PRECR_SRA_QH_PW:
14979 case OPC_PRECR_SRA_R_QH_PW:
14980 /* Return value is rt. */
14981 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14982 break;
14983 case OPC_PRECR_OB_QH:
14984 case OPC_PRECRQ_OB_QH:
14985 case OPC_PRECRQ_PW_L:
14986 case OPC_PRECRQ_QH_PW:
14987 case OPC_PRECRQ_RS_QH_PW:
14988 case OPC_PRECRQU_S_OB_QH:
14989 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14990 break;
14991 case OPC_CMPU_EQ_OB:
14992 case OPC_CMPU_LT_OB:
14993 case OPC_CMPU_LE_OB:
14994 case OPC_CMP_EQ_QH:
14995 case OPC_CMP_LT_QH:
14996 case OPC_CMP_LE_QH:
14997 case OPC_CMP_EQ_PW:
14998 case OPC_CMP_LT_PW:
14999 case OPC_CMP_LE_PW:
15000 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
15001 break;
15002 case OPC_CMPGDU_EQ_OB:
15003 case OPC_CMPGDU_LT_OB:
15004 case OPC_CMPGDU_LE_OB:
15005 case OPC_CMPGU_EQ_OB:
15006 case OPC_CMPGU_LT_OB:
15007 case OPC_CMPGU_LE_OB:
15008 case OPC_PACKRL_PW:
15009 case OPC_PICK_OB:
15010 case OPC_PICK_PW:
15011 case OPC_PICK_QH:
15012 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
15013 break;
15014 default: /* Invalid */
15015 MIPS_INVAL("MASK CMPU_EQ.OB");
15016 gen_reserved_instruction(ctx);
15017 break;
15019 break;
15020 case OPC_DAPPEND_DSP:
15021 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
15022 break;
15023 case OPC_DEXTR_W_DSP:
15024 op2 = MASK_DEXTR_W(ctx->opcode);
15025 switch (op2) {
15026 case OPC_DEXTP:
15027 case OPC_DEXTPDP:
15028 case OPC_DEXTPDPV:
15029 case OPC_DEXTPV:
15030 case OPC_DEXTR_L:
15031 case OPC_DEXTR_R_L:
15032 case OPC_DEXTR_RS_L:
15033 case OPC_DEXTR_W:
15034 case OPC_DEXTR_R_W:
15035 case OPC_DEXTR_RS_W:
15036 case OPC_DEXTR_S_H:
15037 case OPC_DEXTRV_L:
15038 case OPC_DEXTRV_R_L:
15039 case OPC_DEXTRV_RS_L:
15040 case OPC_DEXTRV_S_H:
15041 case OPC_DEXTRV_W:
15042 case OPC_DEXTRV_R_W:
15043 case OPC_DEXTRV_RS_W:
15044 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
15045 break;
15046 case OPC_DMTHLIP:
15047 case OPC_DSHILO:
15048 case OPC_DSHILOV:
15049 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
15050 break;
15051 default: /* Invalid */
15052 MIPS_INVAL("MASK EXTR.W");
15053 gen_reserved_instruction(ctx);
15054 break;
15056 break;
15057 case OPC_DPAQ_W_QH_DSP:
15058 op2 = MASK_DPAQ_W_QH(ctx->opcode);
15059 switch (op2) {
15060 case OPC_DPAU_H_OBL:
15061 case OPC_DPAU_H_OBR:
15062 case OPC_DPSU_H_OBL:
15063 case OPC_DPSU_H_OBR:
15064 case OPC_DPA_W_QH:
15065 case OPC_DPAQ_S_W_QH:
15066 case OPC_DPS_W_QH:
15067 case OPC_DPSQ_S_W_QH:
15068 case OPC_MULSAQ_S_W_QH:
15069 case OPC_DPAQ_SA_L_PW:
15070 case OPC_DPSQ_SA_L_PW:
15071 case OPC_MULSAQ_S_L_PW:
15072 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15073 break;
15074 case OPC_MAQ_S_W_QHLL:
15075 case OPC_MAQ_S_W_QHLR:
15076 case OPC_MAQ_S_W_QHRL:
15077 case OPC_MAQ_S_W_QHRR:
15078 case OPC_MAQ_SA_W_QHLL:
15079 case OPC_MAQ_SA_W_QHLR:
15080 case OPC_MAQ_SA_W_QHRL:
15081 case OPC_MAQ_SA_W_QHRR:
15082 case OPC_MAQ_S_L_PWL:
15083 case OPC_MAQ_S_L_PWR:
15084 case OPC_DMADD:
15085 case OPC_DMADDU:
15086 case OPC_DMSUB:
15087 case OPC_DMSUBU:
15088 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15089 break;
15090 default: /* Invalid */
15091 MIPS_INVAL("MASK DPAQ.W.QH");
15092 gen_reserved_instruction(ctx);
15093 break;
15095 break;
15096 case OPC_DINSV_DSP:
15097 op2 = MASK_INSV(ctx->opcode);
15098 switch (op2) {
15099 case OPC_DINSV:
15101 TCGv t0, t1;
15103 check_dsp(ctx);
15105 if (rt == 0) {
15106 break;
15109 t0 = tcg_temp_new();
15110 t1 = tcg_temp_new();
15112 gen_load_gpr(t0, rt);
15113 gen_load_gpr(t1, rs);
15115 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
15117 tcg_temp_free(t0);
15118 tcg_temp_free(t1);
15119 break;
15121 default: /* Invalid */
15122 MIPS_INVAL("MASK DINSV");
15123 gen_reserved_instruction(ctx);
15124 break;
15126 break;
15127 case OPC_SHLL_OB_DSP:
15128 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
15129 break;
15130 #endif
15131 default: /* Invalid */
15132 MIPS_INVAL("special3_legacy");
15133 gen_reserved_instruction(ctx);
15134 break;
15139 #if defined(TARGET_MIPS64)
15141 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
15143 uint32_t opc = MASK_MMI(ctx->opcode);
15144 int rs = extract32(ctx->opcode, 21, 5);
15145 int rt = extract32(ctx->opcode, 16, 5);
15146 int rd = extract32(ctx->opcode, 11, 5);
15148 switch (opc) {
15149 case MMI_OPC_MULT1:
15150 case MMI_OPC_MULTU1:
15151 case MMI_OPC_MADD:
15152 case MMI_OPC_MADDU:
15153 case MMI_OPC_MADD1:
15154 case MMI_OPC_MADDU1:
15155 gen_mul_txx9(ctx, opc, rd, rs, rt);
15156 break;
15157 case MMI_OPC_DIV1:
15158 case MMI_OPC_DIVU1:
15159 gen_div1_tx79(ctx, opc, rs, rt);
15160 break;
15161 default:
15162 MIPS_INVAL("TX79 MMI class");
15163 gen_reserved_instruction(ctx);
15164 break;
15168 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
15170 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
15174 * The TX79-specific instruction Store Quadword
15176 * +--------+-------+-------+------------------------+
15177 * | 011111 | base | rt | offset | SQ
15178 * +--------+-------+-------+------------------------+
15179 * 6 5 5 16
15181 * has the same opcode as the Read Hardware Register instruction
15183 * +--------+-------+-------+-------+-------+--------+
15184 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
15185 * +--------+-------+-------+-------+-------+--------+
15186 * 6 5 5 5 5 6
15188 * that is required, trapped and emulated by the Linux kernel. However, all
15189 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
15190 * offset is odd. Therefore all valid SQ instructions can execute normally.
15191 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
15192 * between SQ and RDHWR, as the Linux kernel does.
15194 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
15196 int base = extract32(ctx->opcode, 21, 5);
15197 int rt = extract32(ctx->opcode, 16, 5);
15198 int offset = extract32(ctx->opcode, 0, 16);
15200 #ifdef CONFIG_USER_ONLY
15201 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
15202 uint32_t op2 = extract32(ctx->opcode, 6, 5);
15204 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
15205 int rd = extract32(ctx->opcode, 11, 5);
15207 gen_rdhwr(ctx, rt, rd, 0);
15208 return;
15210 #endif
15212 gen_mmi_sq(ctx, base, rt, offset);
15215 #endif
15217 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
15219 int rs, rt, rd, sa;
15220 uint32_t op1, op2;
15221 int16_t imm;
15223 rs = (ctx->opcode >> 21) & 0x1f;
15224 rt = (ctx->opcode >> 16) & 0x1f;
15225 rd = (ctx->opcode >> 11) & 0x1f;
15226 sa = (ctx->opcode >> 6) & 0x1f;
15227 imm = sextract32(ctx->opcode, 7, 9);
15229 op1 = MASK_SPECIAL3(ctx->opcode);
15232 * EVA loads and stores overlap Loongson 2E instructions decoded by
15233 * decode_opc_special3_legacy(), so be careful to allow their decoding when
15234 * EVA is absent.
15236 if (ctx->eva) {
15237 switch (op1) {
15238 case OPC_LWLE:
15239 case OPC_LWRE:
15240 case OPC_LBUE:
15241 case OPC_LHUE:
15242 case OPC_LBE:
15243 case OPC_LHE:
15244 case OPC_LLE:
15245 case OPC_LWE:
15246 check_cp0_enabled(ctx);
15247 gen_ld(ctx, op1, rt, rs, imm);
15248 return;
15249 case OPC_SWLE:
15250 case OPC_SWRE:
15251 case OPC_SBE:
15252 case OPC_SHE:
15253 case OPC_SWE:
15254 check_cp0_enabled(ctx);
15255 gen_st(ctx, op1, rt, rs, imm);
15256 return;
15257 case OPC_SCE:
15258 check_cp0_enabled(ctx);
15259 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
15260 return;
15261 case OPC_CACHEE:
15262 check_eva(ctx);
15263 check_cp0_enabled(ctx);
15264 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15265 gen_cache_operation(ctx, rt, rs, imm);
15267 return;
15268 case OPC_PREFE:
15269 check_cp0_enabled(ctx);
15270 /* Treat as NOP. */
15271 return;
15275 switch (op1) {
15276 case OPC_EXT:
15277 case OPC_INS:
15278 check_insn(ctx, ISA_MIPS_R2);
15279 gen_bitops(ctx, op1, rt, rs, sa, rd);
15280 break;
15281 case OPC_BSHFL:
15282 op2 = MASK_BSHFL(ctx->opcode);
15283 switch (op2) {
15284 case OPC_ALIGN:
15285 case OPC_ALIGN_1:
15286 case OPC_ALIGN_2:
15287 case OPC_ALIGN_3:
15288 case OPC_BITSWAP:
15289 check_insn(ctx, ISA_MIPS_R6);
15290 decode_opc_special3_r6(env, ctx);
15291 break;
15292 default:
15293 check_insn(ctx, ISA_MIPS_R2);
15294 gen_bshfl(ctx, op2, rt, rd);
15295 break;
15297 break;
15298 #if defined(TARGET_MIPS64)
15299 case OPC_DEXTM:
15300 case OPC_DEXTU:
15301 case OPC_DEXT:
15302 case OPC_DINSM:
15303 case OPC_DINSU:
15304 case OPC_DINS:
15305 check_insn(ctx, ISA_MIPS_R2);
15306 check_mips_64(ctx);
15307 gen_bitops(ctx, op1, rt, rs, sa, rd);
15308 break;
15309 case OPC_DBSHFL:
15310 op2 = MASK_DBSHFL(ctx->opcode);
15311 switch (op2) {
15312 case OPC_DALIGN:
15313 case OPC_DALIGN_1:
15314 case OPC_DALIGN_2:
15315 case OPC_DALIGN_3:
15316 case OPC_DALIGN_4:
15317 case OPC_DALIGN_5:
15318 case OPC_DALIGN_6:
15319 case OPC_DALIGN_7:
15320 case OPC_DBITSWAP:
15321 check_insn(ctx, ISA_MIPS_R6);
15322 decode_opc_special3_r6(env, ctx);
15323 break;
15324 default:
15325 check_insn(ctx, ISA_MIPS_R2);
15326 check_mips_64(ctx);
15327 op2 = MASK_DBSHFL(ctx->opcode);
15328 gen_bshfl(ctx, op2, rt, rd);
15329 break;
15331 break;
15332 #endif
15333 case OPC_RDHWR:
15334 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
15335 break;
15336 case OPC_FORK:
15337 check_mt(ctx);
15339 TCGv t0 = tcg_temp_new();
15340 TCGv t1 = tcg_temp_new();
15342 gen_load_gpr(t0, rt);
15343 gen_load_gpr(t1, rs);
15344 gen_helper_fork(t0, t1);
15345 tcg_temp_free(t0);
15346 tcg_temp_free(t1);
15348 break;
15349 case OPC_YIELD:
15350 check_mt(ctx);
15352 TCGv t0 = tcg_temp_new();
15354 gen_load_gpr(t0, rs);
15355 gen_helper_yield(t0, cpu_env, t0);
15356 gen_store_gpr(t0, rd);
15357 tcg_temp_free(t0);
15359 break;
15360 default:
15361 if (ctx->insn_flags & ISA_MIPS_R6) {
15362 decode_opc_special3_r6(env, ctx);
15363 } else {
15364 decode_opc_special3_legacy(env, ctx);
15369 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
15371 int32_t offset;
15372 int rs, rt, rd, sa;
15373 uint32_t op, op1;
15374 int16_t imm;
15376 op = MASK_OP_MAJOR(ctx->opcode);
15377 rs = (ctx->opcode >> 21) & 0x1f;
15378 rt = (ctx->opcode >> 16) & 0x1f;
15379 rd = (ctx->opcode >> 11) & 0x1f;
15380 sa = (ctx->opcode >> 6) & 0x1f;
15381 imm = (int16_t)ctx->opcode;
15382 switch (op) {
15383 case OPC_SPECIAL:
15384 decode_opc_special(env, ctx);
15385 break;
15386 case OPC_SPECIAL2:
15387 #if defined(TARGET_MIPS64)
15388 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
15389 decode_mmi(env, ctx);
15390 break;
15392 #endif
15393 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
15394 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
15395 gen_arith(ctx, OPC_MUL, rd, rs, rt);
15396 } else {
15397 decode_ase_mxu(ctx, ctx->opcode);
15399 break;
15401 decode_opc_special2_legacy(env, ctx);
15402 break;
15403 case OPC_SPECIAL3:
15404 #if defined(TARGET_MIPS64)
15405 if (ctx->insn_flags & INSN_R5900) {
15406 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
15407 } else {
15408 decode_opc_special3(env, ctx);
15410 #else
15411 decode_opc_special3(env, ctx);
15412 #endif
15413 break;
15414 case OPC_REGIMM:
15415 op1 = MASK_REGIMM(ctx->opcode);
15416 switch (op1) {
15417 case OPC_BLTZL: /* REGIMM branches */
15418 case OPC_BGEZL:
15419 case OPC_BLTZALL:
15420 case OPC_BGEZALL:
15421 check_insn(ctx, ISA_MIPS2);
15422 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15423 /* Fallthrough */
15424 case OPC_BLTZ:
15425 case OPC_BGEZ:
15426 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
15427 break;
15428 case OPC_BLTZAL:
15429 case OPC_BGEZAL:
15430 if (ctx->insn_flags & ISA_MIPS_R6) {
15431 if (rs == 0) {
15432 /* OPC_NAL, OPC_BAL */
15433 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
15434 } else {
15435 gen_reserved_instruction(ctx);
15437 } else {
15438 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
15440 break;
15441 case OPC_TGEI: /* REGIMM traps */
15442 case OPC_TGEIU:
15443 case OPC_TLTI:
15444 case OPC_TLTIU:
15445 case OPC_TEQI:
15447 case OPC_TNEI:
15448 check_insn(ctx, ISA_MIPS2);
15449 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15450 gen_trap(ctx, op1, rs, -1, imm);
15451 break;
15452 case OPC_SIGRIE:
15453 check_insn(ctx, ISA_MIPS_R6);
15454 gen_reserved_instruction(ctx);
15455 break;
15456 case OPC_SYNCI:
15457 check_insn(ctx, ISA_MIPS_R2);
15459 * Break the TB to be able to sync copied instructions
15460 * immediately.
15462 ctx->base.is_jmp = DISAS_STOP;
15463 break;
15464 case OPC_BPOSGE32: /* MIPS DSP branch */
15465 #if defined(TARGET_MIPS64)
15466 case OPC_BPOSGE64:
15467 #endif
15468 check_dsp(ctx);
15469 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
15470 break;
15471 #if defined(TARGET_MIPS64)
15472 case OPC_DAHI:
15473 check_insn(ctx, ISA_MIPS_R6);
15474 check_mips_64(ctx);
15475 if (rs != 0) {
15476 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
15478 break;
15479 case OPC_DATI:
15480 check_insn(ctx, ISA_MIPS_R6);
15481 check_mips_64(ctx);
15482 if (rs != 0) {
15483 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
15485 break;
15486 #endif
15487 default: /* Invalid */
15488 MIPS_INVAL("regimm");
15489 gen_reserved_instruction(ctx);
15490 break;
15492 break;
15493 case OPC_CP0:
15494 check_cp0_enabled(ctx);
15495 op1 = MASK_CP0(ctx->opcode);
15496 switch (op1) {
15497 case OPC_MFC0:
15498 case OPC_MTC0:
15499 case OPC_MFTR:
15500 case OPC_MTTR:
15501 case OPC_MFHC0:
15502 case OPC_MTHC0:
15503 #if defined(TARGET_MIPS64)
15504 case OPC_DMFC0:
15505 case OPC_DMTC0:
15506 #endif
15507 #ifndef CONFIG_USER_ONLY
15508 gen_cp0(env, ctx, op1, rt, rd);
15509 #endif /* !CONFIG_USER_ONLY */
15510 break;
15511 case OPC_C0:
15512 case OPC_C0_1:
15513 case OPC_C0_2:
15514 case OPC_C0_3:
15515 case OPC_C0_4:
15516 case OPC_C0_5:
15517 case OPC_C0_6:
15518 case OPC_C0_7:
15519 case OPC_C0_8:
15520 case OPC_C0_9:
15521 case OPC_C0_A:
15522 case OPC_C0_B:
15523 case OPC_C0_C:
15524 case OPC_C0_D:
15525 case OPC_C0_E:
15526 case OPC_C0_F:
15527 #ifndef CONFIG_USER_ONLY
15528 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
15529 #endif /* !CONFIG_USER_ONLY */
15530 break;
15531 case OPC_MFMC0:
15532 #ifndef CONFIG_USER_ONLY
15534 uint32_t op2;
15535 TCGv t0 = tcg_temp_new();
15537 op2 = MASK_MFMC0(ctx->opcode);
15538 switch (op2) {
15539 case OPC_DMT:
15540 check_cp0_mt(ctx);
15541 gen_helper_dmt(t0);
15542 gen_store_gpr(t0, rt);
15543 break;
15544 case OPC_EMT:
15545 check_cp0_mt(ctx);
15546 gen_helper_emt(t0);
15547 gen_store_gpr(t0, rt);
15548 break;
15549 case OPC_DVPE:
15550 check_cp0_mt(ctx);
15551 gen_helper_dvpe(t0, cpu_env);
15552 gen_store_gpr(t0, rt);
15553 break;
15554 case OPC_EVPE:
15555 check_cp0_mt(ctx);
15556 gen_helper_evpe(t0, cpu_env);
15557 gen_store_gpr(t0, rt);
15558 break;
15559 case OPC_DVP:
15560 check_insn(ctx, ISA_MIPS_R6);
15561 if (ctx->vp) {
15562 gen_helper_dvp(t0, cpu_env);
15563 gen_store_gpr(t0, rt);
15565 break;
15566 case OPC_EVP:
15567 check_insn(ctx, ISA_MIPS_R6);
15568 if (ctx->vp) {
15569 gen_helper_evp(t0, cpu_env);
15570 gen_store_gpr(t0, rt);
15572 break;
15573 case OPC_DI:
15574 check_insn(ctx, ISA_MIPS_R2);
15575 save_cpu_state(ctx, 1);
15576 gen_helper_di(t0, cpu_env);
15577 gen_store_gpr(t0, rt);
15579 * Stop translation as we may have switched
15580 * the execution mode.
15582 ctx->base.is_jmp = DISAS_STOP;
15583 break;
15584 case OPC_EI:
15585 check_insn(ctx, ISA_MIPS_R2);
15586 save_cpu_state(ctx, 1);
15587 gen_helper_ei(t0, cpu_env);
15588 gen_store_gpr(t0, rt);
15590 * DISAS_STOP isn't sufficient, we need to ensure we break
15591 * out of translated code to check for pending interrupts.
15593 gen_save_pc(ctx->base.pc_next + 4);
15594 ctx->base.is_jmp = DISAS_EXIT;
15595 break;
15596 default: /* Invalid */
15597 MIPS_INVAL("mfmc0");
15598 gen_reserved_instruction(ctx);
15599 break;
15601 tcg_temp_free(t0);
15603 #endif /* !CONFIG_USER_ONLY */
15604 break;
15605 case OPC_RDPGPR:
15606 check_insn(ctx, ISA_MIPS_R2);
15607 gen_load_srsgpr(rt, rd);
15608 break;
15609 case OPC_WRPGPR:
15610 check_insn(ctx, ISA_MIPS_R2);
15611 gen_store_srsgpr(rt, rd);
15612 break;
15613 default:
15614 MIPS_INVAL("cp0");
15615 gen_reserved_instruction(ctx);
15616 break;
15618 break;
15619 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
15620 if (ctx->insn_flags & ISA_MIPS_R6) {
15621 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
15622 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15623 } else {
15624 /* OPC_ADDI */
15625 /* Arithmetic with immediate opcode */
15626 gen_arith_imm(ctx, op, rt, rs, imm);
15628 break;
15629 case OPC_ADDIU:
15630 gen_arith_imm(ctx, op, rt, rs, imm);
15631 break;
15632 case OPC_SLTI: /* Set on less than with immediate opcode */
15633 case OPC_SLTIU:
15634 gen_slt_imm(ctx, op, rt, rs, imm);
15635 break;
15636 case OPC_ANDI: /* Arithmetic with immediate opcode */
15637 case OPC_LUI: /* OPC_AUI */
15638 case OPC_ORI:
15639 case OPC_XORI:
15640 gen_logic_imm(ctx, op, rt, rs, imm);
15641 break;
15642 case OPC_J: /* Jump */
15643 case OPC_JAL:
15644 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15645 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
15646 break;
15647 /* Branch */
15648 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
15649 if (ctx->insn_flags & ISA_MIPS_R6) {
15650 if (rt == 0) {
15651 gen_reserved_instruction(ctx);
15652 break;
15654 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
15655 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15656 } else {
15657 /* OPC_BLEZL */
15658 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15660 break;
15661 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
15662 if (ctx->insn_flags & ISA_MIPS_R6) {
15663 if (rt == 0) {
15664 gen_reserved_instruction(ctx);
15665 break;
15667 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
15668 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15669 } else {
15670 /* OPC_BGTZL */
15671 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15673 break;
15674 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
15675 if (rt == 0) {
15676 /* OPC_BLEZ */
15677 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15678 } else {
15679 check_insn(ctx, ISA_MIPS_R6);
15680 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
15681 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15683 break;
15684 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
15685 if (rt == 0) {
15686 /* OPC_BGTZ */
15687 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15688 } else {
15689 check_insn(ctx, ISA_MIPS_R6);
15690 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
15691 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
15693 break;
15694 case OPC_BEQL:
15695 case OPC_BNEL:
15696 check_insn(ctx, ISA_MIPS2);
15697 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15698 /* Fallthrough */
15699 case OPC_BEQ:
15700 case OPC_BNE:
15701 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
15702 break;
15703 case OPC_LL: /* Load and stores */
15704 check_insn(ctx, ISA_MIPS2);
15705 if (ctx->insn_flags & INSN_R5900) {
15706 check_insn_opc_user_only(ctx, INSN_R5900);
15708 /* Fallthrough */
15709 case OPC_LWL:
15710 case OPC_LWR:
15711 case OPC_LB:
15712 case OPC_LH:
15713 case OPC_LW:
15714 case OPC_LWPC:
15715 case OPC_LBU:
15716 case OPC_LHU:
15717 gen_ld(ctx, op, rt, rs, imm);
15718 break;
15719 case OPC_SWL:
15720 case OPC_SWR:
15721 case OPC_SB:
15722 case OPC_SH:
15723 case OPC_SW:
15724 gen_st(ctx, op, rt, rs, imm);
15725 break;
15726 case OPC_SC:
15727 check_insn(ctx, ISA_MIPS2);
15728 if (ctx->insn_flags & INSN_R5900) {
15729 check_insn_opc_user_only(ctx, INSN_R5900);
15731 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
15732 break;
15733 case OPC_CACHE:
15734 check_cp0_enabled(ctx);
15735 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
15736 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15737 gen_cache_operation(ctx, rt, rs, imm);
15739 /* Treat as NOP. */
15740 break;
15741 case OPC_PREF:
15742 if (ctx->insn_flags & INSN_R5900) {
15743 /* Treat as NOP. */
15744 } else {
15745 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
15746 /* Treat as NOP. */
15748 break;
15750 /* Floating point (COP1). */
15751 case OPC_LWC1:
15752 case OPC_LDC1:
15753 case OPC_SWC1:
15754 case OPC_SDC1:
15755 gen_cop1_ldst(ctx, op, rt, rs, imm);
15756 break;
15758 case OPC_CP1:
15759 op1 = MASK_CP1(ctx->opcode);
15761 switch (op1) {
15762 case OPC_MFHC1:
15763 case OPC_MTHC1:
15764 check_cp1_enabled(ctx);
15765 check_insn(ctx, ISA_MIPS_R2);
15766 /* fall through */
15767 case OPC_MFC1:
15768 case OPC_CFC1:
15769 case OPC_MTC1:
15770 case OPC_CTC1:
15771 check_cp1_enabled(ctx);
15772 gen_cp1(ctx, op1, rt, rd);
15773 break;
15774 #if defined(TARGET_MIPS64)
15775 case OPC_DMFC1:
15776 case OPC_DMTC1:
15777 check_cp1_enabled(ctx);
15778 check_insn(ctx, ISA_MIPS3);
15779 check_mips_64(ctx);
15780 gen_cp1(ctx, op1, rt, rd);
15781 break;
15782 #endif
15783 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
15784 check_cp1_enabled(ctx);
15785 if (ctx->insn_flags & ISA_MIPS_R6) {
15786 /* OPC_BC1EQZ */
15787 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
15788 rt, imm << 2, 4);
15789 } else {
15790 /* OPC_BC1ANY2 */
15791 check_cop1x(ctx);
15792 check_insn(ctx, ASE_MIPS3D);
15793 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
15794 (rt >> 2) & 0x7, imm << 2);
15796 break;
15797 case OPC_BC1NEZ:
15798 check_cp1_enabled(ctx);
15799 check_insn(ctx, ISA_MIPS_R6);
15800 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
15801 rt, imm << 2, 4);
15802 break;
15803 case OPC_BC1ANY4:
15804 check_cp1_enabled(ctx);
15805 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15806 check_cop1x(ctx);
15807 check_insn(ctx, ASE_MIPS3D);
15808 /* fall through */
15809 case OPC_BC1:
15810 check_cp1_enabled(ctx);
15811 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15812 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
15813 (rt >> 2) & 0x7, imm << 2);
15814 break;
15815 case OPC_PS_FMT:
15816 check_ps(ctx);
15817 /* fall through */
15818 case OPC_S_FMT:
15819 case OPC_D_FMT:
15820 check_cp1_enabled(ctx);
15821 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
15822 (imm >> 8) & 0x7);
15823 break;
15824 case OPC_W_FMT:
15825 case OPC_L_FMT:
15827 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
15828 check_cp1_enabled(ctx);
15829 if (ctx->insn_flags & ISA_MIPS_R6) {
15830 switch (r6_op) {
15831 case R6_OPC_CMP_AF_S:
15832 case R6_OPC_CMP_UN_S:
15833 case R6_OPC_CMP_EQ_S:
15834 case R6_OPC_CMP_UEQ_S:
15835 case R6_OPC_CMP_LT_S:
15836 case R6_OPC_CMP_ULT_S:
15837 case R6_OPC_CMP_LE_S:
15838 case R6_OPC_CMP_ULE_S:
15839 case R6_OPC_CMP_SAF_S:
15840 case R6_OPC_CMP_SUN_S:
15841 case R6_OPC_CMP_SEQ_S:
15842 case R6_OPC_CMP_SEUQ_S:
15843 case R6_OPC_CMP_SLT_S:
15844 case R6_OPC_CMP_SULT_S:
15845 case R6_OPC_CMP_SLE_S:
15846 case R6_OPC_CMP_SULE_S:
15847 case R6_OPC_CMP_OR_S:
15848 case R6_OPC_CMP_UNE_S:
15849 case R6_OPC_CMP_NE_S:
15850 case R6_OPC_CMP_SOR_S:
15851 case R6_OPC_CMP_SUNE_S:
15852 case R6_OPC_CMP_SNE_S:
15853 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
15854 break;
15855 case R6_OPC_CMP_AF_D:
15856 case R6_OPC_CMP_UN_D:
15857 case R6_OPC_CMP_EQ_D:
15858 case R6_OPC_CMP_UEQ_D:
15859 case R6_OPC_CMP_LT_D:
15860 case R6_OPC_CMP_ULT_D:
15861 case R6_OPC_CMP_LE_D:
15862 case R6_OPC_CMP_ULE_D:
15863 case R6_OPC_CMP_SAF_D:
15864 case R6_OPC_CMP_SUN_D:
15865 case R6_OPC_CMP_SEQ_D:
15866 case R6_OPC_CMP_SEUQ_D:
15867 case R6_OPC_CMP_SLT_D:
15868 case R6_OPC_CMP_SULT_D:
15869 case R6_OPC_CMP_SLE_D:
15870 case R6_OPC_CMP_SULE_D:
15871 case R6_OPC_CMP_OR_D:
15872 case R6_OPC_CMP_UNE_D:
15873 case R6_OPC_CMP_NE_D:
15874 case R6_OPC_CMP_SOR_D:
15875 case R6_OPC_CMP_SUNE_D:
15876 case R6_OPC_CMP_SNE_D:
15877 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
15878 break;
15879 default:
15880 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
15881 rt, rd, sa, (imm >> 8) & 0x7);
15883 break;
15885 } else {
15886 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
15887 (imm >> 8) & 0x7);
15889 break;
15891 default:
15892 MIPS_INVAL("cp1");
15893 gen_reserved_instruction(ctx);
15894 break;
15896 break;
15898 /* Compact branches [R6] and COP2 [non-R6] */
15899 case OPC_BC: /* OPC_LWC2 */
15900 case OPC_BALC: /* OPC_SWC2 */
15901 if (ctx->insn_flags & ISA_MIPS_R6) {
15902 /* OPC_BC, OPC_BALC */
15903 gen_compute_compact_branch(ctx, op, 0, 0,
15904 sextract32(ctx->opcode << 2, 0, 28));
15905 } else if (ctx->insn_flags & ASE_LEXT) {
15906 gen_loongson_lswc2(ctx, rt, rs, rd);
15907 } else {
15908 /* OPC_LWC2, OPC_SWC2 */
15909 /* COP2: Not implemented. */
15910 generate_exception_err(ctx, EXCP_CpU, 2);
15912 break;
15913 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
15914 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
15915 if (ctx->insn_flags & ISA_MIPS_R6) {
15916 if (rs != 0) {
15917 /* OPC_BEQZC, OPC_BNEZC */
15918 gen_compute_compact_branch(ctx, op, rs, 0,
15919 sextract32(ctx->opcode << 2, 0, 23));
15920 } else {
15921 /* OPC_JIC, OPC_JIALC */
15922 gen_compute_compact_branch(ctx, op, 0, rt, imm);
15924 } else if (ctx->insn_flags & ASE_LEXT) {
15925 gen_loongson_lsdc2(ctx, rt, rs, rd);
15926 } else {
15927 /* OPC_LWC2, OPC_SWC2 */
15928 /* COP2: Not implemented. */
15929 generate_exception_err(ctx, EXCP_CpU, 2);
15931 break;
15932 case OPC_CP2:
15933 check_insn(ctx, ASE_LMMI);
15934 /* Note that these instructions use different fields. */
15935 gen_loongson_multimedia(ctx, sa, rd, rt);
15936 break;
15938 case OPC_CP3:
15939 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15940 check_cp1_enabled(ctx);
15941 op1 = MASK_CP3(ctx->opcode);
15942 switch (op1) {
15943 case OPC_LUXC1:
15944 case OPC_SUXC1:
15945 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
15946 /* Fallthrough */
15947 case OPC_LWXC1:
15948 case OPC_LDXC1:
15949 case OPC_SWXC1:
15950 case OPC_SDXC1:
15951 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
15952 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
15953 break;
15954 case OPC_PREFX:
15955 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
15956 /* Treat as NOP. */
15957 break;
15958 case OPC_ALNV_PS:
15959 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
15960 /* Fallthrough */
15961 case OPC_MADD_S:
15962 case OPC_MADD_D:
15963 case OPC_MADD_PS:
15964 case OPC_MSUB_S:
15965 case OPC_MSUB_D:
15966 case OPC_MSUB_PS:
15967 case OPC_NMADD_S:
15968 case OPC_NMADD_D:
15969 case OPC_NMADD_PS:
15970 case OPC_NMSUB_S:
15971 case OPC_NMSUB_D:
15972 case OPC_NMSUB_PS:
15973 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
15974 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
15975 break;
15976 default:
15977 MIPS_INVAL("cp3");
15978 gen_reserved_instruction(ctx);
15979 break;
15981 } else {
15982 generate_exception_err(ctx, EXCP_CpU, 1);
15984 break;
15986 #if defined(TARGET_MIPS64)
15987 /* MIPS64 opcodes */
15988 case OPC_LLD:
15989 if (ctx->insn_flags & INSN_R5900) {
15990 check_insn_opc_user_only(ctx, INSN_R5900);
15992 /* fall through */
15993 case OPC_LDL:
15994 case OPC_LDR:
15995 case OPC_LWU:
15996 case OPC_LD:
15997 check_insn(ctx, ISA_MIPS3);
15998 check_mips_64(ctx);
15999 gen_ld(ctx, op, rt, rs, imm);
16000 break;
16001 case OPC_SDL:
16002 case OPC_SDR:
16003 case OPC_SD:
16004 check_insn(ctx, ISA_MIPS3);
16005 check_mips_64(ctx);
16006 gen_st(ctx, op, rt, rs, imm);
16007 break;
16008 case OPC_SCD:
16009 check_insn(ctx, ISA_MIPS3);
16010 if (ctx->insn_flags & INSN_R5900) {
16011 check_insn_opc_user_only(ctx, INSN_R5900);
16013 check_mips_64(ctx);
16014 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
16015 break;
16016 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
16017 if (ctx->insn_flags & ISA_MIPS_R6) {
16018 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
16019 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
16020 } else {
16021 /* OPC_DADDI */
16022 check_insn(ctx, ISA_MIPS3);
16023 check_mips_64(ctx);
16024 gen_arith_imm(ctx, op, rt, rs, imm);
16026 break;
16027 case OPC_DADDIU:
16028 check_insn(ctx, ISA_MIPS3);
16029 check_mips_64(ctx);
16030 gen_arith_imm(ctx, op, rt, rs, imm);
16031 break;
16032 #else
16033 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
16034 if (ctx->insn_flags & ISA_MIPS_R6) {
16035 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
16036 } else {
16037 MIPS_INVAL("major opcode");
16038 gen_reserved_instruction(ctx);
16040 break;
16041 #endif
16042 case OPC_DAUI: /* OPC_JALX */
16043 if (ctx->insn_flags & ISA_MIPS_R6) {
16044 #if defined(TARGET_MIPS64)
16045 /* OPC_DAUI */
16046 check_mips_64(ctx);
16047 if (rs == 0) {
16048 generate_exception(ctx, EXCP_RI);
16049 } else if (rt != 0) {
16050 TCGv t0 = tcg_temp_new();
16051 gen_load_gpr(t0, rs);
16052 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
16053 tcg_temp_free(t0);
16055 #else
16056 gen_reserved_instruction(ctx);
16057 MIPS_INVAL("major opcode");
16058 #endif
16059 } else {
16060 /* OPC_JALX */
16061 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
16062 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16063 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
16065 break;
16066 case OPC_MDMX:
16067 /* MDMX: Not implemented. */
16068 break;
16069 case OPC_PCREL:
16070 check_insn(ctx, ISA_MIPS_R6);
16071 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
16072 break;
16073 default: /* Invalid */
16074 MIPS_INVAL("major opcode");
16075 return false;
16077 return true;
16080 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
16082 /* make sure instructions are on a word boundary */
16083 if (ctx->base.pc_next & 0x3) {
16084 env->CP0_BadVAddr = ctx->base.pc_next;
16085 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
16086 return;
16089 /* Handle blikely not taken case */
16090 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
16091 TCGLabel *l1 = gen_new_label();
16093 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
16094 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
16095 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
16096 gen_set_label(l1);
16099 /* Transition to the auto-generated decoder. */
16101 /* ISA extensions */
16102 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
16103 return;
16106 /* ISA (from latest to oldest) */
16107 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
16108 return;
16110 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
16111 return;
16114 if (decode_opc_legacy(env, ctx)) {
16115 return;
16118 gen_reserved_instruction(ctx);
16121 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
16123 DisasContext *ctx = container_of(dcbase, DisasContext, base);
16124 CPUMIPSState *env = cs->env_ptr;
16126 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
16127 ctx->saved_pc = -1;
16128 ctx->insn_flags = env->insn_flags;
16129 ctx->CP0_Config1 = env->CP0_Config1;
16130 ctx->CP0_Config2 = env->CP0_Config2;
16131 ctx->CP0_Config3 = env->CP0_Config3;
16132 ctx->CP0_Config5 = env->CP0_Config5;
16133 ctx->btarget = 0;
16134 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
16135 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
16136 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
16137 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
16138 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
16139 ctx->PAMask = env->PAMask;
16140 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
16141 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
16142 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
16143 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
16144 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
16145 /* Restore delay slot state from the tb context. */
16146 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
16147 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
16148 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
16149 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
16150 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
16151 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
16152 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
16153 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
16154 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
16155 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
16156 restore_cpu_state(env, ctx);
16157 #ifdef CONFIG_USER_ONLY
16158 ctx->mem_idx = MIPS_HFLAG_UM;
16159 #else
16160 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
16161 #endif
16162 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
16163 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
16165 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
16166 ctx->hflags);
16169 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
16173 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
16175 DisasContext *ctx = container_of(dcbase, DisasContext, base);
16177 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
16178 ctx->btarget);
16181 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
16183 CPUMIPSState *env = cs->env_ptr;
16184 DisasContext *ctx = container_of(dcbase, DisasContext, base);
16185 int insn_bytes;
16186 int is_slot;
16188 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
16189 if (ctx->insn_flags & ISA_NANOMIPS32) {
16190 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
16191 insn_bytes = decode_isa_nanomips(env, ctx);
16192 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
16193 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
16194 insn_bytes = 4;
16195 decode_opc(env, ctx);
16196 } else if (ctx->insn_flags & ASE_MICROMIPS) {
16197 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
16198 insn_bytes = decode_isa_micromips(env, ctx);
16199 } else if (ctx->insn_flags & ASE_MIPS16) {
16200 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
16201 insn_bytes = decode_ase_mips16e(env, ctx);
16202 } else {
16203 gen_reserved_instruction(ctx);
16204 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
16205 return;
16208 if (ctx->hflags & MIPS_HFLAG_BMASK) {
16209 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
16210 MIPS_HFLAG_FBNSLOT))) {
16212 * Force to generate branch as there is neither delay nor
16213 * forbidden slot.
16215 is_slot = 1;
16217 if ((ctx->hflags & MIPS_HFLAG_M16) &&
16218 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
16220 * Force to generate branch as microMIPS R6 doesn't restrict
16221 * branches in the forbidden slot.
16223 is_slot = 1;
16226 if (is_slot) {
16227 gen_branch(ctx, insn_bytes);
16229 ctx->base.pc_next += insn_bytes;
16231 if (ctx->base.is_jmp != DISAS_NEXT) {
16232 return;
16235 * Execute a branch and its delay slot as a single instruction.
16236 * This is what GDB expects and is consistent with what the
16237 * hardware does (e.g. if a delay slot instruction faults, the
16238 * reported PC is the PC of the branch).
16240 if (ctx->base.singlestep_enabled &&
16241 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
16242 ctx->base.is_jmp = DISAS_TOO_MANY;
16244 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
16245 ctx->base.is_jmp = DISAS_TOO_MANY;
16249 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
16251 DisasContext *ctx = container_of(dcbase, DisasContext, base);
16253 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
16254 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
16255 gen_helper_raise_exception_debug(cpu_env);
16256 } else {
16257 switch (ctx->base.is_jmp) {
16258 case DISAS_STOP:
16259 gen_save_pc(ctx->base.pc_next);
16260 tcg_gen_lookup_and_goto_ptr();
16261 break;
16262 case DISAS_NEXT:
16263 case DISAS_TOO_MANY:
16264 save_cpu_state(ctx, 0);
16265 gen_goto_tb(ctx, 0, ctx->base.pc_next);
16266 break;
16267 case DISAS_EXIT:
16268 tcg_gen_exit_tb(NULL, 0);
16269 break;
16270 case DISAS_NORETURN:
16271 break;
16272 default:
16273 g_assert_not_reached();
16278 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
16280 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
16281 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
16284 static const TranslatorOps mips_tr_ops = {
16285 .init_disas_context = mips_tr_init_disas_context,
16286 .tb_start = mips_tr_tb_start,
16287 .insn_start = mips_tr_insn_start,
16288 .translate_insn = mips_tr_translate_insn,
16289 .tb_stop = mips_tr_tb_stop,
16290 .disas_log = mips_tr_disas_log,
16293 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
16295 DisasContext ctx;
16297 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
16300 void mips_tcg_init(void)
16302 int i;
16304 cpu_gpr[0] = NULL;
16305 for (i = 1; i < 32; i++)
16306 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
16307 offsetof(CPUMIPSState,
16308 active_tc.gpr[i]),
16309 regnames[i]);
16310 #if defined(TARGET_MIPS64)
16311 cpu_gpr_hi[0] = NULL;
16313 for (unsigned i = 1; i < 32; i++) {
16314 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
16316 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
16317 offsetof(CPUMIPSState,
16318 active_tc.gpr_hi[i]),
16319 rname);
16321 #endif /* !TARGET_MIPS64 */
16322 for (i = 0; i < 32; i++) {
16323 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
16325 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
16327 msa_translate_init();
16328 cpu_PC = tcg_global_mem_new(cpu_env,
16329 offsetof(CPUMIPSState, active_tc.PC), "PC");
16330 for (i = 0; i < MIPS_DSP_ACC; i++) {
16331 cpu_HI[i] = tcg_global_mem_new(cpu_env,
16332 offsetof(CPUMIPSState, active_tc.HI[i]),
16333 regnames_HI[i]);
16334 cpu_LO[i] = tcg_global_mem_new(cpu_env,
16335 offsetof(CPUMIPSState, active_tc.LO[i]),
16336 regnames_LO[i]);
16338 cpu_dspctrl = tcg_global_mem_new(cpu_env,
16339 offsetof(CPUMIPSState,
16340 active_tc.DSPControl),
16341 "DSPControl");
16342 bcond = tcg_global_mem_new(cpu_env,
16343 offsetof(CPUMIPSState, bcond), "bcond");
16344 btarget = tcg_global_mem_new(cpu_env,
16345 offsetof(CPUMIPSState, btarget), "btarget");
16346 hflags = tcg_global_mem_new_i32(cpu_env,
16347 offsetof(CPUMIPSState, hflags), "hflags");
16349 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
16350 offsetof(CPUMIPSState, active_fpu.fcr0),
16351 "fcr0");
16352 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
16353 offsetof(CPUMIPSState, active_fpu.fcr31),
16354 "fcr31");
16355 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
16356 "lladdr");
16357 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
16358 "llval");
16360 if (TARGET_LONG_BITS == 32) {
16361 mxu_translate_init();
16365 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
16366 target_ulong *data)
16368 env->active_tc.PC = data[0];
16369 env->hflags &= ~MIPS_HFLAG_BMASK;
16370 env->hflags |= data[1];
16371 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
16372 case MIPS_HFLAG_BR:
16373 break;
16374 case MIPS_HFLAG_BC:
16375 case MIPS_HFLAG_BL:
16376 case MIPS_HFLAG_B:
16377 env->btarget = data[2];
16378 break;