target/mips: Add emulation of DSP ASE for nanoMIPS - part 4
[qemu/ar7.git] / target / mips / translate.c
blob24476a53ec6f8fed259b31b9c0a1bb22c6614fdd
1 /*
2 * MIPS32 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)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
467 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
468 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
471 /* DBSHFL opcodes */
472 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
474 enum {
475 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
476 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
477 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
478 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
479 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
482 /* MIPS DSP REGIMM opcodes */
483 enum {
484 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
485 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
488 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
489 /* MIPS DSP Load */
490 enum {
491 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
492 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
493 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
494 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
497 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498 enum {
499 /* MIPS DSP Arithmetic Sub-class */
500 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
501 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
502 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
503 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
507 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
508 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
509 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
516 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
517 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
518 /* MIPS DSP Multiply Sub-class insns */
519 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
521 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
522 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
527 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
528 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
532 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
533 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
543 /* MIPS DSP Multiply Sub-class insns */
544 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
545 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
546 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
550 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551 enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
554 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
555 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
566 /* DSP Bit/Manipulation Sub-class */
567 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
574 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
584 /* DSP Compare-Pick Sub-class */
585 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
602 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
603 enum {
604 /* MIPS DSP GPR-Based Shift Sub-class */
605 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
607 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
629 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
630 enum {
631 /* MIPS DSP Multiply Sub-class insns */
632 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
634 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
656 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657 enum {
658 /* DSP Bit/Manipulation Sub-class */
659 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
662 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
663 enum {
664 /* MIPS DSP Append Sub-class */
665 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
666 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
667 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
670 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
673 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
674 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
675 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
685 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
686 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
687 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
688 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
689 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
692 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
693 enum {
694 /* MIPS DSP Arithmetic Sub-class */
695 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
721 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
722 enum {
723 /* MIPS DSP Multiply Sub-class insns */
724 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
725 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
726 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
729 /* MIPS DSP Arithmetic Sub-class */
730 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
731 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
732 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
741 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
742 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
753 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
754 enum {
755 /* DSP Compare-Pick Sub-class */
756 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
786 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
787 enum {
788 /* DSP Append Sub-class */
789 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
790 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
791 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
792 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
795 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
798 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
799 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
800 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
801 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
821 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
822 enum {
823 /* DSP Bit/Manipulation Sub-class */
824 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
827 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
828 enum {
829 /* MIPS DSP Multiply Sub-class insns */
830 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
858 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
859 enum {
860 /* MIPS DSP GPR-Based Shift Sub-class */
861 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
889 /* Coprocessor 0 (rs field) */
890 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
892 enum {
893 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
894 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
895 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
896 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
897 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
898 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
899 OPC_MFTR = (0x08 << 21) | OPC_CP0,
900 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
901 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
902 OPC_MTTR = (0x0C << 21) | OPC_CP0,
903 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
904 OPC_C0 = (0x10 << 21) | OPC_CP0,
905 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
906 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
907 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
908 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
909 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
910 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
911 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
912 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
913 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
914 OPC_C0_A = (0x1A << 21) | OPC_CP0,
915 OPC_C0_B = (0x1B << 21) | OPC_CP0,
916 OPC_C0_C = (0x1C << 21) | OPC_CP0,
917 OPC_C0_D = (0x1D << 21) | OPC_CP0,
918 OPC_C0_E = (0x1E << 21) | OPC_CP0,
919 OPC_C0_F = (0x1F << 21) | OPC_CP0,
922 /* MFMC0 opcodes */
923 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
925 enum {
926 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
927 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
928 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
929 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
930 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
931 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
932 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
933 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
936 /* Coprocessor 0 (with rs == C0) */
937 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
939 enum {
940 OPC_TLBR = 0x01 | OPC_C0,
941 OPC_TLBWI = 0x02 | OPC_C0,
942 OPC_TLBINV = 0x03 | OPC_C0,
943 OPC_TLBINVF = 0x04 | OPC_C0,
944 OPC_TLBWR = 0x06 | OPC_C0,
945 OPC_TLBP = 0x08 | OPC_C0,
946 OPC_RFE = 0x10 | OPC_C0,
947 OPC_ERET = 0x18 | OPC_C0,
948 OPC_DERET = 0x1F | OPC_C0,
949 OPC_WAIT = 0x20 | OPC_C0,
952 /* Coprocessor 1 (rs field) */
953 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
955 /* Values for the fmt field in FP instructions */
956 enum {
957 /* 0 - 15 are reserved */
958 FMT_S = 16, /* single fp */
959 FMT_D = 17, /* double fp */
960 FMT_E = 18, /* extended fp */
961 FMT_Q = 19, /* quad fp */
962 FMT_W = 20, /* 32-bit fixed */
963 FMT_L = 21, /* 64-bit fixed */
964 FMT_PS = 22, /* paired single fp */
965 /* 23 - 31 are reserved */
968 enum {
969 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
970 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
971 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
972 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
973 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
974 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
975 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
976 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
977 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
978 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
979 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
980 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
981 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
982 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
983 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
984 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
985 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
986 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
987 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
988 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
989 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
990 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
991 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
992 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
993 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
994 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
995 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
996 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
997 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
998 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1001 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1002 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1004 enum {
1005 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1006 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1007 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1008 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1011 enum {
1012 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1013 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1016 enum {
1017 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1018 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1021 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1023 enum {
1024 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1025 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1026 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1027 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1028 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1029 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1030 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1031 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1032 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1033 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1034 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1037 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1039 enum {
1040 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1041 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1042 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1043 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1044 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1045 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1046 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1047 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1049 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1050 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1051 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1052 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1053 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1054 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1055 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1056 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1059 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1060 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1061 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1062 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1063 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1064 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1065 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1067 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1068 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1069 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1070 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1071 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1072 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1073 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1074 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1076 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1077 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1078 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1079 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1080 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1081 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1083 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1084 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1085 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1086 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1087 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1088 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1090 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1091 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1092 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1093 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1094 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1095 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1097 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1098 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1099 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1100 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1101 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1102 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1104 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1105 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1106 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1107 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1108 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1109 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1111 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1112 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1113 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1114 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1115 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1116 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1118 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1119 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1120 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1121 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1122 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1123 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1125 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1126 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1127 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1128 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1129 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1130 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1134 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1136 enum {
1137 OPC_LWXC1 = 0x00 | OPC_CP3,
1138 OPC_LDXC1 = 0x01 | OPC_CP3,
1139 OPC_LUXC1 = 0x05 | OPC_CP3,
1140 OPC_SWXC1 = 0x08 | OPC_CP3,
1141 OPC_SDXC1 = 0x09 | OPC_CP3,
1142 OPC_SUXC1 = 0x0D | OPC_CP3,
1143 OPC_PREFX = 0x0F | OPC_CP3,
1144 OPC_ALNV_PS = 0x1E | OPC_CP3,
1145 OPC_MADD_S = 0x20 | OPC_CP3,
1146 OPC_MADD_D = 0x21 | OPC_CP3,
1147 OPC_MADD_PS = 0x26 | OPC_CP3,
1148 OPC_MSUB_S = 0x28 | OPC_CP3,
1149 OPC_MSUB_D = 0x29 | OPC_CP3,
1150 OPC_MSUB_PS = 0x2E | OPC_CP3,
1151 OPC_NMADD_S = 0x30 | OPC_CP3,
1152 OPC_NMADD_D = 0x31 | OPC_CP3,
1153 OPC_NMADD_PS= 0x36 | OPC_CP3,
1154 OPC_NMSUB_S = 0x38 | OPC_CP3,
1155 OPC_NMSUB_D = 0x39 | OPC_CP3,
1156 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1159 /* MSA Opcodes */
1160 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1161 enum {
1162 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1163 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1164 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1165 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1166 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1167 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1168 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1169 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1170 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1171 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1172 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1173 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1174 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1175 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1176 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1177 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1178 OPC_MSA_ELM = 0x19 | OPC_MSA,
1179 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1180 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1181 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1182 OPC_MSA_VEC = 0x1E | OPC_MSA,
1184 /* MI10 instruction */
1185 OPC_LD_B = (0x20) | OPC_MSA,
1186 OPC_LD_H = (0x21) | OPC_MSA,
1187 OPC_LD_W = (0x22) | OPC_MSA,
1188 OPC_LD_D = (0x23) | OPC_MSA,
1189 OPC_ST_B = (0x24) | OPC_MSA,
1190 OPC_ST_H = (0x25) | OPC_MSA,
1191 OPC_ST_W = (0x26) | OPC_MSA,
1192 OPC_ST_D = (0x27) | OPC_MSA,
1195 enum {
1196 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1197 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1198 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1199 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1200 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1201 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1202 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1203 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1204 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1205 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1206 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1207 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1208 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1210 /* I8 instruction */
1211 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1212 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1213 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1214 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1215 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1216 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1217 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1218 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1219 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1220 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1222 /* VEC/2R/2RF instruction */
1223 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1224 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1225 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1226 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1227 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1228 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1229 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1231 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1232 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1234 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1235 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1236 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1237 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1238 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1240 /* 2RF instruction df(bit 16) = _w, _d */
1241 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1242 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1243 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1244 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1245 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1246 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1247 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1248 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1249 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1250 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1251 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1252 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1253 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1254 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1255 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1256 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1258 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1259 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1260 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1261 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1262 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1263 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1264 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1265 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1266 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1267 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1268 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1269 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1270 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1272 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1274 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1275 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1276 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1278 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1279 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1281 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1282 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1283 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1284 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1285 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1290 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1292 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1293 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1294 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1295 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1296 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1297 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1298 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1299 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1300 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1301 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1310 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1311 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1312 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1313 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1314 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1315 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1316 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1317 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1318 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1319 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1320 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1321 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1323 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1324 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1325 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1326 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1327 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1328 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1329 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1330 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1331 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1332 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1334 /* 3RF instruction _df(bit 21) = _w, _d */
1335 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1337 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1338 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1339 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1340 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1342 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1343 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1346 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1348 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1351 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1353 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1357 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1358 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1361 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1362 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1363 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1364 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1365 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1366 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1367 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1369 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1370 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1372 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1373 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1377 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1378 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1379 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1380 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1381 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1382 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1383 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1384 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1385 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1386 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1387 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1388 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1389 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1392 /* global register indices */
1393 static TCGv cpu_gpr[32], cpu_PC;
1394 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1395 static TCGv cpu_dspctrl, btarget, bcond;
1396 static TCGv_i32 hflags;
1397 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1398 static TCGv_i64 fpu_f64[32];
1399 static TCGv_i64 msa_wr_d[64];
1401 #include "exec/gen-icount.h"
1403 #define gen_helper_0e0i(name, arg) do { \
1404 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1405 gen_helper_##name(cpu_env, helper_tmp); \
1406 tcg_temp_free_i32(helper_tmp); \
1407 } while(0)
1409 #define gen_helper_0e1i(name, arg1, arg2) do { \
1410 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1411 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1412 tcg_temp_free_i32(helper_tmp); \
1413 } while(0)
1415 #define gen_helper_1e0i(name, ret, arg1) do { \
1416 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1417 gen_helper_##name(ret, cpu_env, helper_tmp); \
1418 tcg_temp_free_i32(helper_tmp); \
1419 } while(0)
1421 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1422 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1423 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1424 tcg_temp_free_i32(helper_tmp); \
1425 } while(0)
1427 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1428 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1429 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1430 tcg_temp_free_i32(helper_tmp); \
1431 } while(0)
1433 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1434 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1435 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1436 tcg_temp_free_i32(helper_tmp); \
1437 } while(0)
1439 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1440 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1441 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1442 tcg_temp_free_i32(helper_tmp); \
1443 } while(0)
1445 typedef struct DisasContext {
1446 DisasContextBase base;
1447 target_ulong saved_pc;
1448 target_ulong page_start;
1449 uint32_t opcode;
1450 int insn_flags;
1451 int32_t CP0_Config1;
1452 int32_t CP0_Config3;
1453 int32_t CP0_Config5;
1454 /* Routine used to access memory */
1455 int mem_idx;
1456 TCGMemOp default_tcg_memop_mask;
1457 uint32_t hflags, saved_hflags;
1458 target_ulong btarget;
1459 bool ulri;
1460 int kscrexist;
1461 bool rxi;
1462 int ie;
1463 bool bi;
1464 bool bp;
1465 uint64_t PAMask;
1466 bool mvh;
1467 bool eva;
1468 bool sc;
1469 int CP0_LLAddr_shift;
1470 bool ps;
1471 bool vp;
1472 bool cmgcr;
1473 bool mrp;
1474 bool nan2008;
1475 bool abs2008;
1476 } DisasContext;
1478 #define DISAS_STOP DISAS_TARGET_0
1479 #define DISAS_EXIT DISAS_TARGET_1
1481 static const char * const regnames[] = {
1482 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1483 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1484 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1485 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1488 static const char * const regnames_HI[] = {
1489 "HI0", "HI1", "HI2", "HI3",
1492 static const char * const regnames_LO[] = {
1493 "LO0", "LO1", "LO2", "LO3",
1496 static const char * const fregnames[] = {
1497 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1498 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1499 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1500 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1503 static const char * const msaregnames[] = {
1504 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1505 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1506 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1507 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1508 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1509 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1510 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1511 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1512 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1513 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1514 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1515 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1516 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1517 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1518 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1519 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1522 #define LOG_DISAS(...) \
1523 do { \
1524 if (MIPS_DEBUG_DISAS) { \
1525 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1527 } while (0)
1529 #define MIPS_INVAL(op) \
1530 do { \
1531 if (MIPS_DEBUG_DISAS) { \
1532 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1533 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1534 ctx->base.pc_next, ctx->opcode, op, \
1535 ctx->opcode >> 26, ctx->opcode & 0x3F, \
1536 ((ctx->opcode >> 16) & 0x1F)); \
1538 } while (0)
1540 /* General purpose registers moves. */
1541 static inline void gen_load_gpr (TCGv t, int reg)
1543 if (reg == 0)
1544 tcg_gen_movi_tl(t, 0);
1545 else
1546 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1549 static inline void gen_store_gpr (TCGv t, int reg)
1551 if (reg != 0)
1552 tcg_gen_mov_tl(cpu_gpr[reg], t);
1555 /* Moves to/from shadow registers. */
1556 static inline void gen_load_srsgpr (int from, int to)
1558 TCGv t0 = tcg_temp_new();
1560 if (from == 0)
1561 tcg_gen_movi_tl(t0, 0);
1562 else {
1563 TCGv_i32 t2 = tcg_temp_new_i32();
1564 TCGv_ptr addr = tcg_temp_new_ptr();
1566 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1567 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1568 tcg_gen_andi_i32(t2, t2, 0xf);
1569 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1570 tcg_gen_ext_i32_ptr(addr, t2);
1571 tcg_gen_add_ptr(addr, cpu_env, addr);
1573 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1574 tcg_temp_free_ptr(addr);
1575 tcg_temp_free_i32(t2);
1577 gen_store_gpr(t0, to);
1578 tcg_temp_free(t0);
1581 static inline void gen_store_srsgpr (int from, int to)
1583 if (to != 0) {
1584 TCGv t0 = tcg_temp_new();
1585 TCGv_i32 t2 = tcg_temp_new_i32();
1586 TCGv_ptr addr = tcg_temp_new_ptr();
1588 gen_load_gpr(t0, from);
1589 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1590 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1591 tcg_gen_andi_i32(t2, t2, 0xf);
1592 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1593 tcg_gen_ext_i32_ptr(addr, t2);
1594 tcg_gen_add_ptr(addr, cpu_env, addr);
1596 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1597 tcg_temp_free_ptr(addr);
1598 tcg_temp_free_i32(t2);
1599 tcg_temp_free(t0);
1603 /* Tests */
1604 static inline void gen_save_pc(target_ulong pc)
1606 tcg_gen_movi_tl(cpu_PC, pc);
1609 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1611 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1612 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1613 gen_save_pc(ctx->base.pc_next);
1614 ctx->saved_pc = ctx->base.pc_next;
1616 if (ctx->hflags != ctx->saved_hflags) {
1617 tcg_gen_movi_i32(hflags, ctx->hflags);
1618 ctx->saved_hflags = ctx->hflags;
1619 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1620 case MIPS_HFLAG_BR:
1621 break;
1622 case MIPS_HFLAG_BC:
1623 case MIPS_HFLAG_BL:
1624 case MIPS_HFLAG_B:
1625 tcg_gen_movi_tl(btarget, ctx->btarget);
1626 break;
1631 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1633 ctx->saved_hflags = ctx->hflags;
1634 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1635 case MIPS_HFLAG_BR:
1636 break;
1637 case MIPS_HFLAG_BC:
1638 case MIPS_HFLAG_BL:
1639 case MIPS_HFLAG_B:
1640 ctx->btarget = env->btarget;
1641 break;
1645 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1647 TCGv_i32 texcp = tcg_const_i32(excp);
1648 TCGv_i32 terr = tcg_const_i32(err);
1649 save_cpu_state(ctx, 1);
1650 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1651 tcg_temp_free_i32(terr);
1652 tcg_temp_free_i32(texcp);
1653 ctx->base.is_jmp = DISAS_NORETURN;
1656 static inline void generate_exception(DisasContext *ctx, int excp)
1658 gen_helper_0e0i(raise_exception, excp);
1661 static inline void generate_exception_end(DisasContext *ctx, int excp)
1663 generate_exception_err(ctx, excp, 0);
1666 /* Floating point register moves. */
1667 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1669 if (ctx->hflags & MIPS_HFLAG_FRE) {
1670 generate_exception(ctx, EXCP_RI);
1672 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1675 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1677 TCGv_i64 t64;
1678 if (ctx->hflags & MIPS_HFLAG_FRE) {
1679 generate_exception(ctx, EXCP_RI);
1681 t64 = tcg_temp_new_i64();
1682 tcg_gen_extu_i32_i64(t64, t);
1683 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1684 tcg_temp_free_i64(t64);
1687 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1689 if (ctx->hflags & MIPS_HFLAG_F64) {
1690 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1691 } else {
1692 gen_load_fpr32(ctx, t, reg | 1);
1696 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1698 if (ctx->hflags & MIPS_HFLAG_F64) {
1699 TCGv_i64 t64 = tcg_temp_new_i64();
1700 tcg_gen_extu_i32_i64(t64, t);
1701 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1702 tcg_temp_free_i64(t64);
1703 } else {
1704 gen_store_fpr32(ctx, t, reg | 1);
1708 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1710 if (ctx->hflags & MIPS_HFLAG_F64) {
1711 tcg_gen_mov_i64(t, fpu_f64[reg]);
1712 } else {
1713 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1717 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1719 if (ctx->hflags & MIPS_HFLAG_F64) {
1720 tcg_gen_mov_i64(fpu_f64[reg], t);
1721 } else {
1722 TCGv_i64 t0;
1723 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1724 t0 = tcg_temp_new_i64();
1725 tcg_gen_shri_i64(t0, t, 32);
1726 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1727 tcg_temp_free_i64(t0);
1731 static inline int get_fp_bit (int cc)
1733 if (cc)
1734 return 24 + cc;
1735 else
1736 return 23;
1739 /* Addresses computation */
1740 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1742 tcg_gen_add_tl(ret, arg0, arg1);
1744 #if defined(TARGET_MIPS64)
1745 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1746 tcg_gen_ext32s_i64(ret, ret);
1748 #endif
1751 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1752 target_long ofs)
1754 tcg_gen_addi_tl(ret, base, ofs);
1756 #if defined(TARGET_MIPS64)
1757 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1758 tcg_gen_ext32s_i64(ret, ret);
1760 #endif
1763 /* Addresses computation (translation time) */
1764 static target_long addr_add(DisasContext *ctx, target_long base,
1765 target_long offset)
1767 target_long sum = base + offset;
1769 #if defined(TARGET_MIPS64)
1770 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1771 sum = (int32_t)sum;
1773 #endif
1774 return sum;
1777 /* Sign-extract the low 32-bits to a target_long. */
1778 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1780 #if defined(TARGET_MIPS64)
1781 tcg_gen_ext32s_i64(ret, arg);
1782 #else
1783 tcg_gen_extrl_i64_i32(ret, arg);
1784 #endif
1787 /* Sign-extract the high 32-bits to a target_long. */
1788 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1790 #if defined(TARGET_MIPS64)
1791 tcg_gen_sari_i64(ret, arg, 32);
1792 #else
1793 tcg_gen_extrh_i64_i32(ret, arg);
1794 #endif
1797 static inline void check_cp0_enabled(DisasContext *ctx)
1799 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1800 generate_exception_err(ctx, EXCP_CpU, 0);
1803 static inline void check_cp1_enabled(DisasContext *ctx)
1805 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1806 generate_exception_err(ctx, EXCP_CpU, 1);
1809 /* Verify that the processor is running with COP1X instructions enabled.
1810 This is associated with the nabla symbol in the MIPS32 and MIPS64
1811 opcode tables. */
1813 static inline void check_cop1x(DisasContext *ctx)
1815 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1816 generate_exception_end(ctx, EXCP_RI);
1819 /* Verify that the processor is running with 64-bit floating-point
1820 operations enabled. */
1822 static inline void check_cp1_64bitmode(DisasContext *ctx)
1824 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1825 generate_exception_end(ctx, EXCP_RI);
1829 * Verify if floating point register is valid; an operation is not defined
1830 * if bit 0 of any register specification is set and the FR bit in the
1831 * Status register equals zero, since the register numbers specify an
1832 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1833 * in the Status register equals one, both even and odd register numbers
1834 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1836 * Multiple 64 bit wide registers can be checked by calling
1837 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1839 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1841 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1842 generate_exception_end(ctx, EXCP_RI);
1845 /* Verify that the processor is running with DSP instructions enabled.
1846 This is enabled by CP0 Status register MX(24) bit.
1849 static inline void check_dsp(DisasContext *ctx)
1851 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1852 if (ctx->insn_flags & ASE_DSP) {
1853 generate_exception_end(ctx, EXCP_DSPDIS);
1854 } else {
1855 generate_exception_end(ctx, EXCP_RI);
1860 static inline void check_dspr2(DisasContext *ctx)
1862 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1863 if (ctx->insn_flags & ASE_DSP) {
1864 generate_exception_end(ctx, EXCP_DSPDIS);
1865 } else {
1866 generate_exception_end(ctx, EXCP_RI);
1871 /* This code generates a "reserved instruction" exception if the
1872 CPU does not support the instruction set corresponding to flags. */
1873 static inline void check_insn(DisasContext *ctx, int flags)
1875 if (unlikely(!(ctx->insn_flags & flags))) {
1876 generate_exception_end(ctx, EXCP_RI);
1880 /* This code generates a "reserved instruction" exception if the
1881 CPU has corresponding flag set which indicates that the instruction
1882 has been removed. */
1883 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1885 if (unlikely(ctx->insn_flags & flags)) {
1886 generate_exception_end(ctx, EXCP_RI);
1890 /* This code generates a "reserved instruction" exception if the
1891 CPU does not support 64-bit paired-single (PS) floating point data type */
1892 static inline void check_ps(DisasContext *ctx)
1894 if (unlikely(!ctx->ps)) {
1895 generate_exception(ctx, EXCP_RI);
1897 check_cp1_64bitmode(ctx);
1900 #ifdef TARGET_MIPS64
1901 /* This code generates a "reserved instruction" exception if 64-bit
1902 instructions are not enabled. */
1903 static inline void check_mips_64(DisasContext *ctx)
1905 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1906 generate_exception_end(ctx, EXCP_RI);
1908 #endif
1910 #ifndef CONFIG_USER_ONLY
1911 static inline void check_mvh(DisasContext *ctx)
1913 if (unlikely(!ctx->mvh)) {
1914 generate_exception(ctx, EXCP_RI);
1917 #endif
1920 * This code generates a "reserved instruction" exception if the
1921 * Config5 XNP bit is set.
1923 static inline void check_xnp(DisasContext *ctx)
1925 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1926 generate_exception_end(ctx, EXCP_RI);
1931 * This code generates a "reserved instruction" exception if the
1932 * Config3 MT bit is NOT set.
1934 static inline void check_mt(DisasContext *ctx)
1936 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1937 generate_exception_end(ctx, EXCP_RI);
1941 #ifndef CONFIG_USER_ONLY
1943 * This code generates a "coprocessor unusable" exception if CP0 is not
1944 * available, and, if that is not the case, generates a "reserved instruction"
1945 * exception if the Config5 MT bit is NOT set. This is needed for availability
1946 * control of some of MT ASE instructions.
1948 static inline void check_cp0_mt(DisasContext *ctx)
1950 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1951 generate_exception_err(ctx, EXCP_CpU, 0);
1952 } else {
1953 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1954 generate_exception_err(ctx, EXCP_RI, 0);
1958 #endif
1961 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1962 calling interface for 32 and 64-bit FPRs. No sense in changing
1963 all callers for gen_load_fpr32 when we need the CTX parameter for
1964 this one use. */
1965 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1966 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1967 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1968 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1969 int ft, int fs, int cc) \
1971 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1972 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1973 switch (ifmt) { \
1974 case FMT_PS: \
1975 check_ps(ctx); \
1976 break; \
1977 case FMT_D: \
1978 if (abs) { \
1979 check_cop1x(ctx); \
1981 check_cp1_registers(ctx, fs | ft); \
1982 break; \
1983 case FMT_S: \
1984 if (abs) { \
1985 check_cop1x(ctx); \
1987 break; \
1989 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1990 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1991 switch (n) { \
1992 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1993 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1994 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1995 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1996 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1997 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1998 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1999 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
2000 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
2001 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
2002 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
2003 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
2004 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
2005 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
2006 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
2007 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
2008 default: abort(); \
2010 tcg_temp_free_i##bits (fp0); \
2011 tcg_temp_free_i##bits (fp1); \
2014 FOP_CONDS(, 0, d, FMT_D, 64)
2015 FOP_CONDS(abs, 1, d, FMT_D, 64)
2016 FOP_CONDS(, 0, s, FMT_S, 32)
2017 FOP_CONDS(abs, 1, s, FMT_S, 32)
2018 FOP_CONDS(, 0, ps, FMT_PS, 64)
2019 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2020 #undef FOP_CONDS
2022 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2023 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
2024 int ft, int fs, int fd) \
2026 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2027 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2028 if (ifmt == FMT_D) { \
2029 check_cp1_registers(ctx, fs | ft | fd); \
2031 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2032 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2033 switch (n) { \
2034 case 0: \
2035 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2036 break; \
2037 case 1: \
2038 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2039 break; \
2040 case 2: \
2041 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2042 break; \
2043 case 3: \
2044 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2045 break; \
2046 case 4: \
2047 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2048 break; \
2049 case 5: \
2050 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2051 break; \
2052 case 6: \
2053 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2054 break; \
2055 case 7: \
2056 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2057 break; \
2058 case 8: \
2059 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2060 break; \
2061 case 9: \
2062 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2063 break; \
2064 case 10: \
2065 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2066 break; \
2067 case 11: \
2068 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2069 break; \
2070 case 12: \
2071 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2072 break; \
2073 case 13: \
2074 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2075 break; \
2076 case 14: \
2077 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2078 break; \
2079 case 15: \
2080 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2081 break; \
2082 case 17: \
2083 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2084 break; \
2085 case 18: \
2086 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2087 break; \
2088 case 19: \
2089 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2090 break; \
2091 case 25: \
2092 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2093 break; \
2094 case 26: \
2095 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2096 break; \
2097 case 27: \
2098 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2099 break; \
2100 default: \
2101 abort(); \
2103 STORE; \
2104 tcg_temp_free_i ## bits (fp0); \
2105 tcg_temp_free_i ## bits (fp1); \
2108 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2109 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2110 #undef FOP_CONDNS
2111 #undef gen_ldcmp_fpr32
2112 #undef gen_ldcmp_fpr64
2114 /* load/store instructions. */
2115 #ifdef CONFIG_USER_ONLY
2116 #define OP_LD_ATOMIC(insn,fname) \
2117 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2118 DisasContext *ctx) \
2120 TCGv t0 = tcg_temp_new(); \
2121 tcg_gen_mov_tl(t0, arg1); \
2122 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2123 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2124 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2125 tcg_temp_free(t0); \
2127 #else
2128 #define OP_LD_ATOMIC(insn,fname) \
2129 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2130 DisasContext *ctx) \
2132 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2134 #endif
2135 OP_LD_ATOMIC(ll,ld32s);
2136 #if defined(TARGET_MIPS64)
2137 OP_LD_ATOMIC(lld,ld64);
2138 #endif
2139 #undef OP_LD_ATOMIC
2141 #ifdef CONFIG_USER_ONLY
2142 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2143 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2144 DisasContext *ctx) \
2146 TCGv t0 = tcg_temp_new(); \
2147 TCGLabel *l1 = gen_new_label(); \
2148 TCGLabel *l2 = gen_new_label(); \
2150 tcg_gen_andi_tl(t0, arg2, almask); \
2151 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2152 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2153 generate_exception(ctx, EXCP_AdES); \
2154 gen_set_label(l1); \
2155 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2156 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2157 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2158 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2159 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2160 generate_exception_end(ctx, EXCP_SC); \
2161 gen_set_label(l2); \
2162 tcg_gen_movi_tl(t0, 0); \
2163 gen_store_gpr(t0, rt); \
2164 tcg_temp_free(t0); \
2166 #else
2167 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2168 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2169 DisasContext *ctx) \
2171 TCGv t0 = tcg_temp_new(); \
2172 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
2173 gen_store_gpr(t0, rt); \
2174 tcg_temp_free(t0); \
2176 #endif
2177 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2178 #if defined(TARGET_MIPS64)
2179 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2180 #endif
2181 #undef OP_ST_ATOMIC
2183 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2184 int base, int offset)
2186 if (base == 0) {
2187 tcg_gen_movi_tl(addr, offset);
2188 } else if (offset == 0) {
2189 gen_load_gpr(addr, base);
2190 } else {
2191 tcg_gen_movi_tl(addr, offset);
2192 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2196 static target_ulong pc_relative_pc (DisasContext *ctx)
2198 target_ulong pc = ctx->base.pc_next;
2200 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2201 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2203 pc -= branch_bytes;
2206 pc &= ~(target_ulong)3;
2207 return pc;
2210 /* Load */
2211 static void gen_ld(DisasContext *ctx, uint32_t opc,
2212 int rt, int base, int offset)
2214 TCGv t0, t1, t2;
2215 int mem_idx = ctx->mem_idx;
2217 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2218 /* Loongson CPU uses a load to zero register for prefetch.
2219 We emulate it as a NOP. On other CPU we must perform the
2220 actual memory access. */
2221 return;
2224 t0 = tcg_temp_new();
2225 gen_base_offset_addr(ctx, t0, base, offset);
2227 switch (opc) {
2228 #if defined(TARGET_MIPS64)
2229 case OPC_LWU:
2230 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2231 ctx->default_tcg_memop_mask);
2232 gen_store_gpr(t0, rt);
2233 break;
2234 case OPC_LD:
2235 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2236 ctx->default_tcg_memop_mask);
2237 gen_store_gpr(t0, rt);
2238 break;
2239 case OPC_LLD:
2240 case R6_OPC_LLD:
2241 op_ld_lld(t0, t0, mem_idx, ctx);
2242 gen_store_gpr(t0, rt);
2243 break;
2244 case OPC_LDL:
2245 t1 = tcg_temp_new();
2246 /* Do a byte access to possibly trigger a page
2247 fault with the unaligned address. */
2248 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2249 tcg_gen_andi_tl(t1, t0, 7);
2250 #ifndef TARGET_WORDS_BIGENDIAN
2251 tcg_gen_xori_tl(t1, t1, 7);
2252 #endif
2253 tcg_gen_shli_tl(t1, t1, 3);
2254 tcg_gen_andi_tl(t0, t0, ~7);
2255 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2256 tcg_gen_shl_tl(t0, t0, t1);
2257 t2 = tcg_const_tl(-1);
2258 tcg_gen_shl_tl(t2, t2, t1);
2259 gen_load_gpr(t1, rt);
2260 tcg_gen_andc_tl(t1, t1, t2);
2261 tcg_temp_free(t2);
2262 tcg_gen_or_tl(t0, t0, t1);
2263 tcg_temp_free(t1);
2264 gen_store_gpr(t0, rt);
2265 break;
2266 case OPC_LDR:
2267 t1 = tcg_temp_new();
2268 /* Do a byte access to possibly trigger a page
2269 fault with the unaligned address. */
2270 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2271 tcg_gen_andi_tl(t1, t0, 7);
2272 #ifdef TARGET_WORDS_BIGENDIAN
2273 tcg_gen_xori_tl(t1, t1, 7);
2274 #endif
2275 tcg_gen_shli_tl(t1, t1, 3);
2276 tcg_gen_andi_tl(t0, t0, ~7);
2277 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2278 tcg_gen_shr_tl(t0, t0, t1);
2279 tcg_gen_xori_tl(t1, t1, 63);
2280 t2 = tcg_const_tl(0xfffffffffffffffeull);
2281 tcg_gen_shl_tl(t2, t2, t1);
2282 gen_load_gpr(t1, rt);
2283 tcg_gen_and_tl(t1, t1, t2);
2284 tcg_temp_free(t2);
2285 tcg_gen_or_tl(t0, t0, t1);
2286 tcg_temp_free(t1);
2287 gen_store_gpr(t0, rt);
2288 break;
2289 case OPC_LDPC:
2290 t1 = tcg_const_tl(pc_relative_pc(ctx));
2291 gen_op_addr_add(ctx, t0, t0, t1);
2292 tcg_temp_free(t1);
2293 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2294 gen_store_gpr(t0, rt);
2295 break;
2296 #endif
2297 case OPC_LWPC:
2298 t1 = tcg_const_tl(pc_relative_pc(ctx));
2299 gen_op_addr_add(ctx, t0, t0, t1);
2300 tcg_temp_free(t1);
2301 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2302 gen_store_gpr(t0, rt);
2303 break;
2304 case OPC_LWE:
2305 mem_idx = MIPS_HFLAG_UM;
2306 /* fall through */
2307 case OPC_LW:
2308 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2309 ctx->default_tcg_memop_mask);
2310 gen_store_gpr(t0, rt);
2311 break;
2312 case OPC_LHE:
2313 mem_idx = MIPS_HFLAG_UM;
2314 /* fall through */
2315 case OPC_LH:
2316 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2317 ctx->default_tcg_memop_mask);
2318 gen_store_gpr(t0, rt);
2319 break;
2320 case OPC_LHUE:
2321 mem_idx = MIPS_HFLAG_UM;
2322 /* fall through */
2323 case OPC_LHU:
2324 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2325 ctx->default_tcg_memop_mask);
2326 gen_store_gpr(t0, rt);
2327 break;
2328 case OPC_LBE:
2329 mem_idx = MIPS_HFLAG_UM;
2330 /* fall through */
2331 case OPC_LB:
2332 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2333 gen_store_gpr(t0, rt);
2334 break;
2335 case OPC_LBUE:
2336 mem_idx = MIPS_HFLAG_UM;
2337 /* fall through */
2338 case OPC_LBU:
2339 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2340 gen_store_gpr(t0, rt);
2341 break;
2342 case OPC_LWLE:
2343 mem_idx = MIPS_HFLAG_UM;
2344 /* fall through */
2345 case OPC_LWL:
2346 t1 = tcg_temp_new();
2347 /* Do a byte access to possibly trigger a page
2348 fault with the unaligned address. */
2349 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2350 tcg_gen_andi_tl(t1, t0, 3);
2351 #ifndef TARGET_WORDS_BIGENDIAN
2352 tcg_gen_xori_tl(t1, t1, 3);
2353 #endif
2354 tcg_gen_shli_tl(t1, t1, 3);
2355 tcg_gen_andi_tl(t0, t0, ~3);
2356 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2357 tcg_gen_shl_tl(t0, t0, t1);
2358 t2 = tcg_const_tl(-1);
2359 tcg_gen_shl_tl(t2, t2, t1);
2360 gen_load_gpr(t1, rt);
2361 tcg_gen_andc_tl(t1, t1, t2);
2362 tcg_temp_free(t2);
2363 tcg_gen_or_tl(t0, t0, t1);
2364 tcg_temp_free(t1);
2365 tcg_gen_ext32s_tl(t0, t0);
2366 gen_store_gpr(t0, rt);
2367 break;
2368 case OPC_LWRE:
2369 mem_idx = MIPS_HFLAG_UM;
2370 /* fall through */
2371 case OPC_LWR:
2372 t1 = tcg_temp_new();
2373 /* Do a byte access to possibly trigger a page
2374 fault with the unaligned address. */
2375 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2376 tcg_gen_andi_tl(t1, t0, 3);
2377 #ifdef TARGET_WORDS_BIGENDIAN
2378 tcg_gen_xori_tl(t1, t1, 3);
2379 #endif
2380 tcg_gen_shli_tl(t1, t1, 3);
2381 tcg_gen_andi_tl(t0, t0, ~3);
2382 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2383 tcg_gen_shr_tl(t0, t0, t1);
2384 tcg_gen_xori_tl(t1, t1, 31);
2385 t2 = tcg_const_tl(0xfffffffeull);
2386 tcg_gen_shl_tl(t2, t2, t1);
2387 gen_load_gpr(t1, rt);
2388 tcg_gen_and_tl(t1, t1, t2);
2389 tcg_temp_free(t2);
2390 tcg_gen_or_tl(t0, t0, t1);
2391 tcg_temp_free(t1);
2392 tcg_gen_ext32s_tl(t0, t0);
2393 gen_store_gpr(t0, rt);
2394 break;
2395 case OPC_LLE:
2396 mem_idx = MIPS_HFLAG_UM;
2397 /* fall through */
2398 case OPC_LL:
2399 case R6_OPC_LL:
2400 op_ld_ll(t0, t0, mem_idx, ctx);
2401 gen_store_gpr(t0, rt);
2402 break;
2404 tcg_temp_free(t0);
2407 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2408 uint32_t reg1, uint32_t reg2)
2410 TCGv taddr = tcg_temp_new();
2411 TCGv_i64 tval = tcg_temp_new_i64();
2412 TCGv tmp1 = tcg_temp_new();
2413 TCGv tmp2 = tcg_temp_new();
2415 gen_base_offset_addr(ctx, taddr, base, offset);
2416 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2417 #ifdef TARGET_WORDS_BIGENDIAN
2418 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2419 #else
2420 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2421 #endif
2422 gen_store_gpr(tmp1, reg1);
2423 tcg_temp_free(tmp1);
2424 gen_store_gpr(tmp2, reg2);
2425 tcg_temp_free(tmp2);
2426 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2427 tcg_temp_free_i64(tval);
2428 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2429 tcg_temp_free(taddr);
2432 /* Store */
2433 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2434 int base, int offset)
2436 TCGv t0 = tcg_temp_new();
2437 TCGv t1 = tcg_temp_new();
2438 int mem_idx = ctx->mem_idx;
2440 gen_base_offset_addr(ctx, t0, base, offset);
2441 gen_load_gpr(t1, rt);
2442 switch (opc) {
2443 #if defined(TARGET_MIPS64)
2444 case OPC_SD:
2445 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2446 ctx->default_tcg_memop_mask);
2447 break;
2448 case OPC_SDL:
2449 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2450 break;
2451 case OPC_SDR:
2452 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2453 break;
2454 #endif
2455 case OPC_SWE:
2456 mem_idx = MIPS_HFLAG_UM;
2457 /* fall through */
2458 case OPC_SW:
2459 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2460 ctx->default_tcg_memop_mask);
2461 break;
2462 case OPC_SHE:
2463 mem_idx = MIPS_HFLAG_UM;
2464 /* fall through */
2465 case OPC_SH:
2466 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2467 ctx->default_tcg_memop_mask);
2468 break;
2469 case OPC_SBE:
2470 mem_idx = MIPS_HFLAG_UM;
2471 /* fall through */
2472 case OPC_SB:
2473 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2474 break;
2475 case OPC_SWLE:
2476 mem_idx = MIPS_HFLAG_UM;
2477 /* fall through */
2478 case OPC_SWL:
2479 gen_helper_0e2i(swl, t1, t0, mem_idx);
2480 break;
2481 case OPC_SWRE:
2482 mem_idx = MIPS_HFLAG_UM;
2483 /* fall through */
2484 case OPC_SWR:
2485 gen_helper_0e2i(swr, t1, t0, mem_idx);
2486 break;
2488 tcg_temp_free(t0);
2489 tcg_temp_free(t1);
2493 /* Store conditional */
2494 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2495 int base, int16_t offset)
2497 TCGv t0, t1;
2498 int mem_idx = ctx->mem_idx;
2500 #ifdef CONFIG_USER_ONLY
2501 t0 = tcg_temp_local_new();
2502 t1 = tcg_temp_local_new();
2503 #else
2504 t0 = tcg_temp_new();
2505 t1 = tcg_temp_new();
2506 #endif
2507 gen_base_offset_addr(ctx, t0, base, offset);
2508 gen_load_gpr(t1, rt);
2509 switch (opc) {
2510 #if defined(TARGET_MIPS64)
2511 case OPC_SCD:
2512 case R6_OPC_SCD:
2513 op_st_scd(t1, t0, rt, mem_idx, ctx);
2514 break;
2515 #endif
2516 case OPC_SCE:
2517 mem_idx = MIPS_HFLAG_UM;
2518 /* fall through */
2519 case OPC_SC:
2520 case R6_OPC_SC:
2521 op_st_sc(t1, t0, rt, mem_idx, ctx);
2522 break;
2524 tcg_temp_free(t1);
2525 tcg_temp_free(t0);
2528 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2529 uint32_t reg1, uint32_t reg2)
2531 TCGv taddr = tcg_temp_local_new();
2532 TCGv lladdr = tcg_temp_local_new();
2533 TCGv_i64 tval = tcg_temp_new_i64();
2534 TCGv_i64 llval = tcg_temp_new_i64();
2535 TCGv_i64 val = tcg_temp_new_i64();
2536 TCGv tmp1 = tcg_temp_new();
2537 TCGv tmp2 = tcg_temp_new();
2538 TCGLabel *lab_fail = gen_new_label();
2539 TCGLabel *lab_done = gen_new_label();
2541 gen_base_offset_addr(ctx, taddr, base, offset);
2543 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2544 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2546 gen_load_gpr(tmp1, reg1);
2547 gen_load_gpr(tmp2, reg2);
2549 #ifdef TARGET_WORDS_BIGENDIAN
2550 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2551 #else
2552 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2553 #endif
2555 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2556 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2557 ctx->mem_idx, MO_64);
2558 if (reg1 != 0) {
2559 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2561 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2563 gen_set_label(lab_fail);
2565 if (reg1 != 0) {
2566 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2568 gen_set_label(lab_done);
2569 tcg_gen_movi_tl(lladdr, -1);
2570 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2573 /* Load and store */
2574 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2575 TCGv t0)
2577 /* Don't do NOP if destination is zero: we must perform the actual
2578 memory access. */
2579 switch (opc) {
2580 case OPC_LWC1:
2582 TCGv_i32 fp0 = tcg_temp_new_i32();
2583 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2584 ctx->default_tcg_memop_mask);
2585 gen_store_fpr32(ctx, fp0, ft);
2586 tcg_temp_free_i32(fp0);
2588 break;
2589 case OPC_SWC1:
2591 TCGv_i32 fp0 = tcg_temp_new_i32();
2592 gen_load_fpr32(ctx, fp0, ft);
2593 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2594 ctx->default_tcg_memop_mask);
2595 tcg_temp_free_i32(fp0);
2597 break;
2598 case OPC_LDC1:
2600 TCGv_i64 fp0 = tcg_temp_new_i64();
2601 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2602 ctx->default_tcg_memop_mask);
2603 gen_store_fpr64(ctx, fp0, ft);
2604 tcg_temp_free_i64(fp0);
2606 break;
2607 case OPC_SDC1:
2609 TCGv_i64 fp0 = tcg_temp_new_i64();
2610 gen_load_fpr64(ctx, fp0, ft);
2611 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2612 ctx->default_tcg_memop_mask);
2613 tcg_temp_free_i64(fp0);
2615 break;
2616 default:
2617 MIPS_INVAL("flt_ldst");
2618 generate_exception_end(ctx, EXCP_RI);
2619 break;
2623 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2624 int rs, int16_t imm)
2626 TCGv t0 = tcg_temp_new();
2628 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2629 check_cp1_enabled(ctx);
2630 switch (op) {
2631 case OPC_LDC1:
2632 case OPC_SDC1:
2633 check_insn(ctx, ISA_MIPS2);
2634 /* Fallthrough */
2635 default:
2636 gen_base_offset_addr(ctx, t0, rs, imm);
2637 gen_flt_ldst(ctx, op, rt, t0);
2639 } else {
2640 generate_exception_err(ctx, EXCP_CpU, 1);
2642 tcg_temp_free(t0);
2645 /* Arithmetic with immediate operand */
2646 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2647 int rt, int rs, int imm)
2649 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2651 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2652 /* If no destination, treat it as a NOP.
2653 For addi, we must generate the overflow exception when needed. */
2654 return;
2656 switch (opc) {
2657 case OPC_ADDI:
2659 TCGv t0 = tcg_temp_local_new();
2660 TCGv t1 = tcg_temp_new();
2661 TCGv t2 = tcg_temp_new();
2662 TCGLabel *l1 = gen_new_label();
2664 gen_load_gpr(t1, rs);
2665 tcg_gen_addi_tl(t0, t1, uimm);
2666 tcg_gen_ext32s_tl(t0, t0);
2668 tcg_gen_xori_tl(t1, t1, ~uimm);
2669 tcg_gen_xori_tl(t2, t0, uimm);
2670 tcg_gen_and_tl(t1, t1, t2);
2671 tcg_temp_free(t2);
2672 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2673 tcg_temp_free(t1);
2674 /* operands of same sign, result different sign */
2675 generate_exception(ctx, EXCP_OVERFLOW);
2676 gen_set_label(l1);
2677 tcg_gen_ext32s_tl(t0, t0);
2678 gen_store_gpr(t0, rt);
2679 tcg_temp_free(t0);
2681 break;
2682 case OPC_ADDIU:
2683 if (rs != 0) {
2684 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2685 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2686 } else {
2687 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2689 break;
2690 #if defined(TARGET_MIPS64)
2691 case OPC_DADDI:
2693 TCGv t0 = tcg_temp_local_new();
2694 TCGv t1 = tcg_temp_new();
2695 TCGv t2 = tcg_temp_new();
2696 TCGLabel *l1 = gen_new_label();
2698 gen_load_gpr(t1, rs);
2699 tcg_gen_addi_tl(t0, t1, uimm);
2701 tcg_gen_xori_tl(t1, t1, ~uimm);
2702 tcg_gen_xori_tl(t2, t0, uimm);
2703 tcg_gen_and_tl(t1, t1, t2);
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, rt);
2711 tcg_temp_free(t0);
2713 break;
2714 case OPC_DADDIU:
2715 if (rs != 0) {
2716 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2717 } else {
2718 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2720 break;
2721 #endif
2725 /* Logic with immediate operand */
2726 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2727 int rt, int rs, int16_t imm)
2729 target_ulong uimm;
2731 if (rt == 0) {
2732 /* If no destination, treat it as a NOP. */
2733 return;
2735 uimm = (uint16_t)imm;
2736 switch (opc) {
2737 case OPC_ANDI:
2738 if (likely(rs != 0))
2739 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2740 else
2741 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2742 break;
2743 case OPC_ORI:
2744 if (rs != 0)
2745 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2746 else
2747 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2748 break;
2749 case OPC_XORI:
2750 if (likely(rs != 0))
2751 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2752 else
2753 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2754 break;
2755 case OPC_LUI:
2756 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2757 /* OPC_AUI */
2758 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2759 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2760 } else {
2761 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2763 break;
2765 default:
2766 break;
2770 /* Set on less than with immediate operand */
2771 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2772 int rt, int rs, int16_t imm)
2774 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2775 TCGv t0;
2777 if (rt == 0) {
2778 /* If no destination, treat it as a NOP. */
2779 return;
2781 t0 = tcg_temp_new();
2782 gen_load_gpr(t0, rs);
2783 switch (opc) {
2784 case OPC_SLTI:
2785 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2786 break;
2787 case OPC_SLTIU:
2788 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2789 break;
2791 tcg_temp_free(t0);
2794 /* Shifts with immediate operand */
2795 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2796 int rt, int rs, int16_t imm)
2798 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2799 TCGv t0;
2801 if (rt == 0) {
2802 /* If no destination, treat it as a NOP. */
2803 return;
2806 t0 = tcg_temp_new();
2807 gen_load_gpr(t0, rs);
2808 switch (opc) {
2809 case OPC_SLL:
2810 tcg_gen_shli_tl(t0, t0, uimm);
2811 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2812 break;
2813 case OPC_SRA:
2814 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2815 break;
2816 case OPC_SRL:
2817 if (uimm != 0) {
2818 tcg_gen_ext32u_tl(t0, t0);
2819 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2820 } else {
2821 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2823 break;
2824 case OPC_ROTR:
2825 if (uimm != 0) {
2826 TCGv_i32 t1 = tcg_temp_new_i32();
2828 tcg_gen_trunc_tl_i32(t1, t0);
2829 tcg_gen_rotri_i32(t1, t1, uimm);
2830 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2831 tcg_temp_free_i32(t1);
2832 } else {
2833 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2835 break;
2836 #if defined(TARGET_MIPS64)
2837 case OPC_DSLL:
2838 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2839 break;
2840 case OPC_DSRA:
2841 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2842 break;
2843 case OPC_DSRL:
2844 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2845 break;
2846 case OPC_DROTR:
2847 if (uimm != 0) {
2848 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2849 } else {
2850 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2852 break;
2853 case OPC_DSLL32:
2854 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2855 break;
2856 case OPC_DSRA32:
2857 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2858 break;
2859 case OPC_DSRL32:
2860 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2861 break;
2862 case OPC_DROTR32:
2863 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2864 break;
2865 #endif
2867 tcg_temp_free(t0);
2870 /* Arithmetic */
2871 static void gen_arith(DisasContext *ctx, uint32_t opc,
2872 int rd, int rs, int rt)
2874 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2875 && opc != OPC_DADD && opc != OPC_DSUB) {
2876 /* If no destination, treat it as a NOP.
2877 For add & sub, we must generate the overflow exception when needed. */
2878 return;
2881 switch (opc) {
2882 case OPC_ADD:
2884 TCGv t0 = tcg_temp_local_new();
2885 TCGv t1 = tcg_temp_new();
2886 TCGv t2 = tcg_temp_new();
2887 TCGLabel *l1 = gen_new_label();
2889 gen_load_gpr(t1, rs);
2890 gen_load_gpr(t2, rt);
2891 tcg_gen_add_tl(t0, t1, t2);
2892 tcg_gen_ext32s_tl(t0, t0);
2893 tcg_gen_xor_tl(t1, t1, t2);
2894 tcg_gen_xor_tl(t2, t0, t2);
2895 tcg_gen_andc_tl(t1, t2, t1);
2896 tcg_temp_free(t2);
2897 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2898 tcg_temp_free(t1);
2899 /* operands of same sign, result different sign */
2900 generate_exception(ctx, EXCP_OVERFLOW);
2901 gen_set_label(l1);
2902 gen_store_gpr(t0, rd);
2903 tcg_temp_free(t0);
2905 break;
2906 case OPC_ADDU:
2907 if (rs != 0 && rt != 0) {
2908 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2909 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2910 } else if (rs == 0 && rt != 0) {
2911 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2912 } else if (rs != 0 && rt == 0) {
2913 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2914 } else {
2915 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2917 break;
2918 case OPC_SUB:
2920 TCGv t0 = tcg_temp_local_new();
2921 TCGv t1 = tcg_temp_new();
2922 TCGv t2 = tcg_temp_new();
2923 TCGLabel *l1 = gen_new_label();
2925 gen_load_gpr(t1, rs);
2926 gen_load_gpr(t2, rt);
2927 tcg_gen_sub_tl(t0, t1, t2);
2928 tcg_gen_ext32s_tl(t0, t0);
2929 tcg_gen_xor_tl(t2, t1, t2);
2930 tcg_gen_xor_tl(t1, t0, t1);
2931 tcg_gen_and_tl(t1, t1, t2);
2932 tcg_temp_free(t2);
2933 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2934 tcg_temp_free(t1);
2935 /* operands of different sign, first operand and result different sign */
2936 generate_exception(ctx, EXCP_OVERFLOW);
2937 gen_set_label(l1);
2938 gen_store_gpr(t0, rd);
2939 tcg_temp_free(t0);
2941 break;
2942 case OPC_SUBU:
2943 if (rs != 0 && rt != 0) {
2944 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2945 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2946 } else if (rs == 0 && rt != 0) {
2947 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2948 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2949 } else if (rs != 0 && rt == 0) {
2950 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2951 } else {
2952 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2954 break;
2955 #if defined(TARGET_MIPS64)
2956 case OPC_DADD:
2958 TCGv t0 = tcg_temp_local_new();
2959 TCGv t1 = tcg_temp_new();
2960 TCGv t2 = tcg_temp_new();
2961 TCGLabel *l1 = gen_new_label();
2963 gen_load_gpr(t1, rs);
2964 gen_load_gpr(t2, rt);
2965 tcg_gen_add_tl(t0, t1, t2);
2966 tcg_gen_xor_tl(t1, t1, t2);
2967 tcg_gen_xor_tl(t2, t0, t2);
2968 tcg_gen_andc_tl(t1, t2, t1);
2969 tcg_temp_free(t2);
2970 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2971 tcg_temp_free(t1);
2972 /* operands of same sign, result different sign */
2973 generate_exception(ctx, EXCP_OVERFLOW);
2974 gen_set_label(l1);
2975 gen_store_gpr(t0, rd);
2976 tcg_temp_free(t0);
2978 break;
2979 case OPC_DADDU:
2980 if (rs != 0 && rt != 0) {
2981 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2982 } else if (rs == 0 && rt != 0) {
2983 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2984 } else if (rs != 0 && rt == 0) {
2985 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2986 } else {
2987 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2989 break;
2990 case OPC_DSUB:
2992 TCGv t0 = tcg_temp_local_new();
2993 TCGv t1 = tcg_temp_new();
2994 TCGv t2 = tcg_temp_new();
2995 TCGLabel *l1 = gen_new_label();
2997 gen_load_gpr(t1, rs);
2998 gen_load_gpr(t2, rt);
2999 tcg_gen_sub_tl(t0, t1, t2);
3000 tcg_gen_xor_tl(t2, t1, t2);
3001 tcg_gen_xor_tl(t1, t0, t1);
3002 tcg_gen_and_tl(t1, t1, t2);
3003 tcg_temp_free(t2);
3004 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3005 tcg_temp_free(t1);
3006 /* operands of different sign, first operand and result different sign */
3007 generate_exception(ctx, EXCP_OVERFLOW);
3008 gen_set_label(l1);
3009 gen_store_gpr(t0, rd);
3010 tcg_temp_free(t0);
3012 break;
3013 case OPC_DSUBU:
3014 if (rs != 0 && rt != 0) {
3015 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3016 } else if (rs == 0 && rt != 0) {
3017 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3018 } else if (rs != 0 && rt == 0) {
3019 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3020 } else {
3021 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3023 break;
3024 #endif
3025 case OPC_MUL:
3026 if (likely(rs != 0 && rt != 0)) {
3027 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3028 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3029 } else {
3030 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3032 break;
3036 /* Conditional move */
3037 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3038 int rd, int rs, int rt)
3040 TCGv t0, t1, t2;
3042 if (rd == 0) {
3043 /* If no destination, treat it as a NOP. */
3044 return;
3047 t0 = tcg_temp_new();
3048 gen_load_gpr(t0, rt);
3049 t1 = tcg_const_tl(0);
3050 t2 = tcg_temp_new();
3051 gen_load_gpr(t2, rs);
3052 switch (opc) {
3053 case OPC_MOVN:
3054 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3055 break;
3056 case OPC_MOVZ:
3057 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3058 break;
3059 case OPC_SELNEZ:
3060 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3061 break;
3062 case OPC_SELEQZ:
3063 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3064 break;
3066 tcg_temp_free(t2);
3067 tcg_temp_free(t1);
3068 tcg_temp_free(t0);
3071 /* Logic */
3072 static void gen_logic(DisasContext *ctx, uint32_t opc,
3073 int rd, int rs, int rt)
3075 if (rd == 0) {
3076 /* If no destination, treat it as a NOP. */
3077 return;
3080 switch (opc) {
3081 case OPC_AND:
3082 if (likely(rs != 0 && rt != 0)) {
3083 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3084 } else {
3085 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3087 break;
3088 case OPC_NOR:
3089 if (rs != 0 && rt != 0) {
3090 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3091 } else if (rs == 0 && rt != 0) {
3092 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3093 } else if (rs != 0 && rt == 0) {
3094 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3095 } else {
3096 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3098 break;
3099 case OPC_OR:
3100 if (likely(rs != 0 && rt != 0)) {
3101 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3102 } else if (rs == 0 && rt != 0) {
3103 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3104 } else if (rs != 0 && rt == 0) {
3105 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3106 } else {
3107 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3109 break;
3110 case OPC_XOR:
3111 if (likely(rs != 0 && rt != 0)) {
3112 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3113 } else if (rs == 0 && rt != 0) {
3114 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3115 } else if (rs != 0 && rt == 0) {
3116 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3117 } else {
3118 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3120 break;
3124 /* Set on lower than */
3125 static void gen_slt(DisasContext *ctx, uint32_t opc,
3126 int rd, int rs, int rt)
3128 TCGv t0, t1;
3130 if (rd == 0) {
3131 /* If no destination, treat it as a NOP. */
3132 return;
3135 t0 = tcg_temp_new();
3136 t1 = tcg_temp_new();
3137 gen_load_gpr(t0, rs);
3138 gen_load_gpr(t1, rt);
3139 switch (opc) {
3140 case OPC_SLT:
3141 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3142 break;
3143 case OPC_SLTU:
3144 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3145 break;
3147 tcg_temp_free(t0);
3148 tcg_temp_free(t1);
3151 /* Shifts */
3152 static void gen_shift(DisasContext *ctx, uint32_t opc,
3153 int rd, int rs, int rt)
3155 TCGv t0, t1;
3157 if (rd == 0) {
3158 /* If no destination, treat it as a NOP.
3159 For add & sub, we must generate the overflow exception when needed. */
3160 return;
3163 t0 = tcg_temp_new();
3164 t1 = tcg_temp_new();
3165 gen_load_gpr(t0, rs);
3166 gen_load_gpr(t1, rt);
3167 switch (opc) {
3168 case OPC_SLLV:
3169 tcg_gen_andi_tl(t0, t0, 0x1f);
3170 tcg_gen_shl_tl(t0, t1, t0);
3171 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3172 break;
3173 case OPC_SRAV:
3174 tcg_gen_andi_tl(t0, t0, 0x1f);
3175 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3176 break;
3177 case OPC_SRLV:
3178 tcg_gen_ext32u_tl(t1, t1);
3179 tcg_gen_andi_tl(t0, t0, 0x1f);
3180 tcg_gen_shr_tl(t0, t1, t0);
3181 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3182 break;
3183 case OPC_ROTRV:
3185 TCGv_i32 t2 = tcg_temp_new_i32();
3186 TCGv_i32 t3 = tcg_temp_new_i32();
3188 tcg_gen_trunc_tl_i32(t2, t0);
3189 tcg_gen_trunc_tl_i32(t3, t1);
3190 tcg_gen_andi_i32(t2, t2, 0x1f);
3191 tcg_gen_rotr_i32(t2, t3, t2);
3192 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3193 tcg_temp_free_i32(t2);
3194 tcg_temp_free_i32(t3);
3196 break;
3197 #if defined(TARGET_MIPS64)
3198 case OPC_DSLLV:
3199 tcg_gen_andi_tl(t0, t0, 0x3f);
3200 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3201 break;
3202 case OPC_DSRAV:
3203 tcg_gen_andi_tl(t0, t0, 0x3f);
3204 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3205 break;
3206 case OPC_DSRLV:
3207 tcg_gen_andi_tl(t0, t0, 0x3f);
3208 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3209 break;
3210 case OPC_DROTRV:
3211 tcg_gen_andi_tl(t0, t0, 0x3f);
3212 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3213 break;
3214 #endif
3216 tcg_temp_free(t0);
3217 tcg_temp_free(t1);
3220 /* Arithmetic on HI/LO registers */
3221 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3223 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3224 /* Treat as NOP. */
3225 return;
3228 if (acc != 0) {
3229 check_dsp(ctx);
3232 switch (opc) {
3233 case OPC_MFHI:
3234 #if defined(TARGET_MIPS64)
3235 if (acc != 0) {
3236 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3237 } else
3238 #endif
3240 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3242 break;
3243 case OPC_MFLO:
3244 #if defined(TARGET_MIPS64)
3245 if (acc != 0) {
3246 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3247 } else
3248 #endif
3250 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3252 break;
3253 case OPC_MTHI:
3254 if (reg != 0) {
3255 #if defined(TARGET_MIPS64)
3256 if (acc != 0) {
3257 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3258 } else
3259 #endif
3261 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3263 } else {
3264 tcg_gen_movi_tl(cpu_HI[acc], 0);
3266 break;
3267 case OPC_MTLO:
3268 if (reg != 0) {
3269 #if defined(TARGET_MIPS64)
3270 if (acc != 0) {
3271 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3272 } else
3273 #endif
3275 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3277 } else {
3278 tcg_gen_movi_tl(cpu_LO[acc], 0);
3280 break;
3284 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3285 TCGMemOp memop)
3287 TCGv t0 = tcg_const_tl(addr);
3288 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3289 gen_store_gpr(t0, reg);
3290 tcg_temp_free(t0);
3293 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3294 int rs)
3296 target_long offset;
3297 target_long addr;
3299 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3300 case OPC_ADDIUPC:
3301 if (rs != 0) {
3302 offset = sextract32(ctx->opcode << 2, 0, 21);
3303 addr = addr_add(ctx, pc, offset);
3304 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3306 break;
3307 case R6_OPC_LWPC:
3308 offset = sextract32(ctx->opcode << 2, 0, 21);
3309 addr = addr_add(ctx, pc, offset);
3310 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3311 break;
3312 #if defined(TARGET_MIPS64)
3313 case OPC_LWUPC:
3314 check_mips_64(ctx);
3315 offset = sextract32(ctx->opcode << 2, 0, 21);
3316 addr = addr_add(ctx, pc, offset);
3317 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3318 break;
3319 #endif
3320 default:
3321 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3322 case OPC_AUIPC:
3323 if (rs != 0) {
3324 offset = sextract32(ctx->opcode, 0, 16) << 16;
3325 addr = addr_add(ctx, pc, offset);
3326 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3328 break;
3329 case OPC_ALUIPC:
3330 if (rs != 0) {
3331 offset = sextract32(ctx->opcode, 0, 16) << 16;
3332 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3333 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3335 break;
3336 #if defined(TARGET_MIPS64)
3337 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3338 case R6_OPC_LDPC + (1 << 16):
3339 case R6_OPC_LDPC + (2 << 16):
3340 case R6_OPC_LDPC + (3 << 16):
3341 check_mips_64(ctx);
3342 offset = sextract32(ctx->opcode << 3, 0, 21);
3343 addr = addr_add(ctx, (pc & ~0x7), offset);
3344 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3345 break;
3346 #endif
3347 default:
3348 MIPS_INVAL("OPC_PCREL");
3349 generate_exception_end(ctx, EXCP_RI);
3350 break;
3352 break;
3356 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3358 TCGv t0, t1;
3360 if (rd == 0) {
3361 /* Treat as NOP. */
3362 return;
3365 t0 = tcg_temp_new();
3366 t1 = tcg_temp_new();
3368 gen_load_gpr(t0, rs);
3369 gen_load_gpr(t1, rt);
3371 switch (opc) {
3372 case R6_OPC_DIV:
3374 TCGv t2 = tcg_temp_new();
3375 TCGv t3 = tcg_temp_new();
3376 tcg_gen_ext32s_tl(t0, t0);
3377 tcg_gen_ext32s_tl(t1, t1);
3378 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3379 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3380 tcg_gen_and_tl(t2, t2, t3);
3381 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3382 tcg_gen_or_tl(t2, t2, t3);
3383 tcg_gen_movi_tl(t3, 0);
3384 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3385 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3386 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3387 tcg_temp_free(t3);
3388 tcg_temp_free(t2);
3390 break;
3391 case R6_OPC_MOD:
3393 TCGv t2 = tcg_temp_new();
3394 TCGv t3 = tcg_temp_new();
3395 tcg_gen_ext32s_tl(t0, t0);
3396 tcg_gen_ext32s_tl(t1, t1);
3397 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3398 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3399 tcg_gen_and_tl(t2, t2, t3);
3400 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3401 tcg_gen_or_tl(t2, t2, t3);
3402 tcg_gen_movi_tl(t3, 0);
3403 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3404 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3405 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3406 tcg_temp_free(t3);
3407 tcg_temp_free(t2);
3409 break;
3410 case R6_OPC_DIVU:
3412 TCGv t2 = tcg_const_tl(0);
3413 TCGv t3 = tcg_const_tl(1);
3414 tcg_gen_ext32u_tl(t0, t0);
3415 tcg_gen_ext32u_tl(t1, t1);
3416 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3417 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3418 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3419 tcg_temp_free(t3);
3420 tcg_temp_free(t2);
3422 break;
3423 case R6_OPC_MODU:
3425 TCGv t2 = tcg_const_tl(0);
3426 TCGv t3 = tcg_const_tl(1);
3427 tcg_gen_ext32u_tl(t0, t0);
3428 tcg_gen_ext32u_tl(t1, t1);
3429 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3430 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3431 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3432 tcg_temp_free(t3);
3433 tcg_temp_free(t2);
3435 break;
3436 case R6_OPC_MUL:
3438 TCGv_i32 t2 = tcg_temp_new_i32();
3439 TCGv_i32 t3 = tcg_temp_new_i32();
3440 tcg_gen_trunc_tl_i32(t2, t0);
3441 tcg_gen_trunc_tl_i32(t3, t1);
3442 tcg_gen_mul_i32(t2, t2, t3);
3443 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3444 tcg_temp_free_i32(t2);
3445 tcg_temp_free_i32(t3);
3447 break;
3448 case R6_OPC_MUH:
3450 TCGv_i32 t2 = tcg_temp_new_i32();
3451 TCGv_i32 t3 = tcg_temp_new_i32();
3452 tcg_gen_trunc_tl_i32(t2, t0);
3453 tcg_gen_trunc_tl_i32(t3, t1);
3454 tcg_gen_muls2_i32(t2, t3, t2, t3);
3455 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3456 tcg_temp_free_i32(t2);
3457 tcg_temp_free_i32(t3);
3459 break;
3460 case R6_OPC_MULU:
3462 TCGv_i32 t2 = tcg_temp_new_i32();
3463 TCGv_i32 t3 = tcg_temp_new_i32();
3464 tcg_gen_trunc_tl_i32(t2, t0);
3465 tcg_gen_trunc_tl_i32(t3, t1);
3466 tcg_gen_mul_i32(t2, t2, t3);
3467 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3468 tcg_temp_free_i32(t2);
3469 tcg_temp_free_i32(t3);
3471 break;
3472 case R6_OPC_MUHU:
3474 TCGv_i32 t2 = tcg_temp_new_i32();
3475 TCGv_i32 t3 = tcg_temp_new_i32();
3476 tcg_gen_trunc_tl_i32(t2, t0);
3477 tcg_gen_trunc_tl_i32(t3, t1);
3478 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3479 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3480 tcg_temp_free_i32(t2);
3481 tcg_temp_free_i32(t3);
3483 break;
3484 #if defined(TARGET_MIPS64)
3485 case R6_OPC_DDIV:
3487 TCGv t2 = tcg_temp_new();
3488 TCGv t3 = tcg_temp_new();
3489 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3490 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3491 tcg_gen_and_tl(t2, t2, t3);
3492 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3493 tcg_gen_or_tl(t2, t2, t3);
3494 tcg_gen_movi_tl(t3, 0);
3495 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3496 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3497 tcg_temp_free(t3);
3498 tcg_temp_free(t2);
3500 break;
3501 case R6_OPC_DMOD:
3503 TCGv t2 = tcg_temp_new();
3504 TCGv t3 = tcg_temp_new();
3505 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3506 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3507 tcg_gen_and_tl(t2, t2, t3);
3508 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3509 tcg_gen_or_tl(t2, t2, t3);
3510 tcg_gen_movi_tl(t3, 0);
3511 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3512 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3513 tcg_temp_free(t3);
3514 tcg_temp_free(t2);
3516 break;
3517 case R6_OPC_DDIVU:
3519 TCGv t2 = tcg_const_tl(0);
3520 TCGv t3 = tcg_const_tl(1);
3521 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3522 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3523 tcg_temp_free(t3);
3524 tcg_temp_free(t2);
3526 break;
3527 case R6_OPC_DMODU:
3529 TCGv t2 = tcg_const_tl(0);
3530 TCGv t3 = tcg_const_tl(1);
3531 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3532 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3533 tcg_temp_free(t3);
3534 tcg_temp_free(t2);
3536 break;
3537 case R6_OPC_DMUL:
3538 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3539 break;
3540 case R6_OPC_DMUH:
3542 TCGv t2 = tcg_temp_new();
3543 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3544 tcg_temp_free(t2);
3546 break;
3547 case R6_OPC_DMULU:
3548 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3549 break;
3550 case R6_OPC_DMUHU:
3552 TCGv t2 = tcg_temp_new();
3553 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3554 tcg_temp_free(t2);
3556 break;
3557 #endif
3558 default:
3559 MIPS_INVAL("r6 mul/div");
3560 generate_exception_end(ctx, EXCP_RI);
3561 goto out;
3563 out:
3564 tcg_temp_free(t0);
3565 tcg_temp_free(t1);
3568 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3569 int acc, int rs, int rt)
3571 TCGv t0, t1;
3573 t0 = tcg_temp_new();
3574 t1 = tcg_temp_new();
3576 gen_load_gpr(t0, rs);
3577 gen_load_gpr(t1, rt);
3579 if (acc != 0) {
3580 check_dsp(ctx);
3583 switch (opc) {
3584 case OPC_DIV:
3586 TCGv t2 = tcg_temp_new();
3587 TCGv t3 = tcg_temp_new();
3588 tcg_gen_ext32s_tl(t0, t0);
3589 tcg_gen_ext32s_tl(t1, t1);
3590 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3591 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3592 tcg_gen_and_tl(t2, t2, t3);
3593 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3594 tcg_gen_or_tl(t2, t2, t3);
3595 tcg_gen_movi_tl(t3, 0);
3596 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3597 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3598 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3599 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3600 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3601 tcg_temp_free(t3);
3602 tcg_temp_free(t2);
3604 break;
3605 case OPC_DIVU:
3607 TCGv t2 = tcg_const_tl(0);
3608 TCGv t3 = tcg_const_tl(1);
3609 tcg_gen_ext32u_tl(t0, t0);
3610 tcg_gen_ext32u_tl(t1, t1);
3611 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3612 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3613 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3614 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3615 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3616 tcg_temp_free(t3);
3617 tcg_temp_free(t2);
3619 break;
3620 case OPC_MULT:
3622 TCGv_i32 t2 = tcg_temp_new_i32();
3623 TCGv_i32 t3 = tcg_temp_new_i32();
3624 tcg_gen_trunc_tl_i32(t2, t0);
3625 tcg_gen_trunc_tl_i32(t3, t1);
3626 tcg_gen_muls2_i32(t2, t3, t2, t3);
3627 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3628 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3629 tcg_temp_free_i32(t2);
3630 tcg_temp_free_i32(t3);
3632 break;
3633 case OPC_MULTU:
3635 TCGv_i32 t2 = tcg_temp_new_i32();
3636 TCGv_i32 t3 = tcg_temp_new_i32();
3637 tcg_gen_trunc_tl_i32(t2, t0);
3638 tcg_gen_trunc_tl_i32(t3, t1);
3639 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3640 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3641 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3642 tcg_temp_free_i32(t2);
3643 tcg_temp_free_i32(t3);
3645 break;
3646 #if defined(TARGET_MIPS64)
3647 case OPC_DDIV:
3649 TCGv t2 = tcg_temp_new();
3650 TCGv t3 = tcg_temp_new();
3651 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3652 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3653 tcg_gen_and_tl(t2, t2, t3);
3654 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3655 tcg_gen_or_tl(t2, t2, t3);
3656 tcg_gen_movi_tl(t3, 0);
3657 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3658 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3659 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3660 tcg_temp_free(t3);
3661 tcg_temp_free(t2);
3663 break;
3664 case OPC_DDIVU:
3666 TCGv t2 = tcg_const_tl(0);
3667 TCGv t3 = tcg_const_tl(1);
3668 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3669 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3670 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3671 tcg_temp_free(t3);
3672 tcg_temp_free(t2);
3674 break;
3675 case OPC_DMULT:
3676 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3677 break;
3678 case OPC_DMULTU:
3679 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3680 break;
3681 #endif
3682 case OPC_MADD:
3684 TCGv_i64 t2 = tcg_temp_new_i64();
3685 TCGv_i64 t3 = tcg_temp_new_i64();
3687 tcg_gen_ext_tl_i64(t2, t0);
3688 tcg_gen_ext_tl_i64(t3, t1);
3689 tcg_gen_mul_i64(t2, t2, t3);
3690 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3691 tcg_gen_add_i64(t2, t2, t3);
3692 tcg_temp_free_i64(t3);
3693 gen_move_low32(cpu_LO[acc], t2);
3694 gen_move_high32(cpu_HI[acc], t2);
3695 tcg_temp_free_i64(t2);
3697 break;
3698 case OPC_MADDU:
3700 TCGv_i64 t2 = tcg_temp_new_i64();
3701 TCGv_i64 t3 = tcg_temp_new_i64();
3703 tcg_gen_ext32u_tl(t0, t0);
3704 tcg_gen_ext32u_tl(t1, t1);
3705 tcg_gen_extu_tl_i64(t2, t0);
3706 tcg_gen_extu_tl_i64(t3, t1);
3707 tcg_gen_mul_i64(t2, t2, t3);
3708 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3709 tcg_gen_add_i64(t2, t2, t3);
3710 tcg_temp_free_i64(t3);
3711 gen_move_low32(cpu_LO[acc], t2);
3712 gen_move_high32(cpu_HI[acc], t2);
3713 tcg_temp_free_i64(t2);
3715 break;
3716 case OPC_MSUB:
3718 TCGv_i64 t2 = tcg_temp_new_i64();
3719 TCGv_i64 t3 = tcg_temp_new_i64();
3721 tcg_gen_ext_tl_i64(t2, t0);
3722 tcg_gen_ext_tl_i64(t3, t1);
3723 tcg_gen_mul_i64(t2, t2, t3);
3724 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3725 tcg_gen_sub_i64(t2, t3, t2);
3726 tcg_temp_free_i64(t3);
3727 gen_move_low32(cpu_LO[acc], t2);
3728 gen_move_high32(cpu_HI[acc], t2);
3729 tcg_temp_free_i64(t2);
3731 break;
3732 case OPC_MSUBU:
3734 TCGv_i64 t2 = tcg_temp_new_i64();
3735 TCGv_i64 t3 = tcg_temp_new_i64();
3737 tcg_gen_ext32u_tl(t0, t0);
3738 tcg_gen_ext32u_tl(t1, t1);
3739 tcg_gen_extu_tl_i64(t2, t0);
3740 tcg_gen_extu_tl_i64(t3, t1);
3741 tcg_gen_mul_i64(t2, t2, t3);
3742 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3743 tcg_gen_sub_i64(t2, t3, t2);
3744 tcg_temp_free_i64(t3);
3745 gen_move_low32(cpu_LO[acc], t2);
3746 gen_move_high32(cpu_HI[acc], t2);
3747 tcg_temp_free_i64(t2);
3749 break;
3750 default:
3751 MIPS_INVAL("mul/div");
3752 generate_exception_end(ctx, EXCP_RI);
3753 goto out;
3755 out:
3756 tcg_temp_free(t0);
3757 tcg_temp_free(t1);
3760 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3761 int rd, int rs, int rt)
3763 TCGv t0 = tcg_temp_new();
3764 TCGv t1 = tcg_temp_new();
3766 gen_load_gpr(t0, rs);
3767 gen_load_gpr(t1, rt);
3769 switch (opc) {
3770 case OPC_VR54XX_MULS:
3771 gen_helper_muls(t0, cpu_env, t0, t1);
3772 break;
3773 case OPC_VR54XX_MULSU:
3774 gen_helper_mulsu(t0, cpu_env, t0, t1);
3775 break;
3776 case OPC_VR54XX_MACC:
3777 gen_helper_macc(t0, cpu_env, t0, t1);
3778 break;
3779 case OPC_VR54XX_MACCU:
3780 gen_helper_maccu(t0, cpu_env, t0, t1);
3781 break;
3782 case OPC_VR54XX_MSAC:
3783 gen_helper_msac(t0, cpu_env, t0, t1);
3784 break;
3785 case OPC_VR54XX_MSACU:
3786 gen_helper_msacu(t0, cpu_env, t0, t1);
3787 break;
3788 case OPC_VR54XX_MULHI:
3789 gen_helper_mulhi(t0, cpu_env, t0, t1);
3790 break;
3791 case OPC_VR54XX_MULHIU:
3792 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3793 break;
3794 case OPC_VR54XX_MULSHI:
3795 gen_helper_mulshi(t0, cpu_env, t0, t1);
3796 break;
3797 case OPC_VR54XX_MULSHIU:
3798 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3799 break;
3800 case OPC_VR54XX_MACCHI:
3801 gen_helper_macchi(t0, cpu_env, t0, t1);
3802 break;
3803 case OPC_VR54XX_MACCHIU:
3804 gen_helper_macchiu(t0, cpu_env, t0, t1);
3805 break;
3806 case OPC_VR54XX_MSACHI:
3807 gen_helper_msachi(t0, cpu_env, t0, t1);
3808 break;
3809 case OPC_VR54XX_MSACHIU:
3810 gen_helper_msachiu(t0, cpu_env, t0, t1);
3811 break;
3812 default:
3813 MIPS_INVAL("mul vr54xx");
3814 generate_exception_end(ctx, EXCP_RI);
3815 goto out;
3817 gen_store_gpr(t0, rd);
3819 out:
3820 tcg_temp_free(t0);
3821 tcg_temp_free(t1);
3824 static void gen_cl (DisasContext *ctx, uint32_t opc,
3825 int rd, int rs)
3827 TCGv t0;
3829 if (rd == 0) {
3830 /* Treat as NOP. */
3831 return;
3833 t0 = cpu_gpr[rd];
3834 gen_load_gpr(t0, rs);
3836 switch (opc) {
3837 case OPC_CLO:
3838 case R6_OPC_CLO:
3839 #if defined(TARGET_MIPS64)
3840 case OPC_DCLO:
3841 case R6_OPC_DCLO:
3842 #endif
3843 tcg_gen_not_tl(t0, t0);
3844 break;
3847 switch (opc) {
3848 case OPC_CLO:
3849 case R6_OPC_CLO:
3850 case OPC_CLZ:
3851 case R6_OPC_CLZ:
3852 tcg_gen_ext32u_tl(t0, t0);
3853 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3854 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3855 break;
3856 #if defined(TARGET_MIPS64)
3857 case OPC_DCLO:
3858 case R6_OPC_DCLO:
3859 case OPC_DCLZ:
3860 case R6_OPC_DCLZ:
3861 tcg_gen_clzi_i64(t0, t0, 64);
3862 break;
3863 #endif
3867 /* Godson integer instructions */
3868 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3869 int rd, int rs, int rt)
3871 TCGv t0, t1;
3873 if (rd == 0) {
3874 /* Treat as NOP. */
3875 return;
3878 switch (opc) {
3879 case OPC_MULT_G_2E:
3880 case OPC_MULT_G_2F:
3881 case OPC_MULTU_G_2E:
3882 case OPC_MULTU_G_2F:
3883 #if defined(TARGET_MIPS64)
3884 case OPC_DMULT_G_2E:
3885 case OPC_DMULT_G_2F:
3886 case OPC_DMULTU_G_2E:
3887 case OPC_DMULTU_G_2F:
3888 #endif
3889 t0 = tcg_temp_new();
3890 t1 = tcg_temp_new();
3891 break;
3892 default:
3893 t0 = tcg_temp_local_new();
3894 t1 = tcg_temp_local_new();
3895 break;
3898 gen_load_gpr(t0, rs);
3899 gen_load_gpr(t1, rt);
3901 switch (opc) {
3902 case OPC_MULT_G_2E:
3903 case OPC_MULT_G_2F:
3904 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3905 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3906 break;
3907 case OPC_MULTU_G_2E:
3908 case OPC_MULTU_G_2F:
3909 tcg_gen_ext32u_tl(t0, t0);
3910 tcg_gen_ext32u_tl(t1, t1);
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_DIV_G_2E:
3915 case OPC_DIV_G_2F:
3917 TCGLabel *l1 = gen_new_label();
3918 TCGLabel *l2 = gen_new_label();
3919 TCGLabel *l3 = gen_new_label();
3920 tcg_gen_ext32s_tl(t0, t0);
3921 tcg_gen_ext32s_tl(t1, t1);
3922 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3923 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3924 tcg_gen_br(l3);
3925 gen_set_label(l1);
3926 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3927 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3928 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3929 tcg_gen_br(l3);
3930 gen_set_label(l2);
3931 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3932 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3933 gen_set_label(l3);
3935 break;
3936 case OPC_DIVU_G_2E:
3937 case OPC_DIVU_G_2F:
3939 TCGLabel *l1 = gen_new_label();
3940 TCGLabel *l2 = gen_new_label();
3941 tcg_gen_ext32u_tl(t0, t0);
3942 tcg_gen_ext32u_tl(t1, t1);
3943 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3944 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3945 tcg_gen_br(l2);
3946 gen_set_label(l1);
3947 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3948 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3949 gen_set_label(l2);
3951 break;
3952 case OPC_MOD_G_2E:
3953 case OPC_MOD_G_2F:
3955 TCGLabel *l1 = gen_new_label();
3956 TCGLabel *l2 = gen_new_label();
3957 TCGLabel *l3 = gen_new_label();
3958 tcg_gen_ext32u_tl(t0, t0);
3959 tcg_gen_ext32u_tl(t1, t1);
3960 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3961 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3962 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3963 gen_set_label(l1);
3964 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3965 tcg_gen_br(l3);
3966 gen_set_label(l2);
3967 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3968 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3969 gen_set_label(l3);
3971 break;
3972 case OPC_MODU_G_2E:
3973 case OPC_MODU_G_2F:
3975 TCGLabel *l1 = gen_new_label();
3976 TCGLabel *l2 = gen_new_label();
3977 tcg_gen_ext32u_tl(t0, t0);
3978 tcg_gen_ext32u_tl(t1, t1);
3979 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3980 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3981 tcg_gen_br(l2);
3982 gen_set_label(l1);
3983 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3984 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3985 gen_set_label(l2);
3987 break;
3988 #if defined(TARGET_MIPS64)
3989 case OPC_DMULT_G_2E:
3990 case OPC_DMULT_G_2F:
3991 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3992 break;
3993 case OPC_DMULTU_G_2E:
3994 case OPC_DMULTU_G_2F:
3995 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3996 break;
3997 case OPC_DDIV_G_2E:
3998 case OPC_DDIV_G_2F:
4000 TCGLabel *l1 = gen_new_label();
4001 TCGLabel *l2 = gen_new_label();
4002 TCGLabel *l3 = gen_new_label();
4003 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4004 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4005 tcg_gen_br(l3);
4006 gen_set_label(l1);
4007 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4008 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4009 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4010 tcg_gen_br(l3);
4011 gen_set_label(l2);
4012 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4013 gen_set_label(l3);
4015 break;
4016 case OPC_DDIVU_G_2E:
4017 case OPC_DDIVU_G_2F:
4019 TCGLabel *l1 = gen_new_label();
4020 TCGLabel *l2 = gen_new_label();
4021 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4022 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4023 tcg_gen_br(l2);
4024 gen_set_label(l1);
4025 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4026 gen_set_label(l2);
4028 break;
4029 case OPC_DMOD_G_2E:
4030 case OPC_DMOD_G_2F:
4032 TCGLabel *l1 = gen_new_label();
4033 TCGLabel *l2 = gen_new_label();
4034 TCGLabel *l3 = gen_new_label();
4035 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4036 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4037 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4038 gen_set_label(l1);
4039 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4040 tcg_gen_br(l3);
4041 gen_set_label(l2);
4042 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4043 gen_set_label(l3);
4045 break;
4046 case OPC_DMODU_G_2E:
4047 case OPC_DMODU_G_2F:
4049 TCGLabel *l1 = gen_new_label();
4050 TCGLabel *l2 = gen_new_label();
4051 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4052 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4053 tcg_gen_br(l2);
4054 gen_set_label(l1);
4055 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4056 gen_set_label(l2);
4058 break;
4059 #endif
4062 tcg_temp_free(t0);
4063 tcg_temp_free(t1);
4066 /* Loongson multimedia instructions */
4067 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4069 uint32_t opc, shift_max;
4070 TCGv_i64 t0, t1;
4072 opc = MASK_LMI(ctx->opcode);
4073 switch (opc) {
4074 case OPC_ADD_CP2:
4075 case OPC_SUB_CP2:
4076 case OPC_DADD_CP2:
4077 case OPC_DSUB_CP2:
4078 t0 = tcg_temp_local_new_i64();
4079 t1 = tcg_temp_local_new_i64();
4080 break;
4081 default:
4082 t0 = tcg_temp_new_i64();
4083 t1 = tcg_temp_new_i64();
4084 break;
4087 check_cp1_enabled(ctx);
4088 gen_load_fpr64(ctx, t0, rs);
4089 gen_load_fpr64(ctx, t1, rt);
4091 #define LMI_HELPER(UP, LO) \
4092 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
4093 #define LMI_HELPER_1(UP, LO) \
4094 case OPC_##UP: gen_helper_##LO(t0, t0); break
4095 #define LMI_DIRECT(UP, LO, OP) \
4096 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
4098 switch (opc) {
4099 LMI_HELPER(PADDSH, paddsh);
4100 LMI_HELPER(PADDUSH, paddush);
4101 LMI_HELPER(PADDH, paddh);
4102 LMI_HELPER(PADDW, paddw);
4103 LMI_HELPER(PADDSB, paddsb);
4104 LMI_HELPER(PADDUSB, paddusb);
4105 LMI_HELPER(PADDB, paddb);
4107 LMI_HELPER(PSUBSH, psubsh);
4108 LMI_HELPER(PSUBUSH, psubush);
4109 LMI_HELPER(PSUBH, psubh);
4110 LMI_HELPER(PSUBW, psubw);
4111 LMI_HELPER(PSUBSB, psubsb);
4112 LMI_HELPER(PSUBUSB, psubusb);
4113 LMI_HELPER(PSUBB, psubb);
4115 LMI_HELPER(PSHUFH, pshufh);
4116 LMI_HELPER(PACKSSWH, packsswh);
4117 LMI_HELPER(PACKSSHB, packsshb);
4118 LMI_HELPER(PACKUSHB, packushb);
4120 LMI_HELPER(PUNPCKLHW, punpcklhw);
4121 LMI_HELPER(PUNPCKHHW, punpckhhw);
4122 LMI_HELPER(PUNPCKLBH, punpcklbh);
4123 LMI_HELPER(PUNPCKHBH, punpckhbh);
4124 LMI_HELPER(PUNPCKLWD, punpcklwd);
4125 LMI_HELPER(PUNPCKHWD, punpckhwd);
4127 LMI_HELPER(PAVGH, pavgh);
4128 LMI_HELPER(PAVGB, pavgb);
4129 LMI_HELPER(PMAXSH, pmaxsh);
4130 LMI_HELPER(PMINSH, pminsh);
4131 LMI_HELPER(PMAXUB, pmaxub);
4132 LMI_HELPER(PMINUB, pminub);
4134 LMI_HELPER(PCMPEQW, pcmpeqw);
4135 LMI_HELPER(PCMPGTW, pcmpgtw);
4136 LMI_HELPER(PCMPEQH, pcmpeqh);
4137 LMI_HELPER(PCMPGTH, pcmpgth);
4138 LMI_HELPER(PCMPEQB, pcmpeqb);
4139 LMI_HELPER(PCMPGTB, pcmpgtb);
4141 LMI_HELPER(PSLLW, psllw);
4142 LMI_HELPER(PSLLH, psllh);
4143 LMI_HELPER(PSRLW, psrlw);
4144 LMI_HELPER(PSRLH, psrlh);
4145 LMI_HELPER(PSRAW, psraw);
4146 LMI_HELPER(PSRAH, psrah);
4148 LMI_HELPER(PMULLH, pmullh);
4149 LMI_HELPER(PMULHH, pmulhh);
4150 LMI_HELPER(PMULHUH, pmulhuh);
4151 LMI_HELPER(PMADDHW, pmaddhw);
4153 LMI_HELPER(PASUBUB, pasubub);
4154 LMI_HELPER_1(BIADD, biadd);
4155 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4157 LMI_DIRECT(PADDD, paddd, add);
4158 LMI_DIRECT(PSUBD, psubd, sub);
4159 LMI_DIRECT(XOR_CP2, xor, xor);
4160 LMI_DIRECT(NOR_CP2, nor, nor);
4161 LMI_DIRECT(AND_CP2, and, and);
4162 LMI_DIRECT(OR_CP2, or, or);
4164 case OPC_PANDN:
4165 tcg_gen_andc_i64(t0, t1, t0);
4166 break;
4168 case OPC_PINSRH_0:
4169 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4170 break;
4171 case OPC_PINSRH_1:
4172 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4173 break;
4174 case OPC_PINSRH_2:
4175 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4176 break;
4177 case OPC_PINSRH_3:
4178 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4179 break;
4181 case OPC_PEXTRH:
4182 tcg_gen_andi_i64(t1, t1, 3);
4183 tcg_gen_shli_i64(t1, t1, 4);
4184 tcg_gen_shr_i64(t0, t0, t1);
4185 tcg_gen_ext16u_i64(t0, t0);
4186 break;
4188 case OPC_ADDU_CP2:
4189 tcg_gen_add_i64(t0, t0, t1);
4190 tcg_gen_ext32s_i64(t0, t0);
4191 break;
4192 case OPC_SUBU_CP2:
4193 tcg_gen_sub_i64(t0, t0, t1);
4194 tcg_gen_ext32s_i64(t0, t0);
4195 break;
4197 case OPC_SLL_CP2:
4198 shift_max = 32;
4199 goto do_shift;
4200 case OPC_SRL_CP2:
4201 shift_max = 32;
4202 goto do_shift;
4203 case OPC_SRA_CP2:
4204 shift_max = 32;
4205 goto do_shift;
4206 case OPC_DSLL_CP2:
4207 shift_max = 64;
4208 goto do_shift;
4209 case OPC_DSRL_CP2:
4210 shift_max = 64;
4211 goto do_shift;
4212 case OPC_DSRA_CP2:
4213 shift_max = 64;
4214 goto do_shift;
4215 do_shift:
4216 /* Make sure shift count isn't TCG undefined behaviour. */
4217 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4219 switch (opc) {
4220 case OPC_SLL_CP2:
4221 case OPC_DSLL_CP2:
4222 tcg_gen_shl_i64(t0, t0, t1);
4223 break;
4224 case OPC_SRA_CP2:
4225 case OPC_DSRA_CP2:
4226 /* Since SRA is UndefinedResult without sign-extended inputs,
4227 we can treat SRA and DSRA the same. */
4228 tcg_gen_sar_i64(t0, t0, t1);
4229 break;
4230 case OPC_SRL_CP2:
4231 /* We want to shift in zeros for SRL; zero-extend first. */
4232 tcg_gen_ext32u_i64(t0, t0);
4233 /* FALLTHRU */
4234 case OPC_DSRL_CP2:
4235 tcg_gen_shr_i64(t0, t0, t1);
4236 break;
4239 if (shift_max == 32) {
4240 tcg_gen_ext32s_i64(t0, t0);
4243 /* Shifts larger than MAX produce zero. */
4244 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4245 tcg_gen_neg_i64(t1, t1);
4246 tcg_gen_and_i64(t0, t0, t1);
4247 break;
4249 case OPC_ADD_CP2:
4250 case OPC_DADD_CP2:
4252 TCGv_i64 t2 = tcg_temp_new_i64();
4253 TCGLabel *lab = gen_new_label();
4255 tcg_gen_mov_i64(t2, t0);
4256 tcg_gen_add_i64(t0, t1, t2);
4257 if (opc == OPC_ADD_CP2) {
4258 tcg_gen_ext32s_i64(t0, t0);
4260 tcg_gen_xor_i64(t1, t1, t2);
4261 tcg_gen_xor_i64(t2, t2, t0);
4262 tcg_gen_andc_i64(t1, t2, t1);
4263 tcg_temp_free_i64(t2);
4264 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4265 generate_exception(ctx, EXCP_OVERFLOW);
4266 gen_set_label(lab);
4267 break;
4270 case OPC_SUB_CP2:
4271 case OPC_DSUB_CP2:
4273 TCGv_i64 t2 = tcg_temp_new_i64();
4274 TCGLabel *lab = gen_new_label();
4276 tcg_gen_mov_i64(t2, t0);
4277 tcg_gen_sub_i64(t0, t1, t2);
4278 if (opc == OPC_SUB_CP2) {
4279 tcg_gen_ext32s_i64(t0, t0);
4281 tcg_gen_xor_i64(t1, t1, t2);
4282 tcg_gen_xor_i64(t2, t2, t0);
4283 tcg_gen_and_i64(t1, t1, t2);
4284 tcg_temp_free_i64(t2);
4285 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4286 generate_exception(ctx, EXCP_OVERFLOW);
4287 gen_set_label(lab);
4288 break;
4291 case OPC_PMULUW:
4292 tcg_gen_ext32u_i64(t0, t0);
4293 tcg_gen_ext32u_i64(t1, t1);
4294 tcg_gen_mul_i64(t0, t0, t1);
4295 break;
4297 case OPC_SEQU_CP2:
4298 case OPC_SEQ_CP2:
4299 case OPC_SLTU_CP2:
4300 case OPC_SLT_CP2:
4301 case OPC_SLEU_CP2:
4302 case OPC_SLE_CP2:
4303 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4304 FD field is the CC field? */
4305 default:
4306 MIPS_INVAL("loongson_cp2");
4307 generate_exception_end(ctx, EXCP_RI);
4308 return;
4311 #undef LMI_HELPER
4312 #undef LMI_DIRECT
4314 gen_store_fpr64(ctx, t0, rd);
4316 tcg_temp_free_i64(t0);
4317 tcg_temp_free_i64(t1);
4320 /* Traps */
4321 static void gen_trap (DisasContext *ctx, uint32_t opc,
4322 int rs, int rt, int16_t imm)
4324 int cond;
4325 TCGv t0 = tcg_temp_new();
4326 TCGv t1 = tcg_temp_new();
4328 cond = 0;
4329 /* Load needed operands */
4330 switch (opc) {
4331 case OPC_TEQ:
4332 case OPC_TGE:
4333 case OPC_TGEU:
4334 case OPC_TLT:
4335 case OPC_TLTU:
4336 case OPC_TNE:
4337 /* Compare two registers */
4338 if (rs != rt) {
4339 gen_load_gpr(t0, rs);
4340 gen_load_gpr(t1, rt);
4341 cond = 1;
4343 break;
4344 case OPC_TEQI:
4345 case OPC_TGEI:
4346 case OPC_TGEIU:
4347 case OPC_TLTI:
4348 case OPC_TLTIU:
4349 case OPC_TNEI:
4350 /* Compare register to immediate */
4351 if (rs != 0 || imm != 0) {
4352 gen_load_gpr(t0, rs);
4353 tcg_gen_movi_tl(t1, (int32_t)imm);
4354 cond = 1;
4356 break;
4358 if (cond == 0) {
4359 switch (opc) {
4360 case OPC_TEQ: /* rs == rs */
4361 case OPC_TEQI: /* r0 == 0 */
4362 case OPC_TGE: /* rs >= rs */
4363 case OPC_TGEI: /* r0 >= 0 */
4364 case OPC_TGEU: /* rs >= rs unsigned */
4365 case OPC_TGEIU: /* r0 >= 0 unsigned */
4366 /* Always trap */
4367 generate_exception_end(ctx, EXCP_TRAP);
4368 break;
4369 case OPC_TLT: /* rs < rs */
4370 case OPC_TLTI: /* r0 < 0 */
4371 case OPC_TLTU: /* rs < rs unsigned */
4372 case OPC_TLTIU: /* r0 < 0 unsigned */
4373 case OPC_TNE: /* rs != rs */
4374 case OPC_TNEI: /* r0 != 0 */
4375 /* Never trap: treat as NOP. */
4376 break;
4378 } else {
4379 TCGLabel *l1 = gen_new_label();
4381 switch (opc) {
4382 case OPC_TEQ:
4383 case OPC_TEQI:
4384 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4385 break;
4386 case OPC_TGE:
4387 case OPC_TGEI:
4388 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4389 break;
4390 case OPC_TGEU:
4391 case OPC_TGEIU:
4392 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4393 break;
4394 case OPC_TLT:
4395 case OPC_TLTI:
4396 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4397 break;
4398 case OPC_TLTU:
4399 case OPC_TLTIU:
4400 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4401 break;
4402 case OPC_TNE:
4403 case OPC_TNEI:
4404 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4405 break;
4407 generate_exception(ctx, EXCP_TRAP);
4408 gen_set_label(l1);
4410 tcg_temp_free(t0);
4411 tcg_temp_free(t1);
4414 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4416 if (unlikely(ctx->base.singlestep_enabled)) {
4417 return false;
4420 #ifndef CONFIG_USER_ONLY
4421 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4422 #else
4423 return true;
4424 #endif
4427 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4429 if (use_goto_tb(ctx, dest)) {
4430 tcg_gen_goto_tb(n);
4431 gen_save_pc(dest);
4432 tcg_gen_exit_tb(ctx->base.tb, n);
4433 } else {
4434 gen_save_pc(dest);
4435 if (ctx->base.singlestep_enabled) {
4436 save_cpu_state(ctx, 0);
4437 gen_helper_raise_exception_debug(cpu_env);
4439 tcg_gen_lookup_and_goto_ptr();
4443 /* Branches (before delay slot) */
4444 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4445 int insn_bytes,
4446 int rs, int rt, int32_t offset,
4447 int delayslot_size)
4449 target_ulong btgt = -1;
4450 int blink = 0;
4451 int bcond_compute = 0;
4452 TCGv t0 = tcg_temp_new();
4453 TCGv t1 = tcg_temp_new();
4455 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4456 #ifdef MIPS_DEBUG_DISAS
4457 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4458 TARGET_FMT_lx "\n", ctx->base.pc_next);
4459 #endif
4460 generate_exception_end(ctx, EXCP_RI);
4461 goto out;
4464 /* Load needed operands */
4465 switch (opc) {
4466 case OPC_BEQ:
4467 case OPC_BEQL:
4468 case OPC_BNE:
4469 case OPC_BNEL:
4470 /* Compare two registers */
4471 if (rs != rt) {
4472 gen_load_gpr(t0, rs);
4473 gen_load_gpr(t1, rt);
4474 bcond_compute = 1;
4476 btgt = ctx->base.pc_next + insn_bytes + offset;
4477 break;
4478 case OPC_BGEZ:
4479 case OPC_BGEZAL:
4480 case OPC_BGEZALL:
4481 case OPC_BGEZL:
4482 case OPC_BGTZ:
4483 case OPC_BGTZL:
4484 case OPC_BLEZ:
4485 case OPC_BLEZL:
4486 case OPC_BLTZ:
4487 case OPC_BLTZAL:
4488 case OPC_BLTZALL:
4489 case OPC_BLTZL:
4490 /* Compare to zero */
4491 if (rs != 0) {
4492 gen_load_gpr(t0, rs);
4493 bcond_compute = 1;
4495 btgt = ctx->base.pc_next + insn_bytes + offset;
4496 break;
4497 case OPC_BPOSGE32:
4498 #if defined(TARGET_MIPS64)
4499 case OPC_BPOSGE64:
4500 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4501 #else
4502 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4503 #endif
4504 bcond_compute = 1;
4505 btgt = ctx->base.pc_next + insn_bytes + offset;
4506 break;
4507 case OPC_J:
4508 case OPC_JAL:
4509 case OPC_JALX:
4510 /* Jump to immediate */
4511 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
4512 (uint32_t)offset;
4513 break;
4514 case OPC_JR:
4515 case OPC_JALR:
4516 /* Jump to register */
4517 if (offset != 0 && offset != 16) {
4518 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4519 others are reserved. */
4520 MIPS_INVAL("jump hint");
4521 generate_exception_end(ctx, EXCP_RI);
4522 goto out;
4524 gen_load_gpr(btarget, rs);
4525 break;
4526 default:
4527 MIPS_INVAL("branch/jump");
4528 generate_exception_end(ctx, EXCP_RI);
4529 goto out;
4531 if (bcond_compute == 0) {
4532 /* No condition to be computed */
4533 switch (opc) {
4534 case OPC_BEQ: /* rx == rx */
4535 case OPC_BEQL: /* rx == rx likely */
4536 case OPC_BGEZ: /* 0 >= 0 */
4537 case OPC_BGEZL: /* 0 >= 0 likely */
4538 case OPC_BLEZ: /* 0 <= 0 */
4539 case OPC_BLEZL: /* 0 <= 0 likely */
4540 /* Always take */
4541 ctx->hflags |= MIPS_HFLAG_B;
4542 break;
4543 case OPC_BGEZAL: /* 0 >= 0 */
4544 case OPC_BGEZALL: /* 0 >= 0 likely */
4545 /* Always take and link */
4546 blink = 31;
4547 ctx->hflags |= MIPS_HFLAG_B;
4548 break;
4549 case OPC_BNE: /* rx != rx */
4550 case OPC_BGTZ: /* 0 > 0 */
4551 case OPC_BLTZ: /* 0 < 0 */
4552 /* Treat as NOP. */
4553 goto out;
4554 case OPC_BLTZAL: /* 0 < 0 */
4555 /* Handle as an unconditional branch to get correct delay
4556 slot checking. */
4557 blink = 31;
4558 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
4559 ctx->hflags |= MIPS_HFLAG_B;
4560 break;
4561 case OPC_BLTZALL: /* 0 < 0 likely */
4562 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
4563 /* Skip the instruction in the delay slot */
4564 ctx->base.pc_next += 4;
4565 goto out;
4566 case OPC_BNEL: /* rx != rx likely */
4567 case OPC_BGTZL: /* 0 > 0 likely */
4568 case OPC_BLTZL: /* 0 < 0 likely */
4569 /* Skip the instruction in the delay slot */
4570 ctx->base.pc_next += 4;
4571 goto out;
4572 case OPC_J:
4573 ctx->hflags |= MIPS_HFLAG_B;
4574 break;
4575 case OPC_JALX:
4576 ctx->hflags |= MIPS_HFLAG_BX;
4577 /* Fallthrough */
4578 case OPC_JAL:
4579 blink = 31;
4580 ctx->hflags |= MIPS_HFLAG_B;
4581 break;
4582 case OPC_JR:
4583 ctx->hflags |= MIPS_HFLAG_BR;
4584 break;
4585 case OPC_JALR:
4586 blink = rt;
4587 ctx->hflags |= MIPS_HFLAG_BR;
4588 break;
4589 default:
4590 MIPS_INVAL("branch/jump");
4591 generate_exception_end(ctx, EXCP_RI);
4592 goto out;
4594 } else {
4595 switch (opc) {
4596 case OPC_BEQ:
4597 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4598 goto not_likely;
4599 case OPC_BEQL:
4600 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4601 goto likely;
4602 case OPC_BNE:
4603 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4604 goto not_likely;
4605 case OPC_BNEL:
4606 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4607 goto likely;
4608 case OPC_BGEZ:
4609 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4610 goto not_likely;
4611 case OPC_BGEZL:
4612 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4613 goto likely;
4614 case OPC_BGEZAL:
4615 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4616 blink = 31;
4617 goto not_likely;
4618 case OPC_BGEZALL:
4619 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4620 blink = 31;
4621 goto likely;
4622 case OPC_BGTZ:
4623 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4624 goto not_likely;
4625 case OPC_BGTZL:
4626 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4627 goto likely;
4628 case OPC_BLEZ:
4629 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4630 goto not_likely;
4631 case OPC_BLEZL:
4632 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4633 goto likely;
4634 case OPC_BLTZ:
4635 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4636 goto not_likely;
4637 case OPC_BLTZL:
4638 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4639 goto likely;
4640 case OPC_BPOSGE32:
4641 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4642 goto not_likely;
4643 #if defined(TARGET_MIPS64)
4644 case OPC_BPOSGE64:
4645 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4646 goto not_likely;
4647 #endif
4648 case OPC_BLTZAL:
4649 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4650 blink = 31;
4651 not_likely:
4652 ctx->hflags |= MIPS_HFLAG_BC;
4653 break;
4654 case OPC_BLTZALL:
4655 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4656 blink = 31;
4657 likely:
4658 ctx->hflags |= MIPS_HFLAG_BL;
4659 break;
4660 default:
4661 MIPS_INVAL("conditional branch/jump");
4662 generate_exception_end(ctx, EXCP_RI);
4663 goto out;
4667 ctx->btarget = btgt;
4669 switch (delayslot_size) {
4670 case 2:
4671 ctx->hflags |= MIPS_HFLAG_BDS16;
4672 break;
4673 case 4:
4674 ctx->hflags |= MIPS_HFLAG_BDS32;
4675 break;
4678 if (blink > 0) {
4679 int post_delay = insn_bytes + delayslot_size;
4680 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4682 tcg_gen_movi_tl(cpu_gpr[blink],
4683 ctx->base.pc_next + post_delay + lowbit);
4686 out:
4687 if (insn_bytes == 2)
4688 ctx->hflags |= MIPS_HFLAG_B16;
4689 tcg_temp_free(t0);
4690 tcg_temp_free(t1);
4694 /* nanoMIPS Branches */
4695 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
4696 int insn_bytes,
4697 int rs, int rt, int32_t offset)
4699 target_ulong btgt = -1;
4700 int bcond_compute = 0;
4701 TCGv t0 = tcg_temp_new();
4702 TCGv t1 = tcg_temp_new();
4704 /* Load needed operands */
4705 switch (opc) {
4706 case OPC_BEQ:
4707 case OPC_BNE:
4708 /* Compare two registers */
4709 if (rs != rt) {
4710 gen_load_gpr(t0, rs);
4711 gen_load_gpr(t1, rt);
4712 bcond_compute = 1;
4714 btgt = ctx->base.pc_next + insn_bytes + offset;
4715 break;
4716 case OPC_BGEZAL:
4717 /* Compare to zero */
4718 if (rs != 0) {
4719 gen_load_gpr(t0, rs);
4720 bcond_compute = 1;
4722 btgt = ctx->base.pc_next + insn_bytes + offset;
4723 break;
4724 case OPC_BPOSGE32:
4725 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4726 bcond_compute = 1;
4727 btgt = ctx->base.pc_next + insn_bytes + offset;
4728 break;
4729 case OPC_JR:
4730 case OPC_JALR:
4731 /* Jump to register */
4732 if (offset != 0 && offset != 16) {
4733 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4734 others are reserved. */
4735 MIPS_INVAL("jump hint");
4736 generate_exception_end(ctx, EXCP_RI);
4737 goto out;
4739 gen_load_gpr(btarget, rs);
4740 break;
4741 default:
4742 MIPS_INVAL("branch/jump");
4743 generate_exception_end(ctx, EXCP_RI);
4744 goto out;
4746 if (bcond_compute == 0) {
4747 /* No condition to be computed */
4748 switch (opc) {
4749 case OPC_BEQ: /* rx == rx */
4750 /* Always take */
4751 ctx->hflags |= MIPS_HFLAG_B;
4752 break;
4753 case OPC_BGEZAL: /* 0 >= 0 */
4754 /* Always take and link */
4755 tcg_gen_movi_tl(cpu_gpr[31],
4756 ctx->base.pc_next + insn_bytes);
4757 ctx->hflags |= MIPS_HFLAG_B;
4758 break;
4759 case OPC_BNE: /* rx != rx */
4760 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
4761 /* Skip the instruction in the delay slot */
4762 ctx->base.pc_next += 4;
4763 goto out;
4764 case OPC_JR:
4765 ctx->hflags |= MIPS_HFLAG_BR;
4766 break;
4767 case OPC_JALR:
4768 if (rt > 0) {
4769 tcg_gen_movi_tl(cpu_gpr[rt],
4770 ctx->base.pc_next + insn_bytes);
4772 ctx->hflags |= MIPS_HFLAG_BR;
4773 break;
4774 default:
4775 MIPS_INVAL("branch/jump");
4776 generate_exception_end(ctx, EXCP_RI);
4777 goto out;
4779 } else {
4780 switch (opc) {
4781 case OPC_BEQ:
4782 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4783 goto not_likely;
4784 case OPC_BNE:
4785 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4786 goto not_likely;
4787 case OPC_BGEZAL:
4788 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4789 tcg_gen_movi_tl(cpu_gpr[31],
4790 ctx->base.pc_next + insn_bytes);
4791 goto not_likely;
4792 case OPC_BPOSGE32:
4793 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4794 not_likely:
4795 ctx->hflags |= MIPS_HFLAG_BC;
4796 break;
4797 default:
4798 MIPS_INVAL("conditional branch/jump");
4799 generate_exception_end(ctx, EXCP_RI);
4800 goto out;
4804 ctx->btarget = btgt;
4806 out:
4807 if (insn_bytes == 2) {
4808 ctx->hflags |= MIPS_HFLAG_B16;
4810 tcg_temp_free(t0);
4811 tcg_temp_free(t1);
4815 /* special3 bitfield operations */
4816 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4817 int rs, int lsb, int msb)
4819 TCGv t0 = tcg_temp_new();
4820 TCGv t1 = tcg_temp_new();
4822 gen_load_gpr(t1, rs);
4823 switch (opc) {
4824 case OPC_EXT:
4825 if (lsb + msb > 31) {
4826 goto fail;
4828 if (msb != 31) {
4829 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4830 } else {
4831 /* The two checks together imply that lsb == 0,
4832 so this is a simple sign-extension. */
4833 tcg_gen_ext32s_tl(t0, t1);
4835 break;
4836 #if defined(TARGET_MIPS64)
4837 case OPC_DEXTU:
4838 lsb += 32;
4839 goto do_dext;
4840 case OPC_DEXTM:
4841 msb += 32;
4842 goto do_dext;
4843 case OPC_DEXT:
4844 do_dext:
4845 if (lsb + msb > 63) {
4846 goto fail;
4848 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4849 break;
4850 #endif
4851 case OPC_INS:
4852 if (lsb > msb) {
4853 goto fail;
4855 gen_load_gpr(t0, rt);
4856 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4857 tcg_gen_ext32s_tl(t0, t0);
4858 break;
4859 #if defined(TARGET_MIPS64)
4860 case OPC_DINSU:
4861 lsb += 32;
4862 /* FALLTHRU */
4863 case OPC_DINSM:
4864 msb += 32;
4865 /* FALLTHRU */
4866 case OPC_DINS:
4867 if (lsb > msb) {
4868 goto fail;
4870 gen_load_gpr(t0, rt);
4871 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4872 break;
4873 #endif
4874 default:
4875 fail:
4876 MIPS_INVAL("bitops");
4877 generate_exception_end(ctx, EXCP_RI);
4878 tcg_temp_free(t0);
4879 tcg_temp_free(t1);
4880 return;
4882 gen_store_gpr(t0, rt);
4883 tcg_temp_free(t0);
4884 tcg_temp_free(t1);
4887 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4889 TCGv t0;
4891 if (rd == 0) {
4892 /* If no destination, treat it as a NOP. */
4893 return;
4896 t0 = tcg_temp_new();
4897 gen_load_gpr(t0, rt);
4898 switch (op2) {
4899 case OPC_WSBH:
4901 TCGv t1 = tcg_temp_new();
4902 TCGv t2 = tcg_const_tl(0x00FF00FF);
4904 tcg_gen_shri_tl(t1, t0, 8);
4905 tcg_gen_and_tl(t1, t1, t2);
4906 tcg_gen_and_tl(t0, t0, t2);
4907 tcg_gen_shli_tl(t0, t0, 8);
4908 tcg_gen_or_tl(t0, t0, t1);
4909 tcg_temp_free(t2);
4910 tcg_temp_free(t1);
4911 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4913 break;
4914 case OPC_SEB:
4915 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4916 break;
4917 case OPC_SEH:
4918 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4919 break;
4920 #if defined(TARGET_MIPS64)
4921 case OPC_DSBH:
4923 TCGv t1 = tcg_temp_new();
4924 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
4926 tcg_gen_shri_tl(t1, t0, 8);
4927 tcg_gen_and_tl(t1, t1, t2);
4928 tcg_gen_and_tl(t0, t0, t2);
4929 tcg_gen_shli_tl(t0, t0, 8);
4930 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4931 tcg_temp_free(t2);
4932 tcg_temp_free(t1);
4934 break;
4935 case OPC_DSHD:
4937 TCGv t1 = tcg_temp_new();
4938 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
4940 tcg_gen_shri_tl(t1, t0, 16);
4941 tcg_gen_and_tl(t1, t1, t2);
4942 tcg_gen_and_tl(t0, t0, t2);
4943 tcg_gen_shli_tl(t0, t0, 16);
4944 tcg_gen_or_tl(t0, t0, t1);
4945 tcg_gen_shri_tl(t1, t0, 32);
4946 tcg_gen_shli_tl(t0, t0, 32);
4947 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4948 tcg_temp_free(t2);
4949 tcg_temp_free(t1);
4951 break;
4952 #endif
4953 default:
4954 MIPS_INVAL("bsfhl");
4955 generate_exception_end(ctx, EXCP_RI);
4956 tcg_temp_free(t0);
4957 return;
4959 tcg_temp_free(t0);
4962 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4963 int imm2)
4965 TCGv t0;
4966 TCGv t1;
4967 if (rd == 0) {
4968 /* Treat as NOP. */
4969 return;
4971 t0 = tcg_temp_new();
4972 t1 = tcg_temp_new();
4973 gen_load_gpr(t0, rs);
4974 gen_load_gpr(t1, rt);
4975 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4976 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4977 if (opc == OPC_LSA) {
4978 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4981 tcg_temp_free(t1);
4982 tcg_temp_free(t0);
4984 return;
4987 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
4988 int rt, int bits)
4990 TCGv t0;
4991 if (rd == 0) {
4992 /* Treat as NOP. */
4993 return;
4995 t0 = tcg_temp_new();
4996 if (bits == 0 || bits == wordsz) {
4997 if (bits == 0) {
4998 gen_load_gpr(t0, rt);
4999 } else {
5000 gen_load_gpr(t0, rs);
5002 switch (wordsz) {
5003 case 32:
5004 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5005 break;
5006 #if defined(TARGET_MIPS64)
5007 case 64:
5008 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5009 break;
5010 #endif
5012 } else {
5013 TCGv t1 = tcg_temp_new();
5014 gen_load_gpr(t0, rt);
5015 gen_load_gpr(t1, rs);
5016 switch (wordsz) {
5017 case 32:
5019 TCGv_i64 t2 = tcg_temp_new_i64();
5020 tcg_gen_concat_tl_i64(t2, t1, t0);
5021 tcg_gen_shri_i64(t2, t2, 32 - bits);
5022 gen_move_low32(cpu_gpr[rd], t2);
5023 tcg_temp_free_i64(t2);
5025 break;
5026 #if defined(TARGET_MIPS64)
5027 case 64:
5028 tcg_gen_shli_tl(t0, t0, bits);
5029 tcg_gen_shri_tl(t1, t1, 64 - bits);
5030 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5031 break;
5032 #endif
5034 tcg_temp_free(t1);
5037 tcg_temp_free(t0);
5040 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5041 int bp)
5043 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5046 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5047 int shift)
5049 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5052 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5054 TCGv t0;
5055 if (rd == 0) {
5056 /* Treat as NOP. */
5057 return;
5059 t0 = tcg_temp_new();
5060 gen_load_gpr(t0, rt);
5061 switch (opc) {
5062 case OPC_BITSWAP:
5063 gen_helper_bitswap(cpu_gpr[rd], t0);
5064 break;
5065 #if defined(TARGET_MIPS64)
5066 case OPC_DBITSWAP:
5067 gen_helper_dbitswap(cpu_gpr[rd], t0);
5068 break;
5069 #endif
5071 tcg_temp_free(t0);
5074 #ifndef CONFIG_USER_ONLY
5075 /* CP0 (MMU and control) */
5076 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5078 TCGv_i64 t0 = tcg_temp_new_i64();
5079 TCGv_i64 t1 = tcg_temp_new_i64();
5081 tcg_gen_ext_tl_i64(t0, arg);
5082 tcg_gen_ld_i64(t1, cpu_env, off);
5083 #if defined(TARGET_MIPS64)
5084 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5085 #else
5086 tcg_gen_concat32_i64(t1, t1, t0);
5087 #endif
5088 tcg_gen_st_i64(t1, cpu_env, off);
5089 tcg_temp_free_i64(t1);
5090 tcg_temp_free_i64(t0);
5093 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5095 TCGv_i64 t0 = tcg_temp_new_i64();
5096 TCGv_i64 t1 = tcg_temp_new_i64();
5098 tcg_gen_ext_tl_i64(t0, arg);
5099 tcg_gen_ld_i64(t1, cpu_env, off);
5100 tcg_gen_concat32_i64(t1, t1, t0);
5101 tcg_gen_st_i64(t1, cpu_env, off);
5102 tcg_temp_free_i64(t1);
5103 tcg_temp_free_i64(t0);
5106 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5108 TCGv_i64 t0 = tcg_temp_new_i64();
5110 tcg_gen_ld_i64(t0, cpu_env, off);
5111 #if defined(TARGET_MIPS64)
5112 tcg_gen_shri_i64(t0, t0, 30);
5113 #else
5114 tcg_gen_shri_i64(t0, t0, 32);
5115 #endif
5116 gen_move_low32(arg, t0);
5117 tcg_temp_free_i64(t0);
5120 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5122 TCGv_i64 t0 = tcg_temp_new_i64();
5124 tcg_gen_ld_i64(t0, cpu_env, off);
5125 tcg_gen_shri_i64(t0, t0, 32 + shift);
5126 gen_move_low32(arg, t0);
5127 tcg_temp_free_i64(t0);
5130 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5132 TCGv_i32 t0 = tcg_temp_new_i32();
5134 tcg_gen_ld_i32(t0, cpu_env, off);
5135 tcg_gen_ext_i32_tl(arg, t0);
5136 tcg_temp_free_i32(t0);
5139 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5141 tcg_gen_ld_tl(arg, cpu_env, off);
5142 tcg_gen_ext32s_tl(arg, arg);
5145 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5147 TCGv_i32 t0 = tcg_temp_new_i32();
5149 tcg_gen_trunc_tl_i32(t0, arg);
5150 tcg_gen_st_i32(t0, cpu_env, off);
5151 tcg_temp_free_i32(t0);
5154 #define CP0_CHECK(c) \
5155 do { \
5156 if (!(c)) { \
5157 goto cp0_unimplemented; \
5159 } while (0)
5161 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5163 const char *rn = "invalid";
5165 switch (reg) {
5166 case 2:
5167 switch (sel) {
5168 case 0:
5169 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5170 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5171 rn = "EntryLo0";
5172 break;
5173 default:
5174 goto cp0_unimplemented;
5176 break;
5177 case 3:
5178 switch (sel) {
5179 case 0:
5180 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5181 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5182 rn = "EntryLo1";
5183 break;
5184 default:
5185 goto cp0_unimplemented;
5187 break;
5188 case 17:
5189 switch (sel) {
5190 case 0:
5191 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5192 ctx->CP0_LLAddr_shift);
5193 rn = "LLAddr";
5194 break;
5195 case 1:
5196 CP0_CHECK(ctx->mrp);
5197 gen_helper_mfhc0_maar(arg, cpu_env);
5198 rn = "MAAR";
5199 break;
5200 default:
5201 goto cp0_unimplemented;
5203 break;
5204 case 28:
5205 switch (sel) {
5206 case 0:
5207 case 2:
5208 case 4:
5209 case 6:
5210 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5211 rn = "TagLo";
5212 break;
5213 default:
5214 goto cp0_unimplemented;
5216 break;
5217 default:
5218 goto cp0_unimplemented;
5220 trace_mips_translate_c0("mfhc0", rn, reg, sel);
5221 return;
5223 cp0_unimplemented:
5224 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5225 tcg_gen_movi_tl(arg, 0);
5228 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5230 const char *rn = "invalid";
5231 uint64_t mask = ctx->PAMask >> 36;
5233 switch (reg) {
5234 case 2:
5235 switch (sel) {
5236 case 0:
5237 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5238 tcg_gen_andi_tl(arg, arg, mask);
5239 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5240 rn = "EntryLo0";
5241 break;
5242 default:
5243 goto cp0_unimplemented;
5245 break;
5246 case 3:
5247 switch (sel) {
5248 case 0:
5249 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5250 tcg_gen_andi_tl(arg, arg, mask);
5251 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5252 rn = "EntryLo1";
5253 break;
5254 default:
5255 goto cp0_unimplemented;
5257 break;
5258 case 17:
5259 switch (sel) {
5260 case 0:
5261 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5262 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5263 relevant for modern MIPS cores supporting MTHC0, therefore
5264 treating MTHC0 to LLAddr as NOP. */
5265 rn = "LLAddr";
5266 break;
5267 case 1:
5268 CP0_CHECK(ctx->mrp);
5269 gen_helper_mthc0_maar(cpu_env, arg);
5270 rn = "MAAR";
5271 break;
5272 default:
5273 goto cp0_unimplemented;
5275 break;
5276 case 28:
5277 switch (sel) {
5278 case 0:
5279 case 2:
5280 case 4:
5281 case 6:
5282 tcg_gen_andi_tl(arg, arg, mask);
5283 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5284 rn = "TagLo";
5285 break;
5286 default:
5287 goto cp0_unimplemented;
5289 break;
5290 default:
5291 goto cp0_unimplemented;
5293 trace_mips_translate_c0("mthc0", rn, reg, sel);
5295 cp0_unimplemented:
5296 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5299 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5301 if (ctx->insn_flags & ISA_MIPS32R6) {
5302 tcg_gen_movi_tl(arg, 0);
5303 } else {
5304 tcg_gen_movi_tl(arg, ~0);
5308 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5310 const char *rn = "invalid";
5312 if (sel != 0)
5313 check_insn(ctx, ISA_MIPS32);
5315 switch (reg) {
5316 case 0:
5317 switch (sel) {
5318 case 0:
5319 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5320 rn = "Index";
5321 break;
5322 case 1:
5323 CP0_CHECK(ctx->insn_flags & ASE_MT);
5324 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5325 rn = "MVPControl";
5326 break;
5327 case 2:
5328 CP0_CHECK(ctx->insn_flags & ASE_MT);
5329 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5330 rn = "MVPConf0";
5331 break;
5332 case 3:
5333 CP0_CHECK(ctx->insn_flags & ASE_MT);
5334 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5335 rn = "MVPConf1";
5336 break;
5337 case 4:
5338 CP0_CHECK(ctx->vp);
5339 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5340 rn = "VPControl";
5341 break;
5342 default:
5343 goto cp0_unimplemented;
5345 break;
5346 case 1:
5347 switch (sel) {
5348 case 0:
5349 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5350 gen_helper_mfc0_random(arg, cpu_env);
5351 rn = "Random";
5352 break;
5353 case 1:
5354 CP0_CHECK(ctx->insn_flags & ASE_MT);
5355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5356 rn = "VPEControl";
5357 break;
5358 case 2:
5359 CP0_CHECK(ctx->insn_flags & ASE_MT);
5360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5361 rn = "VPEConf0";
5362 break;
5363 case 3:
5364 CP0_CHECK(ctx->insn_flags & ASE_MT);
5365 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5366 rn = "VPEConf1";
5367 break;
5368 case 4:
5369 CP0_CHECK(ctx->insn_flags & ASE_MT);
5370 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5371 rn = "YQMask";
5372 break;
5373 case 5:
5374 CP0_CHECK(ctx->insn_flags & ASE_MT);
5375 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5376 rn = "VPESchedule";
5377 break;
5378 case 6:
5379 CP0_CHECK(ctx->insn_flags & ASE_MT);
5380 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5381 rn = "VPEScheFBack";
5382 break;
5383 case 7:
5384 CP0_CHECK(ctx->insn_flags & ASE_MT);
5385 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5386 rn = "VPEOpt";
5387 break;
5388 default:
5389 goto cp0_unimplemented;
5391 break;
5392 case 2:
5393 switch (sel) {
5394 case 0:
5396 TCGv_i64 tmp = tcg_temp_new_i64();
5397 tcg_gen_ld_i64(tmp, cpu_env,
5398 offsetof(CPUMIPSState, CP0_EntryLo0));
5399 #if defined(TARGET_MIPS64)
5400 if (ctx->rxi) {
5401 /* Move RI/XI fields to bits 31:30 */
5402 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5403 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5405 #endif
5406 gen_move_low32(arg, tmp);
5407 tcg_temp_free_i64(tmp);
5409 rn = "EntryLo0";
5410 break;
5411 case 1:
5412 CP0_CHECK(ctx->insn_flags & ASE_MT);
5413 gen_helper_mfc0_tcstatus(arg, cpu_env);
5414 rn = "TCStatus";
5415 break;
5416 case 2:
5417 CP0_CHECK(ctx->insn_flags & ASE_MT);
5418 gen_helper_mfc0_tcbind(arg, cpu_env);
5419 rn = "TCBind";
5420 break;
5421 case 3:
5422 CP0_CHECK(ctx->insn_flags & ASE_MT);
5423 gen_helper_mfc0_tcrestart(arg, cpu_env);
5424 rn = "TCRestart";
5425 break;
5426 case 4:
5427 CP0_CHECK(ctx->insn_flags & ASE_MT);
5428 gen_helper_mfc0_tchalt(arg, cpu_env);
5429 rn = "TCHalt";
5430 break;
5431 case 5:
5432 CP0_CHECK(ctx->insn_flags & ASE_MT);
5433 gen_helper_mfc0_tccontext(arg, cpu_env);
5434 rn = "TCContext";
5435 break;
5436 case 6:
5437 CP0_CHECK(ctx->insn_flags & ASE_MT);
5438 gen_helper_mfc0_tcschedule(arg, cpu_env);
5439 rn = "TCSchedule";
5440 break;
5441 case 7:
5442 CP0_CHECK(ctx->insn_flags & ASE_MT);
5443 gen_helper_mfc0_tcschefback(arg, cpu_env);
5444 rn = "TCScheFBack";
5445 break;
5446 default:
5447 goto cp0_unimplemented;
5449 break;
5450 case 3:
5451 switch (sel) {
5452 case 0:
5454 TCGv_i64 tmp = tcg_temp_new_i64();
5455 tcg_gen_ld_i64(tmp, cpu_env,
5456 offsetof(CPUMIPSState, CP0_EntryLo1));
5457 #if defined(TARGET_MIPS64)
5458 if (ctx->rxi) {
5459 /* Move RI/XI fields to bits 31:30 */
5460 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5461 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5463 #endif
5464 gen_move_low32(arg, tmp);
5465 tcg_temp_free_i64(tmp);
5467 rn = "EntryLo1";
5468 break;
5469 case 1:
5470 CP0_CHECK(ctx->vp);
5471 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5472 rn = "GlobalNumber";
5473 break;
5474 default:
5475 goto cp0_unimplemented;
5477 break;
5478 case 4:
5479 switch (sel) {
5480 case 0:
5481 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5482 tcg_gen_ext32s_tl(arg, arg);
5483 rn = "Context";
5484 break;
5485 case 1:
5486 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5487 rn = "ContextConfig";
5488 goto cp0_unimplemented;
5489 case 2:
5490 CP0_CHECK(ctx->ulri);
5491 tcg_gen_ld_tl(arg, cpu_env,
5492 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5493 tcg_gen_ext32s_tl(arg, arg);
5494 rn = "UserLocal";
5495 break;
5496 default:
5497 goto cp0_unimplemented;
5499 break;
5500 case 5:
5501 switch (sel) {
5502 case 0:
5503 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5504 rn = "PageMask";
5505 break;
5506 case 1:
5507 check_insn(ctx, ISA_MIPS32R2);
5508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5509 rn = "PageGrain";
5510 break;
5511 case 2:
5512 CP0_CHECK(ctx->sc);
5513 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5514 tcg_gen_ext32s_tl(arg, arg);
5515 rn = "SegCtl0";
5516 break;
5517 case 3:
5518 CP0_CHECK(ctx->sc);
5519 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5520 tcg_gen_ext32s_tl(arg, arg);
5521 rn = "SegCtl1";
5522 break;
5523 case 4:
5524 CP0_CHECK(ctx->sc);
5525 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5526 tcg_gen_ext32s_tl(arg, arg);
5527 rn = "SegCtl2";
5528 break;
5529 default:
5530 goto cp0_unimplemented;
5532 break;
5533 case 6:
5534 switch (sel) {
5535 case 0:
5536 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5537 rn = "Wired";
5538 break;
5539 case 1:
5540 check_insn(ctx, ISA_MIPS32R2);
5541 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5542 rn = "SRSConf0";
5543 break;
5544 case 2:
5545 check_insn(ctx, ISA_MIPS32R2);
5546 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5547 rn = "SRSConf1";
5548 break;
5549 case 3:
5550 check_insn(ctx, ISA_MIPS32R2);
5551 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5552 rn = "SRSConf2";
5553 break;
5554 case 4:
5555 check_insn(ctx, ISA_MIPS32R2);
5556 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5557 rn = "SRSConf3";
5558 break;
5559 case 5:
5560 check_insn(ctx, ISA_MIPS32R2);
5561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5562 rn = "SRSConf4";
5563 break;
5564 default:
5565 goto cp0_unimplemented;
5567 break;
5568 case 7:
5569 switch (sel) {
5570 case 0:
5571 check_insn(ctx, ISA_MIPS32R2);
5572 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5573 rn = "HWREna";
5574 break;
5575 default:
5576 goto cp0_unimplemented;
5578 break;
5579 case 8:
5580 switch (sel) {
5581 case 0:
5582 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5583 tcg_gen_ext32s_tl(arg, arg);
5584 rn = "BadVAddr";
5585 break;
5586 case 1:
5587 CP0_CHECK(ctx->bi);
5588 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5589 rn = "BadInstr";
5590 break;
5591 case 2:
5592 CP0_CHECK(ctx->bp);
5593 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5594 rn = "BadInstrP";
5595 break;
5596 case 3:
5597 CP0_CHECK(ctx->bi);
5598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
5599 tcg_gen_andi_tl(arg, arg, ~0xffff);
5600 rn = "BadInstrX";
5601 break;
5602 default:
5603 goto cp0_unimplemented;
5605 break;
5606 case 9:
5607 switch (sel) {
5608 case 0:
5609 /* Mark as an IO operation because we read the time. */
5610 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
5611 gen_io_start();
5613 gen_helper_mfc0_count(arg, cpu_env);
5614 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
5615 gen_io_end();
5617 /* Break the TB to be able to take timer interrupts immediately
5618 after reading count. DISAS_STOP isn't sufficient, we need to
5619 ensure we break completely out of translated code. */
5620 gen_save_pc(ctx->base.pc_next + 4);
5621 ctx->base.is_jmp = DISAS_EXIT;
5622 rn = "Count";
5623 break;
5624 /* 6,7 are implementation dependent */
5625 default:
5626 goto cp0_unimplemented;
5628 break;
5629 case 10:
5630 switch (sel) {
5631 case 0:
5632 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5633 tcg_gen_ext32s_tl(arg, arg);
5634 rn = "EntryHi";
5635 break;
5636 default:
5637 goto cp0_unimplemented;
5639 break;
5640 case 11:
5641 switch (sel) {
5642 case 0:
5643 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5644 rn = "Compare";
5645 break;
5646 /* 6,7 are implementation dependent */
5647 default:
5648 goto cp0_unimplemented;
5650 break;
5651 case 12:
5652 switch (sel) {
5653 case 0:
5654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5655 rn = "Status";
5656 break;
5657 case 1:
5658 check_insn(ctx, ISA_MIPS32R2);
5659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5660 rn = "IntCtl";
5661 break;
5662 case 2:
5663 check_insn(ctx, ISA_MIPS32R2);
5664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5665 rn = "SRSCtl";
5666 break;
5667 case 3:
5668 check_insn(ctx, ISA_MIPS32R2);
5669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5670 rn = "SRSMap";
5671 break;
5672 default:
5673 goto cp0_unimplemented;
5675 break;
5676 case 13:
5677 switch (sel) {
5678 case 0:
5679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5680 rn = "Cause";
5681 break;
5682 default:
5683 goto cp0_unimplemented;
5685 break;
5686 case 14:
5687 switch (sel) {
5688 case 0:
5689 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5690 tcg_gen_ext32s_tl(arg, arg);
5691 rn = "EPC";
5692 break;
5693 default:
5694 goto cp0_unimplemented;
5696 break;
5697 case 15:
5698 switch (sel) {
5699 case 0:
5700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5701 rn = "PRid";
5702 break;
5703 case 1:
5704 check_insn(ctx, ISA_MIPS32R2);
5705 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
5706 tcg_gen_ext32s_tl(arg, arg);
5707 rn = "EBase";
5708 break;
5709 case 3:
5710 check_insn(ctx, ISA_MIPS32R2);
5711 CP0_CHECK(ctx->cmgcr);
5712 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5713 tcg_gen_ext32s_tl(arg, arg);
5714 rn = "CMGCRBase";
5715 break;
5716 default:
5717 goto cp0_unimplemented;
5719 break;
5720 case 16:
5721 switch (sel) {
5722 case 0:
5723 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5724 rn = "Config";
5725 break;
5726 case 1:
5727 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5728 rn = "Config1";
5729 break;
5730 case 2:
5731 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5732 rn = "Config2";
5733 break;
5734 case 3:
5735 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5736 rn = "Config3";
5737 break;
5738 case 4:
5739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5740 rn = "Config4";
5741 break;
5742 case 5:
5743 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5744 rn = "Config5";
5745 break;
5746 /* 6,7 are implementation dependent */
5747 case 6:
5748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5749 rn = "Config6";
5750 break;
5751 case 7:
5752 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5753 rn = "Config7";
5754 break;
5755 default:
5756 goto cp0_unimplemented;
5758 break;
5759 case 17:
5760 switch (sel) {
5761 case 0:
5762 gen_helper_mfc0_lladdr(arg, cpu_env);
5763 rn = "LLAddr";
5764 break;
5765 case 1:
5766 CP0_CHECK(ctx->mrp);
5767 gen_helper_mfc0_maar(arg, cpu_env);
5768 rn = "MAAR";
5769 break;
5770 case 2:
5771 CP0_CHECK(ctx->mrp);
5772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5773 rn = "MAARI";
5774 break;
5775 default:
5776 goto cp0_unimplemented;
5778 break;
5779 case 18:
5780 switch (sel) {
5781 case 0:
5782 case 1:
5783 case 2:
5784 case 3:
5785 case 4:
5786 case 5:
5787 case 6:
5788 case 7:
5789 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
5790 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5791 rn = "WatchLo";
5792 break;
5793 default:
5794 goto cp0_unimplemented;
5796 break;
5797 case 19:
5798 switch (sel) {
5799 case 0:
5800 case 1:
5801 case 2:
5802 case 3:
5803 case 4:
5804 case 5:
5805 case 6:
5806 case 7:
5807 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
5808 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5809 rn = "WatchHi";
5810 break;
5811 default:
5812 goto cp0_unimplemented;
5814 break;
5815 case 20:
5816 switch (sel) {
5817 case 0:
5818 #if defined(TARGET_MIPS64)
5819 check_insn(ctx, ISA_MIPS3);
5820 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5821 tcg_gen_ext32s_tl(arg, arg);
5822 rn = "XContext";
5823 break;
5824 #endif
5825 default:
5826 goto cp0_unimplemented;
5828 break;
5829 case 21:
5830 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5831 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5832 switch (sel) {
5833 case 0:
5834 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5835 rn = "Framemask";
5836 break;
5837 default:
5838 goto cp0_unimplemented;
5840 break;
5841 case 22:
5842 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5843 rn = "'Diagnostic"; /* implementation dependent */
5844 break;
5845 case 23:
5846 switch (sel) {
5847 case 0:
5848 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5849 rn = "Debug";
5850 break;
5851 case 1:
5852 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5853 rn = "TraceControl";
5854 goto cp0_unimplemented;
5855 case 2:
5856 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5857 rn = "TraceControl2";
5858 goto cp0_unimplemented;
5859 case 3:
5860 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5861 rn = "UserTraceData";
5862 goto cp0_unimplemented;
5863 case 4:
5864 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5865 rn = "TraceBPC";
5866 goto cp0_unimplemented;
5867 default:
5868 goto cp0_unimplemented;
5870 break;
5871 case 24:
5872 switch (sel) {
5873 case 0:
5874 /* EJTAG support */
5875 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5876 tcg_gen_ext32s_tl(arg, arg);
5877 rn = "DEPC";
5878 break;
5879 default:
5880 goto cp0_unimplemented;
5882 break;
5883 case 25:
5884 switch (sel) {
5885 case 0:
5886 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5887 rn = "Performance0";
5888 break;
5889 case 1:
5890 // gen_helper_mfc0_performance1(arg);
5891 rn = "Performance1";
5892 goto cp0_unimplemented;
5893 case 2:
5894 // gen_helper_mfc0_performance2(arg);
5895 rn = "Performance2";
5896 goto cp0_unimplemented;
5897 case 3:
5898 // gen_helper_mfc0_performance3(arg);
5899 rn = "Performance3";
5900 goto cp0_unimplemented;
5901 case 4:
5902 // gen_helper_mfc0_performance4(arg);
5903 rn = "Performance4";
5904 goto cp0_unimplemented;
5905 case 5:
5906 // gen_helper_mfc0_performance5(arg);
5907 rn = "Performance5";
5908 goto cp0_unimplemented;
5909 case 6:
5910 // gen_helper_mfc0_performance6(arg);
5911 rn = "Performance6";
5912 goto cp0_unimplemented;
5913 case 7:
5914 // gen_helper_mfc0_performance7(arg);
5915 rn = "Performance7";
5916 goto cp0_unimplemented;
5917 default:
5918 goto cp0_unimplemented;
5920 break;
5921 case 26:
5922 switch (sel) {
5923 case 0:
5924 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5925 rn = "ErrCtl";
5926 break;
5927 default:
5928 goto cp0_unimplemented;
5930 break;
5931 case 27:
5932 switch (sel) {
5933 case 0:
5934 case 1:
5935 case 2:
5936 case 3:
5937 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5938 rn = "CacheErr";
5939 break;
5940 default:
5941 goto cp0_unimplemented;
5943 break;
5944 case 28:
5945 switch (sel) {
5946 case 0:
5947 case 2:
5948 case 4:
5949 case 6:
5951 TCGv_i64 tmp = tcg_temp_new_i64();
5952 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5953 gen_move_low32(arg, tmp);
5954 tcg_temp_free_i64(tmp);
5956 rn = "TagLo";
5957 break;
5958 case 1:
5959 case 3:
5960 case 5:
5961 case 7:
5962 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5963 rn = "DataLo";
5964 break;
5965 default:
5966 goto cp0_unimplemented;
5968 break;
5969 case 29:
5970 switch (sel) {
5971 case 0:
5972 case 2:
5973 case 4:
5974 case 6:
5975 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5976 rn = "TagHi";
5977 break;
5978 case 1:
5979 case 3:
5980 case 5:
5981 case 7:
5982 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5983 rn = "DataHi";
5984 break;
5985 default:
5986 goto cp0_unimplemented;
5988 break;
5989 case 30:
5990 switch (sel) {
5991 case 0:
5992 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5993 tcg_gen_ext32s_tl(arg, arg);
5994 rn = "ErrorEPC";
5995 break;
5996 default:
5997 goto cp0_unimplemented;
5999 break;
6000 case 31:
6001 switch (sel) {
6002 case 0:
6003 /* EJTAG support */
6004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6005 rn = "DESAVE";
6006 break;
6007 case 2:
6008 case 3:
6009 case 4:
6010 case 5:
6011 case 6:
6012 case 7:
6013 CP0_CHECK(ctx->kscrexist & (1 << sel));
6014 tcg_gen_ld_tl(arg, cpu_env,
6015 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6016 tcg_gen_ext32s_tl(arg, arg);
6017 rn = "KScratch";
6018 break;
6019 default:
6020 goto cp0_unimplemented;
6022 break;
6023 default:
6024 goto cp0_unimplemented;
6026 trace_mips_translate_c0("mfc0", rn, reg, sel);
6027 return;
6029 cp0_unimplemented:
6030 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6031 gen_mfc0_unimplemented(ctx, arg);
6034 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6036 const char *rn = "invalid";
6038 if (sel != 0)
6039 check_insn(ctx, ISA_MIPS32);
6041 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6042 gen_io_start();
6045 switch (reg) {
6046 case 0:
6047 switch (sel) {
6048 case 0:
6049 gen_helper_mtc0_index(cpu_env, arg);
6050 rn = "Index";
6051 break;
6052 case 1:
6053 CP0_CHECK(ctx->insn_flags & ASE_MT);
6054 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6055 rn = "MVPControl";
6056 break;
6057 case 2:
6058 CP0_CHECK(ctx->insn_flags & ASE_MT);
6059 /* ignored */
6060 rn = "MVPConf0";
6061 break;
6062 case 3:
6063 CP0_CHECK(ctx->insn_flags & ASE_MT);
6064 /* ignored */
6065 rn = "MVPConf1";
6066 break;
6067 case 4:
6068 CP0_CHECK(ctx->vp);
6069 /* ignored */
6070 rn = "VPControl";
6071 break;
6072 default:
6073 goto cp0_unimplemented;
6075 break;
6076 case 1:
6077 switch (sel) {
6078 case 0:
6079 /* ignored */
6080 rn = "Random";
6081 break;
6082 case 1:
6083 CP0_CHECK(ctx->insn_flags & ASE_MT);
6084 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6085 rn = "VPEControl";
6086 break;
6087 case 2:
6088 CP0_CHECK(ctx->insn_flags & ASE_MT);
6089 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6090 rn = "VPEConf0";
6091 break;
6092 case 3:
6093 CP0_CHECK(ctx->insn_flags & ASE_MT);
6094 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6095 rn = "VPEConf1";
6096 break;
6097 case 4:
6098 CP0_CHECK(ctx->insn_flags & ASE_MT);
6099 gen_helper_mtc0_yqmask(cpu_env, arg);
6100 rn = "YQMask";
6101 break;
6102 case 5:
6103 CP0_CHECK(ctx->insn_flags & ASE_MT);
6104 tcg_gen_st_tl(arg, cpu_env,
6105 offsetof(CPUMIPSState, CP0_VPESchedule));
6106 rn = "VPESchedule";
6107 break;
6108 case 6:
6109 CP0_CHECK(ctx->insn_flags & ASE_MT);
6110 tcg_gen_st_tl(arg, cpu_env,
6111 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6112 rn = "VPEScheFBack";
6113 break;
6114 case 7:
6115 CP0_CHECK(ctx->insn_flags & ASE_MT);
6116 gen_helper_mtc0_vpeopt(cpu_env, arg);
6117 rn = "VPEOpt";
6118 break;
6119 default:
6120 goto cp0_unimplemented;
6122 break;
6123 case 2:
6124 switch (sel) {
6125 case 0:
6126 gen_helper_mtc0_entrylo0(cpu_env, arg);
6127 rn = "EntryLo0";
6128 break;
6129 case 1:
6130 CP0_CHECK(ctx->insn_flags & ASE_MT);
6131 gen_helper_mtc0_tcstatus(cpu_env, arg);
6132 rn = "TCStatus";
6133 break;
6134 case 2:
6135 CP0_CHECK(ctx->insn_flags & ASE_MT);
6136 gen_helper_mtc0_tcbind(cpu_env, arg);
6137 rn = "TCBind";
6138 break;
6139 case 3:
6140 CP0_CHECK(ctx->insn_flags & ASE_MT);
6141 gen_helper_mtc0_tcrestart(cpu_env, arg);
6142 rn = "TCRestart";
6143 break;
6144 case 4:
6145 CP0_CHECK(ctx->insn_flags & ASE_MT);
6146 gen_helper_mtc0_tchalt(cpu_env, arg);
6147 rn = "TCHalt";
6148 break;
6149 case 5:
6150 CP0_CHECK(ctx->insn_flags & ASE_MT);
6151 gen_helper_mtc0_tccontext(cpu_env, arg);
6152 rn = "TCContext";
6153 break;
6154 case 6:
6155 CP0_CHECK(ctx->insn_flags & ASE_MT);
6156 gen_helper_mtc0_tcschedule(cpu_env, arg);
6157 rn = "TCSchedule";
6158 break;
6159 case 7:
6160 CP0_CHECK(ctx->insn_flags & ASE_MT);
6161 gen_helper_mtc0_tcschefback(cpu_env, arg);
6162 rn = "TCScheFBack";
6163 break;
6164 default:
6165 goto cp0_unimplemented;
6167 break;
6168 case 3:
6169 switch (sel) {
6170 case 0:
6171 gen_helper_mtc0_entrylo1(cpu_env, arg);
6172 rn = "EntryLo1";
6173 break;
6174 case 1:
6175 CP0_CHECK(ctx->vp);
6176 /* ignored */
6177 rn = "GlobalNumber";
6178 break;
6179 default:
6180 goto cp0_unimplemented;
6182 break;
6183 case 4:
6184 switch (sel) {
6185 case 0:
6186 gen_helper_mtc0_context(cpu_env, arg);
6187 rn = "Context";
6188 break;
6189 case 1:
6190 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6191 rn = "ContextConfig";
6192 goto cp0_unimplemented;
6193 case 2:
6194 CP0_CHECK(ctx->ulri);
6195 tcg_gen_st_tl(arg, cpu_env,
6196 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6197 rn = "UserLocal";
6198 break;
6199 default:
6200 goto cp0_unimplemented;
6202 break;
6203 case 5:
6204 switch (sel) {
6205 case 0:
6206 gen_helper_mtc0_pagemask(cpu_env, arg);
6207 rn = "PageMask";
6208 break;
6209 case 1:
6210 check_insn(ctx, ISA_MIPS32R2);
6211 gen_helper_mtc0_pagegrain(cpu_env, arg);
6212 rn = "PageGrain";
6213 ctx->base.is_jmp = DISAS_STOP;
6214 break;
6215 case 2:
6216 CP0_CHECK(ctx->sc);
6217 gen_helper_mtc0_segctl0(cpu_env, arg);
6218 rn = "SegCtl0";
6219 break;
6220 case 3:
6221 CP0_CHECK(ctx->sc);
6222 gen_helper_mtc0_segctl1(cpu_env, arg);
6223 rn = "SegCtl1";
6224 break;
6225 case 4:
6226 CP0_CHECK(ctx->sc);
6227 gen_helper_mtc0_segctl2(cpu_env, arg);
6228 rn = "SegCtl2";
6229 break;
6230 default:
6231 goto cp0_unimplemented;
6233 break;
6234 case 6:
6235 switch (sel) {
6236 case 0:
6237 gen_helper_mtc0_wired(cpu_env, arg);
6238 rn = "Wired";
6239 break;
6240 case 1:
6241 check_insn(ctx, ISA_MIPS32R2);
6242 gen_helper_mtc0_srsconf0(cpu_env, arg);
6243 rn = "SRSConf0";
6244 break;
6245 case 2:
6246 check_insn(ctx, ISA_MIPS32R2);
6247 gen_helper_mtc0_srsconf1(cpu_env, arg);
6248 rn = "SRSConf1";
6249 break;
6250 case 3:
6251 check_insn(ctx, ISA_MIPS32R2);
6252 gen_helper_mtc0_srsconf2(cpu_env, arg);
6253 rn = "SRSConf2";
6254 break;
6255 case 4:
6256 check_insn(ctx, ISA_MIPS32R2);
6257 gen_helper_mtc0_srsconf3(cpu_env, arg);
6258 rn = "SRSConf3";
6259 break;
6260 case 5:
6261 check_insn(ctx, ISA_MIPS32R2);
6262 gen_helper_mtc0_srsconf4(cpu_env, arg);
6263 rn = "SRSConf4";
6264 break;
6265 default:
6266 goto cp0_unimplemented;
6268 break;
6269 case 7:
6270 switch (sel) {
6271 case 0:
6272 check_insn(ctx, ISA_MIPS32R2);
6273 gen_helper_mtc0_hwrena(cpu_env, arg);
6274 ctx->base.is_jmp = DISAS_STOP;
6275 rn = "HWREna";
6276 break;
6277 default:
6278 goto cp0_unimplemented;
6280 break;
6281 case 8:
6282 switch (sel) {
6283 case 0:
6284 /* ignored */
6285 rn = "BadVAddr";
6286 break;
6287 case 1:
6288 /* ignored */
6289 rn = "BadInstr";
6290 break;
6291 case 2:
6292 /* ignored */
6293 rn = "BadInstrP";
6294 break;
6295 case 3:
6296 /* ignored */
6297 rn = "BadInstrX";
6298 break;
6299 default:
6300 goto cp0_unimplemented;
6302 break;
6303 case 9:
6304 switch (sel) {
6305 case 0:
6306 gen_helper_mtc0_count(cpu_env, arg);
6307 rn = "Count";
6308 break;
6309 /* 6,7 are implementation dependent */
6310 default:
6311 goto cp0_unimplemented;
6313 break;
6314 case 10:
6315 switch (sel) {
6316 case 0:
6317 gen_helper_mtc0_entryhi(cpu_env, arg);
6318 rn = "EntryHi";
6319 break;
6320 default:
6321 goto cp0_unimplemented;
6323 break;
6324 case 11:
6325 switch (sel) {
6326 case 0:
6327 gen_helper_mtc0_compare(cpu_env, arg);
6328 rn = "Compare";
6329 break;
6330 /* 6,7 are implementation dependent */
6331 default:
6332 goto cp0_unimplemented;
6334 break;
6335 case 12:
6336 switch (sel) {
6337 case 0:
6338 save_cpu_state(ctx, 1);
6339 gen_helper_mtc0_status(cpu_env, arg);
6340 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6341 gen_save_pc(ctx->base.pc_next + 4);
6342 ctx->base.is_jmp = DISAS_EXIT;
6343 rn = "Status";
6344 break;
6345 case 1:
6346 check_insn(ctx, ISA_MIPS32R2);
6347 gen_helper_mtc0_intctl(cpu_env, arg);
6348 /* Stop translation as we may have switched the execution mode */
6349 ctx->base.is_jmp = DISAS_STOP;
6350 rn = "IntCtl";
6351 break;
6352 case 2:
6353 check_insn(ctx, ISA_MIPS32R2);
6354 gen_helper_mtc0_srsctl(cpu_env, arg);
6355 /* Stop translation as we may have switched the execution mode */
6356 ctx->base.is_jmp = DISAS_STOP;
6357 rn = "SRSCtl";
6358 break;
6359 case 3:
6360 check_insn(ctx, ISA_MIPS32R2);
6361 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6362 /* Stop translation as we may have switched the execution mode */
6363 ctx->base.is_jmp = DISAS_STOP;
6364 rn = "SRSMap";
6365 break;
6366 default:
6367 goto cp0_unimplemented;
6369 break;
6370 case 13:
6371 switch (sel) {
6372 case 0:
6373 save_cpu_state(ctx, 1);
6374 gen_helper_mtc0_cause(cpu_env, arg);
6375 /* Stop translation as we may have triggered an interrupt.
6376 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6377 * translated code to check for pending interrupts. */
6378 gen_save_pc(ctx->base.pc_next + 4);
6379 ctx->base.is_jmp = DISAS_EXIT;
6380 rn = "Cause";
6381 break;
6382 default:
6383 goto cp0_unimplemented;
6385 break;
6386 case 14:
6387 switch (sel) {
6388 case 0:
6389 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6390 rn = "EPC";
6391 break;
6392 default:
6393 goto cp0_unimplemented;
6395 break;
6396 case 15:
6397 switch (sel) {
6398 case 0:
6399 /* ignored */
6400 rn = "PRid";
6401 break;
6402 case 1:
6403 check_insn(ctx, ISA_MIPS32R2);
6404 gen_helper_mtc0_ebase(cpu_env, arg);
6405 rn = "EBase";
6406 break;
6407 default:
6408 goto cp0_unimplemented;
6410 break;
6411 case 16:
6412 switch (sel) {
6413 case 0:
6414 gen_helper_mtc0_config0(cpu_env, arg);
6415 rn = "Config";
6416 /* Stop translation as we may have switched the execution mode */
6417 ctx->base.is_jmp = DISAS_STOP;
6418 break;
6419 case 1:
6420 /* ignored, read only */
6421 rn = "Config1";
6422 break;
6423 case 2:
6424 gen_helper_mtc0_config2(cpu_env, arg);
6425 rn = "Config2";
6426 /* Stop translation as we may have switched the execution mode */
6427 ctx->base.is_jmp = DISAS_STOP;
6428 break;
6429 case 3:
6430 gen_helper_mtc0_config3(cpu_env, arg);
6431 rn = "Config3";
6432 /* Stop translation as we may have switched the execution mode */
6433 ctx->base.is_jmp = DISAS_STOP;
6434 break;
6435 case 4:
6436 gen_helper_mtc0_config4(cpu_env, arg);
6437 rn = "Config4";
6438 ctx->base.is_jmp = DISAS_STOP;
6439 break;
6440 case 5:
6441 gen_helper_mtc0_config5(cpu_env, arg);
6442 rn = "Config5";
6443 /* Stop translation as we may have switched the execution mode */
6444 ctx->base.is_jmp = DISAS_STOP;
6445 break;
6446 /* 6,7 are implementation dependent */
6447 case 6:
6448 /* ignored */
6449 rn = "Config6";
6450 break;
6451 case 7:
6452 /* ignored */
6453 rn = "Config7";
6454 break;
6455 default:
6456 rn = "Invalid config selector";
6457 goto cp0_unimplemented;
6459 break;
6460 case 17:
6461 switch (sel) {
6462 case 0:
6463 gen_helper_mtc0_lladdr(cpu_env, arg);
6464 rn = "LLAddr";
6465 break;
6466 case 1:
6467 CP0_CHECK(ctx->mrp);
6468 gen_helper_mtc0_maar(cpu_env, arg);
6469 rn = "MAAR";
6470 break;
6471 case 2:
6472 CP0_CHECK(ctx->mrp);
6473 gen_helper_mtc0_maari(cpu_env, arg);
6474 rn = "MAARI";
6475 break;
6476 default:
6477 goto cp0_unimplemented;
6479 break;
6480 case 18:
6481 switch (sel) {
6482 case 0:
6483 case 1:
6484 case 2:
6485 case 3:
6486 case 4:
6487 case 5:
6488 case 6:
6489 case 7:
6490 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6491 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6492 rn = "WatchLo";
6493 break;
6494 default:
6495 goto cp0_unimplemented;
6497 break;
6498 case 19:
6499 switch (sel) {
6500 case 0:
6501 case 1:
6502 case 2:
6503 case 3:
6504 case 4:
6505 case 5:
6506 case 6:
6507 case 7:
6508 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6509 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6510 rn = "WatchHi";
6511 break;
6512 default:
6513 goto cp0_unimplemented;
6515 break;
6516 case 20:
6517 switch (sel) {
6518 case 0:
6519 #if defined(TARGET_MIPS64)
6520 check_insn(ctx, ISA_MIPS3);
6521 gen_helper_mtc0_xcontext(cpu_env, arg);
6522 rn = "XContext";
6523 break;
6524 #endif
6525 default:
6526 goto cp0_unimplemented;
6528 break;
6529 case 21:
6530 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6531 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6532 switch (sel) {
6533 case 0:
6534 gen_helper_mtc0_framemask(cpu_env, arg);
6535 rn = "Framemask";
6536 break;
6537 default:
6538 goto cp0_unimplemented;
6540 break;
6541 case 22:
6542 /* ignored */
6543 rn = "Diagnostic"; /* implementation dependent */
6544 break;
6545 case 23:
6546 switch (sel) {
6547 case 0:
6548 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6549 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6550 gen_save_pc(ctx->base.pc_next + 4);
6551 ctx->base.is_jmp = DISAS_EXIT;
6552 rn = "Debug";
6553 break;
6554 case 1:
6555 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6556 rn = "TraceControl";
6557 /* Stop translation as we may have switched the execution mode */
6558 ctx->base.is_jmp = DISAS_STOP;
6559 goto cp0_unimplemented;
6560 case 2:
6561 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6562 rn = "TraceControl2";
6563 /* Stop translation as we may have switched the execution mode */
6564 ctx->base.is_jmp = DISAS_STOP;
6565 goto cp0_unimplemented;
6566 case 3:
6567 /* Stop translation as we may have switched the execution mode */
6568 ctx->base.is_jmp = DISAS_STOP;
6569 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6570 rn = "UserTraceData";
6571 /* Stop translation as we may have switched the execution mode */
6572 ctx->base.is_jmp = DISAS_STOP;
6573 goto cp0_unimplemented;
6574 case 4:
6575 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6576 /* Stop translation as we may have switched the execution mode */
6577 ctx->base.is_jmp = DISAS_STOP;
6578 rn = "TraceBPC";
6579 goto cp0_unimplemented;
6580 default:
6581 goto cp0_unimplemented;
6583 break;
6584 case 24:
6585 switch (sel) {
6586 case 0:
6587 /* EJTAG support */
6588 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6589 rn = "DEPC";
6590 break;
6591 default:
6592 goto cp0_unimplemented;
6594 break;
6595 case 25:
6596 switch (sel) {
6597 case 0:
6598 gen_helper_mtc0_performance0(cpu_env, arg);
6599 rn = "Performance0";
6600 break;
6601 case 1:
6602 // gen_helper_mtc0_performance1(arg);
6603 rn = "Performance1";
6604 goto cp0_unimplemented;
6605 case 2:
6606 // gen_helper_mtc0_performance2(arg);
6607 rn = "Performance2";
6608 goto cp0_unimplemented;
6609 case 3:
6610 // gen_helper_mtc0_performance3(arg);
6611 rn = "Performance3";
6612 goto cp0_unimplemented;
6613 case 4:
6614 // gen_helper_mtc0_performance4(arg);
6615 rn = "Performance4";
6616 goto cp0_unimplemented;
6617 case 5:
6618 // gen_helper_mtc0_performance5(arg);
6619 rn = "Performance5";
6620 goto cp0_unimplemented;
6621 case 6:
6622 // gen_helper_mtc0_performance6(arg);
6623 rn = "Performance6";
6624 goto cp0_unimplemented;
6625 case 7:
6626 // gen_helper_mtc0_performance7(arg);
6627 rn = "Performance7";
6628 goto cp0_unimplemented;
6629 default:
6630 goto cp0_unimplemented;
6632 break;
6633 case 26:
6634 switch (sel) {
6635 case 0:
6636 gen_helper_mtc0_errctl(cpu_env, arg);
6637 ctx->base.is_jmp = DISAS_STOP;
6638 rn = "ErrCtl";
6639 break;
6640 default:
6641 goto cp0_unimplemented;
6643 break;
6644 case 27:
6645 switch (sel) {
6646 case 0:
6647 case 1:
6648 case 2:
6649 case 3:
6650 /* ignored */
6651 rn = "CacheErr";
6652 break;
6653 default:
6654 goto cp0_unimplemented;
6656 break;
6657 case 28:
6658 switch (sel) {
6659 case 0:
6660 case 2:
6661 case 4:
6662 case 6:
6663 gen_helper_mtc0_taglo(cpu_env, arg);
6664 rn = "TagLo";
6665 break;
6666 case 1:
6667 case 3:
6668 case 5:
6669 case 7:
6670 gen_helper_mtc0_datalo(cpu_env, arg);
6671 rn = "DataLo";
6672 break;
6673 default:
6674 goto cp0_unimplemented;
6676 break;
6677 case 29:
6678 switch (sel) {
6679 case 0:
6680 case 2:
6681 case 4:
6682 case 6:
6683 gen_helper_mtc0_taghi(cpu_env, arg);
6684 rn = "TagHi";
6685 break;
6686 case 1:
6687 case 3:
6688 case 5:
6689 case 7:
6690 gen_helper_mtc0_datahi(cpu_env, arg);
6691 rn = "DataHi";
6692 break;
6693 default:
6694 rn = "invalid sel";
6695 goto cp0_unimplemented;
6697 break;
6698 case 30:
6699 switch (sel) {
6700 case 0:
6701 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6702 rn = "ErrorEPC";
6703 break;
6704 default:
6705 goto cp0_unimplemented;
6707 break;
6708 case 31:
6709 switch (sel) {
6710 case 0:
6711 /* EJTAG support */
6712 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6713 rn = "DESAVE";
6714 break;
6715 case 2:
6716 case 3:
6717 case 4:
6718 case 5:
6719 case 6:
6720 case 7:
6721 CP0_CHECK(ctx->kscrexist & (1 << sel));
6722 tcg_gen_st_tl(arg, cpu_env,
6723 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6724 rn = "KScratch";
6725 break;
6726 default:
6727 goto cp0_unimplemented;
6729 break;
6730 default:
6731 goto cp0_unimplemented;
6733 trace_mips_translate_c0("mtc0", rn, reg, sel);
6735 /* For simplicity assume that all writes can cause interrupts. */
6736 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6737 gen_io_end();
6738 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
6739 * translated code to check for pending interrupts. */
6740 gen_save_pc(ctx->base.pc_next + 4);
6741 ctx->base.is_jmp = DISAS_EXIT;
6743 return;
6745 cp0_unimplemented:
6746 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6749 #if defined(TARGET_MIPS64)
6750 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6752 const char *rn = "invalid";
6754 if (sel != 0)
6755 check_insn(ctx, ISA_MIPS64);
6757 switch (reg) {
6758 case 0:
6759 switch (sel) {
6760 case 0:
6761 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6762 rn = "Index";
6763 break;
6764 case 1:
6765 CP0_CHECK(ctx->insn_flags & ASE_MT);
6766 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6767 rn = "MVPControl";
6768 break;
6769 case 2:
6770 CP0_CHECK(ctx->insn_flags & ASE_MT);
6771 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6772 rn = "MVPConf0";
6773 break;
6774 case 3:
6775 CP0_CHECK(ctx->insn_flags & ASE_MT);
6776 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6777 rn = "MVPConf1";
6778 break;
6779 case 4:
6780 CP0_CHECK(ctx->vp);
6781 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6782 rn = "VPControl";
6783 break;
6784 default:
6785 goto cp0_unimplemented;
6787 break;
6788 case 1:
6789 switch (sel) {
6790 case 0:
6791 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6792 gen_helper_mfc0_random(arg, cpu_env);
6793 rn = "Random";
6794 break;
6795 case 1:
6796 CP0_CHECK(ctx->insn_flags & ASE_MT);
6797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6798 rn = "VPEControl";
6799 break;
6800 case 2:
6801 CP0_CHECK(ctx->insn_flags & ASE_MT);
6802 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6803 rn = "VPEConf0";
6804 break;
6805 case 3:
6806 CP0_CHECK(ctx->insn_flags & ASE_MT);
6807 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6808 rn = "VPEConf1";
6809 break;
6810 case 4:
6811 CP0_CHECK(ctx->insn_flags & ASE_MT);
6812 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6813 rn = "YQMask";
6814 break;
6815 case 5:
6816 CP0_CHECK(ctx->insn_flags & ASE_MT);
6817 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6818 rn = "VPESchedule";
6819 break;
6820 case 6:
6821 CP0_CHECK(ctx->insn_flags & ASE_MT);
6822 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6823 rn = "VPEScheFBack";
6824 break;
6825 case 7:
6826 CP0_CHECK(ctx->insn_flags & ASE_MT);
6827 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6828 rn = "VPEOpt";
6829 break;
6830 default:
6831 goto cp0_unimplemented;
6833 break;
6834 case 2:
6835 switch (sel) {
6836 case 0:
6837 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6838 rn = "EntryLo0";
6839 break;
6840 case 1:
6841 CP0_CHECK(ctx->insn_flags & ASE_MT);
6842 gen_helper_mfc0_tcstatus(arg, cpu_env);
6843 rn = "TCStatus";
6844 break;
6845 case 2:
6846 CP0_CHECK(ctx->insn_flags & ASE_MT);
6847 gen_helper_mfc0_tcbind(arg, cpu_env);
6848 rn = "TCBind";
6849 break;
6850 case 3:
6851 CP0_CHECK(ctx->insn_flags & ASE_MT);
6852 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6853 rn = "TCRestart";
6854 break;
6855 case 4:
6856 CP0_CHECK(ctx->insn_flags & ASE_MT);
6857 gen_helper_dmfc0_tchalt(arg, cpu_env);
6858 rn = "TCHalt";
6859 break;
6860 case 5:
6861 CP0_CHECK(ctx->insn_flags & ASE_MT);
6862 gen_helper_dmfc0_tccontext(arg, cpu_env);
6863 rn = "TCContext";
6864 break;
6865 case 6:
6866 CP0_CHECK(ctx->insn_flags & ASE_MT);
6867 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6868 rn = "TCSchedule";
6869 break;
6870 case 7:
6871 CP0_CHECK(ctx->insn_flags & ASE_MT);
6872 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6873 rn = "TCScheFBack";
6874 break;
6875 default:
6876 goto cp0_unimplemented;
6878 break;
6879 case 3:
6880 switch (sel) {
6881 case 0:
6882 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6883 rn = "EntryLo1";
6884 break;
6885 case 1:
6886 CP0_CHECK(ctx->vp);
6887 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6888 rn = "GlobalNumber";
6889 break;
6890 default:
6891 goto cp0_unimplemented;
6893 break;
6894 case 4:
6895 switch (sel) {
6896 case 0:
6897 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6898 rn = "Context";
6899 break;
6900 case 1:
6901 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6902 rn = "ContextConfig";
6903 goto cp0_unimplemented;
6904 case 2:
6905 CP0_CHECK(ctx->ulri);
6906 tcg_gen_ld_tl(arg, cpu_env,
6907 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6908 rn = "UserLocal";
6909 break;
6910 default:
6911 goto cp0_unimplemented;
6913 break;
6914 case 5:
6915 switch (sel) {
6916 case 0:
6917 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6918 rn = "PageMask";
6919 break;
6920 case 1:
6921 check_insn(ctx, ISA_MIPS32R2);
6922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6923 rn = "PageGrain";
6924 break;
6925 case 2:
6926 CP0_CHECK(ctx->sc);
6927 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6928 rn = "SegCtl0";
6929 break;
6930 case 3:
6931 CP0_CHECK(ctx->sc);
6932 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6933 rn = "SegCtl1";
6934 break;
6935 case 4:
6936 CP0_CHECK(ctx->sc);
6937 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6938 rn = "SegCtl2";
6939 break;
6940 default:
6941 goto cp0_unimplemented;
6943 break;
6944 case 6:
6945 switch (sel) {
6946 case 0:
6947 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6948 rn = "Wired";
6949 break;
6950 case 1:
6951 check_insn(ctx, ISA_MIPS32R2);
6952 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6953 rn = "SRSConf0";
6954 break;
6955 case 2:
6956 check_insn(ctx, ISA_MIPS32R2);
6957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6958 rn = "SRSConf1";
6959 break;
6960 case 3:
6961 check_insn(ctx, ISA_MIPS32R2);
6962 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6963 rn = "SRSConf2";
6964 break;
6965 case 4:
6966 check_insn(ctx, ISA_MIPS32R2);
6967 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6968 rn = "SRSConf3";
6969 break;
6970 case 5:
6971 check_insn(ctx, ISA_MIPS32R2);
6972 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6973 rn = "SRSConf4";
6974 break;
6975 default:
6976 goto cp0_unimplemented;
6978 break;
6979 case 7:
6980 switch (sel) {
6981 case 0:
6982 check_insn(ctx, ISA_MIPS32R2);
6983 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6984 rn = "HWREna";
6985 break;
6986 default:
6987 goto cp0_unimplemented;
6989 break;
6990 case 8:
6991 switch (sel) {
6992 case 0:
6993 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6994 rn = "BadVAddr";
6995 break;
6996 case 1:
6997 CP0_CHECK(ctx->bi);
6998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6999 rn = "BadInstr";
7000 break;
7001 case 2:
7002 CP0_CHECK(ctx->bp);
7003 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7004 rn = "BadInstrP";
7005 break;
7006 case 3:
7007 CP0_CHECK(ctx->bi);
7008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7009 tcg_gen_andi_tl(arg, arg, ~0xffff);
7010 rn = "BadInstrX";
7011 break;
7012 default:
7013 goto cp0_unimplemented;
7015 break;
7016 case 9:
7017 switch (sel) {
7018 case 0:
7019 /* Mark as an IO operation because we read the time. */
7020 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7021 gen_io_start();
7023 gen_helper_mfc0_count(arg, cpu_env);
7024 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7025 gen_io_end();
7027 /* Break the TB to be able to take timer interrupts immediately
7028 after reading count. DISAS_STOP isn't sufficient, we need to
7029 ensure we break completely out of translated code. */
7030 gen_save_pc(ctx->base.pc_next + 4);
7031 ctx->base.is_jmp = DISAS_EXIT;
7032 rn = "Count";
7033 break;
7034 /* 6,7 are implementation dependent */
7035 default:
7036 goto cp0_unimplemented;
7038 break;
7039 case 10:
7040 switch (sel) {
7041 case 0:
7042 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7043 rn = "EntryHi";
7044 break;
7045 default:
7046 goto cp0_unimplemented;
7048 break;
7049 case 11:
7050 switch (sel) {
7051 case 0:
7052 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7053 rn = "Compare";
7054 break;
7055 /* 6,7 are implementation dependent */
7056 default:
7057 goto cp0_unimplemented;
7059 break;
7060 case 12:
7061 switch (sel) {
7062 case 0:
7063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7064 rn = "Status";
7065 break;
7066 case 1:
7067 check_insn(ctx, ISA_MIPS32R2);
7068 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7069 rn = "IntCtl";
7070 break;
7071 case 2:
7072 check_insn(ctx, ISA_MIPS32R2);
7073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7074 rn = "SRSCtl";
7075 break;
7076 case 3:
7077 check_insn(ctx, ISA_MIPS32R2);
7078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7079 rn = "SRSMap";
7080 break;
7081 default:
7082 goto cp0_unimplemented;
7084 break;
7085 case 13:
7086 switch (sel) {
7087 case 0:
7088 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7089 rn = "Cause";
7090 break;
7091 default:
7092 goto cp0_unimplemented;
7094 break;
7095 case 14:
7096 switch (sel) {
7097 case 0:
7098 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7099 rn = "EPC";
7100 break;
7101 default:
7102 goto cp0_unimplemented;
7104 break;
7105 case 15:
7106 switch (sel) {
7107 case 0:
7108 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7109 rn = "PRid";
7110 break;
7111 case 1:
7112 check_insn(ctx, ISA_MIPS32R2);
7113 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7114 rn = "EBase";
7115 break;
7116 case 3:
7117 check_insn(ctx, ISA_MIPS32R2);
7118 CP0_CHECK(ctx->cmgcr);
7119 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7120 rn = "CMGCRBase";
7121 break;
7122 default:
7123 goto cp0_unimplemented;
7125 break;
7126 case 16:
7127 switch (sel) {
7128 case 0:
7129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7130 rn = "Config";
7131 break;
7132 case 1:
7133 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7134 rn = "Config1";
7135 break;
7136 case 2:
7137 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7138 rn = "Config2";
7139 break;
7140 case 3:
7141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7142 rn = "Config3";
7143 break;
7144 case 4:
7145 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7146 rn = "Config4";
7147 break;
7148 case 5:
7149 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7150 rn = "Config5";
7151 break;
7152 /* 6,7 are implementation dependent */
7153 case 6:
7154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7155 rn = "Config6";
7156 break;
7157 case 7:
7158 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7159 rn = "Config7";
7160 break;
7161 default:
7162 goto cp0_unimplemented;
7164 break;
7165 case 17:
7166 switch (sel) {
7167 case 0:
7168 gen_helper_dmfc0_lladdr(arg, cpu_env);
7169 rn = "LLAddr";
7170 break;
7171 case 1:
7172 CP0_CHECK(ctx->mrp);
7173 gen_helper_dmfc0_maar(arg, cpu_env);
7174 rn = "MAAR";
7175 break;
7176 case 2:
7177 CP0_CHECK(ctx->mrp);
7178 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7179 rn = "MAARI";
7180 break;
7181 default:
7182 goto cp0_unimplemented;
7184 break;
7185 case 18:
7186 switch (sel) {
7187 case 0:
7188 case 1:
7189 case 2:
7190 case 3:
7191 case 4:
7192 case 5:
7193 case 6:
7194 case 7:
7195 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7196 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7197 rn = "WatchLo";
7198 break;
7199 default:
7200 goto cp0_unimplemented;
7202 break;
7203 case 19:
7204 switch (sel) {
7205 case 0:
7206 case 1:
7207 case 2:
7208 case 3:
7209 case 4:
7210 case 5:
7211 case 6:
7212 case 7:
7213 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7214 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7215 rn = "WatchHi";
7216 break;
7217 default:
7218 goto cp0_unimplemented;
7220 break;
7221 case 20:
7222 switch (sel) {
7223 case 0:
7224 check_insn(ctx, ISA_MIPS3);
7225 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7226 rn = "XContext";
7227 break;
7228 default:
7229 goto cp0_unimplemented;
7231 break;
7232 case 21:
7233 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7234 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7235 switch (sel) {
7236 case 0:
7237 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7238 rn = "Framemask";
7239 break;
7240 default:
7241 goto cp0_unimplemented;
7243 break;
7244 case 22:
7245 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7246 rn = "'Diagnostic"; /* implementation dependent */
7247 break;
7248 case 23:
7249 switch (sel) {
7250 case 0:
7251 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7252 rn = "Debug";
7253 break;
7254 case 1:
7255 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
7256 rn = "TraceControl";
7257 goto cp0_unimplemented;
7258 case 2:
7259 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
7260 rn = "TraceControl2";
7261 goto cp0_unimplemented;
7262 case 3:
7263 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
7264 rn = "UserTraceData";
7265 goto cp0_unimplemented;
7266 case 4:
7267 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
7268 rn = "TraceBPC";
7269 goto cp0_unimplemented;
7270 default:
7271 goto cp0_unimplemented;
7273 break;
7274 case 24:
7275 switch (sel) {
7276 case 0:
7277 /* EJTAG support */
7278 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7279 rn = "DEPC";
7280 break;
7281 default:
7282 goto cp0_unimplemented;
7284 break;
7285 case 25:
7286 switch (sel) {
7287 case 0:
7288 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7289 rn = "Performance0";
7290 break;
7291 case 1:
7292 // gen_helper_dmfc0_performance1(arg);
7293 rn = "Performance1";
7294 goto cp0_unimplemented;
7295 case 2:
7296 // gen_helper_dmfc0_performance2(arg);
7297 rn = "Performance2";
7298 goto cp0_unimplemented;
7299 case 3:
7300 // gen_helper_dmfc0_performance3(arg);
7301 rn = "Performance3";
7302 goto cp0_unimplemented;
7303 case 4:
7304 // gen_helper_dmfc0_performance4(arg);
7305 rn = "Performance4";
7306 goto cp0_unimplemented;
7307 case 5:
7308 // gen_helper_dmfc0_performance5(arg);
7309 rn = "Performance5";
7310 goto cp0_unimplemented;
7311 case 6:
7312 // gen_helper_dmfc0_performance6(arg);
7313 rn = "Performance6";
7314 goto cp0_unimplemented;
7315 case 7:
7316 // gen_helper_dmfc0_performance7(arg);
7317 rn = "Performance7";
7318 goto cp0_unimplemented;
7319 default:
7320 goto cp0_unimplemented;
7322 break;
7323 case 26:
7324 switch (sel) {
7325 case 0:
7326 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7327 rn = "ErrCtl";
7328 break;
7329 default:
7330 goto cp0_unimplemented;
7332 break;
7333 case 27:
7334 switch (sel) {
7335 /* ignored */
7336 case 0:
7337 case 1:
7338 case 2:
7339 case 3:
7340 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7341 rn = "CacheErr";
7342 break;
7343 default:
7344 goto cp0_unimplemented;
7346 break;
7347 case 28:
7348 switch (sel) {
7349 case 0:
7350 case 2:
7351 case 4:
7352 case 6:
7353 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7354 rn = "TagLo";
7355 break;
7356 case 1:
7357 case 3:
7358 case 5:
7359 case 7:
7360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7361 rn = "DataLo";
7362 break;
7363 default:
7364 goto cp0_unimplemented;
7366 break;
7367 case 29:
7368 switch (sel) {
7369 case 0:
7370 case 2:
7371 case 4:
7372 case 6:
7373 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7374 rn = "TagHi";
7375 break;
7376 case 1:
7377 case 3:
7378 case 5:
7379 case 7:
7380 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7381 rn = "DataHi";
7382 break;
7383 default:
7384 goto cp0_unimplemented;
7386 break;
7387 case 30:
7388 switch (sel) {
7389 case 0:
7390 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7391 rn = "ErrorEPC";
7392 break;
7393 default:
7394 goto cp0_unimplemented;
7396 break;
7397 case 31:
7398 switch (sel) {
7399 case 0:
7400 /* EJTAG support */
7401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7402 rn = "DESAVE";
7403 break;
7404 case 2:
7405 case 3:
7406 case 4:
7407 case 5:
7408 case 6:
7409 case 7:
7410 CP0_CHECK(ctx->kscrexist & (1 << sel));
7411 tcg_gen_ld_tl(arg, cpu_env,
7412 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7413 rn = "KScratch";
7414 break;
7415 default:
7416 goto cp0_unimplemented;
7418 break;
7419 default:
7420 goto cp0_unimplemented;
7422 trace_mips_translate_c0("dmfc0", rn, reg, sel);
7423 return;
7425 cp0_unimplemented:
7426 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7427 gen_mfc0_unimplemented(ctx, arg);
7430 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7432 const char *rn = "invalid";
7434 if (sel != 0)
7435 check_insn(ctx, ISA_MIPS64);
7437 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7438 gen_io_start();
7441 switch (reg) {
7442 case 0:
7443 switch (sel) {
7444 case 0:
7445 gen_helper_mtc0_index(cpu_env, arg);
7446 rn = "Index";
7447 break;
7448 case 1:
7449 CP0_CHECK(ctx->insn_flags & ASE_MT);
7450 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7451 rn = "MVPControl";
7452 break;
7453 case 2:
7454 CP0_CHECK(ctx->insn_flags & ASE_MT);
7455 /* ignored */
7456 rn = "MVPConf0";
7457 break;
7458 case 3:
7459 CP0_CHECK(ctx->insn_flags & ASE_MT);
7460 /* ignored */
7461 rn = "MVPConf1";
7462 break;
7463 case 4:
7464 CP0_CHECK(ctx->vp);
7465 /* ignored */
7466 rn = "VPControl";
7467 break;
7468 default:
7469 goto cp0_unimplemented;
7471 break;
7472 case 1:
7473 switch (sel) {
7474 case 0:
7475 /* ignored */
7476 rn = "Random";
7477 break;
7478 case 1:
7479 CP0_CHECK(ctx->insn_flags & ASE_MT);
7480 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7481 rn = "VPEControl";
7482 break;
7483 case 2:
7484 CP0_CHECK(ctx->insn_flags & ASE_MT);
7485 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7486 rn = "VPEConf0";
7487 break;
7488 case 3:
7489 CP0_CHECK(ctx->insn_flags & ASE_MT);
7490 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7491 rn = "VPEConf1";
7492 break;
7493 case 4:
7494 CP0_CHECK(ctx->insn_flags & ASE_MT);
7495 gen_helper_mtc0_yqmask(cpu_env, arg);
7496 rn = "YQMask";
7497 break;
7498 case 5:
7499 CP0_CHECK(ctx->insn_flags & ASE_MT);
7500 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7501 rn = "VPESchedule";
7502 break;
7503 case 6:
7504 CP0_CHECK(ctx->insn_flags & ASE_MT);
7505 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7506 rn = "VPEScheFBack";
7507 break;
7508 case 7:
7509 CP0_CHECK(ctx->insn_flags & ASE_MT);
7510 gen_helper_mtc0_vpeopt(cpu_env, arg);
7511 rn = "VPEOpt";
7512 break;
7513 default:
7514 goto cp0_unimplemented;
7516 break;
7517 case 2:
7518 switch (sel) {
7519 case 0:
7520 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7521 rn = "EntryLo0";
7522 break;
7523 case 1:
7524 CP0_CHECK(ctx->insn_flags & ASE_MT);
7525 gen_helper_mtc0_tcstatus(cpu_env, arg);
7526 rn = "TCStatus";
7527 break;
7528 case 2:
7529 CP0_CHECK(ctx->insn_flags & ASE_MT);
7530 gen_helper_mtc0_tcbind(cpu_env, arg);
7531 rn = "TCBind";
7532 break;
7533 case 3:
7534 CP0_CHECK(ctx->insn_flags & ASE_MT);
7535 gen_helper_mtc0_tcrestart(cpu_env, arg);
7536 rn = "TCRestart";
7537 break;
7538 case 4:
7539 CP0_CHECK(ctx->insn_flags & ASE_MT);
7540 gen_helper_mtc0_tchalt(cpu_env, arg);
7541 rn = "TCHalt";
7542 break;
7543 case 5:
7544 CP0_CHECK(ctx->insn_flags & ASE_MT);
7545 gen_helper_mtc0_tccontext(cpu_env, arg);
7546 rn = "TCContext";
7547 break;
7548 case 6:
7549 CP0_CHECK(ctx->insn_flags & ASE_MT);
7550 gen_helper_mtc0_tcschedule(cpu_env, arg);
7551 rn = "TCSchedule";
7552 break;
7553 case 7:
7554 CP0_CHECK(ctx->insn_flags & ASE_MT);
7555 gen_helper_mtc0_tcschefback(cpu_env, arg);
7556 rn = "TCScheFBack";
7557 break;
7558 default:
7559 goto cp0_unimplemented;
7561 break;
7562 case 3:
7563 switch (sel) {
7564 case 0:
7565 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7566 rn = "EntryLo1";
7567 break;
7568 case 1:
7569 CP0_CHECK(ctx->vp);
7570 /* ignored */
7571 rn = "GlobalNumber";
7572 break;
7573 default:
7574 goto cp0_unimplemented;
7576 break;
7577 case 4:
7578 switch (sel) {
7579 case 0:
7580 gen_helper_mtc0_context(cpu_env, arg);
7581 rn = "Context";
7582 break;
7583 case 1:
7584 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7585 rn = "ContextConfig";
7586 goto cp0_unimplemented;
7587 case 2:
7588 CP0_CHECK(ctx->ulri);
7589 tcg_gen_st_tl(arg, cpu_env,
7590 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7591 rn = "UserLocal";
7592 break;
7593 default:
7594 goto cp0_unimplemented;
7596 break;
7597 case 5:
7598 switch (sel) {
7599 case 0:
7600 gen_helper_mtc0_pagemask(cpu_env, arg);
7601 rn = "PageMask";
7602 break;
7603 case 1:
7604 check_insn(ctx, ISA_MIPS32R2);
7605 gen_helper_mtc0_pagegrain(cpu_env, arg);
7606 rn = "PageGrain";
7607 break;
7608 case 2:
7609 CP0_CHECK(ctx->sc);
7610 gen_helper_mtc0_segctl0(cpu_env, arg);
7611 rn = "SegCtl0";
7612 break;
7613 case 3:
7614 CP0_CHECK(ctx->sc);
7615 gen_helper_mtc0_segctl1(cpu_env, arg);
7616 rn = "SegCtl1";
7617 break;
7618 case 4:
7619 CP0_CHECK(ctx->sc);
7620 gen_helper_mtc0_segctl2(cpu_env, arg);
7621 rn = "SegCtl2";
7622 break;
7623 default:
7624 goto cp0_unimplemented;
7626 break;
7627 case 6:
7628 switch (sel) {
7629 case 0:
7630 gen_helper_mtc0_wired(cpu_env, arg);
7631 rn = "Wired";
7632 break;
7633 case 1:
7634 check_insn(ctx, ISA_MIPS32R2);
7635 gen_helper_mtc0_srsconf0(cpu_env, arg);
7636 rn = "SRSConf0";
7637 break;
7638 case 2:
7639 check_insn(ctx, ISA_MIPS32R2);
7640 gen_helper_mtc0_srsconf1(cpu_env, arg);
7641 rn = "SRSConf1";
7642 break;
7643 case 3:
7644 check_insn(ctx, ISA_MIPS32R2);
7645 gen_helper_mtc0_srsconf2(cpu_env, arg);
7646 rn = "SRSConf2";
7647 break;
7648 case 4:
7649 check_insn(ctx, ISA_MIPS32R2);
7650 gen_helper_mtc0_srsconf3(cpu_env, arg);
7651 rn = "SRSConf3";
7652 break;
7653 case 5:
7654 check_insn(ctx, ISA_MIPS32R2);
7655 gen_helper_mtc0_srsconf4(cpu_env, arg);
7656 rn = "SRSConf4";
7657 break;
7658 default:
7659 goto cp0_unimplemented;
7661 break;
7662 case 7:
7663 switch (sel) {
7664 case 0:
7665 check_insn(ctx, ISA_MIPS32R2);
7666 gen_helper_mtc0_hwrena(cpu_env, arg);
7667 ctx->base.is_jmp = DISAS_STOP;
7668 rn = "HWREna";
7669 break;
7670 default:
7671 goto cp0_unimplemented;
7673 break;
7674 case 8:
7675 switch (sel) {
7676 case 0:
7677 /* ignored */
7678 rn = "BadVAddr";
7679 break;
7680 case 1:
7681 /* ignored */
7682 rn = "BadInstr";
7683 break;
7684 case 2:
7685 /* ignored */
7686 rn = "BadInstrP";
7687 break;
7688 case 3:
7689 /* ignored */
7690 rn = "BadInstrX";
7691 break;
7692 default:
7693 goto cp0_unimplemented;
7695 break;
7696 case 9:
7697 switch (sel) {
7698 case 0:
7699 gen_helper_mtc0_count(cpu_env, arg);
7700 rn = "Count";
7701 break;
7702 /* 6,7 are implementation dependent */
7703 default:
7704 goto cp0_unimplemented;
7706 /* Stop translation as we may have switched the execution mode */
7707 ctx->base.is_jmp = DISAS_STOP;
7708 break;
7709 case 10:
7710 switch (sel) {
7711 case 0:
7712 gen_helper_mtc0_entryhi(cpu_env, arg);
7713 rn = "EntryHi";
7714 break;
7715 default:
7716 goto cp0_unimplemented;
7718 break;
7719 case 11:
7720 switch (sel) {
7721 case 0:
7722 gen_helper_mtc0_compare(cpu_env, arg);
7723 rn = "Compare";
7724 break;
7725 /* 6,7 are implementation dependent */
7726 default:
7727 goto cp0_unimplemented;
7729 /* Stop translation as we may have switched the execution mode */
7730 ctx->base.is_jmp = DISAS_STOP;
7731 break;
7732 case 12:
7733 switch (sel) {
7734 case 0:
7735 save_cpu_state(ctx, 1);
7736 gen_helper_mtc0_status(cpu_env, arg);
7737 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7738 gen_save_pc(ctx->base.pc_next + 4);
7739 ctx->base.is_jmp = DISAS_EXIT;
7740 rn = "Status";
7741 break;
7742 case 1:
7743 check_insn(ctx, ISA_MIPS32R2);
7744 gen_helper_mtc0_intctl(cpu_env, arg);
7745 /* Stop translation as we may have switched the execution mode */
7746 ctx->base.is_jmp = DISAS_STOP;
7747 rn = "IntCtl";
7748 break;
7749 case 2:
7750 check_insn(ctx, ISA_MIPS32R2);
7751 gen_helper_mtc0_srsctl(cpu_env, arg);
7752 /* Stop translation as we may have switched the execution mode */
7753 ctx->base.is_jmp = DISAS_STOP;
7754 rn = "SRSCtl";
7755 break;
7756 case 3:
7757 check_insn(ctx, ISA_MIPS32R2);
7758 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7759 /* Stop translation as we may have switched the execution mode */
7760 ctx->base.is_jmp = DISAS_STOP;
7761 rn = "SRSMap";
7762 break;
7763 default:
7764 goto cp0_unimplemented;
7766 break;
7767 case 13:
7768 switch (sel) {
7769 case 0:
7770 save_cpu_state(ctx, 1);
7771 gen_helper_mtc0_cause(cpu_env, arg);
7772 /* Stop translation as we may have triggered an interrupt.
7773 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7774 * translated code to check for pending interrupts. */
7775 gen_save_pc(ctx->base.pc_next + 4);
7776 ctx->base.is_jmp = DISAS_EXIT;
7777 rn = "Cause";
7778 break;
7779 default:
7780 goto cp0_unimplemented;
7782 break;
7783 case 14:
7784 switch (sel) {
7785 case 0:
7786 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7787 rn = "EPC";
7788 break;
7789 default:
7790 goto cp0_unimplemented;
7792 break;
7793 case 15:
7794 switch (sel) {
7795 case 0:
7796 /* ignored */
7797 rn = "PRid";
7798 break;
7799 case 1:
7800 check_insn(ctx, ISA_MIPS32R2);
7801 gen_helper_mtc0_ebase(cpu_env, arg);
7802 rn = "EBase";
7803 break;
7804 default:
7805 goto cp0_unimplemented;
7807 break;
7808 case 16:
7809 switch (sel) {
7810 case 0:
7811 gen_helper_mtc0_config0(cpu_env, arg);
7812 rn = "Config";
7813 /* Stop translation as we may have switched the execution mode */
7814 ctx->base.is_jmp = DISAS_STOP;
7815 break;
7816 case 1:
7817 /* ignored, read only */
7818 rn = "Config1";
7819 break;
7820 case 2:
7821 gen_helper_mtc0_config2(cpu_env, arg);
7822 rn = "Config2";
7823 /* Stop translation as we may have switched the execution mode */
7824 ctx->base.is_jmp = DISAS_STOP;
7825 break;
7826 case 3:
7827 gen_helper_mtc0_config3(cpu_env, arg);
7828 rn = "Config3";
7829 /* Stop translation as we may have switched the execution mode */
7830 ctx->base.is_jmp = DISAS_STOP;
7831 break;
7832 case 4:
7833 /* currently ignored */
7834 rn = "Config4";
7835 break;
7836 case 5:
7837 gen_helper_mtc0_config5(cpu_env, arg);
7838 rn = "Config5";
7839 /* Stop translation as we may have switched the execution mode */
7840 ctx->base.is_jmp = DISAS_STOP;
7841 break;
7842 /* 6,7 are implementation dependent */
7843 default:
7844 rn = "Invalid config selector";
7845 goto cp0_unimplemented;
7847 break;
7848 case 17:
7849 switch (sel) {
7850 case 0:
7851 gen_helper_mtc0_lladdr(cpu_env, arg);
7852 rn = "LLAddr";
7853 break;
7854 case 1:
7855 CP0_CHECK(ctx->mrp);
7856 gen_helper_mtc0_maar(cpu_env, arg);
7857 rn = "MAAR";
7858 break;
7859 case 2:
7860 CP0_CHECK(ctx->mrp);
7861 gen_helper_mtc0_maari(cpu_env, arg);
7862 rn = "MAARI";
7863 break;
7864 default:
7865 goto cp0_unimplemented;
7867 break;
7868 case 18:
7869 switch (sel) {
7870 case 0:
7871 case 1:
7872 case 2:
7873 case 3:
7874 case 4:
7875 case 5:
7876 case 6:
7877 case 7:
7878 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7879 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7880 rn = "WatchLo";
7881 break;
7882 default:
7883 goto cp0_unimplemented;
7885 break;
7886 case 19:
7887 switch (sel) {
7888 case 0:
7889 case 1:
7890 case 2:
7891 case 3:
7892 case 4:
7893 case 5:
7894 case 6:
7895 case 7:
7896 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7897 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7898 rn = "WatchHi";
7899 break;
7900 default:
7901 goto cp0_unimplemented;
7903 break;
7904 case 20:
7905 switch (sel) {
7906 case 0:
7907 check_insn(ctx, ISA_MIPS3);
7908 gen_helper_mtc0_xcontext(cpu_env, arg);
7909 rn = "XContext";
7910 break;
7911 default:
7912 goto cp0_unimplemented;
7914 break;
7915 case 21:
7916 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7917 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7918 switch (sel) {
7919 case 0:
7920 gen_helper_mtc0_framemask(cpu_env, arg);
7921 rn = "Framemask";
7922 break;
7923 default:
7924 goto cp0_unimplemented;
7926 break;
7927 case 22:
7928 /* ignored */
7929 rn = "Diagnostic"; /* implementation dependent */
7930 break;
7931 case 23:
7932 switch (sel) {
7933 case 0:
7934 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7935 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7936 gen_save_pc(ctx->base.pc_next + 4);
7937 ctx->base.is_jmp = DISAS_EXIT;
7938 rn = "Debug";
7939 break;
7940 case 1:
7941 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7942 /* Stop translation as we may have switched the execution mode */
7943 ctx->base.is_jmp = DISAS_STOP;
7944 rn = "TraceControl";
7945 goto cp0_unimplemented;
7946 case 2:
7947 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7948 /* Stop translation as we may have switched the execution mode */
7949 ctx->base.is_jmp = DISAS_STOP;
7950 rn = "TraceControl2";
7951 goto cp0_unimplemented;
7952 case 3:
7953 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7954 /* Stop translation as we may have switched the execution mode */
7955 ctx->base.is_jmp = DISAS_STOP;
7956 rn = "UserTraceData";
7957 goto cp0_unimplemented;
7958 case 4:
7959 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7960 /* Stop translation as we may have switched the execution mode */
7961 ctx->base.is_jmp = DISAS_STOP;
7962 rn = "TraceBPC";
7963 goto cp0_unimplemented;
7964 default:
7965 goto cp0_unimplemented;
7967 break;
7968 case 24:
7969 switch (sel) {
7970 case 0:
7971 /* EJTAG support */
7972 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7973 rn = "DEPC";
7974 break;
7975 default:
7976 goto cp0_unimplemented;
7978 break;
7979 case 25:
7980 switch (sel) {
7981 case 0:
7982 gen_helper_mtc0_performance0(cpu_env, arg);
7983 rn = "Performance0";
7984 break;
7985 case 1:
7986 // gen_helper_mtc0_performance1(cpu_env, arg);
7987 rn = "Performance1";
7988 goto cp0_unimplemented;
7989 case 2:
7990 // gen_helper_mtc0_performance2(cpu_env, arg);
7991 rn = "Performance2";
7992 goto cp0_unimplemented;
7993 case 3:
7994 // gen_helper_mtc0_performance3(cpu_env, arg);
7995 rn = "Performance3";
7996 goto cp0_unimplemented;
7997 case 4:
7998 // gen_helper_mtc0_performance4(cpu_env, arg);
7999 rn = "Performance4";
8000 goto cp0_unimplemented;
8001 case 5:
8002 // gen_helper_mtc0_performance5(cpu_env, arg);
8003 rn = "Performance5";
8004 goto cp0_unimplemented;
8005 case 6:
8006 // gen_helper_mtc0_performance6(cpu_env, arg);
8007 rn = "Performance6";
8008 goto cp0_unimplemented;
8009 case 7:
8010 // gen_helper_mtc0_performance7(cpu_env, arg);
8011 rn = "Performance7";
8012 goto cp0_unimplemented;
8013 default:
8014 goto cp0_unimplemented;
8016 break;
8017 case 26:
8018 switch (sel) {
8019 case 0:
8020 gen_helper_mtc0_errctl(cpu_env, arg);
8021 ctx->base.is_jmp = DISAS_STOP;
8022 rn = "ErrCtl";
8023 break;
8024 default:
8025 goto cp0_unimplemented;
8027 break;
8028 case 27:
8029 switch (sel) {
8030 case 0:
8031 case 1:
8032 case 2:
8033 case 3:
8034 /* ignored */
8035 rn = "CacheErr";
8036 break;
8037 default:
8038 goto cp0_unimplemented;
8040 break;
8041 case 28:
8042 switch (sel) {
8043 case 0:
8044 case 2:
8045 case 4:
8046 case 6:
8047 gen_helper_mtc0_taglo(cpu_env, arg);
8048 rn = "TagLo";
8049 break;
8050 case 1:
8051 case 3:
8052 case 5:
8053 case 7:
8054 gen_helper_mtc0_datalo(cpu_env, arg);
8055 rn = "DataLo";
8056 break;
8057 default:
8058 goto cp0_unimplemented;
8060 break;
8061 case 29:
8062 switch (sel) {
8063 case 0:
8064 case 2:
8065 case 4:
8066 case 6:
8067 gen_helper_mtc0_taghi(cpu_env, arg);
8068 rn = "TagHi";
8069 break;
8070 case 1:
8071 case 3:
8072 case 5:
8073 case 7:
8074 gen_helper_mtc0_datahi(cpu_env, arg);
8075 rn = "DataHi";
8076 break;
8077 default:
8078 rn = "invalid sel";
8079 goto cp0_unimplemented;
8081 break;
8082 case 30:
8083 switch (sel) {
8084 case 0:
8085 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8086 rn = "ErrorEPC";
8087 break;
8088 default:
8089 goto cp0_unimplemented;
8091 break;
8092 case 31:
8093 switch (sel) {
8094 case 0:
8095 /* EJTAG support */
8096 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8097 rn = "DESAVE";
8098 break;
8099 case 2:
8100 case 3:
8101 case 4:
8102 case 5:
8103 case 6:
8104 case 7:
8105 CP0_CHECK(ctx->kscrexist & (1 << sel));
8106 tcg_gen_st_tl(arg, cpu_env,
8107 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8108 rn = "KScratch";
8109 break;
8110 default:
8111 goto cp0_unimplemented;
8113 break;
8114 default:
8115 goto cp0_unimplemented;
8117 trace_mips_translate_c0("dmtc0", rn, reg, sel);
8119 /* For simplicity assume that all writes can cause interrupts. */
8120 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8121 gen_io_end();
8122 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8123 * translated code to check for pending interrupts. */
8124 gen_save_pc(ctx->base.pc_next + 4);
8125 ctx->base.is_jmp = DISAS_EXIT;
8127 return;
8129 cp0_unimplemented:
8130 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8132 #endif /* TARGET_MIPS64 */
8134 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8135 int u, int sel, int h)
8137 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8138 TCGv t0 = tcg_temp_local_new();
8140 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8141 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8142 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
8143 tcg_gen_movi_tl(t0, -1);
8144 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8145 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
8146 tcg_gen_movi_tl(t0, -1);
8147 else if (u == 0) {
8148 switch (rt) {
8149 case 1:
8150 switch (sel) {
8151 case 1:
8152 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8153 break;
8154 case 2:
8155 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8156 break;
8157 default:
8158 goto die;
8159 break;
8161 break;
8162 case 2:
8163 switch (sel) {
8164 case 1:
8165 gen_helper_mftc0_tcstatus(t0, cpu_env);
8166 break;
8167 case 2:
8168 gen_helper_mftc0_tcbind(t0, cpu_env);
8169 break;
8170 case 3:
8171 gen_helper_mftc0_tcrestart(t0, cpu_env);
8172 break;
8173 case 4:
8174 gen_helper_mftc0_tchalt(t0, cpu_env);
8175 break;
8176 case 5:
8177 gen_helper_mftc0_tccontext(t0, cpu_env);
8178 break;
8179 case 6:
8180 gen_helper_mftc0_tcschedule(t0, cpu_env);
8181 break;
8182 case 7:
8183 gen_helper_mftc0_tcschefback(t0, cpu_env);
8184 break;
8185 default:
8186 gen_mfc0(ctx, t0, rt, sel);
8187 break;
8189 break;
8190 case 10:
8191 switch (sel) {
8192 case 0:
8193 gen_helper_mftc0_entryhi(t0, cpu_env);
8194 break;
8195 default:
8196 gen_mfc0(ctx, t0, rt, sel);
8197 break;
8199 case 12:
8200 switch (sel) {
8201 case 0:
8202 gen_helper_mftc0_status(t0, cpu_env);
8203 break;
8204 default:
8205 gen_mfc0(ctx, t0, rt, sel);
8206 break;
8208 case 13:
8209 switch (sel) {
8210 case 0:
8211 gen_helper_mftc0_cause(t0, cpu_env);
8212 break;
8213 default:
8214 goto die;
8215 break;
8217 break;
8218 case 14:
8219 switch (sel) {
8220 case 0:
8221 gen_helper_mftc0_epc(t0, cpu_env);
8222 break;
8223 default:
8224 goto die;
8225 break;
8227 break;
8228 case 15:
8229 switch (sel) {
8230 case 1:
8231 gen_helper_mftc0_ebase(t0, cpu_env);
8232 break;
8233 default:
8234 goto die;
8235 break;
8237 break;
8238 case 16:
8239 switch (sel) {
8240 case 0:
8241 case 1:
8242 case 2:
8243 case 3:
8244 case 4:
8245 case 5:
8246 case 6:
8247 case 7:
8248 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
8249 break;
8250 default:
8251 goto die;
8252 break;
8254 break;
8255 case 23:
8256 switch (sel) {
8257 case 0:
8258 gen_helper_mftc0_debug(t0, cpu_env);
8259 break;
8260 default:
8261 gen_mfc0(ctx, t0, rt, sel);
8262 break;
8264 break;
8265 default:
8266 gen_mfc0(ctx, t0, rt, sel);
8268 } else switch (sel) {
8269 /* GPR registers. */
8270 case 0:
8271 gen_helper_1e0i(mftgpr, t0, rt);
8272 break;
8273 /* Auxiliary CPU registers */
8274 case 1:
8275 switch (rt) {
8276 case 0:
8277 gen_helper_1e0i(mftlo, t0, 0);
8278 break;
8279 case 1:
8280 gen_helper_1e0i(mfthi, t0, 0);
8281 break;
8282 case 2:
8283 gen_helper_1e0i(mftacx, t0, 0);
8284 break;
8285 case 4:
8286 gen_helper_1e0i(mftlo, t0, 1);
8287 break;
8288 case 5:
8289 gen_helper_1e0i(mfthi, t0, 1);
8290 break;
8291 case 6:
8292 gen_helper_1e0i(mftacx, t0, 1);
8293 break;
8294 case 8:
8295 gen_helper_1e0i(mftlo, t0, 2);
8296 break;
8297 case 9:
8298 gen_helper_1e0i(mfthi, t0, 2);
8299 break;
8300 case 10:
8301 gen_helper_1e0i(mftacx, t0, 2);
8302 break;
8303 case 12:
8304 gen_helper_1e0i(mftlo, t0, 3);
8305 break;
8306 case 13:
8307 gen_helper_1e0i(mfthi, t0, 3);
8308 break;
8309 case 14:
8310 gen_helper_1e0i(mftacx, t0, 3);
8311 break;
8312 case 16:
8313 gen_helper_mftdsp(t0, cpu_env);
8314 break;
8315 default:
8316 goto die;
8318 break;
8319 /* Floating point (COP1). */
8320 case 2:
8321 /* XXX: For now we support only a single FPU context. */
8322 if (h == 0) {
8323 TCGv_i32 fp0 = tcg_temp_new_i32();
8325 gen_load_fpr32(ctx, fp0, rt);
8326 tcg_gen_ext_i32_tl(t0, fp0);
8327 tcg_temp_free_i32(fp0);
8328 } else {
8329 TCGv_i32 fp0 = tcg_temp_new_i32();
8331 gen_load_fpr32h(ctx, fp0, rt);
8332 tcg_gen_ext_i32_tl(t0, fp0);
8333 tcg_temp_free_i32(fp0);
8335 break;
8336 case 3:
8337 /* XXX: For now we support only a single FPU context. */
8338 gen_helper_1e0i(cfc1, t0, rt);
8339 break;
8340 /* COP2: Not implemented. */
8341 case 4:
8342 case 5:
8343 /* fall through */
8344 default:
8345 goto die;
8347 trace_mips_translate_tr("mftr", rt, u, sel, h);
8348 gen_store_gpr(t0, rd);
8349 tcg_temp_free(t0);
8350 return;
8352 die:
8353 tcg_temp_free(t0);
8354 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
8355 generate_exception_end(ctx, EXCP_RI);
8358 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
8359 int u, int sel, int h)
8361 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8362 TCGv t0 = tcg_temp_local_new();
8364 gen_load_gpr(t0, rt);
8365 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8366 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8367 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
8368 /* NOP */ ;
8369 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8370 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
8371 /* NOP */ ;
8372 else if (u == 0) {
8373 switch (rd) {
8374 case 1:
8375 switch (sel) {
8376 case 1:
8377 gen_helper_mttc0_vpecontrol(cpu_env, t0);
8378 break;
8379 case 2:
8380 gen_helper_mttc0_vpeconf0(cpu_env, t0);
8381 break;
8382 default:
8383 goto die;
8384 break;
8386 break;
8387 case 2:
8388 switch (sel) {
8389 case 1:
8390 gen_helper_mttc0_tcstatus(cpu_env, t0);
8391 break;
8392 case 2:
8393 gen_helper_mttc0_tcbind(cpu_env, t0);
8394 break;
8395 case 3:
8396 gen_helper_mttc0_tcrestart(cpu_env, t0);
8397 break;
8398 case 4:
8399 gen_helper_mttc0_tchalt(cpu_env, t0);
8400 break;
8401 case 5:
8402 gen_helper_mttc0_tccontext(cpu_env, t0);
8403 break;
8404 case 6:
8405 gen_helper_mttc0_tcschedule(cpu_env, t0);
8406 break;
8407 case 7:
8408 gen_helper_mttc0_tcschefback(cpu_env, t0);
8409 break;
8410 default:
8411 gen_mtc0(ctx, t0, rd, sel);
8412 break;
8414 break;
8415 case 10:
8416 switch (sel) {
8417 case 0:
8418 gen_helper_mttc0_entryhi(cpu_env, t0);
8419 break;
8420 default:
8421 gen_mtc0(ctx, t0, rd, sel);
8422 break;
8424 case 12:
8425 switch (sel) {
8426 case 0:
8427 gen_helper_mttc0_status(cpu_env, t0);
8428 break;
8429 default:
8430 gen_mtc0(ctx, t0, rd, sel);
8431 break;
8433 case 13:
8434 switch (sel) {
8435 case 0:
8436 gen_helper_mttc0_cause(cpu_env, t0);
8437 break;
8438 default:
8439 goto die;
8440 break;
8442 break;
8443 case 15:
8444 switch (sel) {
8445 case 1:
8446 gen_helper_mttc0_ebase(cpu_env, t0);
8447 break;
8448 default:
8449 goto die;
8450 break;
8452 break;
8453 case 23:
8454 switch (sel) {
8455 case 0:
8456 gen_helper_mttc0_debug(cpu_env, t0);
8457 break;
8458 default:
8459 gen_mtc0(ctx, t0, rd, sel);
8460 break;
8462 break;
8463 default:
8464 gen_mtc0(ctx, t0, rd, sel);
8466 } else switch (sel) {
8467 /* GPR registers. */
8468 case 0:
8469 gen_helper_0e1i(mttgpr, t0, rd);
8470 break;
8471 /* Auxiliary CPU registers */
8472 case 1:
8473 switch (rd) {
8474 case 0:
8475 gen_helper_0e1i(mttlo, t0, 0);
8476 break;
8477 case 1:
8478 gen_helper_0e1i(mtthi, t0, 0);
8479 break;
8480 case 2:
8481 gen_helper_0e1i(mttacx, t0, 0);
8482 break;
8483 case 4:
8484 gen_helper_0e1i(mttlo, t0, 1);
8485 break;
8486 case 5:
8487 gen_helper_0e1i(mtthi, t0, 1);
8488 break;
8489 case 6:
8490 gen_helper_0e1i(mttacx, t0, 1);
8491 break;
8492 case 8:
8493 gen_helper_0e1i(mttlo, t0, 2);
8494 break;
8495 case 9:
8496 gen_helper_0e1i(mtthi, t0, 2);
8497 break;
8498 case 10:
8499 gen_helper_0e1i(mttacx, t0, 2);
8500 break;
8501 case 12:
8502 gen_helper_0e1i(mttlo, t0, 3);
8503 break;
8504 case 13:
8505 gen_helper_0e1i(mtthi, t0, 3);
8506 break;
8507 case 14:
8508 gen_helper_0e1i(mttacx, t0, 3);
8509 break;
8510 case 16:
8511 gen_helper_mttdsp(cpu_env, t0);
8512 break;
8513 default:
8514 goto die;
8516 break;
8517 /* Floating point (COP1). */
8518 case 2:
8519 /* XXX: For now we support only a single FPU context. */
8520 if (h == 0) {
8521 TCGv_i32 fp0 = tcg_temp_new_i32();
8523 tcg_gen_trunc_tl_i32(fp0, t0);
8524 gen_store_fpr32(ctx, fp0, rd);
8525 tcg_temp_free_i32(fp0);
8526 } else {
8527 TCGv_i32 fp0 = tcg_temp_new_i32();
8529 tcg_gen_trunc_tl_i32(fp0, t0);
8530 gen_store_fpr32h(ctx, fp0, rd);
8531 tcg_temp_free_i32(fp0);
8533 break;
8534 case 3:
8535 /* XXX: For now we support only a single FPU context. */
8537 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8539 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8540 tcg_temp_free_i32(fs_tmp);
8542 /* Stop translation as we may have changed hflags */
8543 ctx->base.is_jmp = DISAS_STOP;
8544 break;
8545 /* COP2: Not implemented. */
8546 case 4:
8547 case 5:
8548 /* fall through */
8549 default:
8550 goto die;
8552 trace_mips_translate_tr("mttr", rd, u, sel, h);
8553 tcg_temp_free(t0);
8554 return;
8556 die:
8557 tcg_temp_free(t0);
8558 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8559 generate_exception_end(ctx, EXCP_RI);
8562 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8564 const char *opn = "ldst";
8566 check_cp0_enabled(ctx);
8567 switch (opc) {
8568 case OPC_MFC0:
8569 if (rt == 0) {
8570 /* Treat as NOP. */
8571 return;
8573 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8574 opn = "mfc0";
8575 break;
8576 case OPC_MTC0:
8578 TCGv t0 = tcg_temp_new();
8580 gen_load_gpr(t0, rt);
8581 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8582 tcg_temp_free(t0);
8584 opn = "mtc0";
8585 break;
8586 #if defined(TARGET_MIPS64)
8587 case OPC_DMFC0:
8588 check_insn(ctx, ISA_MIPS3);
8589 if (rt == 0) {
8590 /* Treat as NOP. */
8591 return;
8593 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8594 opn = "dmfc0";
8595 break;
8596 case OPC_DMTC0:
8597 check_insn(ctx, ISA_MIPS3);
8599 TCGv t0 = tcg_temp_new();
8601 gen_load_gpr(t0, rt);
8602 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8603 tcg_temp_free(t0);
8605 opn = "dmtc0";
8606 break;
8607 #endif
8608 case OPC_MFHC0:
8609 check_mvh(ctx);
8610 if (rt == 0) {
8611 /* Treat as NOP. */
8612 return;
8614 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8615 opn = "mfhc0";
8616 break;
8617 case OPC_MTHC0:
8618 check_mvh(ctx);
8620 TCGv t0 = tcg_temp_new();
8621 gen_load_gpr(t0, rt);
8622 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8623 tcg_temp_free(t0);
8625 opn = "mthc0";
8626 break;
8627 case OPC_MFTR:
8628 check_cp0_enabled(ctx);
8629 if (rd == 0) {
8630 /* Treat as NOP. */
8631 return;
8633 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8634 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8635 opn = "mftr";
8636 break;
8637 case OPC_MTTR:
8638 check_cp0_enabled(ctx);
8639 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8640 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8641 opn = "mttr";
8642 break;
8643 case OPC_TLBWI:
8644 opn = "tlbwi";
8645 if (!env->tlb->helper_tlbwi)
8646 goto die;
8647 gen_helper_tlbwi(cpu_env);
8648 break;
8649 case OPC_TLBINV:
8650 opn = "tlbinv";
8651 if (ctx->ie >= 2) {
8652 if (!env->tlb->helper_tlbinv) {
8653 goto die;
8655 gen_helper_tlbinv(cpu_env);
8656 } /* treat as nop if TLBINV not supported */
8657 break;
8658 case OPC_TLBINVF:
8659 opn = "tlbinvf";
8660 if (ctx->ie >= 2) {
8661 if (!env->tlb->helper_tlbinvf) {
8662 goto die;
8664 gen_helper_tlbinvf(cpu_env);
8665 } /* treat as nop if TLBINV not supported */
8666 break;
8667 case OPC_TLBWR:
8668 opn = "tlbwr";
8669 if (!env->tlb->helper_tlbwr)
8670 goto die;
8671 gen_helper_tlbwr(cpu_env);
8672 break;
8673 case OPC_TLBP:
8674 opn = "tlbp";
8675 if (!env->tlb->helper_tlbp)
8676 goto die;
8677 gen_helper_tlbp(cpu_env);
8678 break;
8679 case OPC_TLBR:
8680 opn = "tlbr";
8681 if (!env->tlb->helper_tlbr)
8682 goto die;
8683 gen_helper_tlbr(cpu_env);
8684 break;
8685 case OPC_ERET: /* OPC_ERETNC */
8686 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8687 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8688 goto die;
8689 } else {
8690 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8691 if (ctx->opcode & (1 << bit_shift)) {
8692 /* OPC_ERETNC */
8693 opn = "eretnc";
8694 check_insn(ctx, ISA_MIPS32R5);
8695 gen_helper_eretnc(cpu_env);
8696 } else {
8697 /* OPC_ERET */
8698 opn = "eret";
8699 check_insn(ctx, ISA_MIPS2);
8700 gen_helper_eret(cpu_env);
8702 ctx->base.is_jmp = DISAS_EXIT;
8704 break;
8705 case OPC_DERET:
8706 opn = "deret";
8707 check_insn(ctx, ISA_MIPS32);
8708 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8709 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8710 goto die;
8712 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8713 MIPS_INVAL(opn);
8714 generate_exception_end(ctx, EXCP_RI);
8715 } else {
8716 gen_helper_deret(cpu_env);
8717 ctx->base.is_jmp = DISAS_EXIT;
8719 break;
8720 case OPC_WAIT:
8721 opn = "wait";
8722 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8723 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8724 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8725 goto die;
8727 /* If we get an exception, we want to restart at next instruction */
8728 ctx->base.pc_next += 4;
8729 save_cpu_state(ctx, 1);
8730 ctx->base.pc_next -= 4;
8731 gen_helper_wait(cpu_env);
8732 ctx->base.is_jmp = DISAS_NORETURN;
8733 break;
8734 default:
8735 die:
8736 MIPS_INVAL(opn);
8737 generate_exception_end(ctx, EXCP_RI);
8738 return;
8740 (void)opn; /* avoid a compiler warning */
8742 #endif /* !CONFIG_USER_ONLY */
8744 /* CP1 Branches (before delay slot) */
8745 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8746 int32_t cc, int32_t offset)
8748 target_ulong btarget;
8749 TCGv_i32 t0 = tcg_temp_new_i32();
8751 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8752 generate_exception_end(ctx, EXCP_RI);
8753 goto out;
8756 if (cc != 0)
8757 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8759 btarget = ctx->base.pc_next + 4 + offset;
8761 switch (op) {
8762 case OPC_BC1F:
8763 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8764 tcg_gen_not_i32(t0, t0);
8765 tcg_gen_andi_i32(t0, t0, 1);
8766 tcg_gen_extu_i32_tl(bcond, t0);
8767 goto not_likely;
8768 case OPC_BC1FL:
8769 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8770 tcg_gen_not_i32(t0, t0);
8771 tcg_gen_andi_i32(t0, t0, 1);
8772 tcg_gen_extu_i32_tl(bcond, t0);
8773 goto likely;
8774 case OPC_BC1T:
8775 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8776 tcg_gen_andi_i32(t0, t0, 1);
8777 tcg_gen_extu_i32_tl(bcond, t0);
8778 goto not_likely;
8779 case OPC_BC1TL:
8780 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8781 tcg_gen_andi_i32(t0, t0, 1);
8782 tcg_gen_extu_i32_tl(bcond, t0);
8783 likely:
8784 ctx->hflags |= MIPS_HFLAG_BL;
8785 break;
8786 case OPC_BC1FANY2:
8788 TCGv_i32 t1 = tcg_temp_new_i32();
8789 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8790 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8791 tcg_gen_nand_i32(t0, t0, t1);
8792 tcg_temp_free_i32(t1);
8793 tcg_gen_andi_i32(t0, t0, 1);
8794 tcg_gen_extu_i32_tl(bcond, t0);
8796 goto not_likely;
8797 case OPC_BC1TANY2:
8799 TCGv_i32 t1 = tcg_temp_new_i32();
8800 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8801 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8802 tcg_gen_or_i32(t0, t0, t1);
8803 tcg_temp_free_i32(t1);
8804 tcg_gen_andi_i32(t0, t0, 1);
8805 tcg_gen_extu_i32_tl(bcond, t0);
8807 goto not_likely;
8808 case OPC_BC1FANY4:
8810 TCGv_i32 t1 = tcg_temp_new_i32();
8811 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8812 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8813 tcg_gen_and_i32(t0, t0, t1);
8814 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8815 tcg_gen_and_i32(t0, t0, t1);
8816 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8817 tcg_gen_nand_i32(t0, t0, t1);
8818 tcg_temp_free_i32(t1);
8819 tcg_gen_andi_i32(t0, t0, 1);
8820 tcg_gen_extu_i32_tl(bcond, t0);
8822 goto not_likely;
8823 case OPC_BC1TANY4:
8825 TCGv_i32 t1 = tcg_temp_new_i32();
8826 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8827 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8828 tcg_gen_or_i32(t0, t0, t1);
8829 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8830 tcg_gen_or_i32(t0, t0, t1);
8831 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8832 tcg_gen_or_i32(t0, t0, t1);
8833 tcg_temp_free_i32(t1);
8834 tcg_gen_andi_i32(t0, t0, 1);
8835 tcg_gen_extu_i32_tl(bcond, t0);
8837 not_likely:
8838 ctx->hflags |= MIPS_HFLAG_BC;
8839 break;
8840 default:
8841 MIPS_INVAL("cp1 cond branch");
8842 generate_exception_end(ctx, EXCP_RI);
8843 goto out;
8845 ctx->btarget = btarget;
8846 ctx->hflags |= MIPS_HFLAG_BDS32;
8847 out:
8848 tcg_temp_free_i32(t0);
8851 /* R6 CP1 Branches */
8852 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8853 int32_t ft, int32_t offset,
8854 int delayslot_size)
8856 target_ulong btarget;
8857 TCGv_i64 t0 = tcg_temp_new_i64();
8859 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8860 #ifdef MIPS_DEBUG_DISAS
8861 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8862 "\n", ctx->base.pc_next);
8863 #endif
8864 generate_exception_end(ctx, EXCP_RI);
8865 goto out;
8868 gen_load_fpr64(ctx, t0, ft);
8869 tcg_gen_andi_i64(t0, t0, 1);
8871 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
8873 switch (op) {
8874 case OPC_BC1EQZ:
8875 tcg_gen_xori_i64(t0, t0, 1);
8876 ctx->hflags |= MIPS_HFLAG_BC;
8877 break;
8878 case OPC_BC1NEZ:
8879 /* t0 already set */
8880 ctx->hflags |= MIPS_HFLAG_BC;
8881 break;
8882 default:
8883 MIPS_INVAL("cp1 cond branch");
8884 generate_exception_end(ctx, EXCP_RI);
8885 goto out;
8888 tcg_gen_trunc_i64_tl(bcond, t0);
8890 ctx->btarget = btarget;
8892 switch (delayslot_size) {
8893 case 2:
8894 ctx->hflags |= MIPS_HFLAG_BDS16;
8895 break;
8896 case 4:
8897 ctx->hflags |= MIPS_HFLAG_BDS32;
8898 break;
8901 out:
8902 tcg_temp_free_i64(t0);
8905 /* Coprocessor 1 (FPU) */
8907 #define FOP(func, fmt) (((fmt) << 21) | (func))
8909 enum fopcode {
8910 OPC_ADD_S = FOP(0, FMT_S),
8911 OPC_SUB_S = FOP(1, FMT_S),
8912 OPC_MUL_S = FOP(2, FMT_S),
8913 OPC_DIV_S = FOP(3, FMT_S),
8914 OPC_SQRT_S = FOP(4, FMT_S),
8915 OPC_ABS_S = FOP(5, FMT_S),
8916 OPC_MOV_S = FOP(6, FMT_S),
8917 OPC_NEG_S = FOP(7, FMT_S),
8918 OPC_ROUND_L_S = FOP(8, FMT_S),
8919 OPC_TRUNC_L_S = FOP(9, FMT_S),
8920 OPC_CEIL_L_S = FOP(10, FMT_S),
8921 OPC_FLOOR_L_S = FOP(11, FMT_S),
8922 OPC_ROUND_W_S = FOP(12, FMT_S),
8923 OPC_TRUNC_W_S = FOP(13, FMT_S),
8924 OPC_CEIL_W_S = FOP(14, FMT_S),
8925 OPC_FLOOR_W_S = FOP(15, FMT_S),
8926 OPC_SEL_S = FOP(16, FMT_S),
8927 OPC_MOVCF_S = FOP(17, FMT_S),
8928 OPC_MOVZ_S = FOP(18, FMT_S),
8929 OPC_MOVN_S = FOP(19, FMT_S),
8930 OPC_SELEQZ_S = FOP(20, FMT_S),
8931 OPC_RECIP_S = FOP(21, FMT_S),
8932 OPC_RSQRT_S = FOP(22, FMT_S),
8933 OPC_SELNEZ_S = FOP(23, FMT_S),
8934 OPC_MADDF_S = FOP(24, FMT_S),
8935 OPC_MSUBF_S = FOP(25, FMT_S),
8936 OPC_RINT_S = FOP(26, FMT_S),
8937 OPC_CLASS_S = FOP(27, FMT_S),
8938 OPC_MIN_S = FOP(28, FMT_S),
8939 OPC_RECIP2_S = FOP(28, FMT_S),
8940 OPC_MINA_S = FOP(29, FMT_S),
8941 OPC_RECIP1_S = FOP(29, FMT_S),
8942 OPC_MAX_S = FOP(30, FMT_S),
8943 OPC_RSQRT1_S = FOP(30, FMT_S),
8944 OPC_MAXA_S = FOP(31, FMT_S),
8945 OPC_RSQRT2_S = FOP(31, FMT_S),
8946 OPC_CVT_D_S = FOP(33, FMT_S),
8947 OPC_CVT_W_S = FOP(36, FMT_S),
8948 OPC_CVT_L_S = FOP(37, FMT_S),
8949 OPC_CVT_PS_S = FOP(38, FMT_S),
8950 OPC_CMP_F_S = FOP (48, FMT_S),
8951 OPC_CMP_UN_S = FOP (49, FMT_S),
8952 OPC_CMP_EQ_S = FOP (50, FMT_S),
8953 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8954 OPC_CMP_OLT_S = FOP (52, FMT_S),
8955 OPC_CMP_ULT_S = FOP (53, FMT_S),
8956 OPC_CMP_OLE_S = FOP (54, FMT_S),
8957 OPC_CMP_ULE_S = FOP (55, FMT_S),
8958 OPC_CMP_SF_S = FOP (56, FMT_S),
8959 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8960 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8961 OPC_CMP_NGL_S = FOP (59, FMT_S),
8962 OPC_CMP_LT_S = FOP (60, FMT_S),
8963 OPC_CMP_NGE_S = FOP (61, FMT_S),
8964 OPC_CMP_LE_S = FOP (62, FMT_S),
8965 OPC_CMP_NGT_S = FOP (63, FMT_S),
8967 OPC_ADD_D = FOP(0, FMT_D),
8968 OPC_SUB_D = FOP(1, FMT_D),
8969 OPC_MUL_D = FOP(2, FMT_D),
8970 OPC_DIV_D = FOP(3, FMT_D),
8971 OPC_SQRT_D = FOP(4, FMT_D),
8972 OPC_ABS_D = FOP(5, FMT_D),
8973 OPC_MOV_D = FOP(6, FMT_D),
8974 OPC_NEG_D = FOP(7, FMT_D),
8975 OPC_ROUND_L_D = FOP(8, FMT_D),
8976 OPC_TRUNC_L_D = FOP(9, FMT_D),
8977 OPC_CEIL_L_D = FOP(10, FMT_D),
8978 OPC_FLOOR_L_D = FOP(11, FMT_D),
8979 OPC_ROUND_W_D = FOP(12, FMT_D),
8980 OPC_TRUNC_W_D = FOP(13, FMT_D),
8981 OPC_CEIL_W_D = FOP(14, FMT_D),
8982 OPC_FLOOR_W_D = FOP(15, FMT_D),
8983 OPC_SEL_D = FOP(16, FMT_D),
8984 OPC_MOVCF_D = FOP(17, FMT_D),
8985 OPC_MOVZ_D = FOP(18, FMT_D),
8986 OPC_MOVN_D = FOP(19, FMT_D),
8987 OPC_SELEQZ_D = FOP(20, FMT_D),
8988 OPC_RECIP_D = FOP(21, FMT_D),
8989 OPC_RSQRT_D = FOP(22, FMT_D),
8990 OPC_SELNEZ_D = FOP(23, FMT_D),
8991 OPC_MADDF_D = FOP(24, FMT_D),
8992 OPC_MSUBF_D = FOP(25, FMT_D),
8993 OPC_RINT_D = FOP(26, FMT_D),
8994 OPC_CLASS_D = FOP(27, FMT_D),
8995 OPC_MIN_D = FOP(28, FMT_D),
8996 OPC_RECIP2_D = FOP(28, FMT_D),
8997 OPC_MINA_D = FOP(29, FMT_D),
8998 OPC_RECIP1_D = FOP(29, FMT_D),
8999 OPC_MAX_D = FOP(30, FMT_D),
9000 OPC_RSQRT1_D = FOP(30, FMT_D),
9001 OPC_MAXA_D = FOP(31, FMT_D),
9002 OPC_RSQRT2_D = FOP(31, FMT_D),
9003 OPC_CVT_S_D = FOP(32, FMT_D),
9004 OPC_CVT_W_D = FOP(36, FMT_D),
9005 OPC_CVT_L_D = FOP(37, FMT_D),
9006 OPC_CMP_F_D = FOP (48, FMT_D),
9007 OPC_CMP_UN_D = FOP (49, FMT_D),
9008 OPC_CMP_EQ_D = FOP (50, FMT_D),
9009 OPC_CMP_UEQ_D = FOP (51, FMT_D),
9010 OPC_CMP_OLT_D = FOP (52, FMT_D),
9011 OPC_CMP_ULT_D = FOP (53, FMT_D),
9012 OPC_CMP_OLE_D = FOP (54, FMT_D),
9013 OPC_CMP_ULE_D = FOP (55, FMT_D),
9014 OPC_CMP_SF_D = FOP (56, FMT_D),
9015 OPC_CMP_NGLE_D = FOP (57, FMT_D),
9016 OPC_CMP_SEQ_D = FOP (58, FMT_D),
9017 OPC_CMP_NGL_D = FOP (59, FMT_D),
9018 OPC_CMP_LT_D = FOP (60, FMT_D),
9019 OPC_CMP_NGE_D = FOP (61, FMT_D),
9020 OPC_CMP_LE_D = FOP (62, FMT_D),
9021 OPC_CMP_NGT_D = FOP (63, FMT_D),
9023 OPC_CVT_S_W = FOP(32, FMT_W),
9024 OPC_CVT_D_W = FOP(33, FMT_W),
9025 OPC_CVT_S_L = FOP(32, FMT_L),
9026 OPC_CVT_D_L = FOP(33, FMT_L),
9027 OPC_CVT_PS_PW = FOP(38, FMT_W),
9029 OPC_ADD_PS = FOP(0, FMT_PS),
9030 OPC_SUB_PS = FOP(1, FMT_PS),
9031 OPC_MUL_PS = FOP(2, FMT_PS),
9032 OPC_DIV_PS = FOP(3, FMT_PS),
9033 OPC_ABS_PS = FOP(5, FMT_PS),
9034 OPC_MOV_PS = FOP(6, FMT_PS),
9035 OPC_NEG_PS = FOP(7, FMT_PS),
9036 OPC_MOVCF_PS = FOP(17, FMT_PS),
9037 OPC_MOVZ_PS = FOP(18, FMT_PS),
9038 OPC_MOVN_PS = FOP(19, FMT_PS),
9039 OPC_ADDR_PS = FOP(24, FMT_PS),
9040 OPC_MULR_PS = FOP(26, FMT_PS),
9041 OPC_RECIP2_PS = FOP(28, FMT_PS),
9042 OPC_RECIP1_PS = FOP(29, FMT_PS),
9043 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9044 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9046 OPC_CVT_S_PU = FOP(32, FMT_PS),
9047 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9048 OPC_CVT_S_PL = FOP(40, FMT_PS),
9049 OPC_PLL_PS = FOP(44, FMT_PS),
9050 OPC_PLU_PS = FOP(45, FMT_PS),
9051 OPC_PUL_PS = FOP(46, FMT_PS),
9052 OPC_PUU_PS = FOP(47, FMT_PS),
9053 OPC_CMP_F_PS = FOP (48, FMT_PS),
9054 OPC_CMP_UN_PS = FOP (49, FMT_PS),
9055 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
9056 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
9057 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
9058 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
9059 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
9060 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
9061 OPC_CMP_SF_PS = FOP (56, FMT_PS),
9062 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
9063 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
9064 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
9065 OPC_CMP_LT_PS = FOP (60, FMT_PS),
9066 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
9067 OPC_CMP_LE_PS = FOP (62, FMT_PS),
9068 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
9071 enum r6_f_cmp_op {
9072 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9073 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9074 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9075 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9076 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9077 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9078 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9079 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9080 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9081 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9082 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9083 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9084 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9085 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9086 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9087 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9088 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9089 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9090 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9091 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9092 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9093 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9095 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9096 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9097 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9098 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9099 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9100 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9101 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9102 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9103 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9104 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9105 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9106 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9107 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9108 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9109 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9110 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9111 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9112 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9113 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9114 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9115 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9116 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9118 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
9120 TCGv t0 = tcg_temp_new();
9122 switch (opc) {
9123 case OPC_MFC1:
9125 TCGv_i32 fp0 = tcg_temp_new_i32();
9127 gen_load_fpr32(ctx, fp0, fs);
9128 tcg_gen_ext_i32_tl(t0, fp0);
9129 tcg_temp_free_i32(fp0);
9131 gen_store_gpr(t0, rt);
9132 break;
9133 case OPC_MTC1:
9134 gen_load_gpr(t0, rt);
9136 TCGv_i32 fp0 = tcg_temp_new_i32();
9138 tcg_gen_trunc_tl_i32(fp0, t0);
9139 gen_store_fpr32(ctx, fp0, fs);
9140 tcg_temp_free_i32(fp0);
9142 break;
9143 case OPC_CFC1:
9144 gen_helper_1e0i(cfc1, t0, fs);
9145 gen_store_gpr(t0, rt);
9146 break;
9147 case OPC_CTC1:
9148 gen_load_gpr(t0, rt);
9149 save_cpu_state(ctx, 0);
9151 TCGv_i32 fs_tmp = tcg_const_i32(fs);
9153 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9154 tcg_temp_free_i32(fs_tmp);
9156 /* Stop translation as we may have changed hflags */
9157 ctx->base.is_jmp = DISAS_STOP;
9158 break;
9159 #if defined(TARGET_MIPS64)
9160 case OPC_DMFC1:
9161 gen_load_fpr64(ctx, t0, fs);
9162 gen_store_gpr(t0, rt);
9163 break;
9164 case OPC_DMTC1:
9165 gen_load_gpr(t0, rt);
9166 gen_store_fpr64(ctx, t0, fs);
9167 break;
9168 #endif
9169 case OPC_MFHC1:
9171 TCGv_i32 fp0 = tcg_temp_new_i32();
9173 gen_load_fpr32h(ctx, fp0, fs);
9174 tcg_gen_ext_i32_tl(t0, fp0);
9175 tcg_temp_free_i32(fp0);
9177 gen_store_gpr(t0, rt);
9178 break;
9179 case OPC_MTHC1:
9180 gen_load_gpr(t0, rt);
9182 TCGv_i32 fp0 = tcg_temp_new_i32();
9184 tcg_gen_trunc_tl_i32(fp0, t0);
9185 gen_store_fpr32h(ctx, fp0, fs);
9186 tcg_temp_free_i32(fp0);
9188 break;
9189 default:
9190 MIPS_INVAL("cp1 move");
9191 generate_exception_end(ctx, EXCP_RI);
9192 goto out;
9195 out:
9196 tcg_temp_free(t0);
9199 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
9201 TCGLabel *l1;
9202 TCGCond cond;
9203 TCGv_i32 t0;
9205 if (rd == 0) {
9206 /* Treat as NOP. */
9207 return;
9210 if (tf)
9211 cond = TCG_COND_EQ;
9212 else
9213 cond = TCG_COND_NE;
9215 l1 = gen_new_label();
9216 t0 = tcg_temp_new_i32();
9217 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9218 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9219 tcg_temp_free_i32(t0);
9220 if (rs == 0) {
9221 tcg_gen_movi_tl(cpu_gpr[rd], 0);
9222 } else {
9223 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
9225 gen_set_label(l1);
9228 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9229 int tf)
9231 int cond;
9232 TCGv_i32 t0 = tcg_temp_new_i32();
9233 TCGLabel *l1 = gen_new_label();
9235 if (tf)
9236 cond = TCG_COND_EQ;
9237 else
9238 cond = TCG_COND_NE;
9240 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9241 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9242 gen_load_fpr32(ctx, t0, fs);
9243 gen_store_fpr32(ctx, t0, fd);
9244 gen_set_label(l1);
9245 tcg_temp_free_i32(t0);
9248 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
9250 int cond;
9251 TCGv_i32 t0 = tcg_temp_new_i32();
9252 TCGv_i64 fp0;
9253 TCGLabel *l1 = gen_new_label();
9255 if (tf)
9256 cond = TCG_COND_EQ;
9257 else
9258 cond = TCG_COND_NE;
9260 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9261 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9262 tcg_temp_free_i32(t0);
9263 fp0 = tcg_temp_new_i64();
9264 gen_load_fpr64(ctx, fp0, fs);
9265 gen_store_fpr64(ctx, fp0, fd);
9266 tcg_temp_free_i64(fp0);
9267 gen_set_label(l1);
9270 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9271 int cc, int tf)
9273 int cond;
9274 TCGv_i32 t0 = tcg_temp_new_i32();
9275 TCGLabel *l1 = gen_new_label();
9276 TCGLabel *l2 = gen_new_label();
9278 if (tf)
9279 cond = TCG_COND_EQ;
9280 else
9281 cond = TCG_COND_NE;
9283 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9284 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9285 gen_load_fpr32(ctx, t0, fs);
9286 gen_store_fpr32(ctx, t0, fd);
9287 gen_set_label(l1);
9289 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
9290 tcg_gen_brcondi_i32(cond, t0, 0, l2);
9291 gen_load_fpr32h(ctx, t0, fs);
9292 gen_store_fpr32h(ctx, t0, fd);
9293 tcg_temp_free_i32(t0);
9294 gen_set_label(l2);
9297 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9298 int fs)
9300 TCGv_i32 t1 = tcg_const_i32(0);
9301 TCGv_i32 fp0 = tcg_temp_new_i32();
9302 TCGv_i32 fp1 = tcg_temp_new_i32();
9303 TCGv_i32 fp2 = tcg_temp_new_i32();
9304 gen_load_fpr32(ctx, fp0, fd);
9305 gen_load_fpr32(ctx, fp1, ft);
9306 gen_load_fpr32(ctx, fp2, fs);
9308 switch (op1) {
9309 case OPC_SEL_S:
9310 tcg_gen_andi_i32(fp0, fp0, 1);
9311 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9312 break;
9313 case OPC_SELEQZ_S:
9314 tcg_gen_andi_i32(fp1, fp1, 1);
9315 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9316 break;
9317 case OPC_SELNEZ_S:
9318 tcg_gen_andi_i32(fp1, fp1, 1);
9319 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9320 break;
9321 default:
9322 MIPS_INVAL("gen_sel_s");
9323 generate_exception_end(ctx, EXCP_RI);
9324 break;
9327 gen_store_fpr32(ctx, fp0, fd);
9328 tcg_temp_free_i32(fp2);
9329 tcg_temp_free_i32(fp1);
9330 tcg_temp_free_i32(fp0);
9331 tcg_temp_free_i32(t1);
9334 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9335 int fs)
9337 TCGv_i64 t1 = tcg_const_i64(0);
9338 TCGv_i64 fp0 = tcg_temp_new_i64();
9339 TCGv_i64 fp1 = tcg_temp_new_i64();
9340 TCGv_i64 fp2 = tcg_temp_new_i64();
9341 gen_load_fpr64(ctx, fp0, fd);
9342 gen_load_fpr64(ctx, fp1, ft);
9343 gen_load_fpr64(ctx, fp2, fs);
9345 switch (op1) {
9346 case OPC_SEL_D:
9347 tcg_gen_andi_i64(fp0, fp0, 1);
9348 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9349 break;
9350 case OPC_SELEQZ_D:
9351 tcg_gen_andi_i64(fp1, fp1, 1);
9352 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9353 break;
9354 case OPC_SELNEZ_D:
9355 tcg_gen_andi_i64(fp1, fp1, 1);
9356 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9357 break;
9358 default:
9359 MIPS_INVAL("gen_sel_d");
9360 generate_exception_end(ctx, EXCP_RI);
9361 break;
9364 gen_store_fpr64(ctx, fp0, fd);
9365 tcg_temp_free_i64(fp2);
9366 tcg_temp_free_i64(fp1);
9367 tcg_temp_free_i64(fp0);
9368 tcg_temp_free_i64(t1);
9371 static void gen_farith (DisasContext *ctx, enum fopcode op1,
9372 int ft, int fs, int fd, int cc)
9374 uint32_t func = ctx->opcode & 0x3f;
9375 switch (op1) {
9376 case OPC_ADD_S:
9378 TCGv_i32 fp0 = tcg_temp_new_i32();
9379 TCGv_i32 fp1 = tcg_temp_new_i32();
9381 gen_load_fpr32(ctx, fp0, fs);
9382 gen_load_fpr32(ctx, fp1, ft);
9383 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
9384 tcg_temp_free_i32(fp1);
9385 gen_store_fpr32(ctx, fp0, fd);
9386 tcg_temp_free_i32(fp0);
9388 break;
9389 case OPC_SUB_S:
9391 TCGv_i32 fp0 = tcg_temp_new_i32();
9392 TCGv_i32 fp1 = tcg_temp_new_i32();
9394 gen_load_fpr32(ctx, fp0, fs);
9395 gen_load_fpr32(ctx, fp1, ft);
9396 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
9397 tcg_temp_free_i32(fp1);
9398 gen_store_fpr32(ctx, fp0, fd);
9399 tcg_temp_free_i32(fp0);
9401 break;
9402 case OPC_MUL_S:
9404 TCGv_i32 fp0 = tcg_temp_new_i32();
9405 TCGv_i32 fp1 = tcg_temp_new_i32();
9407 gen_load_fpr32(ctx, fp0, fs);
9408 gen_load_fpr32(ctx, fp1, ft);
9409 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
9410 tcg_temp_free_i32(fp1);
9411 gen_store_fpr32(ctx, fp0, fd);
9412 tcg_temp_free_i32(fp0);
9414 break;
9415 case OPC_DIV_S:
9417 TCGv_i32 fp0 = tcg_temp_new_i32();
9418 TCGv_i32 fp1 = tcg_temp_new_i32();
9420 gen_load_fpr32(ctx, fp0, fs);
9421 gen_load_fpr32(ctx, fp1, ft);
9422 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
9423 tcg_temp_free_i32(fp1);
9424 gen_store_fpr32(ctx, fp0, fd);
9425 tcg_temp_free_i32(fp0);
9427 break;
9428 case OPC_SQRT_S:
9430 TCGv_i32 fp0 = tcg_temp_new_i32();
9432 gen_load_fpr32(ctx, fp0, fs);
9433 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
9434 gen_store_fpr32(ctx, fp0, fd);
9435 tcg_temp_free_i32(fp0);
9437 break;
9438 case OPC_ABS_S:
9440 TCGv_i32 fp0 = tcg_temp_new_i32();
9442 gen_load_fpr32(ctx, fp0, fs);
9443 if (ctx->abs2008) {
9444 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9445 } else {
9446 gen_helper_float_abs_s(fp0, fp0);
9448 gen_store_fpr32(ctx, fp0, fd);
9449 tcg_temp_free_i32(fp0);
9451 break;
9452 case OPC_MOV_S:
9454 TCGv_i32 fp0 = tcg_temp_new_i32();
9456 gen_load_fpr32(ctx, fp0, fs);
9457 gen_store_fpr32(ctx, fp0, fd);
9458 tcg_temp_free_i32(fp0);
9460 break;
9461 case OPC_NEG_S:
9463 TCGv_i32 fp0 = tcg_temp_new_i32();
9465 gen_load_fpr32(ctx, fp0, fs);
9466 if (ctx->abs2008) {
9467 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9468 } else {
9469 gen_helper_float_chs_s(fp0, fp0);
9471 gen_store_fpr32(ctx, fp0, fd);
9472 tcg_temp_free_i32(fp0);
9474 break;
9475 case OPC_ROUND_L_S:
9476 check_cp1_64bitmode(ctx);
9478 TCGv_i32 fp32 = tcg_temp_new_i32();
9479 TCGv_i64 fp64 = tcg_temp_new_i64();
9481 gen_load_fpr32(ctx, fp32, fs);
9482 if (ctx->nan2008) {
9483 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
9484 } else {
9485 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
9487 tcg_temp_free_i32(fp32);
9488 gen_store_fpr64(ctx, fp64, fd);
9489 tcg_temp_free_i64(fp64);
9491 break;
9492 case OPC_TRUNC_L_S:
9493 check_cp1_64bitmode(ctx);
9495 TCGv_i32 fp32 = tcg_temp_new_i32();
9496 TCGv_i64 fp64 = tcg_temp_new_i64();
9498 gen_load_fpr32(ctx, fp32, fs);
9499 if (ctx->nan2008) {
9500 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
9501 } else {
9502 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
9504 tcg_temp_free_i32(fp32);
9505 gen_store_fpr64(ctx, fp64, fd);
9506 tcg_temp_free_i64(fp64);
9508 break;
9509 case OPC_CEIL_L_S:
9510 check_cp1_64bitmode(ctx);
9512 TCGv_i32 fp32 = tcg_temp_new_i32();
9513 TCGv_i64 fp64 = tcg_temp_new_i64();
9515 gen_load_fpr32(ctx, fp32, fs);
9516 if (ctx->nan2008) {
9517 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
9518 } else {
9519 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
9521 tcg_temp_free_i32(fp32);
9522 gen_store_fpr64(ctx, fp64, fd);
9523 tcg_temp_free_i64(fp64);
9525 break;
9526 case OPC_FLOOR_L_S:
9527 check_cp1_64bitmode(ctx);
9529 TCGv_i32 fp32 = tcg_temp_new_i32();
9530 TCGv_i64 fp64 = tcg_temp_new_i64();
9532 gen_load_fpr32(ctx, fp32, fs);
9533 if (ctx->nan2008) {
9534 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
9535 } else {
9536 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
9538 tcg_temp_free_i32(fp32);
9539 gen_store_fpr64(ctx, fp64, fd);
9540 tcg_temp_free_i64(fp64);
9542 break;
9543 case OPC_ROUND_W_S:
9545 TCGv_i32 fp0 = tcg_temp_new_i32();
9547 gen_load_fpr32(ctx, fp0, fs);
9548 if (ctx->nan2008) {
9549 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
9550 } else {
9551 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
9553 gen_store_fpr32(ctx, fp0, fd);
9554 tcg_temp_free_i32(fp0);
9556 break;
9557 case OPC_TRUNC_W_S:
9559 TCGv_i32 fp0 = tcg_temp_new_i32();
9561 gen_load_fpr32(ctx, fp0, fs);
9562 if (ctx->nan2008) {
9563 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
9564 } else {
9565 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
9567 gen_store_fpr32(ctx, fp0, fd);
9568 tcg_temp_free_i32(fp0);
9570 break;
9571 case OPC_CEIL_W_S:
9573 TCGv_i32 fp0 = tcg_temp_new_i32();
9575 gen_load_fpr32(ctx, fp0, fs);
9576 if (ctx->nan2008) {
9577 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
9578 } else {
9579 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
9581 gen_store_fpr32(ctx, fp0, fd);
9582 tcg_temp_free_i32(fp0);
9584 break;
9585 case OPC_FLOOR_W_S:
9587 TCGv_i32 fp0 = tcg_temp_new_i32();
9589 gen_load_fpr32(ctx, fp0, fs);
9590 if (ctx->nan2008) {
9591 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
9592 } else {
9593 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
9595 gen_store_fpr32(ctx, fp0, fd);
9596 tcg_temp_free_i32(fp0);
9598 break;
9599 case OPC_SEL_S:
9600 check_insn(ctx, ISA_MIPS32R6);
9601 gen_sel_s(ctx, op1, fd, ft, fs);
9602 break;
9603 case OPC_SELEQZ_S:
9604 check_insn(ctx, ISA_MIPS32R6);
9605 gen_sel_s(ctx, op1, fd, ft, fs);
9606 break;
9607 case OPC_SELNEZ_S:
9608 check_insn(ctx, ISA_MIPS32R6);
9609 gen_sel_s(ctx, op1, fd, ft, fs);
9610 break;
9611 case OPC_MOVCF_S:
9612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9613 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9614 break;
9615 case OPC_MOVZ_S:
9616 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9618 TCGLabel *l1 = gen_new_label();
9619 TCGv_i32 fp0;
9621 if (ft != 0) {
9622 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9624 fp0 = tcg_temp_new_i32();
9625 gen_load_fpr32(ctx, fp0, fs);
9626 gen_store_fpr32(ctx, fp0, fd);
9627 tcg_temp_free_i32(fp0);
9628 gen_set_label(l1);
9630 break;
9631 case OPC_MOVN_S:
9632 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9634 TCGLabel *l1 = gen_new_label();
9635 TCGv_i32 fp0;
9637 if (ft != 0) {
9638 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9639 fp0 = tcg_temp_new_i32();
9640 gen_load_fpr32(ctx, fp0, fs);
9641 gen_store_fpr32(ctx, fp0, fd);
9642 tcg_temp_free_i32(fp0);
9643 gen_set_label(l1);
9646 break;
9647 case OPC_RECIP_S:
9649 TCGv_i32 fp0 = tcg_temp_new_i32();
9651 gen_load_fpr32(ctx, fp0, fs);
9652 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9653 gen_store_fpr32(ctx, fp0, fd);
9654 tcg_temp_free_i32(fp0);
9656 break;
9657 case OPC_RSQRT_S:
9659 TCGv_i32 fp0 = tcg_temp_new_i32();
9661 gen_load_fpr32(ctx, fp0, fs);
9662 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9663 gen_store_fpr32(ctx, fp0, fd);
9664 tcg_temp_free_i32(fp0);
9666 break;
9667 case OPC_MADDF_S:
9668 check_insn(ctx, ISA_MIPS32R6);
9670 TCGv_i32 fp0 = tcg_temp_new_i32();
9671 TCGv_i32 fp1 = tcg_temp_new_i32();
9672 TCGv_i32 fp2 = tcg_temp_new_i32();
9673 gen_load_fpr32(ctx, fp0, fs);
9674 gen_load_fpr32(ctx, fp1, ft);
9675 gen_load_fpr32(ctx, fp2, fd);
9676 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9677 gen_store_fpr32(ctx, fp2, fd);
9678 tcg_temp_free_i32(fp2);
9679 tcg_temp_free_i32(fp1);
9680 tcg_temp_free_i32(fp0);
9682 break;
9683 case OPC_MSUBF_S:
9684 check_insn(ctx, ISA_MIPS32R6);
9686 TCGv_i32 fp0 = tcg_temp_new_i32();
9687 TCGv_i32 fp1 = tcg_temp_new_i32();
9688 TCGv_i32 fp2 = tcg_temp_new_i32();
9689 gen_load_fpr32(ctx, fp0, fs);
9690 gen_load_fpr32(ctx, fp1, ft);
9691 gen_load_fpr32(ctx, fp2, fd);
9692 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9693 gen_store_fpr32(ctx, fp2, fd);
9694 tcg_temp_free_i32(fp2);
9695 tcg_temp_free_i32(fp1);
9696 tcg_temp_free_i32(fp0);
9698 break;
9699 case OPC_RINT_S:
9700 check_insn(ctx, ISA_MIPS32R6);
9702 TCGv_i32 fp0 = tcg_temp_new_i32();
9703 gen_load_fpr32(ctx, fp0, fs);
9704 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9705 gen_store_fpr32(ctx, fp0, fd);
9706 tcg_temp_free_i32(fp0);
9708 break;
9709 case OPC_CLASS_S:
9710 check_insn(ctx, ISA_MIPS32R6);
9712 TCGv_i32 fp0 = tcg_temp_new_i32();
9713 gen_load_fpr32(ctx, fp0, fs);
9714 gen_helper_float_class_s(fp0, cpu_env, fp0);
9715 gen_store_fpr32(ctx, fp0, fd);
9716 tcg_temp_free_i32(fp0);
9718 break;
9719 case OPC_MIN_S: /* OPC_RECIP2_S */
9720 if (ctx->insn_flags & ISA_MIPS32R6) {
9721 /* OPC_MIN_S */
9722 TCGv_i32 fp0 = tcg_temp_new_i32();
9723 TCGv_i32 fp1 = tcg_temp_new_i32();
9724 TCGv_i32 fp2 = tcg_temp_new_i32();
9725 gen_load_fpr32(ctx, fp0, fs);
9726 gen_load_fpr32(ctx, fp1, ft);
9727 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9728 gen_store_fpr32(ctx, fp2, fd);
9729 tcg_temp_free_i32(fp2);
9730 tcg_temp_free_i32(fp1);
9731 tcg_temp_free_i32(fp0);
9732 } else {
9733 /* OPC_RECIP2_S */
9734 check_cp1_64bitmode(ctx);
9736 TCGv_i32 fp0 = tcg_temp_new_i32();
9737 TCGv_i32 fp1 = tcg_temp_new_i32();
9739 gen_load_fpr32(ctx, fp0, fs);
9740 gen_load_fpr32(ctx, fp1, ft);
9741 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9742 tcg_temp_free_i32(fp1);
9743 gen_store_fpr32(ctx, fp0, fd);
9744 tcg_temp_free_i32(fp0);
9747 break;
9748 case OPC_MINA_S: /* OPC_RECIP1_S */
9749 if (ctx->insn_flags & ISA_MIPS32R6) {
9750 /* OPC_MINA_S */
9751 TCGv_i32 fp0 = tcg_temp_new_i32();
9752 TCGv_i32 fp1 = tcg_temp_new_i32();
9753 TCGv_i32 fp2 = tcg_temp_new_i32();
9754 gen_load_fpr32(ctx, fp0, fs);
9755 gen_load_fpr32(ctx, fp1, ft);
9756 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9757 gen_store_fpr32(ctx, fp2, fd);
9758 tcg_temp_free_i32(fp2);
9759 tcg_temp_free_i32(fp1);
9760 tcg_temp_free_i32(fp0);
9761 } else {
9762 /* OPC_RECIP1_S */
9763 check_cp1_64bitmode(ctx);
9765 TCGv_i32 fp0 = tcg_temp_new_i32();
9767 gen_load_fpr32(ctx, fp0, fs);
9768 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9769 gen_store_fpr32(ctx, fp0, fd);
9770 tcg_temp_free_i32(fp0);
9773 break;
9774 case OPC_MAX_S: /* OPC_RSQRT1_S */
9775 if (ctx->insn_flags & ISA_MIPS32R6) {
9776 /* OPC_MAX_S */
9777 TCGv_i32 fp0 = tcg_temp_new_i32();
9778 TCGv_i32 fp1 = tcg_temp_new_i32();
9779 gen_load_fpr32(ctx, fp0, fs);
9780 gen_load_fpr32(ctx, fp1, ft);
9781 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9782 gen_store_fpr32(ctx, fp1, fd);
9783 tcg_temp_free_i32(fp1);
9784 tcg_temp_free_i32(fp0);
9785 } else {
9786 /* OPC_RSQRT1_S */
9787 check_cp1_64bitmode(ctx);
9789 TCGv_i32 fp0 = tcg_temp_new_i32();
9791 gen_load_fpr32(ctx, fp0, fs);
9792 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9793 gen_store_fpr32(ctx, fp0, fd);
9794 tcg_temp_free_i32(fp0);
9797 break;
9798 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9799 if (ctx->insn_flags & ISA_MIPS32R6) {
9800 /* OPC_MAXA_S */
9801 TCGv_i32 fp0 = tcg_temp_new_i32();
9802 TCGv_i32 fp1 = tcg_temp_new_i32();
9803 gen_load_fpr32(ctx, fp0, fs);
9804 gen_load_fpr32(ctx, fp1, ft);
9805 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9806 gen_store_fpr32(ctx, fp1, fd);
9807 tcg_temp_free_i32(fp1);
9808 tcg_temp_free_i32(fp0);
9809 } else {
9810 /* OPC_RSQRT2_S */
9811 check_cp1_64bitmode(ctx);
9813 TCGv_i32 fp0 = tcg_temp_new_i32();
9814 TCGv_i32 fp1 = tcg_temp_new_i32();
9816 gen_load_fpr32(ctx, fp0, fs);
9817 gen_load_fpr32(ctx, fp1, ft);
9818 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9819 tcg_temp_free_i32(fp1);
9820 gen_store_fpr32(ctx, fp0, fd);
9821 tcg_temp_free_i32(fp0);
9824 break;
9825 case OPC_CVT_D_S:
9826 check_cp1_registers(ctx, fd);
9828 TCGv_i32 fp32 = tcg_temp_new_i32();
9829 TCGv_i64 fp64 = tcg_temp_new_i64();
9831 gen_load_fpr32(ctx, fp32, fs);
9832 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9833 tcg_temp_free_i32(fp32);
9834 gen_store_fpr64(ctx, fp64, fd);
9835 tcg_temp_free_i64(fp64);
9837 break;
9838 case OPC_CVT_W_S:
9840 TCGv_i32 fp0 = tcg_temp_new_i32();
9842 gen_load_fpr32(ctx, fp0, fs);
9843 if (ctx->nan2008) {
9844 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
9845 } else {
9846 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
9848 gen_store_fpr32(ctx, fp0, fd);
9849 tcg_temp_free_i32(fp0);
9851 break;
9852 case OPC_CVT_L_S:
9853 check_cp1_64bitmode(ctx);
9855 TCGv_i32 fp32 = tcg_temp_new_i32();
9856 TCGv_i64 fp64 = tcg_temp_new_i64();
9858 gen_load_fpr32(ctx, fp32, fs);
9859 if (ctx->nan2008) {
9860 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
9861 } else {
9862 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
9864 tcg_temp_free_i32(fp32);
9865 gen_store_fpr64(ctx, fp64, fd);
9866 tcg_temp_free_i64(fp64);
9868 break;
9869 case OPC_CVT_PS_S:
9870 check_ps(ctx);
9872 TCGv_i64 fp64 = tcg_temp_new_i64();
9873 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9874 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9876 gen_load_fpr32(ctx, fp32_0, fs);
9877 gen_load_fpr32(ctx, fp32_1, ft);
9878 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9879 tcg_temp_free_i32(fp32_1);
9880 tcg_temp_free_i32(fp32_0);
9881 gen_store_fpr64(ctx, fp64, fd);
9882 tcg_temp_free_i64(fp64);
9884 break;
9885 case OPC_CMP_F_S:
9886 case OPC_CMP_UN_S:
9887 case OPC_CMP_EQ_S:
9888 case OPC_CMP_UEQ_S:
9889 case OPC_CMP_OLT_S:
9890 case OPC_CMP_ULT_S:
9891 case OPC_CMP_OLE_S:
9892 case OPC_CMP_ULE_S:
9893 case OPC_CMP_SF_S:
9894 case OPC_CMP_NGLE_S:
9895 case OPC_CMP_SEQ_S:
9896 case OPC_CMP_NGL_S:
9897 case OPC_CMP_LT_S:
9898 case OPC_CMP_NGE_S:
9899 case OPC_CMP_LE_S:
9900 case OPC_CMP_NGT_S:
9901 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9902 if (ctx->opcode & (1 << 6)) {
9903 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9904 } else {
9905 gen_cmp_s(ctx, func-48, ft, fs, cc);
9907 break;
9908 case OPC_ADD_D:
9909 check_cp1_registers(ctx, fs | ft | fd);
9911 TCGv_i64 fp0 = tcg_temp_new_i64();
9912 TCGv_i64 fp1 = tcg_temp_new_i64();
9914 gen_load_fpr64(ctx, fp0, fs);
9915 gen_load_fpr64(ctx, fp1, ft);
9916 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9917 tcg_temp_free_i64(fp1);
9918 gen_store_fpr64(ctx, fp0, fd);
9919 tcg_temp_free_i64(fp0);
9921 break;
9922 case OPC_SUB_D:
9923 check_cp1_registers(ctx, fs | ft | fd);
9925 TCGv_i64 fp0 = tcg_temp_new_i64();
9926 TCGv_i64 fp1 = tcg_temp_new_i64();
9928 gen_load_fpr64(ctx, fp0, fs);
9929 gen_load_fpr64(ctx, fp1, ft);
9930 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9931 tcg_temp_free_i64(fp1);
9932 gen_store_fpr64(ctx, fp0, fd);
9933 tcg_temp_free_i64(fp0);
9935 break;
9936 case OPC_MUL_D:
9937 check_cp1_registers(ctx, fs | ft | fd);
9939 TCGv_i64 fp0 = tcg_temp_new_i64();
9940 TCGv_i64 fp1 = tcg_temp_new_i64();
9942 gen_load_fpr64(ctx, fp0, fs);
9943 gen_load_fpr64(ctx, fp1, ft);
9944 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9945 tcg_temp_free_i64(fp1);
9946 gen_store_fpr64(ctx, fp0, fd);
9947 tcg_temp_free_i64(fp0);
9949 break;
9950 case OPC_DIV_D:
9951 check_cp1_registers(ctx, fs | ft | fd);
9953 TCGv_i64 fp0 = tcg_temp_new_i64();
9954 TCGv_i64 fp1 = tcg_temp_new_i64();
9956 gen_load_fpr64(ctx, fp0, fs);
9957 gen_load_fpr64(ctx, fp1, ft);
9958 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9959 tcg_temp_free_i64(fp1);
9960 gen_store_fpr64(ctx, fp0, fd);
9961 tcg_temp_free_i64(fp0);
9963 break;
9964 case OPC_SQRT_D:
9965 check_cp1_registers(ctx, fs | fd);
9967 TCGv_i64 fp0 = tcg_temp_new_i64();
9969 gen_load_fpr64(ctx, fp0, fs);
9970 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9971 gen_store_fpr64(ctx, fp0, fd);
9972 tcg_temp_free_i64(fp0);
9974 break;
9975 case OPC_ABS_D:
9976 check_cp1_registers(ctx, fs | fd);
9978 TCGv_i64 fp0 = tcg_temp_new_i64();
9980 gen_load_fpr64(ctx, fp0, fs);
9981 if (ctx->abs2008) {
9982 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9983 } else {
9984 gen_helper_float_abs_d(fp0, fp0);
9986 gen_store_fpr64(ctx, fp0, fd);
9987 tcg_temp_free_i64(fp0);
9989 break;
9990 case OPC_MOV_D:
9991 check_cp1_registers(ctx, fs | fd);
9993 TCGv_i64 fp0 = tcg_temp_new_i64();
9995 gen_load_fpr64(ctx, fp0, fs);
9996 gen_store_fpr64(ctx, fp0, fd);
9997 tcg_temp_free_i64(fp0);
9999 break;
10000 case OPC_NEG_D:
10001 check_cp1_registers(ctx, fs | fd);
10003 TCGv_i64 fp0 = tcg_temp_new_i64();
10005 gen_load_fpr64(ctx, fp0, fs);
10006 if (ctx->abs2008) {
10007 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10008 } else {
10009 gen_helper_float_chs_d(fp0, fp0);
10011 gen_store_fpr64(ctx, fp0, fd);
10012 tcg_temp_free_i64(fp0);
10014 break;
10015 case OPC_ROUND_L_D:
10016 check_cp1_64bitmode(ctx);
10018 TCGv_i64 fp0 = tcg_temp_new_i64();
10020 gen_load_fpr64(ctx, fp0, fs);
10021 if (ctx->nan2008) {
10022 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10023 } else {
10024 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10026 gen_store_fpr64(ctx, fp0, fd);
10027 tcg_temp_free_i64(fp0);
10029 break;
10030 case OPC_TRUNC_L_D:
10031 check_cp1_64bitmode(ctx);
10033 TCGv_i64 fp0 = tcg_temp_new_i64();
10035 gen_load_fpr64(ctx, fp0, fs);
10036 if (ctx->nan2008) {
10037 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10038 } else {
10039 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10041 gen_store_fpr64(ctx, fp0, fd);
10042 tcg_temp_free_i64(fp0);
10044 break;
10045 case OPC_CEIL_L_D:
10046 check_cp1_64bitmode(ctx);
10048 TCGv_i64 fp0 = tcg_temp_new_i64();
10050 gen_load_fpr64(ctx, fp0, fs);
10051 if (ctx->nan2008) {
10052 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10053 } else {
10054 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10056 gen_store_fpr64(ctx, fp0, fd);
10057 tcg_temp_free_i64(fp0);
10059 break;
10060 case OPC_FLOOR_L_D:
10061 check_cp1_64bitmode(ctx);
10063 TCGv_i64 fp0 = tcg_temp_new_i64();
10065 gen_load_fpr64(ctx, fp0, fs);
10066 if (ctx->nan2008) {
10067 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10068 } else {
10069 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10071 gen_store_fpr64(ctx, fp0, fd);
10072 tcg_temp_free_i64(fp0);
10074 break;
10075 case OPC_ROUND_W_D:
10076 check_cp1_registers(ctx, fs);
10078 TCGv_i32 fp32 = tcg_temp_new_i32();
10079 TCGv_i64 fp64 = tcg_temp_new_i64();
10081 gen_load_fpr64(ctx, fp64, fs);
10082 if (ctx->nan2008) {
10083 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10084 } else {
10085 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10087 tcg_temp_free_i64(fp64);
10088 gen_store_fpr32(ctx, fp32, fd);
10089 tcg_temp_free_i32(fp32);
10091 break;
10092 case OPC_TRUNC_W_D:
10093 check_cp1_registers(ctx, fs);
10095 TCGv_i32 fp32 = tcg_temp_new_i32();
10096 TCGv_i64 fp64 = tcg_temp_new_i64();
10098 gen_load_fpr64(ctx, fp64, fs);
10099 if (ctx->nan2008) {
10100 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10101 } else {
10102 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10104 tcg_temp_free_i64(fp64);
10105 gen_store_fpr32(ctx, fp32, fd);
10106 tcg_temp_free_i32(fp32);
10108 break;
10109 case OPC_CEIL_W_D:
10110 check_cp1_registers(ctx, fs);
10112 TCGv_i32 fp32 = tcg_temp_new_i32();
10113 TCGv_i64 fp64 = tcg_temp_new_i64();
10115 gen_load_fpr64(ctx, fp64, fs);
10116 if (ctx->nan2008) {
10117 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10118 } else {
10119 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10121 tcg_temp_free_i64(fp64);
10122 gen_store_fpr32(ctx, fp32, fd);
10123 tcg_temp_free_i32(fp32);
10125 break;
10126 case OPC_FLOOR_W_D:
10127 check_cp1_registers(ctx, fs);
10129 TCGv_i32 fp32 = tcg_temp_new_i32();
10130 TCGv_i64 fp64 = tcg_temp_new_i64();
10132 gen_load_fpr64(ctx, fp64, fs);
10133 if (ctx->nan2008) {
10134 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10135 } else {
10136 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10138 tcg_temp_free_i64(fp64);
10139 gen_store_fpr32(ctx, fp32, fd);
10140 tcg_temp_free_i32(fp32);
10142 break;
10143 case OPC_SEL_D:
10144 check_insn(ctx, ISA_MIPS32R6);
10145 gen_sel_d(ctx, op1, fd, ft, fs);
10146 break;
10147 case OPC_SELEQZ_D:
10148 check_insn(ctx, ISA_MIPS32R6);
10149 gen_sel_d(ctx, op1, fd, ft, fs);
10150 break;
10151 case OPC_SELNEZ_D:
10152 check_insn(ctx, ISA_MIPS32R6);
10153 gen_sel_d(ctx, op1, fd, ft, fs);
10154 break;
10155 case OPC_MOVCF_D:
10156 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10157 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10158 break;
10159 case OPC_MOVZ_D:
10160 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10162 TCGLabel *l1 = gen_new_label();
10163 TCGv_i64 fp0;
10165 if (ft != 0) {
10166 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10168 fp0 = tcg_temp_new_i64();
10169 gen_load_fpr64(ctx, fp0, fs);
10170 gen_store_fpr64(ctx, fp0, fd);
10171 tcg_temp_free_i64(fp0);
10172 gen_set_label(l1);
10174 break;
10175 case OPC_MOVN_D:
10176 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10178 TCGLabel *l1 = gen_new_label();
10179 TCGv_i64 fp0;
10181 if (ft != 0) {
10182 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10183 fp0 = tcg_temp_new_i64();
10184 gen_load_fpr64(ctx, fp0, fs);
10185 gen_store_fpr64(ctx, fp0, fd);
10186 tcg_temp_free_i64(fp0);
10187 gen_set_label(l1);
10190 break;
10191 case OPC_RECIP_D:
10192 check_cp1_registers(ctx, fs | fd);
10194 TCGv_i64 fp0 = tcg_temp_new_i64();
10196 gen_load_fpr64(ctx, fp0, fs);
10197 gen_helper_float_recip_d(fp0, cpu_env, fp0);
10198 gen_store_fpr64(ctx, fp0, fd);
10199 tcg_temp_free_i64(fp0);
10201 break;
10202 case OPC_RSQRT_D:
10203 check_cp1_registers(ctx, fs | fd);
10205 TCGv_i64 fp0 = tcg_temp_new_i64();
10207 gen_load_fpr64(ctx, fp0, fs);
10208 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
10209 gen_store_fpr64(ctx, fp0, fd);
10210 tcg_temp_free_i64(fp0);
10212 break;
10213 case OPC_MADDF_D:
10214 check_insn(ctx, ISA_MIPS32R6);
10216 TCGv_i64 fp0 = tcg_temp_new_i64();
10217 TCGv_i64 fp1 = tcg_temp_new_i64();
10218 TCGv_i64 fp2 = tcg_temp_new_i64();
10219 gen_load_fpr64(ctx, fp0, fs);
10220 gen_load_fpr64(ctx, fp1, ft);
10221 gen_load_fpr64(ctx, fp2, fd);
10222 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
10223 gen_store_fpr64(ctx, fp2, fd);
10224 tcg_temp_free_i64(fp2);
10225 tcg_temp_free_i64(fp1);
10226 tcg_temp_free_i64(fp0);
10228 break;
10229 case OPC_MSUBF_D:
10230 check_insn(ctx, ISA_MIPS32R6);
10232 TCGv_i64 fp0 = tcg_temp_new_i64();
10233 TCGv_i64 fp1 = tcg_temp_new_i64();
10234 TCGv_i64 fp2 = tcg_temp_new_i64();
10235 gen_load_fpr64(ctx, fp0, fs);
10236 gen_load_fpr64(ctx, fp1, ft);
10237 gen_load_fpr64(ctx, fp2, fd);
10238 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
10239 gen_store_fpr64(ctx, fp2, fd);
10240 tcg_temp_free_i64(fp2);
10241 tcg_temp_free_i64(fp1);
10242 tcg_temp_free_i64(fp0);
10244 break;
10245 case OPC_RINT_D:
10246 check_insn(ctx, ISA_MIPS32R6);
10248 TCGv_i64 fp0 = tcg_temp_new_i64();
10249 gen_load_fpr64(ctx, fp0, fs);
10250 gen_helper_float_rint_d(fp0, cpu_env, fp0);
10251 gen_store_fpr64(ctx, fp0, fd);
10252 tcg_temp_free_i64(fp0);
10254 break;
10255 case OPC_CLASS_D:
10256 check_insn(ctx, ISA_MIPS32R6);
10258 TCGv_i64 fp0 = tcg_temp_new_i64();
10259 gen_load_fpr64(ctx, fp0, fs);
10260 gen_helper_float_class_d(fp0, cpu_env, fp0);
10261 gen_store_fpr64(ctx, fp0, fd);
10262 tcg_temp_free_i64(fp0);
10264 break;
10265 case OPC_MIN_D: /* OPC_RECIP2_D */
10266 if (ctx->insn_flags & ISA_MIPS32R6) {
10267 /* OPC_MIN_D */
10268 TCGv_i64 fp0 = tcg_temp_new_i64();
10269 TCGv_i64 fp1 = tcg_temp_new_i64();
10270 gen_load_fpr64(ctx, fp0, fs);
10271 gen_load_fpr64(ctx, fp1, ft);
10272 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
10273 gen_store_fpr64(ctx, fp1, fd);
10274 tcg_temp_free_i64(fp1);
10275 tcg_temp_free_i64(fp0);
10276 } else {
10277 /* OPC_RECIP2_D */
10278 check_cp1_64bitmode(ctx);
10280 TCGv_i64 fp0 = tcg_temp_new_i64();
10281 TCGv_i64 fp1 = tcg_temp_new_i64();
10283 gen_load_fpr64(ctx, fp0, fs);
10284 gen_load_fpr64(ctx, fp1, ft);
10285 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
10286 tcg_temp_free_i64(fp1);
10287 gen_store_fpr64(ctx, fp0, fd);
10288 tcg_temp_free_i64(fp0);
10291 break;
10292 case OPC_MINA_D: /* OPC_RECIP1_D */
10293 if (ctx->insn_flags & ISA_MIPS32R6) {
10294 /* OPC_MINA_D */
10295 TCGv_i64 fp0 = tcg_temp_new_i64();
10296 TCGv_i64 fp1 = tcg_temp_new_i64();
10297 gen_load_fpr64(ctx, fp0, fs);
10298 gen_load_fpr64(ctx, fp1, ft);
10299 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
10300 gen_store_fpr64(ctx, fp1, fd);
10301 tcg_temp_free_i64(fp1);
10302 tcg_temp_free_i64(fp0);
10303 } else {
10304 /* OPC_RECIP1_D */
10305 check_cp1_64bitmode(ctx);
10307 TCGv_i64 fp0 = tcg_temp_new_i64();
10309 gen_load_fpr64(ctx, fp0, fs);
10310 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
10311 gen_store_fpr64(ctx, fp0, fd);
10312 tcg_temp_free_i64(fp0);
10315 break;
10316 case OPC_MAX_D: /* OPC_RSQRT1_D */
10317 if (ctx->insn_flags & ISA_MIPS32R6) {
10318 /* OPC_MAX_D */
10319 TCGv_i64 fp0 = tcg_temp_new_i64();
10320 TCGv_i64 fp1 = tcg_temp_new_i64();
10321 gen_load_fpr64(ctx, fp0, fs);
10322 gen_load_fpr64(ctx, fp1, ft);
10323 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
10324 gen_store_fpr64(ctx, fp1, fd);
10325 tcg_temp_free_i64(fp1);
10326 tcg_temp_free_i64(fp0);
10327 } else {
10328 /* OPC_RSQRT1_D */
10329 check_cp1_64bitmode(ctx);
10331 TCGv_i64 fp0 = tcg_temp_new_i64();
10333 gen_load_fpr64(ctx, fp0, fs);
10334 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
10335 gen_store_fpr64(ctx, fp0, fd);
10336 tcg_temp_free_i64(fp0);
10339 break;
10340 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10341 if (ctx->insn_flags & ISA_MIPS32R6) {
10342 /* OPC_MAXA_D */
10343 TCGv_i64 fp0 = tcg_temp_new_i64();
10344 TCGv_i64 fp1 = tcg_temp_new_i64();
10345 gen_load_fpr64(ctx, fp0, fs);
10346 gen_load_fpr64(ctx, fp1, ft);
10347 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10348 gen_store_fpr64(ctx, fp1, fd);
10349 tcg_temp_free_i64(fp1);
10350 tcg_temp_free_i64(fp0);
10351 } else {
10352 /* OPC_RSQRT2_D */
10353 check_cp1_64bitmode(ctx);
10355 TCGv_i64 fp0 = tcg_temp_new_i64();
10356 TCGv_i64 fp1 = tcg_temp_new_i64();
10358 gen_load_fpr64(ctx, fp0, fs);
10359 gen_load_fpr64(ctx, fp1, ft);
10360 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10361 tcg_temp_free_i64(fp1);
10362 gen_store_fpr64(ctx, fp0, fd);
10363 tcg_temp_free_i64(fp0);
10366 break;
10367 case OPC_CMP_F_D:
10368 case OPC_CMP_UN_D:
10369 case OPC_CMP_EQ_D:
10370 case OPC_CMP_UEQ_D:
10371 case OPC_CMP_OLT_D:
10372 case OPC_CMP_ULT_D:
10373 case OPC_CMP_OLE_D:
10374 case OPC_CMP_ULE_D:
10375 case OPC_CMP_SF_D:
10376 case OPC_CMP_NGLE_D:
10377 case OPC_CMP_SEQ_D:
10378 case OPC_CMP_NGL_D:
10379 case OPC_CMP_LT_D:
10380 case OPC_CMP_NGE_D:
10381 case OPC_CMP_LE_D:
10382 case OPC_CMP_NGT_D:
10383 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10384 if (ctx->opcode & (1 << 6)) {
10385 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
10386 } else {
10387 gen_cmp_d(ctx, func-48, ft, fs, cc);
10389 break;
10390 case OPC_CVT_S_D:
10391 check_cp1_registers(ctx, fs);
10393 TCGv_i32 fp32 = tcg_temp_new_i32();
10394 TCGv_i64 fp64 = tcg_temp_new_i64();
10396 gen_load_fpr64(ctx, fp64, fs);
10397 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
10398 tcg_temp_free_i64(fp64);
10399 gen_store_fpr32(ctx, fp32, fd);
10400 tcg_temp_free_i32(fp32);
10402 break;
10403 case OPC_CVT_W_D:
10404 check_cp1_registers(ctx, fs);
10406 TCGv_i32 fp32 = tcg_temp_new_i32();
10407 TCGv_i64 fp64 = tcg_temp_new_i64();
10409 gen_load_fpr64(ctx, fp64, fs);
10410 if (ctx->nan2008) {
10411 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
10412 } else {
10413 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
10415 tcg_temp_free_i64(fp64);
10416 gen_store_fpr32(ctx, fp32, fd);
10417 tcg_temp_free_i32(fp32);
10419 break;
10420 case OPC_CVT_L_D:
10421 check_cp1_64bitmode(ctx);
10423 TCGv_i64 fp0 = tcg_temp_new_i64();
10425 gen_load_fpr64(ctx, fp0, fs);
10426 if (ctx->nan2008) {
10427 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
10428 } else {
10429 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
10431 gen_store_fpr64(ctx, fp0, fd);
10432 tcg_temp_free_i64(fp0);
10434 break;
10435 case OPC_CVT_S_W:
10437 TCGv_i32 fp0 = tcg_temp_new_i32();
10439 gen_load_fpr32(ctx, fp0, fs);
10440 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
10441 gen_store_fpr32(ctx, fp0, fd);
10442 tcg_temp_free_i32(fp0);
10444 break;
10445 case OPC_CVT_D_W:
10446 check_cp1_registers(ctx, fd);
10448 TCGv_i32 fp32 = tcg_temp_new_i32();
10449 TCGv_i64 fp64 = tcg_temp_new_i64();
10451 gen_load_fpr32(ctx, fp32, fs);
10452 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
10453 tcg_temp_free_i32(fp32);
10454 gen_store_fpr64(ctx, fp64, fd);
10455 tcg_temp_free_i64(fp64);
10457 break;
10458 case OPC_CVT_S_L:
10459 check_cp1_64bitmode(ctx);
10461 TCGv_i32 fp32 = tcg_temp_new_i32();
10462 TCGv_i64 fp64 = tcg_temp_new_i64();
10464 gen_load_fpr64(ctx, fp64, fs);
10465 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10466 tcg_temp_free_i64(fp64);
10467 gen_store_fpr32(ctx, fp32, fd);
10468 tcg_temp_free_i32(fp32);
10470 break;
10471 case OPC_CVT_D_L:
10472 check_cp1_64bitmode(ctx);
10474 TCGv_i64 fp0 = tcg_temp_new_i64();
10476 gen_load_fpr64(ctx, fp0, fs);
10477 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10478 gen_store_fpr64(ctx, fp0, fd);
10479 tcg_temp_free_i64(fp0);
10481 break;
10482 case OPC_CVT_PS_PW:
10483 check_ps(ctx);
10485 TCGv_i64 fp0 = tcg_temp_new_i64();
10487 gen_load_fpr64(ctx, fp0, fs);
10488 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
10489 gen_store_fpr64(ctx, fp0, fd);
10490 tcg_temp_free_i64(fp0);
10492 break;
10493 case OPC_ADD_PS:
10494 check_ps(ctx);
10496 TCGv_i64 fp0 = tcg_temp_new_i64();
10497 TCGv_i64 fp1 = tcg_temp_new_i64();
10499 gen_load_fpr64(ctx, fp0, fs);
10500 gen_load_fpr64(ctx, fp1, ft);
10501 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
10502 tcg_temp_free_i64(fp1);
10503 gen_store_fpr64(ctx, fp0, fd);
10504 tcg_temp_free_i64(fp0);
10506 break;
10507 case OPC_SUB_PS:
10508 check_ps(ctx);
10510 TCGv_i64 fp0 = tcg_temp_new_i64();
10511 TCGv_i64 fp1 = tcg_temp_new_i64();
10513 gen_load_fpr64(ctx, fp0, fs);
10514 gen_load_fpr64(ctx, fp1, ft);
10515 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
10516 tcg_temp_free_i64(fp1);
10517 gen_store_fpr64(ctx, fp0, fd);
10518 tcg_temp_free_i64(fp0);
10520 break;
10521 case OPC_MUL_PS:
10522 check_ps(ctx);
10524 TCGv_i64 fp0 = tcg_temp_new_i64();
10525 TCGv_i64 fp1 = tcg_temp_new_i64();
10527 gen_load_fpr64(ctx, fp0, fs);
10528 gen_load_fpr64(ctx, fp1, ft);
10529 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
10530 tcg_temp_free_i64(fp1);
10531 gen_store_fpr64(ctx, fp0, fd);
10532 tcg_temp_free_i64(fp0);
10534 break;
10535 case OPC_ABS_PS:
10536 check_ps(ctx);
10538 TCGv_i64 fp0 = tcg_temp_new_i64();
10540 gen_load_fpr64(ctx, fp0, fs);
10541 gen_helper_float_abs_ps(fp0, fp0);
10542 gen_store_fpr64(ctx, fp0, fd);
10543 tcg_temp_free_i64(fp0);
10545 break;
10546 case OPC_MOV_PS:
10547 check_ps(ctx);
10549 TCGv_i64 fp0 = tcg_temp_new_i64();
10551 gen_load_fpr64(ctx, fp0, fs);
10552 gen_store_fpr64(ctx, fp0, fd);
10553 tcg_temp_free_i64(fp0);
10555 break;
10556 case OPC_NEG_PS:
10557 check_ps(ctx);
10559 TCGv_i64 fp0 = tcg_temp_new_i64();
10561 gen_load_fpr64(ctx, fp0, fs);
10562 gen_helper_float_chs_ps(fp0, fp0);
10563 gen_store_fpr64(ctx, fp0, fd);
10564 tcg_temp_free_i64(fp0);
10566 break;
10567 case OPC_MOVCF_PS:
10568 check_ps(ctx);
10569 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10570 break;
10571 case OPC_MOVZ_PS:
10572 check_ps(ctx);
10574 TCGLabel *l1 = gen_new_label();
10575 TCGv_i64 fp0;
10577 if (ft != 0)
10578 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10579 fp0 = tcg_temp_new_i64();
10580 gen_load_fpr64(ctx, fp0, fs);
10581 gen_store_fpr64(ctx, fp0, fd);
10582 tcg_temp_free_i64(fp0);
10583 gen_set_label(l1);
10585 break;
10586 case OPC_MOVN_PS:
10587 check_ps(ctx);
10589 TCGLabel *l1 = gen_new_label();
10590 TCGv_i64 fp0;
10592 if (ft != 0) {
10593 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10594 fp0 = tcg_temp_new_i64();
10595 gen_load_fpr64(ctx, fp0, fs);
10596 gen_store_fpr64(ctx, fp0, fd);
10597 tcg_temp_free_i64(fp0);
10598 gen_set_label(l1);
10601 break;
10602 case OPC_ADDR_PS:
10603 check_ps(ctx);
10605 TCGv_i64 fp0 = tcg_temp_new_i64();
10606 TCGv_i64 fp1 = tcg_temp_new_i64();
10608 gen_load_fpr64(ctx, fp0, ft);
10609 gen_load_fpr64(ctx, fp1, fs);
10610 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10611 tcg_temp_free_i64(fp1);
10612 gen_store_fpr64(ctx, fp0, fd);
10613 tcg_temp_free_i64(fp0);
10615 break;
10616 case OPC_MULR_PS:
10617 check_ps(ctx);
10619 TCGv_i64 fp0 = tcg_temp_new_i64();
10620 TCGv_i64 fp1 = tcg_temp_new_i64();
10622 gen_load_fpr64(ctx, fp0, ft);
10623 gen_load_fpr64(ctx, fp1, fs);
10624 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10625 tcg_temp_free_i64(fp1);
10626 gen_store_fpr64(ctx, fp0, fd);
10627 tcg_temp_free_i64(fp0);
10629 break;
10630 case OPC_RECIP2_PS:
10631 check_ps(ctx);
10633 TCGv_i64 fp0 = tcg_temp_new_i64();
10634 TCGv_i64 fp1 = tcg_temp_new_i64();
10636 gen_load_fpr64(ctx, fp0, fs);
10637 gen_load_fpr64(ctx, fp1, ft);
10638 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10639 tcg_temp_free_i64(fp1);
10640 gen_store_fpr64(ctx, fp0, fd);
10641 tcg_temp_free_i64(fp0);
10643 break;
10644 case OPC_RECIP1_PS:
10645 check_ps(ctx);
10647 TCGv_i64 fp0 = tcg_temp_new_i64();
10649 gen_load_fpr64(ctx, fp0, fs);
10650 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10651 gen_store_fpr64(ctx, fp0, fd);
10652 tcg_temp_free_i64(fp0);
10654 break;
10655 case OPC_RSQRT1_PS:
10656 check_ps(ctx);
10658 TCGv_i64 fp0 = tcg_temp_new_i64();
10660 gen_load_fpr64(ctx, fp0, fs);
10661 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10662 gen_store_fpr64(ctx, fp0, fd);
10663 tcg_temp_free_i64(fp0);
10665 break;
10666 case OPC_RSQRT2_PS:
10667 check_ps(ctx);
10669 TCGv_i64 fp0 = tcg_temp_new_i64();
10670 TCGv_i64 fp1 = tcg_temp_new_i64();
10672 gen_load_fpr64(ctx, fp0, fs);
10673 gen_load_fpr64(ctx, fp1, ft);
10674 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10675 tcg_temp_free_i64(fp1);
10676 gen_store_fpr64(ctx, fp0, fd);
10677 tcg_temp_free_i64(fp0);
10679 break;
10680 case OPC_CVT_S_PU:
10681 check_cp1_64bitmode(ctx);
10683 TCGv_i32 fp0 = tcg_temp_new_i32();
10685 gen_load_fpr32h(ctx, fp0, fs);
10686 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10687 gen_store_fpr32(ctx, fp0, fd);
10688 tcg_temp_free_i32(fp0);
10690 break;
10691 case OPC_CVT_PW_PS:
10692 check_ps(ctx);
10694 TCGv_i64 fp0 = tcg_temp_new_i64();
10696 gen_load_fpr64(ctx, fp0, fs);
10697 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10698 gen_store_fpr64(ctx, fp0, fd);
10699 tcg_temp_free_i64(fp0);
10701 break;
10702 case OPC_CVT_S_PL:
10703 check_cp1_64bitmode(ctx);
10705 TCGv_i32 fp0 = tcg_temp_new_i32();
10707 gen_load_fpr32(ctx, fp0, fs);
10708 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10709 gen_store_fpr32(ctx, fp0, fd);
10710 tcg_temp_free_i32(fp0);
10712 break;
10713 case OPC_PLL_PS:
10714 check_ps(ctx);
10716 TCGv_i32 fp0 = tcg_temp_new_i32();
10717 TCGv_i32 fp1 = tcg_temp_new_i32();
10719 gen_load_fpr32(ctx, fp0, fs);
10720 gen_load_fpr32(ctx, fp1, ft);
10721 gen_store_fpr32h(ctx, fp0, fd);
10722 gen_store_fpr32(ctx, fp1, fd);
10723 tcg_temp_free_i32(fp0);
10724 tcg_temp_free_i32(fp1);
10726 break;
10727 case OPC_PLU_PS:
10728 check_ps(ctx);
10730 TCGv_i32 fp0 = tcg_temp_new_i32();
10731 TCGv_i32 fp1 = tcg_temp_new_i32();
10733 gen_load_fpr32(ctx, fp0, fs);
10734 gen_load_fpr32h(ctx, fp1, ft);
10735 gen_store_fpr32(ctx, fp1, fd);
10736 gen_store_fpr32h(ctx, fp0, fd);
10737 tcg_temp_free_i32(fp0);
10738 tcg_temp_free_i32(fp1);
10740 break;
10741 case OPC_PUL_PS:
10742 check_ps(ctx);
10744 TCGv_i32 fp0 = tcg_temp_new_i32();
10745 TCGv_i32 fp1 = tcg_temp_new_i32();
10747 gen_load_fpr32h(ctx, fp0, fs);
10748 gen_load_fpr32(ctx, fp1, ft);
10749 gen_store_fpr32(ctx, fp1, fd);
10750 gen_store_fpr32h(ctx, fp0, fd);
10751 tcg_temp_free_i32(fp0);
10752 tcg_temp_free_i32(fp1);
10754 break;
10755 case OPC_PUU_PS:
10756 check_ps(ctx);
10758 TCGv_i32 fp0 = tcg_temp_new_i32();
10759 TCGv_i32 fp1 = tcg_temp_new_i32();
10761 gen_load_fpr32h(ctx, fp0, fs);
10762 gen_load_fpr32h(ctx, fp1, ft);
10763 gen_store_fpr32(ctx, fp1, fd);
10764 gen_store_fpr32h(ctx, fp0, fd);
10765 tcg_temp_free_i32(fp0);
10766 tcg_temp_free_i32(fp1);
10768 break;
10769 case OPC_CMP_F_PS:
10770 case OPC_CMP_UN_PS:
10771 case OPC_CMP_EQ_PS:
10772 case OPC_CMP_UEQ_PS:
10773 case OPC_CMP_OLT_PS:
10774 case OPC_CMP_ULT_PS:
10775 case OPC_CMP_OLE_PS:
10776 case OPC_CMP_ULE_PS:
10777 case OPC_CMP_SF_PS:
10778 case OPC_CMP_NGLE_PS:
10779 case OPC_CMP_SEQ_PS:
10780 case OPC_CMP_NGL_PS:
10781 case OPC_CMP_LT_PS:
10782 case OPC_CMP_NGE_PS:
10783 case OPC_CMP_LE_PS:
10784 case OPC_CMP_NGT_PS:
10785 if (ctx->opcode & (1 << 6)) {
10786 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10787 } else {
10788 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10790 break;
10791 default:
10792 MIPS_INVAL("farith");
10793 generate_exception_end(ctx, EXCP_RI);
10794 return;
10798 /* Coprocessor 3 (FPU) */
10799 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10800 int fd, int fs, int base, int index)
10802 TCGv t0 = tcg_temp_new();
10804 if (base == 0) {
10805 gen_load_gpr(t0, index);
10806 } else if (index == 0) {
10807 gen_load_gpr(t0, base);
10808 } else {
10809 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10811 /* Don't do NOP if destination is zero: we must perform the actual
10812 memory access. */
10813 switch (opc) {
10814 case OPC_LWXC1:
10815 check_cop1x(ctx);
10817 TCGv_i32 fp0 = tcg_temp_new_i32();
10819 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10820 tcg_gen_trunc_tl_i32(fp0, t0);
10821 gen_store_fpr32(ctx, fp0, fd);
10822 tcg_temp_free_i32(fp0);
10824 break;
10825 case OPC_LDXC1:
10826 check_cop1x(ctx);
10827 check_cp1_registers(ctx, fd);
10829 TCGv_i64 fp0 = tcg_temp_new_i64();
10830 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10831 gen_store_fpr64(ctx, fp0, fd);
10832 tcg_temp_free_i64(fp0);
10834 break;
10835 case OPC_LUXC1:
10836 check_cp1_64bitmode(ctx);
10837 tcg_gen_andi_tl(t0, t0, ~0x7);
10839 TCGv_i64 fp0 = tcg_temp_new_i64();
10841 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10842 gen_store_fpr64(ctx, fp0, fd);
10843 tcg_temp_free_i64(fp0);
10845 break;
10846 case OPC_SWXC1:
10847 check_cop1x(ctx);
10849 TCGv_i32 fp0 = tcg_temp_new_i32();
10850 gen_load_fpr32(ctx, fp0, fs);
10851 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10852 tcg_temp_free_i32(fp0);
10854 break;
10855 case OPC_SDXC1:
10856 check_cop1x(ctx);
10857 check_cp1_registers(ctx, fs);
10859 TCGv_i64 fp0 = tcg_temp_new_i64();
10860 gen_load_fpr64(ctx, fp0, fs);
10861 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10862 tcg_temp_free_i64(fp0);
10864 break;
10865 case OPC_SUXC1:
10866 check_cp1_64bitmode(ctx);
10867 tcg_gen_andi_tl(t0, t0, ~0x7);
10869 TCGv_i64 fp0 = tcg_temp_new_i64();
10870 gen_load_fpr64(ctx, fp0, fs);
10871 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10872 tcg_temp_free_i64(fp0);
10874 break;
10876 tcg_temp_free(t0);
10879 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10880 int fd, int fr, int fs, int ft)
10882 switch (opc) {
10883 case OPC_ALNV_PS:
10884 check_ps(ctx);
10886 TCGv t0 = tcg_temp_local_new();
10887 TCGv_i32 fp = tcg_temp_new_i32();
10888 TCGv_i32 fph = tcg_temp_new_i32();
10889 TCGLabel *l1 = gen_new_label();
10890 TCGLabel *l2 = gen_new_label();
10892 gen_load_gpr(t0, fr);
10893 tcg_gen_andi_tl(t0, t0, 0x7);
10895 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10896 gen_load_fpr32(ctx, fp, fs);
10897 gen_load_fpr32h(ctx, fph, fs);
10898 gen_store_fpr32(ctx, fp, fd);
10899 gen_store_fpr32h(ctx, fph, fd);
10900 tcg_gen_br(l2);
10901 gen_set_label(l1);
10902 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10903 tcg_temp_free(t0);
10904 #ifdef TARGET_WORDS_BIGENDIAN
10905 gen_load_fpr32(ctx, fp, fs);
10906 gen_load_fpr32h(ctx, fph, ft);
10907 gen_store_fpr32h(ctx, fp, fd);
10908 gen_store_fpr32(ctx, fph, fd);
10909 #else
10910 gen_load_fpr32h(ctx, fph, fs);
10911 gen_load_fpr32(ctx, fp, ft);
10912 gen_store_fpr32(ctx, fph, fd);
10913 gen_store_fpr32h(ctx, fp, fd);
10914 #endif
10915 gen_set_label(l2);
10916 tcg_temp_free_i32(fp);
10917 tcg_temp_free_i32(fph);
10919 break;
10920 case OPC_MADD_S:
10921 check_cop1x(ctx);
10923 TCGv_i32 fp0 = tcg_temp_new_i32();
10924 TCGv_i32 fp1 = tcg_temp_new_i32();
10925 TCGv_i32 fp2 = tcg_temp_new_i32();
10927 gen_load_fpr32(ctx, fp0, fs);
10928 gen_load_fpr32(ctx, fp1, ft);
10929 gen_load_fpr32(ctx, fp2, fr);
10930 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10931 tcg_temp_free_i32(fp0);
10932 tcg_temp_free_i32(fp1);
10933 gen_store_fpr32(ctx, fp2, fd);
10934 tcg_temp_free_i32(fp2);
10936 break;
10937 case OPC_MADD_D:
10938 check_cop1x(ctx);
10939 check_cp1_registers(ctx, fd | fs | ft | fr);
10941 TCGv_i64 fp0 = tcg_temp_new_i64();
10942 TCGv_i64 fp1 = tcg_temp_new_i64();
10943 TCGv_i64 fp2 = tcg_temp_new_i64();
10945 gen_load_fpr64(ctx, fp0, fs);
10946 gen_load_fpr64(ctx, fp1, ft);
10947 gen_load_fpr64(ctx, fp2, fr);
10948 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10949 tcg_temp_free_i64(fp0);
10950 tcg_temp_free_i64(fp1);
10951 gen_store_fpr64(ctx, fp2, fd);
10952 tcg_temp_free_i64(fp2);
10954 break;
10955 case OPC_MADD_PS:
10956 check_ps(ctx);
10958 TCGv_i64 fp0 = tcg_temp_new_i64();
10959 TCGv_i64 fp1 = tcg_temp_new_i64();
10960 TCGv_i64 fp2 = tcg_temp_new_i64();
10962 gen_load_fpr64(ctx, fp0, fs);
10963 gen_load_fpr64(ctx, fp1, ft);
10964 gen_load_fpr64(ctx, fp2, fr);
10965 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10966 tcg_temp_free_i64(fp0);
10967 tcg_temp_free_i64(fp1);
10968 gen_store_fpr64(ctx, fp2, fd);
10969 tcg_temp_free_i64(fp2);
10971 break;
10972 case OPC_MSUB_S:
10973 check_cop1x(ctx);
10975 TCGv_i32 fp0 = tcg_temp_new_i32();
10976 TCGv_i32 fp1 = tcg_temp_new_i32();
10977 TCGv_i32 fp2 = tcg_temp_new_i32();
10979 gen_load_fpr32(ctx, fp0, fs);
10980 gen_load_fpr32(ctx, fp1, ft);
10981 gen_load_fpr32(ctx, fp2, fr);
10982 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10983 tcg_temp_free_i32(fp0);
10984 tcg_temp_free_i32(fp1);
10985 gen_store_fpr32(ctx, fp2, fd);
10986 tcg_temp_free_i32(fp2);
10988 break;
10989 case OPC_MSUB_D:
10990 check_cop1x(ctx);
10991 check_cp1_registers(ctx, fd | fs | ft | fr);
10993 TCGv_i64 fp0 = tcg_temp_new_i64();
10994 TCGv_i64 fp1 = tcg_temp_new_i64();
10995 TCGv_i64 fp2 = tcg_temp_new_i64();
10997 gen_load_fpr64(ctx, fp0, fs);
10998 gen_load_fpr64(ctx, fp1, ft);
10999 gen_load_fpr64(ctx, fp2, fr);
11000 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11001 tcg_temp_free_i64(fp0);
11002 tcg_temp_free_i64(fp1);
11003 gen_store_fpr64(ctx, fp2, fd);
11004 tcg_temp_free_i64(fp2);
11006 break;
11007 case OPC_MSUB_PS:
11008 check_ps(ctx);
11010 TCGv_i64 fp0 = tcg_temp_new_i64();
11011 TCGv_i64 fp1 = tcg_temp_new_i64();
11012 TCGv_i64 fp2 = tcg_temp_new_i64();
11014 gen_load_fpr64(ctx, fp0, fs);
11015 gen_load_fpr64(ctx, fp1, ft);
11016 gen_load_fpr64(ctx, fp2, fr);
11017 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11018 tcg_temp_free_i64(fp0);
11019 tcg_temp_free_i64(fp1);
11020 gen_store_fpr64(ctx, fp2, fd);
11021 tcg_temp_free_i64(fp2);
11023 break;
11024 case OPC_NMADD_S:
11025 check_cop1x(ctx);
11027 TCGv_i32 fp0 = tcg_temp_new_i32();
11028 TCGv_i32 fp1 = tcg_temp_new_i32();
11029 TCGv_i32 fp2 = tcg_temp_new_i32();
11031 gen_load_fpr32(ctx, fp0, fs);
11032 gen_load_fpr32(ctx, fp1, ft);
11033 gen_load_fpr32(ctx, fp2, fr);
11034 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11035 tcg_temp_free_i32(fp0);
11036 tcg_temp_free_i32(fp1);
11037 gen_store_fpr32(ctx, fp2, fd);
11038 tcg_temp_free_i32(fp2);
11040 break;
11041 case OPC_NMADD_D:
11042 check_cop1x(ctx);
11043 check_cp1_registers(ctx, fd | fs | ft | fr);
11045 TCGv_i64 fp0 = tcg_temp_new_i64();
11046 TCGv_i64 fp1 = tcg_temp_new_i64();
11047 TCGv_i64 fp2 = tcg_temp_new_i64();
11049 gen_load_fpr64(ctx, fp0, fs);
11050 gen_load_fpr64(ctx, fp1, ft);
11051 gen_load_fpr64(ctx, fp2, fr);
11052 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11053 tcg_temp_free_i64(fp0);
11054 tcg_temp_free_i64(fp1);
11055 gen_store_fpr64(ctx, fp2, fd);
11056 tcg_temp_free_i64(fp2);
11058 break;
11059 case OPC_NMADD_PS:
11060 check_ps(ctx);
11062 TCGv_i64 fp0 = tcg_temp_new_i64();
11063 TCGv_i64 fp1 = tcg_temp_new_i64();
11064 TCGv_i64 fp2 = tcg_temp_new_i64();
11066 gen_load_fpr64(ctx, fp0, fs);
11067 gen_load_fpr64(ctx, fp1, ft);
11068 gen_load_fpr64(ctx, fp2, fr);
11069 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11070 tcg_temp_free_i64(fp0);
11071 tcg_temp_free_i64(fp1);
11072 gen_store_fpr64(ctx, fp2, fd);
11073 tcg_temp_free_i64(fp2);
11075 break;
11076 case OPC_NMSUB_S:
11077 check_cop1x(ctx);
11079 TCGv_i32 fp0 = tcg_temp_new_i32();
11080 TCGv_i32 fp1 = tcg_temp_new_i32();
11081 TCGv_i32 fp2 = tcg_temp_new_i32();
11083 gen_load_fpr32(ctx, fp0, fs);
11084 gen_load_fpr32(ctx, fp1, ft);
11085 gen_load_fpr32(ctx, fp2, fr);
11086 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11087 tcg_temp_free_i32(fp0);
11088 tcg_temp_free_i32(fp1);
11089 gen_store_fpr32(ctx, fp2, fd);
11090 tcg_temp_free_i32(fp2);
11092 break;
11093 case OPC_NMSUB_D:
11094 check_cop1x(ctx);
11095 check_cp1_registers(ctx, fd | fs | ft | fr);
11097 TCGv_i64 fp0 = tcg_temp_new_i64();
11098 TCGv_i64 fp1 = tcg_temp_new_i64();
11099 TCGv_i64 fp2 = tcg_temp_new_i64();
11101 gen_load_fpr64(ctx, fp0, fs);
11102 gen_load_fpr64(ctx, fp1, ft);
11103 gen_load_fpr64(ctx, fp2, fr);
11104 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11105 tcg_temp_free_i64(fp0);
11106 tcg_temp_free_i64(fp1);
11107 gen_store_fpr64(ctx, fp2, fd);
11108 tcg_temp_free_i64(fp2);
11110 break;
11111 case OPC_NMSUB_PS:
11112 check_ps(ctx);
11114 TCGv_i64 fp0 = tcg_temp_new_i64();
11115 TCGv_i64 fp1 = tcg_temp_new_i64();
11116 TCGv_i64 fp2 = tcg_temp_new_i64();
11118 gen_load_fpr64(ctx, fp0, fs);
11119 gen_load_fpr64(ctx, fp1, ft);
11120 gen_load_fpr64(ctx, fp2, fr);
11121 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11122 tcg_temp_free_i64(fp0);
11123 tcg_temp_free_i64(fp1);
11124 gen_store_fpr64(ctx, fp2, fd);
11125 tcg_temp_free_i64(fp2);
11127 break;
11128 default:
11129 MIPS_INVAL("flt3_arith");
11130 generate_exception_end(ctx, EXCP_RI);
11131 return;
11135 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11137 TCGv t0;
11139 #if !defined(CONFIG_USER_ONLY)
11140 /* The Linux kernel will emulate rdhwr if it's not supported natively.
11141 Therefore only check the ISA in system mode. */
11142 check_insn(ctx, ISA_MIPS32R2);
11143 #endif
11144 t0 = tcg_temp_new();
11146 switch (rd) {
11147 case 0:
11148 gen_helper_rdhwr_cpunum(t0, cpu_env);
11149 gen_store_gpr(t0, rt);
11150 break;
11151 case 1:
11152 gen_helper_rdhwr_synci_step(t0, cpu_env);
11153 gen_store_gpr(t0, rt);
11154 break;
11155 case 2:
11156 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11157 gen_io_start();
11159 gen_helper_rdhwr_cc(t0, cpu_env);
11160 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11161 gen_io_end();
11163 gen_store_gpr(t0, rt);
11164 /* Break the TB to be able to take timer interrupts immediately
11165 after reading count. DISAS_STOP isn't sufficient, we need to ensure
11166 we break completely out of translated code. */
11167 gen_save_pc(ctx->base.pc_next + 4);
11168 ctx->base.is_jmp = DISAS_EXIT;
11169 break;
11170 case 3:
11171 gen_helper_rdhwr_ccres(t0, cpu_env);
11172 gen_store_gpr(t0, rt);
11173 break;
11174 case 4:
11175 check_insn(ctx, ISA_MIPS32R6);
11176 if (sel != 0) {
11177 /* Performance counter registers are not implemented other than
11178 * control register 0.
11180 generate_exception(ctx, EXCP_RI);
11182 gen_helper_rdhwr_performance(t0, cpu_env);
11183 gen_store_gpr(t0, rt);
11184 break;
11185 case 5:
11186 check_insn(ctx, ISA_MIPS32R6);
11187 gen_helper_rdhwr_xnp(t0, cpu_env);
11188 gen_store_gpr(t0, rt);
11189 break;
11190 case 29:
11191 #if defined(CONFIG_USER_ONLY)
11192 tcg_gen_ld_tl(t0, cpu_env,
11193 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11194 gen_store_gpr(t0, rt);
11195 break;
11196 #else
11197 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11198 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
11199 tcg_gen_ld_tl(t0, cpu_env,
11200 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11201 gen_store_gpr(t0, rt);
11202 } else {
11203 generate_exception_end(ctx, EXCP_RI);
11205 break;
11206 #endif
11207 default: /* Invalid */
11208 MIPS_INVAL("rdhwr");
11209 generate_exception_end(ctx, EXCP_RI);
11210 break;
11212 tcg_temp_free(t0);
11215 static inline void clear_branch_hflags(DisasContext *ctx)
11217 ctx->hflags &= ~MIPS_HFLAG_BMASK;
11218 if (ctx->base.is_jmp == DISAS_NEXT) {
11219 save_cpu_state(ctx, 0);
11220 } else {
11221 /* it is not safe to save ctx->hflags as hflags may be changed
11222 in execution time by the instruction in delay / forbidden slot. */
11223 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11227 static void gen_branch(DisasContext *ctx, int insn_bytes)
11229 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11230 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
11231 /* Branches completion */
11232 clear_branch_hflags(ctx);
11233 ctx->base.is_jmp = DISAS_NORETURN;
11234 /* FIXME: Need to clear can_do_io. */
11235 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
11236 case MIPS_HFLAG_FBNSLOT:
11237 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
11238 break;
11239 case MIPS_HFLAG_B:
11240 /* unconditional branch */
11241 if (proc_hflags & MIPS_HFLAG_BX) {
11242 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11244 gen_goto_tb(ctx, 0, ctx->btarget);
11245 break;
11246 case MIPS_HFLAG_BL:
11247 /* blikely taken case */
11248 gen_goto_tb(ctx, 0, ctx->btarget);
11249 break;
11250 case MIPS_HFLAG_BC:
11251 /* Conditional branch */
11253 TCGLabel *l1 = gen_new_label();
11255 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11256 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
11257 gen_set_label(l1);
11258 gen_goto_tb(ctx, 0, ctx->btarget);
11260 break;
11261 case MIPS_HFLAG_BR:
11262 /* unconditional branch to register */
11263 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
11264 TCGv t0 = tcg_temp_new();
11265 TCGv_i32 t1 = tcg_temp_new_i32();
11267 tcg_gen_andi_tl(t0, btarget, 0x1);
11268 tcg_gen_trunc_tl_i32(t1, t0);
11269 tcg_temp_free(t0);
11270 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11271 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11272 tcg_gen_or_i32(hflags, hflags, t1);
11273 tcg_temp_free_i32(t1);
11275 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11276 } else {
11277 tcg_gen_mov_tl(cpu_PC, btarget);
11279 if (ctx->base.singlestep_enabled) {
11280 save_cpu_state(ctx, 0);
11281 gen_helper_raise_exception_debug(cpu_env);
11283 tcg_gen_lookup_and_goto_ptr();
11284 break;
11285 default:
11286 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11287 abort();
11292 /* Compact Branches */
11293 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11294 int rs, int rt, int32_t offset)
11296 int bcond_compute = 0;
11297 TCGv t0 = tcg_temp_new();
11298 TCGv t1 = tcg_temp_new();
11299 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11301 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11302 #ifdef MIPS_DEBUG_DISAS
11303 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11304 "\n", ctx->base.pc_next);
11305 #endif
11306 generate_exception_end(ctx, EXCP_RI);
11307 goto out;
11310 /* Load needed operands and calculate btarget */
11311 switch (opc) {
11312 /* compact branch */
11313 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11314 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11315 gen_load_gpr(t0, rs);
11316 gen_load_gpr(t1, rt);
11317 bcond_compute = 1;
11318 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11319 if (rs <= rt && rs == 0) {
11320 /* OPC_BEQZALC, OPC_BNEZALC */
11321 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11323 break;
11324 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11325 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11326 gen_load_gpr(t0, rs);
11327 gen_load_gpr(t1, rt);
11328 bcond_compute = 1;
11329 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11330 break;
11331 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11332 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11333 if (rs == 0 || rs == rt) {
11334 /* OPC_BLEZALC, OPC_BGEZALC */
11335 /* OPC_BGTZALC, OPC_BLTZALC */
11336 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11338 gen_load_gpr(t0, rs);
11339 gen_load_gpr(t1, rt);
11340 bcond_compute = 1;
11341 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11342 break;
11343 case OPC_BC:
11344 case OPC_BALC:
11345 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11346 break;
11347 case OPC_BEQZC:
11348 case OPC_BNEZC:
11349 if (rs != 0) {
11350 /* OPC_BEQZC, OPC_BNEZC */
11351 gen_load_gpr(t0, rs);
11352 bcond_compute = 1;
11353 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11354 } else {
11355 /* OPC_JIC, OPC_JIALC */
11356 TCGv tbase = tcg_temp_new();
11357 TCGv toffset = tcg_temp_new();
11359 gen_load_gpr(tbase, rt);
11360 tcg_gen_movi_tl(toffset, offset);
11361 gen_op_addr_add(ctx, btarget, tbase, toffset);
11362 tcg_temp_free(tbase);
11363 tcg_temp_free(toffset);
11365 break;
11366 default:
11367 MIPS_INVAL("Compact branch/jump");
11368 generate_exception_end(ctx, EXCP_RI);
11369 goto out;
11372 if (bcond_compute == 0) {
11373 /* Uncoditional compact branch */
11374 switch (opc) {
11375 case OPC_JIALC:
11376 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11377 /* Fallthrough */
11378 case OPC_JIC:
11379 ctx->hflags |= MIPS_HFLAG_BR;
11380 break;
11381 case OPC_BALC:
11382 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11383 /* Fallthrough */
11384 case OPC_BC:
11385 ctx->hflags |= MIPS_HFLAG_B;
11386 break;
11387 default:
11388 MIPS_INVAL("Compact branch/jump");
11389 generate_exception_end(ctx, EXCP_RI);
11390 goto out;
11393 /* Generating branch here as compact branches don't have delay slot */
11394 gen_branch(ctx, 4);
11395 } else {
11396 /* Conditional compact branch */
11397 TCGLabel *fs = gen_new_label();
11398 save_cpu_state(ctx, 0);
11400 switch (opc) {
11401 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11402 if (rs == 0 && rt != 0) {
11403 /* OPC_BLEZALC */
11404 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11405 } else if (rs != 0 && rt != 0 && rs == rt) {
11406 /* OPC_BGEZALC */
11407 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11408 } else {
11409 /* OPC_BGEUC */
11410 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11412 break;
11413 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11414 if (rs == 0 && rt != 0) {
11415 /* OPC_BGTZALC */
11416 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11417 } else if (rs != 0 && rt != 0 && rs == rt) {
11418 /* OPC_BLTZALC */
11419 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11420 } else {
11421 /* OPC_BLTUC */
11422 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11424 break;
11425 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11426 if (rs == 0 && rt != 0) {
11427 /* OPC_BLEZC */
11428 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11429 } else if (rs != 0 && rt != 0 && rs == rt) {
11430 /* OPC_BGEZC */
11431 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11432 } else {
11433 /* OPC_BGEC */
11434 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11436 break;
11437 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11438 if (rs == 0 && rt != 0) {
11439 /* OPC_BGTZC */
11440 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11441 } else if (rs != 0 && rt != 0 && rs == rt) {
11442 /* OPC_BLTZC */
11443 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11444 } else {
11445 /* OPC_BLTC */
11446 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11448 break;
11449 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11450 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11451 if (rs >= rt) {
11452 /* OPC_BOVC, OPC_BNVC */
11453 TCGv t2 = tcg_temp_new();
11454 TCGv t3 = tcg_temp_new();
11455 TCGv t4 = tcg_temp_new();
11456 TCGv input_overflow = tcg_temp_new();
11458 gen_load_gpr(t0, rs);
11459 gen_load_gpr(t1, rt);
11460 tcg_gen_ext32s_tl(t2, t0);
11461 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11462 tcg_gen_ext32s_tl(t3, t1);
11463 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11464 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11466 tcg_gen_add_tl(t4, t2, t3);
11467 tcg_gen_ext32s_tl(t4, t4);
11468 tcg_gen_xor_tl(t2, t2, t3);
11469 tcg_gen_xor_tl(t3, t4, t3);
11470 tcg_gen_andc_tl(t2, t3, t2);
11471 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11472 tcg_gen_or_tl(t4, t4, input_overflow);
11473 if (opc == OPC_BOVC) {
11474 /* OPC_BOVC */
11475 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11476 } else {
11477 /* OPC_BNVC */
11478 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11480 tcg_temp_free(input_overflow);
11481 tcg_temp_free(t4);
11482 tcg_temp_free(t3);
11483 tcg_temp_free(t2);
11484 } else if (rs < rt && rs == 0) {
11485 /* OPC_BEQZALC, OPC_BNEZALC */
11486 if (opc == OPC_BEQZALC) {
11487 /* OPC_BEQZALC */
11488 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11489 } else {
11490 /* OPC_BNEZALC */
11491 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11493 } else {
11494 /* OPC_BEQC, OPC_BNEC */
11495 if (opc == OPC_BEQC) {
11496 /* OPC_BEQC */
11497 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11498 } else {
11499 /* OPC_BNEC */
11500 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11503 break;
11504 case OPC_BEQZC:
11505 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11506 break;
11507 case OPC_BNEZC:
11508 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11509 break;
11510 default:
11511 MIPS_INVAL("Compact conditional branch/jump");
11512 generate_exception_end(ctx, EXCP_RI);
11513 goto out;
11516 /* Generating branch here as compact branches don't have delay slot */
11517 gen_goto_tb(ctx, 1, ctx->btarget);
11518 gen_set_label(fs);
11520 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11523 out:
11524 tcg_temp_free(t0);
11525 tcg_temp_free(t1);
11528 /* ISA extensions (ASEs) */
11529 /* MIPS16 extension to MIPS32 */
11531 /* MIPS16 major opcodes */
11532 enum {
11533 M16_OPC_ADDIUSP = 0x00,
11534 M16_OPC_ADDIUPC = 0x01,
11535 M16_OPC_B = 0x02,
11536 M16_OPC_JAL = 0x03,
11537 M16_OPC_BEQZ = 0x04,
11538 M16_OPC_BNEQZ = 0x05,
11539 M16_OPC_SHIFT = 0x06,
11540 M16_OPC_LD = 0x07,
11541 M16_OPC_RRIA = 0x08,
11542 M16_OPC_ADDIU8 = 0x09,
11543 M16_OPC_SLTI = 0x0a,
11544 M16_OPC_SLTIU = 0x0b,
11545 M16_OPC_I8 = 0x0c,
11546 M16_OPC_LI = 0x0d,
11547 M16_OPC_CMPI = 0x0e,
11548 M16_OPC_SD = 0x0f,
11549 M16_OPC_LB = 0x10,
11550 M16_OPC_LH = 0x11,
11551 M16_OPC_LWSP = 0x12,
11552 M16_OPC_LW = 0x13,
11553 M16_OPC_LBU = 0x14,
11554 M16_OPC_LHU = 0x15,
11555 M16_OPC_LWPC = 0x16,
11556 M16_OPC_LWU = 0x17,
11557 M16_OPC_SB = 0x18,
11558 M16_OPC_SH = 0x19,
11559 M16_OPC_SWSP = 0x1a,
11560 M16_OPC_SW = 0x1b,
11561 M16_OPC_RRR = 0x1c,
11562 M16_OPC_RR = 0x1d,
11563 M16_OPC_EXTEND = 0x1e,
11564 M16_OPC_I64 = 0x1f
11567 /* I8 funct field */
11568 enum {
11569 I8_BTEQZ = 0x0,
11570 I8_BTNEZ = 0x1,
11571 I8_SWRASP = 0x2,
11572 I8_ADJSP = 0x3,
11573 I8_SVRS = 0x4,
11574 I8_MOV32R = 0x5,
11575 I8_MOVR32 = 0x7
11578 /* RRR f field */
11579 enum {
11580 RRR_DADDU = 0x0,
11581 RRR_ADDU = 0x1,
11582 RRR_DSUBU = 0x2,
11583 RRR_SUBU = 0x3
11586 /* RR funct field */
11587 enum {
11588 RR_JR = 0x00,
11589 RR_SDBBP = 0x01,
11590 RR_SLT = 0x02,
11591 RR_SLTU = 0x03,
11592 RR_SLLV = 0x04,
11593 RR_BREAK = 0x05,
11594 RR_SRLV = 0x06,
11595 RR_SRAV = 0x07,
11596 RR_DSRL = 0x08,
11597 RR_CMP = 0x0a,
11598 RR_NEG = 0x0b,
11599 RR_AND = 0x0c,
11600 RR_OR = 0x0d,
11601 RR_XOR = 0x0e,
11602 RR_NOT = 0x0f,
11603 RR_MFHI = 0x10,
11604 RR_CNVT = 0x11,
11605 RR_MFLO = 0x12,
11606 RR_DSRA = 0x13,
11607 RR_DSLLV = 0x14,
11608 RR_DSRLV = 0x16,
11609 RR_DSRAV = 0x17,
11610 RR_MULT = 0x18,
11611 RR_MULTU = 0x19,
11612 RR_DIV = 0x1a,
11613 RR_DIVU = 0x1b,
11614 RR_DMULT = 0x1c,
11615 RR_DMULTU = 0x1d,
11616 RR_DDIV = 0x1e,
11617 RR_DDIVU = 0x1f
11620 /* I64 funct field */
11621 enum {
11622 I64_LDSP = 0x0,
11623 I64_SDSP = 0x1,
11624 I64_SDRASP = 0x2,
11625 I64_DADJSP = 0x3,
11626 I64_LDPC = 0x4,
11627 I64_DADDIU5 = 0x5,
11628 I64_DADDIUPC = 0x6,
11629 I64_DADDIUSP = 0x7
11632 /* RR ry field for CNVT */
11633 enum {
11634 RR_RY_CNVT_ZEB = 0x0,
11635 RR_RY_CNVT_ZEH = 0x1,
11636 RR_RY_CNVT_ZEW = 0x2,
11637 RR_RY_CNVT_SEB = 0x4,
11638 RR_RY_CNVT_SEH = 0x5,
11639 RR_RY_CNVT_SEW = 0x6,
11642 static int xlat (int r)
11644 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11646 return map[r];
11649 static void gen_mips16_save (DisasContext *ctx,
11650 int xsregs, int aregs,
11651 int do_ra, int do_s0, int do_s1,
11652 int framesize)
11654 TCGv t0 = tcg_temp_new();
11655 TCGv t1 = tcg_temp_new();
11656 TCGv t2 = tcg_temp_new();
11657 int args, astatic;
11659 switch (aregs) {
11660 case 0:
11661 case 1:
11662 case 2:
11663 case 3:
11664 case 11:
11665 args = 0;
11666 break;
11667 case 4:
11668 case 5:
11669 case 6:
11670 case 7:
11671 args = 1;
11672 break;
11673 case 8:
11674 case 9:
11675 case 10:
11676 args = 2;
11677 break;
11678 case 12:
11679 case 13:
11680 args = 3;
11681 break;
11682 case 14:
11683 args = 4;
11684 break;
11685 default:
11686 generate_exception_end(ctx, EXCP_RI);
11687 return;
11690 switch (args) {
11691 case 4:
11692 gen_base_offset_addr(ctx, t0, 29, 12);
11693 gen_load_gpr(t1, 7);
11694 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11695 /* Fall through */
11696 case 3:
11697 gen_base_offset_addr(ctx, t0, 29, 8);
11698 gen_load_gpr(t1, 6);
11699 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11700 /* Fall through */
11701 case 2:
11702 gen_base_offset_addr(ctx, t0, 29, 4);
11703 gen_load_gpr(t1, 5);
11704 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11705 /* Fall through */
11706 case 1:
11707 gen_base_offset_addr(ctx, t0, 29, 0);
11708 gen_load_gpr(t1, 4);
11709 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11712 gen_load_gpr(t0, 29);
11714 #define DECR_AND_STORE(reg) do { \
11715 tcg_gen_movi_tl(t2, -4); \
11716 gen_op_addr_add(ctx, t0, t0, t2); \
11717 gen_load_gpr(t1, reg); \
11718 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11719 } while (0)
11721 if (do_ra) {
11722 DECR_AND_STORE(31);
11725 switch (xsregs) {
11726 case 7:
11727 DECR_AND_STORE(30);
11728 /* Fall through */
11729 case 6:
11730 DECR_AND_STORE(23);
11731 /* Fall through */
11732 case 5:
11733 DECR_AND_STORE(22);
11734 /* Fall through */
11735 case 4:
11736 DECR_AND_STORE(21);
11737 /* Fall through */
11738 case 3:
11739 DECR_AND_STORE(20);
11740 /* Fall through */
11741 case 2:
11742 DECR_AND_STORE(19);
11743 /* Fall through */
11744 case 1:
11745 DECR_AND_STORE(18);
11748 if (do_s1) {
11749 DECR_AND_STORE(17);
11751 if (do_s0) {
11752 DECR_AND_STORE(16);
11755 switch (aregs) {
11756 case 0:
11757 case 4:
11758 case 8:
11759 case 12:
11760 case 14:
11761 astatic = 0;
11762 break;
11763 case 1:
11764 case 5:
11765 case 9:
11766 case 13:
11767 astatic = 1;
11768 break;
11769 case 2:
11770 case 6:
11771 case 10:
11772 astatic = 2;
11773 break;
11774 case 3:
11775 case 7:
11776 astatic = 3;
11777 break;
11778 case 11:
11779 astatic = 4;
11780 break;
11781 default:
11782 generate_exception_end(ctx, EXCP_RI);
11783 return;
11786 if (astatic > 0) {
11787 DECR_AND_STORE(7);
11788 if (astatic > 1) {
11789 DECR_AND_STORE(6);
11790 if (astatic > 2) {
11791 DECR_AND_STORE(5);
11792 if (astatic > 3) {
11793 DECR_AND_STORE(4);
11798 #undef DECR_AND_STORE
11800 tcg_gen_movi_tl(t2, -framesize);
11801 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11802 tcg_temp_free(t0);
11803 tcg_temp_free(t1);
11804 tcg_temp_free(t2);
11807 static void gen_mips16_restore (DisasContext *ctx,
11808 int xsregs, int aregs,
11809 int do_ra, int do_s0, int do_s1,
11810 int framesize)
11812 int astatic;
11813 TCGv t0 = tcg_temp_new();
11814 TCGv t1 = tcg_temp_new();
11815 TCGv t2 = tcg_temp_new();
11817 tcg_gen_movi_tl(t2, framesize);
11818 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11820 #define DECR_AND_LOAD(reg) do { \
11821 tcg_gen_movi_tl(t2, -4); \
11822 gen_op_addr_add(ctx, t0, t0, t2); \
11823 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11824 gen_store_gpr(t1, reg); \
11825 } while (0)
11827 if (do_ra) {
11828 DECR_AND_LOAD(31);
11831 switch (xsregs) {
11832 case 7:
11833 DECR_AND_LOAD(30);
11834 /* Fall through */
11835 case 6:
11836 DECR_AND_LOAD(23);
11837 /* Fall through */
11838 case 5:
11839 DECR_AND_LOAD(22);
11840 /* Fall through */
11841 case 4:
11842 DECR_AND_LOAD(21);
11843 /* Fall through */
11844 case 3:
11845 DECR_AND_LOAD(20);
11846 /* Fall through */
11847 case 2:
11848 DECR_AND_LOAD(19);
11849 /* Fall through */
11850 case 1:
11851 DECR_AND_LOAD(18);
11854 if (do_s1) {
11855 DECR_AND_LOAD(17);
11857 if (do_s0) {
11858 DECR_AND_LOAD(16);
11861 switch (aregs) {
11862 case 0:
11863 case 4:
11864 case 8:
11865 case 12:
11866 case 14:
11867 astatic = 0;
11868 break;
11869 case 1:
11870 case 5:
11871 case 9:
11872 case 13:
11873 astatic = 1;
11874 break;
11875 case 2:
11876 case 6:
11877 case 10:
11878 astatic = 2;
11879 break;
11880 case 3:
11881 case 7:
11882 astatic = 3;
11883 break;
11884 case 11:
11885 astatic = 4;
11886 break;
11887 default:
11888 generate_exception_end(ctx, EXCP_RI);
11889 return;
11892 if (astatic > 0) {
11893 DECR_AND_LOAD(7);
11894 if (astatic > 1) {
11895 DECR_AND_LOAD(6);
11896 if (astatic > 2) {
11897 DECR_AND_LOAD(5);
11898 if (astatic > 3) {
11899 DECR_AND_LOAD(4);
11904 #undef DECR_AND_LOAD
11906 tcg_gen_movi_tl(t2, framesize);
11907 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11908 tcg_temp_free(t0);
11909 tcg_temp_free(t1);
11910 tcg_temp_free(t2);
11913 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11914 int is_64_bit, int extended)
11916 TCGv t0;
11918 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11919 generate_exception_end(ctx, EXCP_RI);
11920 return;
11923 t0 = tcg_temp_new();
11925 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11926 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11927 if (!is_64_bit) {
11928 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11931 tcg_temp_free(t0);
11934 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11935 int16_t offset)
11937 TCGv_i32 t0 = tcg_const_i32(op);
11938 TCGv t1 = tcg_temp_new();
11939 gen_base_offset_addr(ctx, t1, base, offset);
11940 gen_helper_cache(cpu_env, t1, t0);
11943 #if defined(TARGET_MIPS64)
11944 static void decode_i64_mips16 (DisasContext *ctx,
11945 int ry, int funct, int16_t offset,
11946 int extended)
11948 switch (funct) {
11949 case I64_LDSP:
11950 check_insn(ctx, ISA_MIPS3);
11951 check_mips_64(ctx);
11952 offset = extended ? offset : offset << 3;
11953 gen_ld(ctx, OPC_LD, ry, 29, offset);
11954 break;
11955 case I64_SDSP:
11956 check_insn(ctx, ISA_MIPS3);
11957 check_mips_64(ctx);
11958 offset = extended ? offset : offset << 3;
11959 gen_st(ctx, OPC_SD, ry, 29, offset);
11960 break;
11961 case I64_SDRASP:
11962 check_insn(ctx, ISA_MIPS3);
11963 check_mips_64(ctx);
11964 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11965 gen_st(ctx, OPC_SD, 31, 29, offset);
11966 break;
11967 case I64_DADJSP:
11968 check_insn(ctx, ISA_MIPS3);
11969 check_mips_64(ctx);
11970 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11971 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11972 break;
11973 case I64_LDPC:
11974 check_insn(ctx, ISA_MIPS3);
11975 check_mips_64(ctx);
11976 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11977 generate_exception_end(ctx, EXCP_RI);
11978 } else {
11979 offset = extended ? offset : offset << 3;
11980 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11982 break;
11983 case I64_DADDIU5:
11984 check_insn(ctx, ISA_MIPS3);
11985 check_mips_64(ctx);
11986 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11987 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11988 break;
11989 case I64_DADDIUPC:
11990 check_insn(ctx, ISA_MIPS3);
11991 check_mips_64(ctx);
11992 offset = extended ? offset : offset << 2;
11993 gen_addiupc(ctx, ry, offset, 1, extended);
11994 break;
11995 case I64_DADDIUSP:
11996 check_insn(ctx, ISA_MIPS3);
11997 check_mips_64(ctx);
11998 offset = extended ? offset : offset << 2;
11999 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12000 break;
12003 #endif
12005 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12007 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
12008 int op, rx, ry, funct, sa;
12009 int16_t imm, offset;
12011 ctx->opcode = (ctx->opcode << 16) | extend;
12012 op = (ctx->opcode >> 11) & 0x1f;
12013 sa = (ctx->opcode >> 22) & 0x1f;
12014 funct = (ctx->opcode >> 8) & 0x7;
12015 rx = xlat((ctx->opcode >> 8) & 0x7);
12016 ry = xlat((ctx->opcode >> 5) & 0x7);
12017 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12018 | ((ctx->opcode >> 21) & 0x3f) << 5
12019 | (ctx->opcode & 0x1f));
12021 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
12022 counterparts. */
12023 switch (op) {
12024 case M16_OPC_ADDIUSP:
12025 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12026 break;
12027 case M16_OPC_ADDIUPC:
12028 gen_addiupc(ctx, rx, imm, 0, 1);
12029 break;
12030 case M16_OPC_B:
12031 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12032 /* No delay slot, so just process as a normal instruction */
12033 break;
12034 case M16_OPC_BEQZ:
12035 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12036 /* No delay slot, so just process as a normal instruction */
12037 break;
12038 case M16_OPC_BNEQZ:
12039 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12040 /* No delay slot, so just process as a normal instruction */
12041 break;
12042 case M16_OPC_SHIFT:
12043 switch (ctx->opcode & 0x3) {
12044 case 0x0:
12045 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12046 break;
12047 case 0x1:
12048 #if defined(TARGET_MIPS64)
12049 check_mips_64(ctx);
12050 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12051 #else
12052 generate_exception_end(ctx, EXCP_RI);
12053 #endif
12054 break;
12055 case 0x2:
12056 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12057 break;
12058 case 0x3:
12059 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12060 break;
12062 break;
12063 #if defined(TARGET_MIPS64)
12064 case M16_OPC_LD:
12065 check_insn(ctx, ISA_MIPS3);
12066 check_mips_64(ctx);
12067 gen_ld(ctx, OPC_LD, ry, rx, offset);
12068 break;
12069 #endif
12070 case M16_OPC_RRIA:
12071 imm = ctx->opcode & 0xf;
12072 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12073 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12074 imm = (int16_t) (imm << 1) >> 1;
12075 if ((ctx->opcode >> 4) & 0x1) {
12076 #if defined(TARGET_MIPS64)
12077 check_mips_64(ctx);
12078 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12079 #else
12080 generate_exception_end(ctx, EXCP_RI);
12081 #endif
12082 } else {
12083 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12085 break;
12086 case M16_OPC_ADDIU8:
12087 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12088 break;
12089 case M16_OPC_SLTI:
12090 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12091 break;
12092 case M16_OPC_SLTIU:
12093 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12094 break;
12095 case M16_OPC_I8:
12096 switch (funct) {
12097 case I8_BTEQZ:
12098 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
12099 break;
12100 case I8_BTNEZ:
12101 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
12102 break;
12103 case I8_SWRASP:
12104 gen_st(ctx, OPC_SW, 31, 29, imm);
12105 break;
12106 case I8_ADJSP:
12107 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
12108 break;
12109 case I8_SVRS:
12110 check_insn(ctx, ISA_MIPS32);
12112 int xsregs = (ctx->opcode >> 24) & 0x7;
12113 int aregs = (ctx->opcode >> 16) & 0xf;
12114 int do_ra = (ctx->opcode >> 6) & 0x1;
12115 int do_s0 = (ctx->opcode >> 5) & 0x1;
12116 int do_s1 = (ctx->opcode >> 4) & 0x1;
12117 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12118 | (ctx->opcode & 0xf)) << 3;
12120 if (ctx->opcode & (1 << 7)) {
12121 gen_mips16_save(ctx, xsregs, aregs,
12122 do_ra, do_s0, do_s1,
12123 framesize);
12124 } else {
12125 gen_mips16_restore(ctx, xsregs, aregs,
12126 do_ra, do_s0, do_s1,
12127 framesize);
12130 break;
12131 default:
12132 generate_exception_end(ctx, EXCP_RI);
12133 break;
12135 break;
12136 case M16_OPC_LI:
12137 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
12138 break;
12139 case M16_OPC_CMPI:
12140 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
12141 break;
12142 #if defined(TARGET_MIPS64)
12143 case M16_OPC_SD:
12144 check_insn(ctx, ISA_MIPS3);
12145 check_mips_64(ctx);
12146 gen_st(ctx, OPC_SD, ry, rx, offset);
12147 break;
12148 #endif
12149 case M16_OPC_LB:
12150 gen_ld(ctx, OPC_LB, ry, rx, offset);
12151 break;
12152 case M16_OPC_LH:
12153 gen_ld(ctx, OPC_LH, ry, rx, offset);
12154 break;
12155 case M16_OPC_LWSP:
12156 gen_ld(ctx, OPC_LW, rx, 29, offset);
12157 break;
12158 case M16_OPC_LW:
12159 gen_ld(ctx, OPC_LW, ry, rx, offset);
12160 break;
12161 case M16_OPC_LBU:
12162 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12163 break;
12164 case M16_OPC_LHU:
12165 gen_ld(ctx, OPC_LHU, ry, rx, offset);
12166 break;
12167 case M16_OPC_LWPC:
12168 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
12169 break;
12170 #if defined(TARGET_MIPS64)
12171 case M16_OPC_LWU:
12172 check_insn(ctx, ISA_MIPS3);
12173 check_mips_64(ctx);
12174 gen_ld(ctx, OPC_LWU, ry, rx, offset);
12175 break;
12176 #endif
12177 case M16_OPC_SB:
12178 gen_st(ctx, OPC_SB, ry, rx, offset);
12179 break;
12180 case M16_OPC_SH:
12181 gen_st(ctx, OPC_SH, ry, rx, offset);
12182 break;
12183 case M16_OPC_SWSP:
12184 gen_st(ctx, OPC_SW, rx, 29, offset);
12185 break;
12186 case M16_OPC_SW:
12187 gen_st(ctx, OPC_SW, ry, rx, offset);
12188 break;
12189 #if defined(TARGET_MIPS64)
12190 case M16_OPC_I64:
12191 decode_i64_mips16(ctx, ry, funct, offset, 1);
12192 break;
12193 #endif
12194 default:
12195 generate_exception_end(ctx, EXCP_RI);
12196 break;
12199 return 4;
12202 static inline bool is_uhi(int sdbbp_code)
12204 #ifdef CONFIG_USER_ONLY
12205 return false;
12206 #else
12207 return semihosting_enabled() && sdbbp_code == 1;
12208 #endif
12211 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12213 int rx, ry;
12214 int sa;
12215 int op, cnvt_op, op1, offset;
12216 int funct;
12217 int n_bytes;
12219 op = (ctx->opcode >> 11) & 0x1f;
12220 sa = (ctx->opcode >> 2) & 0x7;
12221 sa = sa == 0 ? 8 : sa;
12222 rx = xlat((ctx->opcode >> 8) & 0x7);
12223 cnvt_op = (ctx->opcode >> 5) & 0x7;
12224 ry = xlat((ctx->opcode >> 5) & 0x7);
12225 op1 = offset = ctx->opcode & 0x1f;
12227 n_bytes = 2;
12229 switch (op) {
12230 case M16_OPC_ADDIUSP:
12232 int16_t imm = ((uint8_t) ctx->opcode) << 2;
12234 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12236 break;
12237 case M16_OPC_ADDIUPC:
12238 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
12239 break;
12240 case M16_OPC_B:
12241 offset = (ctx->opcode & 0x7ff) << 1;
12242 offset = (int16_t)(offset << 4) >> 4;
12243 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
12244 /* No delay slot, so just process as a normal instruction */
12245 break;
12246 case M16_OPC_JAL:
12247 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
12248 offset = (((ctx->opcode & 0x1f) << 21)
12249 | ((ctx->opcode >> 5) & 0x1f) << 16
12250 | offset) << 2;
12251 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
12252 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
12253 n_bytes = 4;
12254 break;
12255 case M16_OPC_BEQZ:
12256 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
12257 ((int8_t)ctx->opcode) << 1, 0);
12258 /* No delay slot, so just process as a normal instruction */
12259 break;
12260 case M16_OPC_BNEQZ:
12261 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
12262 ((int8_t)ctx->opcode) << 1, 0);
12263 /* No delay slot, so just process as a normal instruction */
12264 break;
12265 case M16_OPC_SHIFT:
12266 switch (ctx->opcode & 0x3) {
12267 case 0x0:
12268 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12269 break;
12270 case 0x1:
12271 #if defined(TARGET_MIPS64)
12272 check_insn(ctx, ISA_MIPS3);
12273 check_mips_64(ctx);
12274 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12275 #else
12276 generate_exception_end(ctx, EXCP_RI);
12277 #endif
12278 break;
12279 case 0x2:
12280 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12281 break;
12282 case 0x3:
12283 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12284 break;
12286 break;
12287 #if defined(TARGET_MIPS64)
12288 case M16_OPC_LD:
12289 check_insn(ctx, ISA_MIPS3);
12290 check_mips_64(ctx);
12291 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
12292 break;
12293 #endif
12294 case M16_OPC_RRIA:
12296 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12298 if ((ctx->opcode >> 4) & 1) {
12299 #if defined(TARGET_MIPS64)
12300 check_insn(ctx, ISA_MIPS3);
12301 check_mips_64(ctx);
12302 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12303 #else
12304 generate_exception_end(ctx, EXCP_RI);
12305 #endif
12306 } else {
12307 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12310 break;
12311 case M16_OPC_ADDIU8:
12313 int16_t imm = (int8_t) ctx->opcode;
12315 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12317 break;
12318 case M16_OPC_SLTI:
12320 int16_t imm = (uint8_t) ctx->opcode;
12321 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12323 break;
12324 case M16_OPC_SLTIU:
12326 int16_t imm = (uint8_t) ctx->opcode;
12327 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12329 break;
12330 case M16_OPC_I8:
12332 int reg32;
12334 funct = (ctx->opcode >> 8) & 0x7;
12335 switch (funct) {
12336 case I8_BTEQZ:
12337 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
12338 ((int8_t)ctx->opcode) << 1, 0);
12339 break;
12340 case I8_BTNEZ:
12341 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
12342 ((int8_t)ctx->opcode) << 1, 0);
12343 break;
12344 case I8_SWRASP:
12345 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
12346 break;
12347 case I8_ADJSP:
12348 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
12349 ((int8_t)ctx->opcode) << 3);
12350 break;
12351 case I8_SVRS:
12352 check_insn(ctx, ISA_MIPS32);
12354 int do_ra = ctx->opcode & (1 << 6);
12355 int do_s0 = ctx->opcode & (1 << 5);
12356 int do_s1 = ctx->opcode & (1 << 4);
12357 int framesize = ctx->opcode & 0xf;
12359 if (framesize == 0) {
12360 framesize = 128;
12361 } else {
12362 framesize = framesize << 3;
12365 if (ctx->opcode & (1 << 7)) {
12366 gen_mips16_save(ctx, 0, 0,
12367 do_ra, do_s0, do_s1, framesize);
12368 } else {
12369 gen_mips16_restore(ctx, 0, 0,
12370 do_ra, do_s0, do_s1, framesize);
12373 break;
12374 case I8_MOV32R:
12376 int rz = xlat(ctx->opcode & 0x7);
12378 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
12379 ((ctx->opcode >> 5) & 0x7);
12380 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
12382 break;
12383 case I8_MOVR32:
12384 reg32 = ctx->opcode & 0x1f;
12385 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
12386 break;
12387 default:
12388 generate_exception_end(ctx, EXCP_RI);
12389 break;
12392 break;
12393 case M16_OPC_LI:
12395 int16_t imm = (uint8_t) ctx->opcode;
12397 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
12399 break;
12400 case M16_OPC_CMPI:
12402 int16_t imm = (uint8_t) ctx->opcode;
12403 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
12405 break;
12406 #if defined(TARGET_MIPS64)
12407 case M16_OPC_SD:
12408 check_insn(ctx, ISA_MIPS3);
12409 check_mips_64(ctx);
12410 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
12411 break;
12412 #endif
12413 case M16_OPC_LB:
12414 gen_ld(ctx, OPC_LB, ry, rx, offset);
12415 break;
12416 case M16_OPC_LH:
12417 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
12418 break;
12419 case M16_OPC_LWSP:
12420 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12421 break;
12422 case M16_OPC_LW:
12423 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
12424 break;
12425 case M16_OPC_LBU:
12426 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12427 break;
12428 case M16_OPC_LHU:
12429 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
12430 break;
12431 case M16_OPC_LWPC:
12432 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
12433 break;
12434 #if defined (TARGET_MIPS64)
12435 case M16_OPC_LWU:
12436 check_insn(ctx, ISA_MIPS3);
12437 check_mips_64(ctx);
12438 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
12439 break;
12440 #endif
12441 case M16_OPC_SB:
12442 gen_st(ctx, OPC_SB, ry, rx, offset);
12443 break;
12444 case M16_OPC_SH:
12445 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
12446 break;
12447 case M16_OPC_SWSP:
12448 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12449 break;
12450 case M16_OPC_SW:
12451 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
12452 break;
12453 case M16_OPC_RRR:
12455 int rz = xlat((ctx->opcode >> 2) & 0x7);
12456 int mips32_op;
12458 switch (ctx->opcode & 0x3) {
12459 case RRR_ADDU:
12460 mips32_op = OPC_ADDU;
12461 break;
12462 case RRR_SUBU:
12463 mips32_op = OPC_SUBU;
12464 break;
12465 #if defined(TARGET_MIPS64)
12466 case RRR_DADDU:
12467 mips32_op = OPC_DADDU;
12468 check_insn(ctx, ISA_MIPS3);
12469 check_mips_64(ctx);
12470 break;
12471 case RRR_DSUBU:
12472 mips32_op = OPC_DSUBU;
12473 check_insn(ctx, ISA_MIPS3);
12474 check_mips_64(ctx);
12475 break;
12476 #endif
12477 default:
12478 generate_exception_end(ctx, EXCP_RI);
12479 goto done;
12482 gen_arith(ctx, mips32_op, rz, rx, ry);
12483 done:
12486 break;
12487 case M16_OPC_RR:
12488 switch (op1) {
12489 case RR_JR:
12491 int nd = (ctx->opcode >> 7) & 0x1;
12492 int link = (ctx->opcode >> 6) & 0x1;
12493 int ra = (ctx->opcode >> 5) & 0x1;
12495 if (nd) {
12496 check_insn(ctx, ISA_MIPS32);
12499 if (link) {
12500 op = OPC_JALR;
12501 } else {
12502 op = OPC_JR;
12505 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12506 (nd ? 0 : 2));
12508 break;
12509 case RR_SDBBP:
12510 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12511 gen_helper_do_semihosting(cpu_env);
12512 } else {
12513 /* XXX: not clear which exception should be raised
12514 * when in debug mode...
12516 check_insn(ctx, ISA_MIPS32);
12517 generate_exception_end(ctx, EXCP_DBp);
12519 break;
12520 case RR_SLT:
12521 gen_slt(ctx, OPC_SLT, 24, rx, ry);
12522 break;
12523 case RR_SLTU:
12524 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
12525 break;
12526 case RR_BREAK:
12527 generate_exception_end(ctx, EXCP_BREAK);
12528 break;
12529 case RR_SLLV:
12530 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
12531 break;
12532 case RR_SRLV:
12533 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
12534 break;
12535 case RR_SRAV:
12536 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
12537 break;
12538 #if defined (TARGET_MIPS64)
12539 case RR_DSRL:
12540 check_insn(ctx, ISA_MIPS3);
12541 check_mips_64(ctx);
12542 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
12543 break;
12544 #endif
12545 case RR_CMP:
12546 gen_logic(ctx, OPC_XOR, 24, rx, ry);
12547 break;
12548 case RR_NEG:
12549 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
12550 break;
12551 case RR_AND:
12552 gen_logic(ctx, OPC_AND, rx, rx, ry);
12553 break;
12554 case RR_OR:
12555 gen_logic(ctx, OPC_OR, rx, rx, ry);
12556 break;
12557 case RR_XOR:
12558 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12559 break;
12560 case RR_NOT:
12561 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12562 break;
12563 case RR_MFHI:
12564 gen_HILO(ctx, OPC_MFHI, 0, rx);
12565 break;
12566 case RR_CNVT:
12567 check_insn(ctx, ISA_MIPS32);
12568 switch (cnvt_op) {
12569 case RR_RY_CNVT_ZEB:
12570 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12571 break;
12572 case RR_RY_CNVT_ZEH:
12573 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12574 break;
12575 case RR_RY_CNVT_SEB:
12576 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12577 break;
12578 case RR_RY_CNVT_SEH:
12579 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12580 break;
12581 #if defined (TARGET_MIPS64)
12582 case RR_RY_CNVT_ZEW:
12583 check_insn(ctx, ISA_MIPS64);
12584 check_mips_64(ctx);
12585 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12586 break;
12587 case RR_RY_CNVT_SEW:
12588 check_insn(ctx, ISA_MIPS64);
12589 check_mips_64(ctx);
12590 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12591 break;
12592 #endif
12593 default:
12594 generate_exception_end(ctx, EXCP_RI);
12595 break;
12597 break;
12598 case RR_MFLO:
12599 gen_HILO(ctx, OPC_MFLO, 0, rx);
12600 break;
12601 #if defined (TARGET_MIPS64)
12602 case RR_DSRA:
12603 check_insn(ctx, ISA_MIPS3);
12604 check_mips_64(ctx);
12605 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12606 break;
12607 case RR_DSLLV:
12608 check_insn(ctx, ISA_MIPS3);
12609 check_mips_64(ctx);
12610 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12611 break;
12612 case RR_DSRLV:
12613 check_insn(ctx, ISA_MIPS3);
12614 check_mips_64(ctx);
12615 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12616 break;
12617 case RR_DSRAV:
12618 check_insn(ctx, ISA_MIPS3);
12619 check_mips_64(ctx);
12620 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12621 break;
12622 #endif
12623 case RR_MULT:
12624 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12625 break;
12626 case RR_MULTU:
12627 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12628 break;
12629 case RR_DIV:
12630 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12631 break;
12632 case RR_DIVU:
12633 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12634 break;
12635 #if defined (TARGET_MIPS64)
12636 case RR_DMULT:
12637 check_insn(ctx, ISA_MIPS3);
12638 check_mips_64(ctx);
12639 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12640 break;
12641 case RR_DMULTU:
12642 check_insn(ctx, ISA_MIPS3);
12643 check_mips_64(ctx);
12644 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12645 break;
12646 case RR_DDIV:
12647 check_insn(ctx, ISA_MIPS3);
12648 check_mips_64(ctx);
12649 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12650 break;
12651 case RR_DDIVU:
12652 check_insn(ctx, ISA_MIPS3);
12653 check_mips_64(ctx);
12654 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12655 break;
12656 #endif
12657 default:
12658 generate_exception_end(ctx, EXCP_RI);
12659 break;
12661 break;
12662 case M16_OPC_EXTEND:
12663 decode_extended_mips16_opc(env, ctx);
12664 n_bytes = 4;
12665 break;
12666 #if defined(TARGET_MIPS64)
12667 case M16_OPC_I64:
12668 funct = (ctx->opcode >> 8) & 0x7;
12669 decode_i64_mips16(ctx, ry, funct, offset, 0);
12670 break;
12671 #endif
12672 default:
12673 generate_exception_end(ctx, EXCP_RI);
12674 break;
12677 return n_bytes;
12680 /* microMIPS extension to MIPS32/MIPS64 */
12683 * microMIPS32/microMIPS64 major opcodes
12685 * 1. MIPS Architecture for Programmers Volume II-B:
12686 * The microMIPS32 Instruction Set (Revision 3.05)
12688 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12690 * 2. MIPS Architecture For Programmers Volume II-A:
12691 * The MIPS64 Instruction Set (Revision 3.51)
12694 enum {
12695 POOL32A = 0x00,
12696 POOL16A = 0x01,
12697 LBU16 = 0x02,
12698 MOVE16 = 0x03,
12699 ADDI32 = 0x04,
12700 R6_LUI = 0x04,
12701 AUI = 0x04,
12702 LBU32 = 0x05,
12703 SB32 = 0x06,
12704 LB32 = 0x07,
12706 POOL32B = 0x08,
12707 POOL16B = 0x09,
12708 LHU16 = 0x0a,
12709 ANDI16 = 0x0b,
12710 ADDIU32 = 0x0c,
12711 LHU32 = 0x0d,
12712 SH32 = 0x0e,
12713 LH32 = 0x0f,
12715 POOL32I = 0x10,
12716 POOL16C = 0x11,
12717 LWSP16 = 0x12,
12718 POOL16D = 0x13,
12719 ORI32 = 0x14,
12720 POOL32F = 0x15,
12721 POOL32S = 0x16, /* MIPS64 */
12722 DADDIU32 = 0x17, /* MIPS64 */
12724 POOL32C = 0x18,
12725 LWGP16 = 0x19,
12726 LW16 = 0x1a,
12727 POOL16E = 0x1b,
12728 XORI32 = 0x1c,
12729 JALS32 = 0x1d,
12730 BOVC = 0x1d,
12731 BEQC = 0x1d,
12732 BEQZALC = 0x1d,
12733 ADDIUPC = 0x1e,
12734 PCREL = 0x1e,
12735 BNVC = 0x1f,
12736 BNEC = 0x1f,
12737 BNEZALC = 0x1f,
12739 R6_BEQZC = 0x20,
12740 JIC = 0x20,
12741 POOL16F = 0x21,
12742 SB16 = 0x22,
12743 BEQZ16 = 0x23,
12744 BEQZC16 = 0x23,
12745 SLTI32 = 0x24,
12746 BEQ32 = 0x25,
12747 BC = 0x25,
12748 SWC132 = 0x26,
12749 LWC132 = 0x27,
12751 /* 0x29 is reserved */
12752 RES_29 = 0x29,
12753 R6_BNEZC = 0x28,
12754 JIALC = 0x28,
12755 SH16 = 0x2a,
12756 BNEZ16 = 0x2b,
12757 BNEZC16 = 0x2b,
12758 SLTIU32 = 0x2c,
12759 BNE32 = 0x2d,
12760 BALC = 0x2d,
12761 SDC132 = 0x2e,
12762 LDC132 = 0x2f,
12764 /* 0x31 is reserved */
12765 RES_31 = 0x31,
12766 BLEZALC = 0x30,
12767 BGEZALC = 0x30,
12768 BGEUC = 0x30,
12769 SWSP16 = 0x32,
12770 B16 = 0x33,
12771 BC16 = 0x33,
12772 ANDI32 = 0x34,
12773 J32 = 0x35,
12774 BGTZC = 0x35,
12775 BLTZC = 0x35,
12776 BLTC = 0x35,
12777 SD32 = 0x36, /* MIPS64 */
12778 LD32 = 0x37, /* MIPS64 */
12780 /* 0x39 is reserved */
12781 RES_39 = 0x39,
12782 BGTZALC = 0x38,
12783 BLTZALC = 0x38,
12784 BLTUC = 0x38,
12785 SW16 = 0x3a,
12786 LI16 = 0x3b,
12787 JALX32 = 0x3c,
12788 JAL32 = 0x3d,
12789 BLEZC = 0x3d,
12790 BGEZC = 0x3d,
12791 BGEC = 0x3d,
12792 SW32 = 0x3e,
12793 LW32 = 0x3f
12796 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12797 enum {
12798 ADDIUPC_00 = 0x00,
12799 ADDIUPC_01 = 0x01,
12800 ADDIUPC_02 = 0x02,
12801 ADDIUPC_03 = 0x03,
12802 ADDIUPC_04 = 0x04,
12803 ADDIUPC_05 = 0x05,
12804 ADDIUPC_06 = 0x06,
12805 ADDIUPC_07 = 0x07,
12806 AUIPC = 0x1e,
12807 ALUIPC = 0x1f,
12808 LWPC_08 = 0x08,
12809 LWPC_09 = 0x09,
12810 LWPC_0A = 0x0A,
12811 LWPC_0B = 0x0B,
12812 LWPC_0C = 0x0C,
12813 LWPC_0D = 0x0D,
12814 LWPC_0E = 0x0E,
12815 LWPC_0F = 0x0F,
12818 /* POOL32A encoding of minor opcode field */
12820 enum {
12821 /* These opcodes are distinguished only by bits 9..6; those bits are
12822 * what are recorded below. */
12823 SLL32 = 0x0,
12824 SRL32 = 0x1,
12825 SRA = 0x2,
12826 ROTR = 0x3,
12827 SELEQZ = 0x5,
12828 SELNEZ = 0x6,
12829 R6_RDHWR = 0x7,
12831 SLLV = 0x0,
12832 SRLV = 0x1,
12833 SRAV = 0x2,
12834 ROTRV = 0x3,
12835 ADD = 0x4,
12836 ADDU32 = 0x5,
12837 SUB = 0x6,
12838 SUBU32 = 0x7,
12839 MUL = 0x8,
12840 AND = 0x9,
12841 OR32 = 0xa,
12842 NOR = 0xb,
12843 XOR32 = 0xc,
12844 SLT = 0xd,
12845 SLTU = 0xe,
12847 MOVN = 0x0,
12848 R6_MUL = 0x0,
12849 MOVZ = 0x1,
12850 MUH = 0x1,
12851 MULU = 0x2,
12852 MUHU = 0x3,
12853 LWXS = 0x4,
12854 R6_DIV = 0x4,
12855 MOD = 0x5,
12856 R6_DIVU = 0x6,
12857 MODU = 0x7,
12859 /* The following can be distinguished by their lower 6 bits. */
12860 BREAK32 = 0x07,
12861 INS = 0x0c,
12862 LSA = 0x0f,
12863 ALIGN = 0x1f,
12864 EXT = 0x2c,
12865 POOL32AXF = 0x3c,
12866 SIGRIE = 0x3f
12869 /* POOL32AXF encoding of minor opcode field extension */
12872 * 1. MIPS Architecture for Programmers Volume II-B:
12873 * The microMIPS32 Instruction Set (Revision 3.05)
12875 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12877 * 2. MIPS Architecture for Programmers VolumeIV-e:
12878 * The MIPS DSP Application-Specific Extension
12879 * to the microMIPS32 Architecture (Revision 2.34)
12881 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12884 enum {
12885 /* bits 11..6 */
12886 TEQ = 0x00,
12887 TGE = 0x08,
12888 TGEU = 0x10,
12889 TLT = 0x20,
12890 TLTU = 0x28,
12891 TNE = 0x30,
12893 MFC0 = 0x03,
12894 MTC0 = 0x0b,
12896 /* begin of microMIPS32 DSP */
12898 /* bits 13..12 for 0x01 */
12899 MFHI_ACC = 0x0,
12900 MFLO_ACC = 0x1,
12901 MTHI_ACC = 0x2,
12902 MTLO_ACC = 0x3,
12904 /* bits 13..12 for 0x2a */
12905 MADD_ACC = 0x0,
12906 MADDU_ACC = 0x1,
12907 MSUB_ACC = 0x2,
12908 MSUBU_ACC = 0x3,
12910 /* bits 13..12 for 0x32 */
12911 MULT_ACC = 0x0,
12912 MULTU_ACC = 0x1,
12914 /* end of microMIPS32 DSP */
12916 /* bits 15..12 for 0x2c */
12917 BITSWAP = 0x0,
12918 SEB = 0x2,
12919 SEH = 0x3,
12920 CLO = 0x4,
12921 CLZ = 0x5,
12922 RDHWR = 0x6,
12923 WSBH = 0x7,
12924 MULT = 0x8,
12925 MULTU = 0x9,
12926 DIV = 0xa,
12927 DIVU = 0xb,
12928 MADD = 0xc,
12929 MADDU = 0xd,
12930 MSUB = 0xe,
12931 MSUBU = 0xf,
12933 /* bits 15..12 for 0x34 */
12934 MFC2 = 0x4,
12935 MTC2 = 0x5,
12936 MFHC2 = 0x8,
12937 MTHC2 = 0x9,
12938 CFC2 = 0xc,
12939 CTC2 = 0xd,
12941 /* bits 15..12 for 0x3c */
12942 JALR = 0x0,
12943 JR = 0x0, /* alias */
12944 JALRC = 0x0,
12945 JRC = 0x0,
12946 JALR_HB = 0x1,
12947 JALRC_HB = 0x1,
12948 JALRS = 0x4,
12949 JALRS_HB = 0x5,
12951 /* bits 15..12 for 0x05 */
12952 RDPGPR = 0xe,
12953 WRPGPR = 0xf,
12955 /* bits 15..12 for 0x0d */
12956 TLBP = 0x0,
12957 TLBR = 0x1,
12958 TLBWI = 0x2,
12959 TLBWR = 0x3,
12960 TLBINV = 0x4,
12961 TLBINVF = 0x5,
12962 WAIT = 0x9,
12963 IRET = 0xd,
12964 DERET = 0xe,
12965 ERET = 0xf,
12967 /* bits 15..12 for 0x15 */
12968 DMT = 0x0,
12969 DVPE = 0x1,
12970 EMT = 0x2,
12971 EVPE = 0x3,
12973 /* bits 15..12 for 0x1d */
12974 DI = 0x4,
12975 EI = 0x5,
12977 /* bits 15..12 for 0x2d */
12978 SYNC = 0x6,
12979 SYSCALL = 0x8,
12980 SDBBP = 0xd,
12982 /* bits 15..12 for 0x35 */
12983 MFHI32 = 0x0,
12984 MFLO32 = 0x1,
12985 MTHI32 = 0x2,
12986 MTLO32 = 0x3,
12989 /* POOL32B encoding of minor opcode field (bits 15..12) */
12991 enum {
12992 LWC2 = 0x0,
12993 LWP = 0x1,
12994 LDP = 0x4,
12995 LWM32 = 0x5,
12996 CACHE = 0x6,
12997 LDM = 0x7,
12998 SWC2 = 0x8,
12999 SWP = 0x9,
13000 SDP = 0xc,
13001 SWM32 = 0xd,
13002 SDM = 0xf
13005 /* POOL32C encoding of minor opcode field (bits 15..12) */
13007 enum {
13008 LWL = 0x0,
13009 SWL = 0x8,
13010 LWR = 0x1,
13011 SWR = 0x9,
13012 PREF = 0x2,
13013 ST_EVA = 0xa,
13014 LL = 0x3,
13015 SC = 0xb,
13016 LDL = 0x4,
13017 SDL = 0xc,
13018 LDR = 0x5,
13019 SDR = 0xd,
13020 LD_EVA = 0x6,
13021 LWU = 0xe,
13022 LLD = 0x7,
13023 SCD = 0xf
13026 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13028 enum {
13029 LBUE = 0x0,
13030 LHUE = 0x1,
13031 LWLE = 0x2,
13032 LWRE = 0x3,
13033 LBE = 0x4,
13034 LHE = 0x5,
13035 LLE = 0x6,
13036 LWE = 0x7,
13039 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13041 enum {
13042 SWLE = 0x0,
13043 SWRE = 0x1,
13044 PREFE = 0x2,
13045 CACHEE = 0x3,
13046 SBE = 0x4,
13047 SHE = 0x5,
13048 SCE = 0x6,
13049 SWE = 0x7,
13052 /* POOL32F encoding of minor opcode field (bits 5..0) */
13054 enum {
13055 /* These are the bit 7..6 values */
13056 ADD_FMT = 0x0,
13058 SUB_FMT = 0x1,
13060 MUL_FMT = 0x2,
13062 DIV_FMT = 0x3,
13064 /* These are the bit 8..6 values */
13065 MOVN_FMT = 0x0,
13066 RSQRT2_FMT = 0x0,
13067 MOVF_FMT = 0x0,
13068 RINT_FMT = 0x0,
13069 SELNEZ_FMT = 0x0,
13071 MOVZ_FMT = 0x1,
13072 LWXC1 = 0x1,
13073 MOVT_FMT = 0x1,
13074 CLASS_FMT = 0x1,
13075 SELEQZ_FMT = 0x1,
13077 PLL_PS = 0x2,
13078 SWXC1 = 0x2,
13079 SEL_FMT = 0x2,
13081 PLU_PS = 0x3,
13082 LDXC1 = 0x3,
13084 MOVN_FMT_04 = 0x4,
13085 PUL_PS = 0x4,
13086 SDXC1 = 0x4,
13087 RECIP2_FMT = 0x4,
13089 MOVZ_FMT_05 = 0x05,
13090 PUU_PS = 0x5,
13091 LUXC1 = 0x5,
13093 CVT_PS_S = 0x6,
13094 SUXC1 = 0x6,
13095 ADDR_PS = 0x6,
13096 PREFX = 0x6,
13097 MADDF_FMT = 0x6,
13099 MULR_PS = 0x7,
13100 MSUBF_FMT = 0x7,
13102 MADD_S = 0x01,
13103 MADD_D = 0x09,
13104 MADD_PS = 0x11,
13105 ALNV_PS = 0x19,
13106 MSUB_S = 0x21,
13107 MSUB_D = 0x29,
13108 MSUB_PS = 0x31,
13110 NMADD_S = 0x02,
13111 NMADD_D = 0x0a,
13112 NMADD_PS = 0x12,
13113 NMSUB_S = 0x22,
13114 NMSUB_D = 0x2a,
13115 NMSUB_PS = 0x32,
13117 MIN_FMT = 0x3,
13118 MAX_FMT = 0xb,
13119 MINA_FMT = 0x23,
13120 MAXA_FMT = 0x2b,
13121 POOL32FXF = 0x3b,
13123 CABS_COND_FMT = 0x1c, /* MIPS3D */
13124 C_COND_FMT = 0x3c,
13126 CMP_CONDN_S = 0x5,
13127 CMP_CONDN_D = 0x15
13130 /* POOL32Fxf encoding of minor opcode extension field */
13132 enum {
13133 CVT_L = 0x04,
13134 RSQRT_FMT = 0x08,
13135 FLOOR_L = 0x0c,
13136 CVT_PW_PS = 0x1c,
13137 CVT_W = 0x24,
13138 SQRT_FMT = 0x28,
13139 FLOOR_W = 0x2c,
13140 CVT_PS_PW = 0x3c,
13141 CFC1 = 0x40,
13142 RECIP_FMT = 0x48,
13143 CEIL_L = 0x4c,
13144 CTC1 = 0x60,
13145 CEIL_W = 0x6c,
13146 MFC1 = 0x80,
13147 CVT_S_PL = 0x84,
13148 TRUNC_L = 0x8c,
13149 MTC1 = 0xa0,
13150 CVT_S_PU = 0xa4,
13151 TRUNC_W = 0xac,
13152 MFHC1 = 0xc0,
13153 ROUND_L = 0xcc,
13154 MTHC1 = 0xe0,
13155 ROUND_W = 0xec,
13157 MOV_FMT = 0x01,
13158 MOVF = 0x05,
13159 ABS_FMT = 0x0d,
13160 RSQRT1_FMT = 0x1d,
13161 MOVT = 0x25,
13162 NEG_FMT = 0x2d,
13163 CVT_D = 0x4d,
13164 RECIP1_FMT = 0x5d,
13165 CVT_S = 0x6d
13168 /* POOL32I encoding of minor opcode field (bits 25..21) */
13170 enum {
13171 BLTZ = 0x00,
13172 BLTZAL = 0x01,
13173 BGEZ = 0x02,
13174 BGEZAL = 0x03,
13175 BLEZ = 0x04,
13176 BNEZC = 0x05,
13177 BGTZ = 0x06,
13178 BEQZC = 0x07,
13179 TLTI = 0x08,
13180 BC1EQZC = 0x08,
13181 TGEI = 0x09,
13182 BC1NEZC = 0x09,
13183 TLTIU = 0x0a,
13184 BC2EQZC = 0x0a,
13185 TGEIU = 0x0b,
13186 BC2NEZC = 0x0a,
13187 TNEI = 0x0c,
13188 R6_SYNCI = 0x0c,
13189 LUI = 0x0d,
13190 TEQI = 0x0e,
13191 SYNCI = 0x10,
13192 BLTZALS = 0x11,
13193 BGEZALS = 0x13,
13194 BC2F = 0x14,
13195 BC2T = 0x15,
13196 BPOSGE64 = 0x1a,
13197 BPOSGE32 = 0x1b,
13198 /* These overlap and are distinguished by bit16 of the instruction */
13199 BC1F = 0x1c,
13200 BC1T = 0x1d,
13201 BC1ANY2F = 0x1c,
13202 BC1ANY2T = 0x1d,
13203 BC1ANY4F = 0x1e,
13204 BC1ANY4T = 0x1f
13207 /* POOL16A encoding of minor opcode field */
13209 enum {
13210 ADDU16 = 0x0,
13211 SUBU16 = 0x1
13214 /* POOL16B encoding of minor opcode field */
13216 enum {
13217 SLL16 = 0x0,
13218 SRL16 = 0x1
13221 /* POOL16C encoding of minor opcode field */
13223 enum {
13224 NOT16 = 0x00,
13225 XOR16 = 0x04,
13226 AND16 = 0x08,
13227 OR16 = 0x0c,
13228 LWM16 = 0x10,
13229 SWM16 = 0x14,
13230 JR16 = 0x18,
13231 JRC16 = 0x1a,
13232 JALR16 = 0x1c,
13233 JALR16S = 0x1e,
13234 MFHI16 = 0x20,
13235 MFLO16 = 0x24,
13236 BREAK16 = 0x28,
13237 SDBBP16 = 0x2c,
13238 JRADDIUSP = 0x30
13241 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
13243 enum {
13244 R6_NOT16 = 0x00,
13245 R6_AND16 = 0x01,
13246 R6_LWM16 = 0x02,
13247 R6_JRC16 = 0x03,
13248 MOVEP = 0x04,
13249 MOVEP_05 = 0x05,
13250 MOVEP_06 = 0x06,
13251 MOVEP_07 = 0x07,
13252 R6_XOR16 = 0x08,
13253 R6_OR16 = 0x09,
13254 R6_SWM16 = 0x0a,
13255 JALRC16 = 0x0b,
13256 MOVEP_0C = 0x0c,
13257 MOVEP_0D = 0x0d,
13258 MOVEP_0E = 0x0e,
13259 MOVEP_0F = 0x0f,
13260 JRCADDIUSP = 0x13,
13261 R6_BREAK16 = 0x1b,
13262 R6_SDBBP16 = 0x3b
13265 /* POOL16D encoding of minor opcode field */
13267 enum {
13268 ADDIUS5 = 0x0,
13269 ADDIUSP = 0x1
13272 /* POOL16E encoding of minor opcode field */
13274 enum {
13275 ADDIUR2 = 0x0,
13276 ADDIUR1SP = 0x1
13279 static int mmreg (int r)
13281 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13283 return map[r];
13286 /* Used for 16-bit store instructions. */
13287 static int mmreg2 (int r)
13289 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
13291 return map[r];
13294 #define uMIPS_RD(op) ((op >> 7) & 0x7)
13295 #define uMIPS_RS(op) ((op >> 4) & 0x7)
13296 #define uMIPS_RS2(op) uMIPS_RS(op)
13297 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
13298 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
13299 #define uMIPS_RS5(op) (op & 0x1f)
13301 /* Signed immediate */
13302 #define SIMM(op, start, width) \
13303 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
13304 << (32-width)) \
13305 >> (32-width))
13306 /* Zero-extended immediate */
13307 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
13309 static void gen_addiur1sp(DisasContext *ctx)
13311 int rd = mmreg(uMIPS_RD(ctx->opcode));
13313 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
13316 static void gen_addiur2(DisasContext *ctx)
13318 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
13319 int rd = mmreg(uMIPS_RD(ctx->opcode));
13320 int rs = mmreg(uMIPS_RS(ctx->opcode));
13322 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
13325 static void gen_addiusp(DisasContext *ctx)
13327 int encoded = ZIMM(ctx->opcode, 1, 9);
13328 int decoded;
13330 if (encoded <= 1) {
13331 decoded = 256 + encoded;
13332 } else if (encoded <= 255) {
13333 decoded = encoded;
13334 } else if (encoded <= 509) {
13335 decoded = encoded - 512;
13336 } else {
13337 decoded = encoded - 768;
13340 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
13343 static void gen_addius5(DisasContext *ctx)
13345 int imm = SIMM(ctx->opcode, 1, 4);
13346 int rd = (ctx->opcode >> 5) & 0x1f;
13348 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
13351 static void gen_andi16(DisasContext *ctx)
13353 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
13354 31, 32, 63, 64, 255, 32768, 65535 };
13355 int rd = mmreg(uMIPS_RD(ctx->opcode));
13356 int rs = mmreg(uMIPS_RS(ctx->opcode));
13357 int encoded = ZIMM(ctx->opcode, 0, 4);
13359 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
13362 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
13363 int base, int16_t offset)
13365 TCGv t0, t1;
13366 TCGv_i32 t2;
13368 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13369 generate_exception_end(ctx, EXCP_RI);
13370 return;
13373 t0 = tcg_temp_new();
13375 gen_base_offset_addr(ctx, t0, base, offset);
13377 t1 = tcg_const_tl(reglist);
13378 t2 = tcg_const_i32(ctx->mem_idx);
13380 save_cpu_state(ctx, 1);
13381 switch (opc) {
13382 case LWM32:
13383 gen_helper_lwm(cpu_env, t0, t1, t2);
13384 break;
13385 case SWM32:
13386 gen_helper_swm(cpu_env, t0, t1, t2);
13387 break;
13388 #ifdef TARGET_MIPS64
13389 case LDM:
13390 gen_helper_ldm(cpu_env, t0, t1, t2);
13391 break;
13392 case SDM:
13393 gen_helper_sdm(cpu_env, t0, t1, t2);
13394 break;
13395 #endif
13397 tcg_temp_free(t0);
13398 tcg_temp_free(t1);
13399 tcg_temp_free_i32(t2);
13403 static void gen_pool16c_insn(DisasContext *ctx)
13405 int rd = mmreg((ctx->opcode >> 3) & 0x7);
13406 int rs = mmreg(ctx->opcode & 0x7);
13408 switch (((ctx->opcode) >> 4) & 0x3f) {
13409 case NOT16 + 0:
13410 case NOT16 + 1:
13411 case NOT16 + 2:
13412 case NOT16 + 3:
13413 gen_logic(ctx, OPC_NOR, rd, rs, 0);
13414 break;
13415 case XOR16 + 0:
13416 case XOR16 + 1:
13417 case XOR16 + 2:
13418 case XOR16 + 3:
13419 gen_logic(ctx, OPC_XOR, rd, rd, rs);
13420 break;
13421 case AND16 + 0:
13422 case AND16 + 1:
13423 case AND16 + 2:
13424 case AND16 + 3:
13425 gen_logic(ctx, OPC_AND, rd, rd, rs);
13426 break;
13427 case OR16 + 0:
13428 case OR16 + 1:
13429 case OR16 + 2:
13430 case OR16 + 3:
13431 gen_logic(ctx, OPC_OR, rd, rd, rs);
13432 break;
13433 case LWM16 + 0:
13434 case LWM16 + 1:
13435 case LWM16 + 2:
13436 case LWM16 + 3:
13438 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13439 int offset = ZIMM(ctx->opcode, 0, 4);
13441 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13442 29, offset << 2);
13444 break;
13445 case SWM16 + 0:
13446 case SWM16 + 1:
13447 case SWM16 + 2:
13448 case SWM16 + 3:
13450 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13451 int offset = ZIMM(ctx->opcode, 0, 4);
13453 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13454 29, offset << 2);
13456 break;
13457 case JR16 + 0:
13458 case JR16 + 1:
13460 int reg = ctx->opcode & 0x1f;
13462 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
13464 break;
13465 case JRC16 + 0:
13466 case JRC16 + 1:
13468 int reg = ctx->opcode & 0x1f;
13469 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
13470 /* Let normal delay slot handling in our caller take us
13471 to the branch target. */
13473 break;
13474 case JALR16 + 0:
13475 case JALR16 + 1:
13476 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13477 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13478 break;
13479 case JALR16S + 0:
13480 case JALR16S + 1:
13481 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13482 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13483 break;
13484 case MFHI16 + 0:
13485 case MFHI16 + 1:
13486 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
13487 break;
13488 case MFLO16 + 0:
13489 case MFLO16 + 1:
13490 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
13491 break;
13492 case BREAK16:
13493 generate_exception_end(ctx, EXCP_BREAK);
13494 break;
13495 case SDBBP16:
13496 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13497 gen_helper_do_semihosting(cpu_env);
13498 } else {
13499 /* XXX: not clear which exception should be raised
13500 * when in debug mode...
13502 check_insn(ctx, ISA_MIPS32);
13503 generate_exception_end(ctx, EXCP_DBp);
13505 break;
13506 case JRADDIUSP + 0:
13507 case JRADDIUSP + 1:
13509 int imm = ZIMM(ctx->opcode, 0, 5);
13510 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13511 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13512 /* Let normal delay slot handling in our caller take us
13513 to the branch target. */
13515 break;
13516 default:
13517 generate_exception_end(ctx, EXCP_RI);
13518 break;
13522 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13523 int enc_rs)
13525 int rd, rs, re, rt;
13526 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13527 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13528 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13529 rd = rd_enc[enc_dest];
13530 re = re_enc[enc_dest];
13531 rs = rs_rt_enc[enc_rs];
13532 rt = rs_rt_enc[enc_rt];
13533 if (rs) {
13534 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13535 } else {
13536 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13538 if (rt) {
13539 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13540 } else {
13541 tcg_gen_movi_tl(cpu_gpr[re], 0);
13545 static void gen_pool16c_r6_insn(DisasContext *ctx)
13547 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13548 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13550 switch (ctx->opcode & 0xf) {
13551 case R6_NOT16:
13552 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13553 break;
13554 case R6_AND16:
13555 gen_logic(ctx, OPC_AND, rt, rt, rs);
13556 break;
13557 case R6_LWM16:
13559 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13560 int offset = extract32(ctx->opcode, 4, 4);
13561 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13563 break;
13564 case R6_JRC16: /* JRCADDIUSP */
13565 if ((ctx->opcode >> 4) & 1) {
13566 /* JRCADDIUSP */
13567 int imm = extract32(ctx->opcode, 5, 5);
13568 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13569 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13570 } else {
13571 /* JRC16 */
13572 rs = extract32(ctx->opcode, 5, 5);
13573 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13575 break;
13576 case MOVEP:
13577 case MOVEP_05:
13578 case MOVEP_06:
13579 case MOVEP_07:
13580 case MOVEP_0C:
13581 case MOVEP_0D:
13582 case MOVEP_0E:
13583 case MOVEP_0F:
13585 int enc_dest = uMIPS_RD(ctx->opcode);
13586 int enc_rt = uMIPS_RS2(ctx->opcode);
13587 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13588 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13590 break;
13591 case R6_XOR16:
13592 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13593 break;
13594 case R6_OR16:
13595 gen_logic(ctx, OPC_OR, rt, rt, rs);
13596 break;
13597 case R6_SWM16:
13599 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13600 int offset = extract32(ctx->opcode, 4, 4);
13601 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13603 break;
13604 case JALRC16: /* BREAK16, SDBBP16 */
13605 switch (ctx->opcode & 0x3f) {
13606 case JALRC16:
13607 case JALRC16 + 0x20:
13608 /* JALRC16 */
13609 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13610 31, 0, 0);
13611 break;
13612 case R6_BREAK16:
13613 /* BREAK16 */
13614 generate_exception(ctx, EXCP_BREAK);
13615 break;
13616 case R6_SDBBP16:
13617 /* SDBBP16 */
13618 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13619 gen_helper_do_semihosting(cpu_env);
13620 } else {
13621 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13622 generate_exception(ctx, EXCP_RI);
13623 } else {
13624 generate_exception(ctx, EXCP_DBp);
13627 break;
13629 break;
13630 default:
13631 generate_exception(ctx, EXCP_RI);
13632 break;
13636 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13638 TCGv t0 = tcg_temp_new();
13639 TCGv t1 = tcg_temp_new();
13641 gen_load_gpr(t0, base);
13643 if (index != 0) {
13644 gen_load_gpr(t1, index);
13645 tcg_gen_shli_tl(t1, t1, 2);
13646 gen_op_addr_add(ctx, t0, t1, t0);
13649 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13650 gen_store_gpr(t1, rd);
13652 tcg_temp_free(t0);
13653 tcg_temp_free(t1);
13656 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13657 int base, int16_t offset)
13659 TCGv t0, t1;
13661 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13662 generate_exception_end(ctx, EXCP_RI);
13663 return;
13666 t0 = tcg_temp_new();
13667 t1 = tcg_temp_new();
13669 gen_base_offset_addr(ctx, t0, base, offset);
13671 switch (opc) {
13672 case LWP:
13673 if (rd == base) {
13674 generate_exception_end(ctx, EXCP_RI);
13675 return;
13677 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13678 gen_store_gpr(t1, rd);
13679 tcg_gen_movi_tl(t1, 4);
13680 gen_op_addr_add(ctx, t0, t0, t1);
13681 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13682 gen_store_gpr(t1, rd+1);
13683 break;
13684 case SWP:
13685 gen_load_gpr(t1, rd);
13686 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13687 tcg_gen_movi_tl(t1, 4);
13688 gen_op_addr_add(ctx, t0, t0, t1);
13689 gen_load_gpr(t1, rd+1);
13690 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13691 break;
13692 #ifdef TARGET_MIPS64
13693 case LDP:
13694 if (rd == base) {
13695 generate_exception_end(ctx, EXCP_RI);
13696 return;
13698 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13699 gen_store_gpr(t1, rd);
13700 tcg_gen_movi_tl(t1, 8);
13701 gen_op_addr_add(ctx, t0, t0, t1);
13702 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13703 gen_store_gpr(t1, rd+1);
13704 break;
13705 case SDP:
13706 gen_load_gpr(t1, rd);
13707 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13708 tcg_gen_movi_tl(t1, 8);
13709 gen_op_addr_add(ctx, t0, t0, t1);
13710 gen_load_gpr(t1, rd+1);
13711 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13712 break;
13713 #endif
13715 tcg_temp_free(t0);
13716 tcg_temp_free(t1);
13719 static void gen_sync(int stype)
13721 TCGBar tcg_mo = TCG_BAR_SC;
13723 switch (stype) {
13724 case 0x4: /* SYNC_WMB */
13725 tcg_mo |= TCG_MO_ST_ST;
13726 break;
13727 case 0x10: /* SYNC_MB */
13728 tcg_mo |= TCG_MO_ALL;
13729 break;
13730 case 0x11: /* SYNC_ACQUIRE */
13731 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
13732 break;
13733 case 0x12: /* SYNC_RELEASE */
13734 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
13735 break;
13736 case 0x13: /* SYNC_RMB */
13737 tcg_mo |= TCG_MO_LD_LD;
13738 break;
13739 default:
13740 tcg_mo |= TCG_MO_ALL;
13741 break;
13744 tcg_gen_mb(tcg_mo);
13747 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13749 int extension = (ctx->opcode >> 6) & 0x3f;
13750 int minor = (ctx->opcode >> 12) & 0xf;
13751 uint32_t mips32_op;
13753 switch (extension) {
13754 case TEQ:
13755 mips32_op = OPC_TEQ;
13756 goto do_trap;
13757 case TGE:
13758 mips32_op = OPC_TGE;
13759 goto do_trap;
13760 case TGEU:
13761 mips32_op = OPC_TGEU;
13762 goto do_trap;
13763 case TLT:
13764 mips32_op = OPC_TLT;
13765 goto do_trap;
13766 case TLTU:
13767 mips32_op = OPC_TLTU;
13768 goto do_trap;
13769 case TNE:
13770 mips32_op = OPC_TNE;
13771 do_trap:
13772 gen_trap(ctx, mips32_op, rs, rt, -1);
13773 break;
13774 #ifndef CONFIG_USER_ONLY
13775 case MFC0:
13776 case MFC0 + 32:
13777 check_cp0_enabled(ctx);
13778 if (rt == 0) {
13779 /* Treat as NOP. */
13780 break;
13782 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13783 break;
13784 case MTC0:
13785 case MTC0 + 32:
13786 check_cp0_enabled(ctx);
13788 TCGv t0 = tcg_temp_new();
13790 gen_load_gpr(t0, rt);
13791 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13792 tcg_temp_free(t0);
13794 break;
13795 #endif
13796 case 0x2a:
13797 switch (minor & 3) {
13798 case MADD_ACC:
13799 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13800 break;
13801 case MADDU_ACC:
13802 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13803 break;
13804 case MSUB_ACC:
13805 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13806 break;
13807 case MSUBU_ACC:
13808 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13809 break;
13810 default:
13811 goto pool32axf_invalid;
13813 break;
13814 case 0x32:
13815 switch (minor & 3) {
13816 case MULT_ACC:
13817 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13818 break;
13819 case MULTU_ACC:
13820 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13821 break;
13822 default:
13823 goto pool32axf_invalid;
13825 break;
13826 case 0x2c:
13827 switch (minor) {
13828 case BITSWAP:
13829 check_insn(ctx, ISA_MIPS32R6);
13830 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13831 break;
13832 case SEB:
13833 gen_bshfl(ctx, OPC_SEB, rs, rt);
13834 break;
13835 case SEH:
13836 gen_bshfl(ctx, OPC_SEH, rs, rt);
13837 break;
13838 case CLO:
13839 mips32_op = OPC_CLO;
13840 goto do_cl;
13841 case CLZ:
13842 mips32_op = OPC_CLZ;
13843 do_cl:
13844 check_insn(ctx, ISA_MIPS32);
13845 gen_cl(ctx, mips32_op, rt, rs);
13846 break;
13847 case RDHWR:
13848 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13849 gen_rdhwr(ctx, rt, rs, 0);
13850 break;
13851 case WSBH:
13852 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13853 break;
13854 case MULT:
13855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13856 mips32_op = OPC_MULT;
13857 goto do_mul;
13858 case MULTU:
13859 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13860 mips32_op = OPC_MULTU;
13861 goto do_mul;
13862 case DIV:
13863 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13864 mips32_op = OPC_DIV;
13865 goto do_div;
13866 case DIVU:
13867 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13868 mips32_op = OPC_DIVU;
13869 goto do_div;
13870 do_div:
13871 check_insn(ctx, ISA_MIPS32);
13872 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13873 break;
13874 case MADD:
13875 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13876 mips32_op = OPC_MADD;
13877 goto do_mul;
13878 case MADDU:
13879 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13880 mips32_op = OPC_MADDU;
13881 goto do_mul;
13882 case MSUB:
13883 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13884 mips32_op = OPC_MSUB;
13885 goto do_mul;
13886 case MSUBU:
13887 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13888 mips32_op = OPC_MSUBU;
13889 do_mul:
13890 check_insn(ctx, ISA_MIPS32);
13891 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13892 break;
13893 default:
13894 goto pool32axf_invalid;
13896 break;
13897 case 0x34:
13898 switch (minor) {
13899 case MFC2:
13900 case MTC2:
13901 case MFHC2:
13902 case MTHC2:
13903 case CFC2:
13904 case CTC2:
13905 generate_exception_err(ctx, EXCP_CpU, 2);
13906 break;
13907 default:
13908 goto pool32axf_invalid;
13910 break;
13911 case 0x3c:
13912 switch (minor) {
13913 case JALR: /* JALRC */
13914 case JALR_HB: /* JALRC_HB */
13915 if (ctx->insn_flags & ISA_MIPS32R6) {
13916 /* JALRC, JALRC_HB */
13917 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13918 } else {
13919 /* JALR, JALR_HB */
13920 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13921 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13923 break;
13924 case JALRS:
13925 case JALRS_HB:
13926 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13927 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13928 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13929 break;
13930 default:
13931 goto pool32axf_invalid;
13933 break;
13934 case 0x05:
13935 switch (minor) {
13936 case RDPGPR:
13937 check_cp0_enabled(ctx);
13938 check_insn(ctx, ISA_MIPS32R2);
13939 gen_load_srsgpr(rs, rt);
13940 break;
13941 case WRPGPR:
13942 check_cp0_enabled(ctx);
13943 check_insn(ctx, ISA_MIPS32R2);
13944 gen_store_srsgpr(rs, rt);
13945 break;
13946 default:
13947 goto pool32axf_invalid;
13949 break;
13950 #ifndef CONFIG_USER_ONLY
13951 case 0x0d:
13952 switch (minor) {
13953 case TLBP:
13954 mips32_op = OPC_TLBP;
13955 goto do_cp0;
13956 case TLBR:
13957 mips32_op = OPC_TLBR;
13958 goto do_cp0;
13959 case TLBWI:
13960 mips32_op = OPC_TLBWI;
13961 goto do_cp0;
13962 case TLBWR:
13963 mips32_op = OPC_TLBWR;
13964 goto do_cp0;
13965 case TLBINV:
13966 mips32_op = OPC_TLBINV;
13967 goto do_cp0;
13968 case TLBINVF:
13969 mips32_op = OPC_TLBINVF;
13970 goto do_cp0;
13971 case WAIT:
13972 mips32_op = OPC_WAIT;
13973 goto do_cp0;
13974 case DERET:
13975 mips32_op = OPC_DERET;
13976 goto do_cp0;
13977 case ERET:
13978 mips32_op = OPC_ERET;
13979 do_cp0:
13980 gen_cp0(env, ctx, mips32_op, rt, rs);
13981 break;
13982 default:
13983 goto pool32axf_invalid;
13985 break;
13986 case 0x1d:
13987 switch (minor) {
13988 case DI:
13989 check_cp0_enabled(ctx);
13991 TCGv t0 = tcg_temp_new();
13993 save_cpu_state(ctx, 1);
13994 gen_helper_di(t0, cpu_env);
13995 gen_store_gpr(t0, rs);
13996 /* Stop translation as we may have switched the execution mode */
13997 ctx->base.is_jmp = DISAS_STOP;
13998 tcg_temp_free(t0);
14000 break;
14001 case EI:
14002 check_cp0_enabled(ctx);
14004 TCGv t0 = tcg_temp_new();
14006 save_cpu_state(ctx, 1);
14007 gen_helper_ei(t0, cpu_env);
14008 gen_store_gpr(t0, rs);
14009 /* DISAS_STOP isn't sufficient, we need to ensure we break out
14010 of translated code to check for pending interrupts. */
14011 gen_save_pc(ctx->base.pc_next + 4);
14012 ctx->base.is_jmp = DISAS_EXIT;
14013 tcg_temp_free(t0);
14015 break;
14016 default:
14017 goto pool32axf_invalid;
14019 break;
14020 #endif
14021 case 0x2d:
14022 switch (minor) {
14023 case SYNC:
14024 gen_sync(extract32(ctx->opcode, 16, 5));
14025 break;
14026 case SYSCALL:
14027 generate_exception_end(ctx, EXCP_SYSCALL);
14028 break;
14029 case SDBBP:
14030 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14031 gen_helper_do_semihosting(cpu_env);
14032 } else {
14033 check_insn(ctx, ISA_MIPS32);
14034 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14035 generate_exception_end(ctx, EXCP_RI);
14036 } else {
14037 generate_exception_end(ctx, EXCP_DBp);
14040 break;
14041 default:
14042 goto pool32axf_invalid;
14044 break;
14045 case 0x01:
14046 switch (minor & 3) {
14047 case MFHI_ACC:
14048 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14049 break;
14050 case MFLO_ACC:
14051 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14052 break;
14053 case MTHI_ACC:
14054 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14055 break;
14056 case MTLO_ACC:
14057 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14058 break;
14059 default:
14060 goto pool32axf_invalid;
14062 break;
14063 case 0x35:
14064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14065 switch (minor) {
14066 case MFHI32:
14067 gen_HILO(ctx, OPC_MFHI, 0, rs);
14068 break;
14069 case MFLO32:
14070 gen_HILO(ctx, OPC_MFLO, 0, rs);
14071 break;
14072 case MTHI32:
14073 gen_HILO(ctx, OPC_MTHI, 0, rs);
14074 break;
14075 case MTLO32:
14076 gen_HILO(ctx, OPC_MTLO, 0, rs);
14077 break;
14078 default:
14079 goto pool32axf_invalid;
14081 break;
14082 default:
14083 pool32axf_invalid:
14084 MIPS_INVAL("pool32axf");
14085 generate_exception_end(ctx, EXCP_RI);
14086 break;
14090 /* Values for microMIPS fmt field. Variable-width, depending on which
14091 formats the instruction supports. */
14093 enum {
14094 FMT_SD_S = 0,
14095 FMT_SD_D = 1,
14097 FMT_SDPS_S = 0,
14098 FMT_SDPS_D = 1,
14099 FMT_SDPS_PS = 2,
14101 FMT_SWL_S = 0,
14102 FMT_SWL_W = 1,
14103 FMT_SWL_L = 2,
14105 FMT_DWL_D = 0,
14106 FMT_DWL_W = 1,
14107 FMT_DWL_L = 2
14110 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
14112 int extension = (ctx->opcode >> 6) & 0x3ff;
14113 uint32_t mips32_op;
14115 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
14116 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
14117 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
14119 switch (extension) {
14120 case FLOAT_1BIT_FMT(CFC1, 0):
14121 mips32_op = OPC_CFC1;
14122 goto do_cp1;
14123 case FLOAT_1BIT_FMT(CTC1, 0):
14124 mips32_op = OPC_CTC1;
14125 goto do_cp1;
14126 case FLOAT_1BIT_FMT(MFC1, 0):
14127 mips32_op = OPC_MFC1;
14128 goto do_cp1;
14129 case FLOAT_1BIT_FMT(MTC1, 0):
14130 mips32_op = OPC_MTC1;
14131 goto do_cp1;
14132 case FLOAT_1BIT_FMT(MFHC1, 0):
14133 mips32_op = OPC_MFHC1;
14134 goto do_cp1;
14135 case FLOAT_1BIT_FMT(MTHC1, 0):
14136 mips32_op = OPC_MTHC1;
14137 do_cp1:
14138 gen_cp1(ctx, mips32_op, rt, rs);
14139 break;
14141 /* Reciprocal square root */
14142 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
14143 mips32_op = OPC_RSQRT_S;
14144 goto do_unaryfp;
14145 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
14146 mips32_op = OPC_RSQRT_D;
14147 goto do_unaryfp;
14149 /* Square root */
14150 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
14151 mips32_op = OPC_SQRT_S;
14152 goto do_unaryfp;
14153 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
14154 mips32_op = OPC_SQRT_D;
14155 goto do_unaryfp;
14157 /* Reciprocal */
14158 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
14159 mips32_op = OPC_RECIP_S;
14160 goto do_unaryfp;
14161 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
14162 mips32_op = OPC_RECIP_D;
14163 goto do_unaryfp;
14165 /* Floor */
14166 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
14167 mips32_op = OPC_FLOOR_L_S;
14168 goto do_unaryfp;
14169 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
14170 mips32_op = OPC_FLOOR_L_D;
14171 goto do_unaryfp;
14172 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
14173 mips32_op = OPC_FLOOR_W_S;
14174 goto do_unaryfp;
14175 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
14176 mips32_op = OPC_FLOOR_W_D;
14177 goto do_unaryfp;
14179 /* Ceiling */
14180 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
14181 mips32_op = OPC_CEIL_L_S;
14182 goto do_unaryfp;
14183 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
14184 mips32_op = OPC_CEIL_L_D;
14185 goto do_unaryfp;
14186 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
14187 mips32_op = OPC_CEIL_W_S;
14188 goto do_unaryfp;
14189 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
14190 mips32_op = OPC_CEIL_W_D;
14191 goto do_unaryfp;
14193 /* Truncation */
14194 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
14195 mips32_op = OPC_TRUNC_L_S;
14196 goto do_unaryfp;
14197 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
14198 mips32_op = OPC_TRUNC_L_D;
14199 goto do_unaryfp;
14200 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
14201 mips32_op = OPC_TRUNC_W_S;
14202 goto do_unaryfp;
14203 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
14204 mips32_op = OPC_TRUNC_W_D;
14205 goto do_unaryfp;
14207 /* Round */
14208 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
14209 mips32_op = OPC_ROUND_L_S;
14210 goto do_unaryfp;
14211 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
14212 mips32_op = OPC_ROUND_L_D;
14213 goto do_unaryfp;
14214 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
14215 mips32_op = OPC_ROUND_W_S;
14216 goto do_unaryfp;
14217 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
14218 mips32_op = OPC_ROUND_W_D;
14219 goto do_unaryfp;
14221 /* Integer to floating-point conversion */
14222 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
14223 mips32_op = OPC_CVT_L_S;
14224 goto do_unaryfp;
14225 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
14226 mips32_op = OPC_CVT_L_D;
14227 goto do_unaryfp;
14228 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
14229 mips32_op = OPC_CVT_W_S;
14230 goto do_unaryfp;
14231 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
14232 mips32_op = OPC_CVT_W_D;
14233 goto do_unaryfp;
14235 /* Paired-foo conversions */
14236 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
14237 mips32_op = OPC_CVT_S_PL;
14238 goto do_unaryfp;
14239 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
14240 mips32_op = OPC_CVT_S_PU;
14241 goto do_unaryfp;
14242 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
14243 mips32_op = OPC_CVT_PW_PS;
14244 goto do_unaryfp;
14245 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
14246 mips32_op = OPC_CVT_PS_PW;
14247 goto do_unaryfp;
14249 /* Floating-point moves */
14250 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
14251 mips32_op = OPC_MOV_S;
14252 goto do_unaryfp;
14253 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
14254 mips32_op = OPC_MOV_D;
14255 goto do_unaryfp;
14256 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
14257 mips32_op = OPC_MOV_PS;
14258 goto do_unaryfp;
14260 /* Absolute value */
14261 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
14262 mips32_op = OPC_ABS_S;
14263 goto do_unaryfp;
14264 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
14265 mips32_op = OPC_ABS_D;
14266 goto do_unaryfp;
14267 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
14268 mips32_op = OPC_ABS_PS;
14269 goto do_unaryfp;
14271 /* Negation */
14272 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
14273 mips32_op = OPC_NEG_S;
14274 goto do_unaryfp;
14275 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
14276 mips32_op = OPC_NEG_D;
14277 goto do_unaryfp;
14278 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
14279 mips32_op = OPC_NEG_PS;
14280 goto do_unaryfp;
14282 /* Reciprocal square root step */
14283 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
14284 mips32_op = OPC_RSQRT1_S;
14285 goto do_unaryfp;
14286 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
14287 mips32_op = OPC_RSQRT1_D;
14288 goto do_unaryfp;
14289 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
14290 mips32_op = OPC_RSQRT1_PS;
14291 goto do_unaryfp;
14293 /* Reciprocal step */
14294 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
14295 mips32_op = OPC_RECIP1_S;
14296 goto do_unaryfp;
14297 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
14298 mips32_op = OPC_RECIP1_S;
14299 goto do_unaryfp;
14300 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
14301 mips32_op = OPC_RECIP1_PS;
14302 goto do_unaryfp;
14304 /* Conversions from double */
14305 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
14306 mips32_op = OPC_CVT_D_S;
14307 goto do_unaryfp;
14308 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
14309 mips32_op = OPC_CVT_D_W;
14310 goto do_unaryfp;
14311 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
14312 mips32_op = OPC_CVT_D_L;
14313 goto do_unaryfp;
14315 /* Conversions from single */
14316 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
14317 mips32_op = OPC_CVT_S_D;
14318 goto do_unaryfp;
14319 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
14320 mips32_op = OPC_CVT_S_W;
14321 goto do_unaryfp;
14322 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
14323 mips32_op = OPC_CVT_S_L;
14324 do_unaryfp:
14325 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
14326 break;
14328 /* Conditional moves on floating-point codes */
14329 case COND_FLOAT_MOV(MOVT, 0):
14330 case COND_FLOAT_MOV(MOVT, 1):
14331 case COND_FLOAT_MOV(MOVT, 2):
14332 case COND_FLOAT_MOV(MOVT, 3):
14333 case COND_FLOAT_MOV(MOVT, 4):
14334 case COND_FLOAT_MOV(MOVT, 5):
14335 case COND_FLOAT_MOV(MOVT, 6):
14336 case COND_FLOAT_MOV(MOVT, 7):
14337 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14338 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
14339 break;
14340 case COND_FLOAT_MOV(MOVF, 0):
14341 case COND_FLOAT_MOV(MOVF, 1):
14342 case COND_FLOAT_MOV(MOVF, 2):
14343 case COND_FLOAT_MOV(MOVF, 3):
14344 case COND_FLOAT_MOV(MOVF, 4):
14345 case COND_FLOAT_MOV(MOVF, 5):
14346 case COND_FLOAT_MOV(MOVF, 6):
14347 case COND_FLOAT_MOV(MOVF, 7):
14348 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14349 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
14350 break;
14351 default:
14352 MIPS_INVAL("pool32fxf");
14353 generate_exception_end(ctx, EXCP_RI);
14354 break;
14358 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
14360 int32_t offset;
14361 uint16_t insn;
14362 int rt, rs, rd, rr;
14363 int16_t imm;
14364 uint32_t op, minor, minor2, mips32_op;
14365 uint32_t cond, fmt, cc;
14367 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
14368 ctx->opcode = (ctx->opcode << 16) | insn;
14370 rt = (ctx->opcode >> 21) & 0x1f;
14371 rs = (ctx->opcode >> 16) & 0x1f;
14372 rd = (ctx->opcode >> 11) & 0x1f;
14373 rr = (ctx->opcode >> 6) & 0x1f;
14374 imm = (int16_t) ctx->opcode;
14376 op = (ctx->opcode >> 26) & 0x3f;
14377 switch (op) {
14378 case POOL32A:
14379 minor = ctx->opcode & 0x3f;
14380 switch (minor) {
14381 case 0x00:
14382 minor = (ctx->opcode >> 6) & 0xf;
14383 switch (minor) {
14384 case SLL32:
14385 mips32_op = OPC_SLL;
14386 goto do_shifti;
14387 case SRA:
14388 mips32_op = OPC_SRA;
14389 goto do_shifti;
14390 case SRL32:
14391 mips32_op = OPC_SRL;
14392 goto do_shifti;
14393 case ROTR:
14394 mips32_op = OPC_ROTR;
14395 do_shifti:
14396 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
14397 break;
14398 case SELEQZ:
14399 check_insn(ctx, ISA_MIPS32R6);
14400 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
14401 break;
14402 case SELNEZ:
14403 check_insn(ctx, ISA_MIPS32R6);
14404 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
14405 break;
14406 case R6_RDHWR:
14407 check_insn(ctx, ISA_MIPS32R6);
14408 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
14409 break;
14410 default:
14411 goto pool32a_invalid;
14413 break;
14414 case 0x10:
14415 minor = (ctx->opcode >> 6) & 0xf;
14416 switch (minor) {
14417 /* Arithmetic */
14418 case ADD:
14419 mips32_op = OPC_ADD;
14420 goto do_arith;
14421 case ADDU32:
14422 mips32_op = OPC_ADDU;
14423 goto do_arith;
14424 case SUB:
14425 mips32_op = OPC_SUB;
14426 goto do_arith;
14427 case SUBU32:
14428 mips32_op = OPC_SUBU;
14429 goto do_arith;
14430 case MUL:
14431 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14432 mips32_op = OPC_MUL;
14433 do_arith:
14434 gen_arith(ctx, mips32_op, rd, rs, rt);
14435 break;
14436 /* Shifts */
14437 case SLLV:
14438 mips32_op = OPC_SLLV;
14439 goto do_shift;
14440 case SRLV:
14441 mips32_op = OPC_SRLV;
14442 goto do_shift;
14443 case SRAV:
14444 mips32_op = OPC_SRAV;
14445 goto do_shift;
14446 case ROTRV:
14447 mips32_op = OPC_ROTRV;
14448 do_shift:
14449 gen_shift(ctx, mips32_op, rd, rs, rt);
14450 break;
14451 /* Logical operations */
14452 case AND:
14453 mips32_op = OPC_AND;
14454 goto do_logic;
14455 case OR32:
14456 mips32_op = OPC_OR;
14457 goto do_logic;
14458 case NOR:
14459 mips32_op = OPC_NOR;
14460 goto do_logic;
14461 case XOR32:
14462 mips32_op = OPC_XOR;
14463 do_logic:
14464 gen_logic(ctx, mips32_op, rd, rs, rt);
14465 break;
14466 /* Set less than */
14467 case SLT:
14468 mips32_op = OPC_SLT;
14469 goto do_slt;
14470 case SLTU:
14471 mips32_op = OPC_SLTU;
14472 do_slt:
14473 gen_slt(ctx, mips32_op, rd, rs, rt);
14474 break;
14475 default:
14476 goto pool32a_invalid;
14478 break;
14479 case 0x18:
14480 minor = (ctx->opcode >> 6) & 0xf;
14481 switch (minor) {
14482 /* Conditional moves */
14483 case MOVN: /* MUL */
14484 if (ctx->insn_flags & ISA_MIPS32R6) {
14485 /* MUL */
14486 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14487 } else {
14488 /* MOVN */
14489 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14491 break;
14492 case MOVZ: /* MUH */
14493 if (ctx->insn_flags & ISA_MIPS32R6) {
14494 /* MUH */
14495 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14496 } else {
14497 /* MOVZ */
14498 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14500 break;
14501 case MULU:
14502 check_insn(ctx, ISA_MIPS32R6);
14503 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14504 break;
14505 case MUHU:
14506 check_insn(ctx, ISA_MIPS32R6);
14507 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14508 break;
14509 case LWXS: /* DIV */
14510 if (ctx->insn_flags & ISA_MIPS32R6) {
14511 /* DIV */
14512 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14513 } else {
14514 /* LWXS */
14515 gen_ldxs(ctx, rs, rt, rd);
14517 break;
14518 case MOD:
14519 check_insn(ctx, ISA_MIPS32R6);
14520 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14521 break;
14522 case R6_DIVU:
14523 check_insn(ctx, ISA_MIPS32R6);
14524 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
14525 break;
14526 case MODU:
14527 check_insn(ctx, ISA_MIPS32R6);
14528 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
14529 break;
14530 default:
14531 goto pool32a_invalid;
14533 break;
14534 case INS:
14535 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14536 return;
14537 case LSA:
14538 check_insn(ctx, ISA_MIPS32R6);
14539 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14540 extract32(ctx->opcode, 9, 2));
14541 break;
14542 case ALIGN:
14543 check_insn(ctx, ISA_MIPS32R6);
14544 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
14545 break;
14546 case EXT:
14547 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14548 return;
14549 case POOL32AXF:
14550 gen_pool32axf(env, ctx, rt, rs);
14551 break;
14552 case BREAK32:
14553 generate_exception_end(ctx, EXCP_BREAK);
14554 break;
14555 case SIGRIE:
14556 check_insn(ctx, ISA_MIPS32R6);
14557 generate_exception_end(ctx, EXCP_RI);
14558 break;
14559 default:
14560 pool32a_invalid:
14561 MIPS_INVAL("pool32a");
14562 generate_exception_end(ctx, EXCP_RI);
14563 break;
14565 break;
14566 case POOL32B:
14567 minor = (ctx->opcode >> 12) & 0xf;
14568 switch (minor) {
14569 case CACHE:
14570 check_cp0_enabled(ctx);
14571 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14572 gen_cache_operation(ctx, rt, rs, imm);
14574 break;
14575 case LWC2:
14576 case SWC2:
14577 /* COP2: Not implemented. */
14578 generate_exception_err(ctx, EXCP_CpU, 2);
14579 break;
14580 #ifdef TARGET_MIPS64
14581 case LDP:
14582 case SDP:
14583 check_insn(ctx, ISA_MIPS3);
14584 check_mips_64(ctx);
14585 #endif
14586 /* fall through */
14587 case LWP:
14588 case SWP:
14589 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14590 break;
14591 #ifdef TARGET_MIPS64
14592 case LDM:
14593 case SDM:
14594 check_insn(ctx, ISA_MIPS3);
14595 check_mips_64(ctx);
14596 #endif
14597 /* fall through */
14598 case LWM32:
14599 case SWM32:
14600 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14601 break;
14602 default:
14603 MIPS_INVAL("pool32b");
14604 generate_exception_end(ctx, EXCP_RI);
14605 break;
14607 break;
14608 case POOL32F:
14609 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14610 minor = ctx->opcode & 0x3f;
14611 check_cp1_enabled(ctx);
14612 switch (minor) {
14613 case ALNV_PS:
14614 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14615 mips32_op = OPC_ALNV_PS;
14616 goto do_madd;
14617 case MADD_S:
14618 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14619 mips32_op = OPC_MADD_S;
14620 goto do_madd;
14621 case MADD_D:
14622 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14623 mips32_op = OPC_MADD_D;
14624 goto do_madd;
14625 case MADD_PS:
14626 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14627 mips32_op = OPC_MADD_PS;
14628 goto do_madd;
14629 case MSUB_S:
14630 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14631 mips32_op = OPC_MSUB_S;
14632 goto do_madd;
14633 case MSUB_D:
14634 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14635 mips32_op = OPC_MSUB_D;
14636 goto do_madd;
14637 case MSUB_PS:
14638 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14639 mips32_op = OPC_MSUB_PS;
14640 goto do_madd;
14641 case NMADD_S:
14642 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14643 mips32_op = OPC_NMADD_S;
14644 goto do_madd;
14645 case NMADD_D:
14646 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14647 mips32_op = OPC_NMADD_D;
14648 goto do_madd;
14649 case NMADD_PS:
14650 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14651 mips32_op = OPC_NMADD_PS;
14652 goto do_madd;
14653 case NMSUB_S:
14654 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14655 mips32_op = OPC_NMSUB_S;
14656 goto do_madd;
14657 case NMSUB_D:
14658 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14659 mips32_op = OPC_NMSUB_D;
14660 goto do_madd;
14661 case NMSUB_PS:
14662 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14663 mips32_op = OPC_NMSUB_PS;
14664 do_madd:
14665 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14666 break;
14667 case CABS_COND_FMT:
14668 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14669 cond = (ctx->opcode >> 6) & 0xf;
14670 cc = (ctx->opcode >> 13) & 0x7;
14671 fmt = (ctx->opcode >> 10) & 0x3;
14672 switch (fmt) {
14673 case 0x0:
14674 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14675 break;
14676 case 0x1:
14677 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14678 break;
14679 case 0x2:
14680 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14681 break;
14682 default:
14683 goto pool32f_invalid;
14685 break;
14686 case C_COND_FMT:
14687 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14688 cond = (ctx->opcode >> 6) & 0xf;
14689 cc = (ctx->opcode >> 13) & 0x7;
14690 fmt = (ctx->opcode >> 10) & 0x3;
14691 switch (fmt) {
14692 case 0x0:
14693 gen_cmp_s(ctx, cond, rt, rs, cc);
14694 break;
14695 case 0x1:
14696 gen_cmp_d(ctx, cond, rt, rs, cc);
14697 break;
14698 case 0x2:
14699 gen_cmp_ps(ctx, cond, rt, rs, cc);
14700 break;
14701 default:
14702 goto pool32f_invalid;
14704 break;
14705 case CMP_CONDN_S:
14706 check_insn(ctx, ISA_MIPS32R6);
14707 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14708 break;
14709 case CMP_CONDN_D:
14710 check_insn(ctx, ISA_MIPS32R6);
14711 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14712 break;
14713 case POOL32FXF:
14714 gen_pool32fxf(ctx, rt, rs);
14715 break;
14716 case 0x00:
14717 /* PLL foo */
14718 switch ((ctx->opcode >> 6) & 0x7) {
14719 case PLL_PS:
14720 mips32_op = OPC_PLL_PS;
14721 goto do_ps;
14722 case PLU_PS:
14723 mips32_op = OPC_PLU_PS;
14724 goto do_ps;
14725 case PUL_PS:
14726 mips32_op = OPC_PUL_PS;
14727 goto do_ps;
14728 case PUU_PS:
14729 mips32_op = OPC_PUU_PS;
14730 goto do_ps;
14731 case CVT_PS_S:
14732 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14733 mips32_op = OPC_CVT_PS_S;
14734 do_ps:
14735 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14736 break;
14737 default:
14738 goto pool32f_invalid;
14740 break;
14741 case MIN_FMT:
14742 check_insn(ctx, ISA_MIPS32R6);
14743 switch ((ctx->opcode >> 9) & 0x3) {
14744 case FMT_SDPS_S:
14745 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14746 break;
14747 case FMT_SDPS_D:
14748 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14749 break;
14750 default:
14751 goto pool32f_invalid;
14753 break;
14754 case 0x08:
14755 /* [LS][WDU]XC1 */
14756 switch ((ctx->opcode >> 6) & 0x7) {
14757 case LWXC1:
14758 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14759 mips32_op = OPC_LWXC1;
14760 goto do_ldst_cp1;
14761 case SWXC1:
14762 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14763 mips32_op = OPC_SWXC1;
14764 goto do_ldst_cp1;
14765 case LDXC1:
14766 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14767 mips32_op = OPC_LDXC1;
14768 goto do_ldst_cp1;
14769 case SDXC1:
14770 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14771 mips32_op = OPC_SDXC1;
14772 goto do_ldst_cp1;
14773 case LUXC1:
14774 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14775 mips32_op = OPC_LUXC1;
14776 goto do_ldst_cp1;
14777 case SUXC1:
14778 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14779 mips32_op = OPC_SUXC1;
14780 do_ldst_cp1:
14781 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14782 break;
14783 default:
14784 goto pool32f_invalid;
14786 break;
14787 case MAX_FMT:
14788 check_insn(ctx, ISA_MIPS32R6);
14789 switch ((ctx->opcode >> 9) & 0x3) {
14790 case FMT_SDPS_S:
14791 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14792 break;
14793 case FMT_SDPS_D:
14794 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14795 break;
14796 default:
14797 goto pool32f_invalid;
14799 break;
14800 case 0x18:
14801 /* 3D insns */
14802 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14803 fmt = (ctx->opcode >> 9) & 0x3;
14804 switch ((ctx->opcode >> 6) & 0x7) {
14805 case RSQRT2_FMT:
14806 switch (fmt) {
14807 case FMT_SDPS_S:
14808 mips32_op = OPC_RSQRT2_S;
14809 goto do_3d;
14810 case FMT_SDPS_D:
14811 mips32_op = OPC_RSQRT2_D;
14812 goto do_3d;
14813 case FMT_SDPS_PS:
14814 mips32_op = OPC_RSQRT2_PS;
14815 goto do_3d;
14816 default:
14817 goto pool32f_invalid;
14819 break;
14820 case RECIP2_FMT:
14821 switch (fmt) {
14822 case FMT_SDPS_S:
14823 mips32_op = OPC_RECIP2_S;
14824 goto do_3d;
14825 case FMT_SDPS_D:
14826 mips32_op = OPC_RECIP2_D;
14827 goto do_3d;
14828 case FMT_SDPS_PS:
14829 mips32_op = OPC_RECIP2_PS;
14830 goto do_3d;
14831 default:
14832 goto pool32f_invalid;
14834 break;
14835 case ADDR_PS:
14836 mips32_op = OPC_ADDR_PS;
14837 goto do_3d;
14838 case MULR_PS:
14839 mips32_op = OPC_MULR_PS;
14840 do_3d:
14841 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14842 break;
14843 default:
14844 goto pool32f_invalid;
14846 break;
14847 case 0x20:
14848 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14849 cc = (ctx->opcode >> 13) & 0x7;
14850 fmt = (ctx->opcode >> 9) & 0x3;
14851 switch ((ctx->opcode >> 6) & 0x7) {
14852 case MOVF_FMT: /* RINT_FMT */
14853 if (ctx->insn_flags & ISA_MIPS32R6) {
14854 /* RINT_FMT */
14855 switch (fmt) {
14856 case FMT_SDPS_S:
14857 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14858 break;
14859 case FMT_SDPS_D:
14860 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14861 break;
14862 default:
14863 goto pool32f_invalid;
14865 } else {
14866 /* MOVF_FMT */
14867 switch (fmt) {
14868 case FMT_SDPS_S:
14869 gen_movcf_s(ctx, rs, rt, cc, 0);
14870 break;
14871 case FMT_SDPS_D:
14872 gen_movcf_d(ctx, rs, rt, cc, 0);
14873 break;
14874 case FMT_SDPS_PS:
14875 check_ps(ctx);
14876 gen_movcf_ps(ctx, rs, rt, cc, 0);
14877 break;
14878 default:
14879 goto pool32f_invalid;
14882 break;
14883 case MOVT_FMT: /* CLASS_FMT */
14884 if (ctx->insn_flags & ISA_MIPS32R6) {
14885 /* CLASS_FMT */
14886 switch (fmt) {
14887 case FMT_SDPS_S:
14888 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14889 break;
14890 case FMT_SDPS_D:
14891 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14892 break;
14893 default:
14894 goto pool32f_invalid;
14896 } else {
14897 /* MOVT_FMT */
14898 switch (fmt) {
14899 case FMT_SDPS_S:
14900 gen_movcf_s(ctx, rs, rt, cc, 1);
14901 break;
14902 case FMT_SDPS_D:
14903 gen_movcf_d(ctx, rs, rt, cc, 1);
14904 break;
14905 case FMT_SDPS_PS:
14906 check_ps(ctx);
14907 gen_movcf_ps(ctx, rs, rt, cc, 1);
14908 break;
14909 default:
14910 goto pool32f_invalid;
14913 break;
14914 case PREFX:
14915 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14916 break;
14917 default:
14918 goto pool32f_invalid;
14920 break;
14921 #define FINSN_3ARG_SDPS(prfx) \
14922 switch ((ctx->opcode >> 8) & 0x3) { \
14923 case FMT_SDPS_S: \
14924 mips32_op = OPC_##prfx##_S; \
14925 goto do_fpop; \
14926 case FMT_SDPS_D: \
14927 mips32_op = OPC_##prfx##_D; \
14928 goto do_fpop; \
14929 case FMT_SDPS_PS: \
14930 check_ps(ctx); \
14931 mips32_op = OPC_##prfx##_PS; \
14932 goto do_fpop; \
14933 default: \
14934 goto pool32f_invalid; \
14936 case MINA_FMT:
14937 check_insn(ctx, ISA_MIPS32R6);
14938 switch ((ctx->opcode >> 9) & 0x3) {
14939 case FMT_SDPS_S:
14940 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14941 break;
14942 case FMT_SDPS_D:
14943 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14944 break;
14945 default:
14946 goto pool32f_invalid;
14948 break;
14949 case MAXA_FMT:
14950 check_insn(ctx, ISA_MIPS32R6);
14951 switch ((ctx->opcode >> 9) & 0x3) {
14952 case FMT_SDPS_S:
14953 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14954 break;
14955 case FMT_SDPS_D:
14956 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14957 break;
14958 default:
14959 goto pool32f_invalid;
14961 break;
14962 case 0x30:
14963 /* regular FP ops */
14964 switch ((ctx->opcode >> 6) & 0x3) {
14965 case ADD_FMT:
14966 FINSN_3ARG_SDPS(ADD);
14967 break;
14968 case SUB_FMT:
14969 FINSN_3ARG_SDPS(SUB);
14970 break;
14971 case MUL_FMT:
14972 FINSN_3ARG_SDPS(MUL);
14973 break;
14974 case DIV_FMT:
14975 fmt = (ctx->opcode >> 8) & 0x3;
14976 if (fmt == 1) {
14977 mips32_op = OPC_DIV_D;
14978 } else if (fmt == 0) {
14979 mips32_op = OPC_DIV_S;
14980 } else {
14981 goto pool32f_invalid;
14983 goto do_fpop;
14984 default:
14985 goto pool32f_invalid;
14987 break;
14988 case 0x38:
14989 /* cmovs */
14990 switch ((ctx->opcode >> 6) & 0x7) {
14991 case MOVN_FMT: /* SELNEZ_FMT */
14992 if (ctx->insn_flags & ISA_MIPS32R6) {
14993 /* SELNEZ_FMT */
14994 switch ((ctx->opcode >> 9) & 0x3) {
14995 case FMT_SDPS_S:
14996 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14997 break;
14998 case FMT_SDPS_D:
14999 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15000 break;
15001 default:
15002 goto pool32f_invalid;
15004 } else {
15005 /* MOVN_FMT */
15006 FINSN_3ARG_SDPS(MOVN);
15008 break;
15009 case MOVN_FMT_04:
15010 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15011 FINSN_3ARG_SDPS(MOVN);
15012 break;
15013 case MOVZ_FMT: /* SELEQZ_FMT */
15014 if (ctx->insn_flags & ISA_MIPS32R6) {
15015 /* SELEQZ_FMT */
15016 switch ((ctx->opcode >> 9) & 0x3) {
15017 case FMT_SDPS_S:
15018 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15019 break;
15020 case FMT_SDPS_D:
15021 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15022 break;
15023 default:
15024 goto pool32f_invalid;
15026 } else {
15027 /* MOVZ_FMT */
15028 FINSN_3ARG_SDPS(MOVZ);
15030 break;
15031 case MOVZ_FMT_05:
15032 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15033 FINSN_3ARG_SDPS(MOVZ);
15034 break;
15035 case SEL_FMT:
15036 check_insn(ctx, ISA_MIPS32R6);
15037 switch ((ctx->opcode >> 9) & 0x3) {
15038 case FMT_SDPS_S:
15039 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15040 break;
15041 case FMT_SDPS_D:
15042 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15043 break;
15044 default:
15045 goto pool32f_invalid;
15047 break;
15048 case MADDF_FMT:
15049 check_insn(ctx, ISA_MIPS32R6);
15050 switch ((ctx->opcode >> 9) & 0x3) {
15051 case FMT_SDPS_S:
15052 mips32_op = OPC_MADDF_S;
15053 goto do_fpop;
15054 case FMT_SDPS_D:
15055 mips32_op = OPC_MADDF_D;
15056 goto do_fpop;
15057 default:
15058 goto pool32f_invalid;
15060 break;
15061 case MSUBF_FMT:
15062 check_insn(ctx, ISA_MIPS32R6);
15063 switch ((ctx->opcode >> 9) & 0x3) {
15064 case FMT_SDPS_S:
15065 mips32_op = OPC_MSUBF_S;
15066 goto do_fpop;
15067 case FMT_SDPS_D:
15068 mips32_op = OPC_MSUBF_D;
15069 goto do_fpop;
15070 default:
15071 goto pool32f_invalid;
15073 break;
15074 default:
15075 goto pool32f_invalid;
15077 break;
15078 do_fpop:
15079 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15080 break;
15081 default:
15082 pool32f_invalid:
15083 MIPS_INVAL("pool32f");
15084 generate_exception_end(ctx, EXCP_RI);
15085 break;
15087 } else {
15088 generate_exception_err(ctx, EXCP_CpU, 1);
15090 break;
15091 case POOL32I:
15092 minor = (ctx->opcode >> 21) & 0x1f;
15093 switch (minor) {
15094 case BLTZ:
15095 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15096 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15097 break;
15098 case BLTZAL:
15099 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15100 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15101 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15102 break;
15103 case BLTZALS:
15104 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15105 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15106 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15107 break;
15108 case BGEZ:
15109 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15110 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15111 break;
15112 case BGEZAL:
15113 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15114 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15115 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15116 break;
15117 case BGEZALS:
15118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15119 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
15120 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15121 break;
15122 case BLEZ:
15123 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15124 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
15125 break;
15126 case BGTZ:
15127 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15128 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
15129 break;
15131 /* Traps */
15132 case TLTI: /* BC1EQZC */
15133 if (ctx->insn_flags & ISA_MIPS32R6) {
15134 /* BC1EQZC */
15135 check_cp1_enabled(ctx);
15136 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
15137 } else {
15138 /* TLTI */
15139 mips32_op = OPC_TLTI;
15140 goto do_trapi;
15142 break;
15143 case TGEI: /* BC1NEZC */
15144 if (ctx->insn_flags & ISA_MIPS32R6) {
15145 /* BC1NEZC */
15146 check_cp1_enabled(ctx);
15147 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
15148 } else {
15149 /* TGEI */
15150 mips32_op = OPC_TGEI;
15151 goto do_trapi;
15153 break;
15154 case TLTIU:
15155 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15156 mips32_op = OPC_TLTIU;
15157 goto do_trapi;
15158 case TGEIU:
15159 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15160 mips32_op = OPC_TGEIU;
15161 goto do_trapi;
15162 case TNEI: /* SYNCI */
15163 if (ctx->insn_flags & ISA_MIPS32R6) {
15164 /* SYNCI */
15165 /* Break the TB to be able to sync copied instructions
15166 immediately */
15167 ctx->base.is_jmp = DISAS_STOP;
15168 } else {
15169 /* TNEI */
15170 mips32_op = OPC_TNEI;
15171 goto do_trapi;
15173 break;
15174 case TEQI:
15175 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15176 mips32_op = OPC_TEQI;
15177 do_trapi:
15178 gen_trap(ctx, mips32_op, rs, -1, imm);
15179 break;
15181 case BNEZC:
15182 case BEQZC:
15183 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15184 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
15185 4, rs, 0, imm << 1, 0);
15186 /* Compact branches don't have a delay slot, so just let
15187 the normal delay slot handling take us to the branch
15188 target. */
15189 break;
15190 case LUI:
15191 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15192 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
15193 break;
15194 case SYNCI:
15195 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15196 /* Break the TB to be able to sync copied instructions
15197 immediately */
15198 ctx->base.is_jmp = DISAS_STOP;
15199 break;
15200 case BC2F:
15201 case BC2T:
15202 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15203 /* COP2: Not implemented. */
15204 generate_exception_err(ctx, EXCP_CpU, 2);
15205 break;
15206 case BC1F:
15207 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15208 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
15209 goto do_cp1branch;
15210 case BC1T:
15211 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15212 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
15213 goto do_cp1branch;
15214 case BC1ANY4F:
15215 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15216 mips32_op = OPC_BC1FANY4;
15217 goto do_cp1mips3d;
15218 case BC1ANY4T:
15219 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15220 mips32_op = OPC_BC1TANY4;
15221 do_cp1mips3d:
15222 check_cop1x(ctx);
15223 check_insn(ctx, ASE_MIPS3D);
15224 /* Fall through */
15225 do_cp1branch:
15226 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15227 check_cp1_enabled(ctx);
15228 gen_compute_branch1(ctx, mips32_op,
15229 (ctx->opcode >> 18) & 0x7, imm << 1);
15230 } else {
15231 generate_exception_err(ctx, EXCP_CpU, 1);
15233 break;
15234 case BPOSGE64:
15235 case BPOSGE32:
15236 /* MIPS DSP: not implemented */
15237 /* Fall through */
15238 default:
15239 MIPS_INVAL("pool32i");
15240 generate_exception_end(ctx, EXCP_RI);
15241 break;
15243 break;
15244 case POOL32C:
15245 minor = (ctx->opcode >> 12) & 0xf;
15246 offset = sextract32(ctx->opcode, 0,
15247 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
15248 switch (minor) {
15249 case LWL:
15250 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15251 mips32_op = OPC_LWL;
15252 goto do_ld_lr;
15253 case SWL:
15254 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15255 mips32_op = OPC_SWL;
15256 goto do_st_lr;
15257 case LWR:
15258 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15259 mips32_op = OPC_LWR;
15260 goto do_ld_lr;
15261 case SWR:
15262 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15263 mips32_op = OPC_SWR;
15264 goto do_st_lr;
15265 #if defined(TARGET_MIPS64)
15266 case LDL:
15267 check_insn(ctx, ISA_MIPS3);
15268 check_mips_64(ctx);
15269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15270 mips32_op = OPC_LDL;
15271 goto do_ld_lr;
15272 case SDL:
15273 check_insn(ctx, ISA_MIPS3);
15274 check_mips_64(ctx);
15275 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15276 mips32_op = OPC_SDL;
15277 goto do_st_lr;
15278 case LDR:
15279 check_insn(ctx, ISA_MIPS3);
15280 check_mips_64(ctx);
15281 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15282 mips32_op = OPC_LDR;
15283 goto do_ld_lr;
15284 case SDR:
15285 check_insn(ctx, ISA_MIPS3);
15286 check_mips_64(ctx);
15287 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15288 mips32_op = OPC_SDR;
15289 goto do_st_lr;
15290 case LWU:
15291 check_insn(ctx, ISA_MIPS3);
15292 check_mips_64(ctx);
15293 mips32_op = OPC_LWU;
15294 goto do_ld_lr;
15295 case LLD:
15296 check_insn(ctx, ISA_MIPS3);
15297 check_mips_64(ctx);
15298 mips32_op = OPC_LLD;
15299 goto do_ld_lr;
15300 #endif
15301 case LL:
15302 mips32_op = OPC_LL;
15303 goto do_ld_lr;
15304 do_ld_lr:
15305 gen_ld(ctx, mips32_op, rt, rs, offset);
15306 break;
15307 do_st_lr:
15308 gen_st(ctx, mips32_op, rt, rs, offset);
15309 break;
15310 case SC:
15311 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
15312 break;
15313 #if defined(TARGET_MIPS64)
15314 case SCD:
15315 check_insn(ctx, ISA_MIPS3);
15316 check_mips_64(ctx);
15317 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
15318 break;
15319 #endif
15320 case LD_EVA:
15321 if (!ctx->eva) {
15322 MIPS_INVAL("pool32c ld-eva");
15323 generate_exception_end(ctx, EXCP_RI);
15324 break;
15326 check_cp0_enabled(ctx);
15328 minor2 = (ctx->opcode >> 9) & 0x7;
15329 offset = sextract32(ctx->opcode, 0, 9);
15330 switch (minor2) {
15331 case LBUE:
15332 mips32_op = OPC_LBUE;
15333 goto do_ld_lr;
15334 case LHUE:
15335 mips32_op = OPC_LHUE;
15336 goto do_ld_lr;
15337 case LWLE:
15338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15339 mips32_op = OPC_LWLE;
15340 goto do_ld_lr;
15341 case LWRE:
15342 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15343 mips32_op = OPC_LWRE;
15344 goto do_ld_lr;
15345 case LBE:
15346 mips32_op = OPC_LBE;
15347 goto do_ld_lr;
15348 case LHE:
15349 mips32_op = OPC_LHE;
15350 goto do_ld_lr;
15351 case LLE:
15352 mips32_op = OPC_LLE;
15353 goto do_ld_lr;
15354 case LWE:
15355 mips32_op = OPC_LWE;
15356 goto do_ld_lr;
15358 break;
15359 case ST_EVA:
15360 if (!ctx->eva) {
15361 MIPS_INVAL("pool32c st-eva");
15362 generate_exception_end(ctx, EXCP_RI);
15363 break;
15365 check_cp0_enabled(ctx);
15367 minor2 = (ctx->opcode >> 9) & 0x7;
15368 offset = sextract32(ctx->opcode, 0, 9);
15369 switch (minor2) {
15370 case SWLE:
15371 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15372 mips32_op = OPC_SWLE;
15373 goto do_st_lr;
15374 case SWRE:
15375 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15376 mips32_op = OPC_SWRE;
15377 goto do_st_lr;
15378 case PREFE:
15379 /* Treat as no-op */
15380 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
15381 /* hint codes 24-31 are reserved and signal RI */
15382 generate_exception(ctx, EXCP_RI);
15384 break;
15385 case CACHEE:
15386 /* Treat as no-op */
15387 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15388 gen_cache_operation(ctx, rt, rs, offset);
15390 break;
15391 case SBE:
15392 mips32_op = OPC_SBE;
15393 goto do_st_lr;
15394 case SHE:
15395 mips32_op = OPC_SHE;
15396 goto do_st_lr;
15397 case SCE:
15398 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
15399 break;
15400 case SWE:
15401 mips32_op = OPC_SWE;
15402 goto do_st_lr;
15404 break;
15405 case PREF:
15406 /* Treat as no-op */
15407 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
15408 /* hint codes 24-31 are reserved and signal RI */
15409 generate_exception(ctx, EXCP_RI);
15411 break;
15412 default:
15413 MIPS_INVAL("pool32c");
15414 generate_exception_end(ctx, EXCP_RI);
15415 break;
15417 break;
15418 case ADDI32: /* AUI, LUI */
15419 if (ctx->insn_flags & ISA_MIPS32R6) {
15420 /* AUI, LUI */
15421 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
15422 } else {
15423 /* ADDI32 */
15424 mips32_op = OPC_ADDI;
15425 goto do_addi;
15427 break;
15428 case ADDIU32:
15429 mips32_op = OPC_ADDIU;
15430 do_addi:
15431 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
15432 break;
15434 /* Logical operations */
15435 case ORI32:
15436 mips32_op = OPC_ORI;
15437 goto do_logici;
15438 case XORI32:
15439 mips32_op = OPC_XORI;
15440 goto do_logici;
15441 case ANDI32:
15442 mips32_op = OPC_ANDI;
15443 do_logici:
15444 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
15445 break;
15447 /* Set less than immediate */
15448 case SLTI32:
15449 mips32_op = OPC_SLTI;
15450 goto do_slti;
15451 case SLTIU32:
15452 mips32_op = OPC_SLTIU;
15453 do_slti:
15454 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
15455 break;
15456 case JALX32:
15457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15458 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15459 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
15460 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15461 break;
15462 case JALS32: /* BOVC, BEQC, BEQZALC */
15463 if (ctx->insn_flags & ISA_MIPS32R6) {
15464 if (rs >= rt) {
15465 /* BOVC */
15466 mips32_op = OPC_BOVC;
15467 } else if (rs < rt && rs == 0) {
15468 /* BEQZALC */
15469 mips32_op = OPC_BEQZALC;
15470 } else {
15471 /* BEQC */
15472 mips32_op = OPC_BEQC;
15474 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15475 } else {
15476 /* JALS32 */
15477 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15478 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15479 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15481 break;
15482 case BEQ32: /* BC */
15483 if (ctx->insn_flags & ISA_MIPS32R6) {
15484 /* BC */
15485 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15486 sextract32(ctx->opcode << 1, 0, 27));
15487 } else {
15488 /* BEQ32 */
15489 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15491 break;
15492 case BNE32: /* BALC */
15493 if (ctx->insn_flags & ISA_MIPS32R6) {
15494 /* BALC */
15495 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15496 sextract32(ctx->opcode << 1, 0, 27));
15497 } else {
15498 /* BNE32 */
15499 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15501 break;
15502 case J32: /* BGTZC, BLTZC, BLTC */
15503 if (ctx->insn_flags & ISA_MIPS32R6) {
15504 if (rs == 0 && rt != 0) {
15505 /* BGTZC */
15506 mips32_op = OPC_BGTZC;
15507 } else if (rs != 0 && rt != 0 && rs == rt) {
15508 /* BLTZC */
15509 mips32_op = OPC_BLTZC;
15510 } else {
15511 /* BLTC */
15512 mips32_op = OPC_BLTC;
15514 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15515 } else {
15516 /* J32 */
15517 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15518 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15520 break;
15521 case JAL32: /* BLEZC, BGEZC, BGEC */
15522 if (ctx->insn_flags & ISA_MIPS32R6) {
15523 if (rs == 0 && rt != 0) {
15524 /* BLEZC */
15525 mips32_op = OPC_BLEZC;
15526 } else if (rs != 0 && rt != 0 && rs == rt) {
15527 /* BGEZC */
15528 mips32_op = OPC_BGEZC;
15529 } else {
15530 /* BGEC */
15531 mips32_op = OPC_BGEC;
15533 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15534 } else {
15535 /* JAL32 */
15536 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15537 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15538 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15540 break;
15541 /* Floating point (COP1) */
15542 case LWC132:
15543 mips32_op = OPC_LWC1;
15544 goto do_cop1;
15545 case LDC132:
15546 mips32_op = OPC_LDC1;
15547 goto do_cop1;
15548 case SWC132:
15549 mips32_op = OPC_SWC1;
15550 goto do_cop1;
15551 case SDC132:
15552 mips32_op = OPC_SDC1;
15553 do_cop1:
15554 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
15555 break;
15556 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15557 if (ctx->insn_flags & ISA_MIPS32R6) {
15558 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15559 switch ((ctx->opcode >> 16) & 0x1f) {
15560 case ADDIUPC_00:
15561 case ADDIUPC_01:
15562 case ADDIUPC_02:
15563 case ADDIUPC_03:
15564 case ADDIUPC_04:
15565 case ADDIUPC_05:
15566 case ADDIUPC_06:
15567 case ADDIUPC_07:
15568 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
15569 break;
15570 case AUIPC:
15571 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
15572 break;
15573 case ALUIPC:
15574 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
15575 break;
15576 case LWPC_08:
15577 case LWPC_09:
15578 case LWPC_0A:
15579 case LWPC_0B:
15580 case LWPC_0C:
15581 case LWPC_0D:
15582 case LWPC_0E:
15583 case LWPC_0F:
15584 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
15585 break;
15586 default:
15587 generate_exception(ctx, EXCP_RI);
15588 break;
15590 } else {
15591 /* ADDIUPC */
15592 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
15593 offset = SIMM(ctx->opcode, 0, 23) << 2;
15595 gen_addiupc(ctx, reg, offset, 0, 0);
15597 break;
15598 case BNVC: /* BNEC, BNEZALC */
15599 check_insn(ctx, ISA_MIPS32R6);
15600 if (rs >= rt) {
15601 /* BNVC */
15602 mips32_op = OPC_BNVC;
15603 } else if (rs < rt && rs == 0) {
15604 /* BNEZALC */
15605 mips32_op = OPC_BNEZALC;
15606 } else {
15607 /* BNEC */
15608 mips32_op = OPC_BNEC;
15610 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15611 break;
15612 case R6_BNEZC: /* JIALC */
15613 check_insn(ctx, ISA_MIPS32R6);
15614 if (rt != 0) {
15615 /* BNEZC */
15616 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15617 sextract32(ctx->opcode << 1, 0, 22));
15618 } else {
15619 /* JIALC */
15620 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15622 break;
15623 case R6_BEQZC: /* JIC */
15624 check_insn(ctx, ISA_MIPS32R6);
15625 if (rt != 0) {
15626 /* BEQZC */
15627 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15628 sextract32(ctx->opcode << 1, 0, 22));
15629 } else {
15630 /* JIC */
15631 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15633 break;
15634 case BLEZALC: /* BGEZALC, BGEUC */
15635 check_insn(ctx, ISA_MIPS32R6);
15636 if (rs == 0 && rt != 0) {
15637 /* BLEZALC */
15638 mips32_op = OPC_BLEZALC;
15639 } else if (rs != 0 && rt != 0 && rs == rt) {
15640 /* BGEZALC */
15641 mips32_op = OPC_BGEZALC;
15642 } else {
15643 /* BGEUC */
15644 mips32_op = OPC_BGEUC;
15646 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15647 break;
15648 case BGTZALC: /* BLTZALC, BLTUC */
15649 check_insn(ctx, ISA_MIPS32R6);
15650 if (rs == 0 && rt != 0) {
15651 /* BGTZALC */
15652 mips32_op = OPC_BGTZALC;
15653 } else if (rs != 0 && rt != 0 && rs == rt) {
15654 /* BLTZALC */
15655 mips32_op = OPC_BLTZALC;
15656 } else {
15657 /* BLTUC */
15658 mips32_op = OPC_BLTUC;
15660 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15661 break;
15662 /* Loads and stores */
15663 case LB32:
15664 mips32_op = OPC_LB;
15665 goto do_ld;
15666 case LBU32:
15667 mips32_op = OPC_LBU;
15668 goto do_ld;
15669 case LH32:
15670 mips32_op = OPC_LH;
15671 goto do_ld;
15672 case LHU32:
15673 mips32_op = OPC_LHU;
15674 goto do_ld;
15675 case LW32:
15676 mips32_op = OPC_LW;
15677 goto do_ld;
15678 #ifdef TARGET_MIPS64
15679 case LD32:
15680 check_insn(ctx, ISA_MIPS3);
15681 check_mips_64(ctx);
15682 mips32_op = OPC_LD;
15683 goto do_ld;
15684 case SD32:
15685 check_insn(ctx, ISA_MIPS3);
15686 check_mips_64(ctx);
15687 mips32_op = OPC_SD;
15688 goto do_st;
15689 #endif
15690 case SB32:
15691 mips32_op = OPC_SB;
15692 goto do_st;
15693 case SH32:
15694 mips32_op = OPC_SH;
15695 goto do_st;
15696 case SW32:
15697 mips32_op = OPC_SW;
15698 goto do_st;
15699 do_ld:
15700 gen_ld(ctx, mips32_op, rt, rs, imm);
15701 break;
15702 do_st:
15703 gen_st(ctx, mips32_op, rt, rs, imm);
15704 break;
15705 default:
15706 generate_exception_end(ctx, EXCP_RI);
15707 break;
15711 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15713 uint32_t op;
15715 /* make sure instructions are on a halfword boundary */
15716 if (ctx->base.pc_next & 0x1) {
15717 env->CP0_BadVAddr = ctx->base.pc_next;
15718 generate_exception_end(ctx, EXCP_AdEL);
15719 return 2;
15722 op = (ctx->opcode >> 10) & 0x3f;
15723 /* Enforce properly-sized instructions in a delay slot */
15724 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15725 switch (op & 0x7) { /* MSB-3..MSB-5 */
15726 case 0:
15727 /* POOL32A, POOL32B, POOL32I, POOL32C */
15728 case 4:
15729 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15730 case 5:
15731 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15732 case 6:
15733 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15734 case 7:
15735 /* LB32, LH32, LWC132, LDC132, LW32 */
15736 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15737 generate_exception_end(ctx, EXCP_RI);
15738 return 2;
15740 break;
15741 case 1:
15742 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15743 case 2:
15744 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15745 case 3:
15746 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15747 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15748 generate_exception_end(ctx, EXCP_RI);
15749 return 2;
15751 break;
15755 switch (op) {
15756 case POOL16A:
15758 int rd = mmreg(uMIPS_RD(ctx->opcode));
15759 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15760 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15761 uint32_t opc = 0;
15763 switch (ctx->opcode & 0x1) {
15764 case ADDU16:
15765 opc = OPC_ADDU;
15766 break;
15767 case SUBU16:
15768 opc = OPC_SUBU;
15769 break;
15771 if (ctx->insn_flags & ISA_MIPS32R6) {
15772 /* In the Release 6 the register number location in
15773 * the instruction encoding has changed.
15775 gen_arith(ctx, opc, rs1, rd, rs2);
15776 } else {
15777 gen_arith(ctx, opc, rd, rs1, rs2);
15780 break;
15781 case POOL16B:
15783 int rd = mmreg(uMIPS_RD(ctx->opcode));
15784 int rs = mmreg(uMIPS_RS(ctx->opcode));
15785 int amount = (ctx->opcode >> 1) & 0x7;
15786 uint32_t opc = 0;
15787 amount = amount == 0 ? 8 : amount;
15789 switch (ctx->opcode & 0x1) {
15790 case SLL16:
15791 opc = OPC_SLL;
15792 break;
15793 case SRL16:
15794 opc = OPC_SRL;
15795 break;
15798 gen_shift_imm(ctx, opc, rd, rs, amount);
15800 break;
15801 case POOL16C:
15802 if (ctx->insn_flags & ISA_MIPS32R6) {
15803 gen_pool16c_r6_insn(ctx);
15804 } else {
15805 gen_pool16c_insn(ctx);
15807 break;
15808 case LWGP16:
15810 int rd = mmreg(uMIPS_RD(ctx->opcode));
15811 int rb = 28; /* GP */
15812 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15814 gen_ld(ctx, OPC_LW, rd, rb, offset);
15816 break;
15817 case POOL16F:
15818 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15819 if (ctx->opcode & 1) {
15820 generate_exception_end(ctx, EXCP_RI);
15821 } else {
15822 /* MOVEP */
15823 int enc_dest = uMIPS_RD(ctx->opcode);
15824 int enc_rt = uMIPS_RS2(ctx->opcode);
15825 int enc_rs = uMIPS_RS1(ctx->opcode);
15826 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15828 break;
15829 case LBU16:
15831 int rd = mmreg(uMIPS_RD(ctx->opcode));
15832 int rb = mmreg(uMIPS_RS(ctx->opcode));
15833 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15834 offset = (offset == 0xf ? -1 : offset);
15836 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15838 break;
15839 case LHU16:
15841 int rd = mmreg(uMIPS_RD(ctx->opcode));
15842 int rb = mmreg(uMIPS_RS(ctx->opcode));
15843 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15845 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15847 break;
15848 case LWSP16:
15850 int rd = (ctx->opcode >> 5) & 0x1f;
15851 int rb = 29; /* SP */
15852 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15854 gen_ld(ctx, OPC_LW, rd, rb, offset);
15856 break;
15857 case LW16:
15859 int rd = mmreg(uMIPS_RD(ctx->opcode));
15860 int rb = mmreg(uMIPS_RS(ctx->opcode));
15861 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15863 gen_ld(ctx, OPC_LW, rd, rb, offset);
15865 break;
15866 case SB16:
15868 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15869 int rb = mmreg(uMIPS_RS(ctx->opcode));
15870 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15872 gen_st(ctx, OPC_SB, rd, rb, offset);
15874 break;
15875 case SH16:
15877 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15878 int rb = mmreg(uMIPS_RS(ctx->opcode));
15879 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15881 gen_st(ctx, OPC_SH, rd, rb, offset);
15883 break;
15884 case SWSP16:
15886 int rd = (ctx->opcode >> 5) & 0x1f;
15887 int rb = 29; /* SP */
15888 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15890 gen_st(ctx, OPC_SW, rd, rb, offset);
15892 break;
15893 case SW16:
15895 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15896 int rb = mmreg(uMIPS_RS(ctx->opcode));
15897 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15899 gen_st(ctx, OPC_SW, rd, rb, offset);
15901 break;
15902 case MOVE16:
15904 int rd = uMIPS_RD5(ctx->opcode);
15905 int rs = uMIPS_RS5(ctx->opcode);
15907 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15909 break;
15910 case ANDI16:
15911 gen_andi16(ctx);
15912 break;
15913 case POOL16D:
15914 switch (ctx->opcode & 0x1) {
15915 case ADDIUS5:
15916 gen_addius5(ctx);
15917 break;
15918 case ADDIUSP:
15919 gen_addiusp(ctx);
15920 break;
15922 break;
15923 case POOL16E:
15924 switch (ctx->opcode & 0x1) {
15925 case ADDIUR2:
15926 gen_addiur2(ctx);
15927 break;
15928 case ADDIUR1SP:
15929 gen_addiur1sp(ctx);
15930 break;
15932 break;
15933 case B16: /* BC16 */
15934 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15935 sextract32(ctx->opcode, 0, 10) << 1,
15936 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15937 break;
15938 case BNEZ16: /* BNEZC16 */
15939 case BEQZ16: /* BEQZC16 */
15940 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15941 mmreg(uMIPS_RD(ctx->opcode)),
15942 0, sextract32(ctx->opcode, 0, 7) << 1,
15943 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15945 break;
15946 case LI16:
15948 int reg = mmreg(uMIPS_RD(ctx->opcode));
15949 int imm = ZIMM(ctx->opcode, 0, 7);
15951 imm = (imm == 0x7f ? -1 : imm);
15952 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15954 break;
15955 case RES_29:
15956 case RES_31:
15957 case RES_39:
15958 generate_exception_end(ctx, EXCP_RI);
15959 break;
15960 default:
15961 decode_micromips32_opc(env, ctx);
15962 return 4;
15965 return 2;
15970 * nanoMIPS opcodes
15974 /* MAJOR, P16, and P32 pools opcodes */
15975 enum {
15976 NM_P_ADDIU = 0x00,
15977 NM_ADDIUPC = 0x01,
15978 NM_MOVE_BALC = 0x02,
15979 NM_P16_MV = 0x04,
15980 NM_LW16 = 0x05,
15981 NM_BC16 = 0x06,
15982 NM_P16_SR = 0x07,
15984 NM_POOL32A = 0x08,
15985 NM_P_BAL = 0x0a,
15986 NM_P16_SHIFT = 0x0c,
15987 NM_LWSP16 = 0x0d,
15988 NM_BALC16 = 0x0e,
15989 NM_P16_4X4 = 0x0f,
15991 NM_P_GP_W = 0x10,
15992 NM_P_GP_BH = 0x11,
15993 NM_P_J = 0x12,
15994 NM_P16C = 0x14,
15995 NM_LWGP16 = 0x15,
15996 NM_P16_LB = 0x17,
15998 NM_P48I = 0x18,
15999 NM_P16_A1 = 0x1c,
16000 NM_LW4X4 = 0x1d,
16001 NM_P16_LH = 0x1f,
16003 NM_P_U12 = 0x20,
16004 NM_P_LS_U12 = 0x21,
16005 NM_P_BR1 = 0x22,
16006 NM_P16_A2 = 0x24,
16007 NM_SW16 = 0x25,
16008 NM_BEQZC16 = 0x26,
16010 NM_POOL32F = 0x28,
16011 NM_P_LS_S9 = 0x29,
16012 NM_P_BR2 = 0x2a,
16014 NM_P16_ADDU = 0x2c,
16015 NM_SWSP16 = 0x2d,
16016 NM_BNEZC16 = 0x2e,
16017 NM_MOVEP = 0x2f,
16019 NM_POOL32S = 0x30,
16020 NM_P_BRI = 0x32,
16021 NM_LI16 = 0x34,
16022 NM_SWGP16 = 0x35,
16023 NM_P16_BR = 0x36,
16025 NM_P_LUI = 0x38,
16026 NM_ANDI16 = 0x3c,
16027 NM_SW4X4 = 0x3d,
16028 NM_MOVEPREV = 0x3f,
16031 /* POOL32A instruction pool */
16032 enum {
16033 NM_POOL32A0 = 0x00,
16034 NM_SPECIAL2 = 0x01,
16035 NM_COP2_1 = 0x02,
16036 NM_UDI = 0x03,
16037 NM_POOL32A5 = 0x05,
16038 NM_POOL32A7 = 0x07,
16041 /* P.GP.W instruction pool */
16042 enum {
16043 NM_ADDIUGP_W = 0x00,
16044 NM_LWGP = 0x02,
16045 NM_SWGP = 0x03,
16048 /* P48I instruction pool */
16049 enum {
16050 NM_LI48 = 0x00,
16051 NM_ADDIU48 = 0x01,
16052 NM_ADDIUGP48 = 0x02,
16053 NM_ADDIUPC48 = 0x03,
16054 NM_LWPC48 = 0x0b,
16055 NM_SWPC48 = 0x0f,
16058 /* P.U12 instruction pool */
16059 enum {
16060 NM_ORI = 0x00,
16061 NM_XORI = 0x01,
16062 NM_ANDI = 0x02,
16063 NM_P_SR = 0x03,
16064 NM_SLTI = 0x04,
16065 NM_SLTIU = 0x05,
16066 NM_SEQI = 0x06,
16067 NM_ADDIUNEG = 0x08,
16068 NM_P_SHIFT = 0x0c,
16069 NM_P_ROTX = 0x0d,
16070 NM_P_INS = 0x0e,
16071 NM_P_EXT = 0x0f,
16074 /* POOL32F instruction pool */
16075 enum {
16076 NM_POOL32F_0 = 0x00,
16077 NM_POOL32F_3 = 0x03,
16078 NM_POOL32F_5 = 0x05,
16081 /* POOL32S instruction pool */
16082 enum {
16083 NM_POOL32S_0 = 0x00,
16084 NM_POOL32S_4 = 0x04,
16087 /* P.LUI instruction pool */
16088 enum {
16089 NM_LUI = 0x00,
16090 NM_ALUIPC = 0x01,
16093 /* P.GP.BH instruction pool */
16094 enum {
16095 NM_LBGP = 0x00,
16096 NM_SBGP = 0x01,
16097 NM_LBUGP = 0x02,
16098 NM_ADDIUGP_B = 0x03,
16099 NM_P_GP_LH = 0x04,
16100 NM_P_GP_SH = 0x05,
16101 NM_P_GP_CP1 = 0x06,
16104 /* P.LS.U12 instruction pool */
16105 enum {
16106 NM_LB = 0x00,
16107 NM_SB = 0x01,
16108 NM_LBU = 0x02,
16109 NM_P_PREFU12 = 0x03,
16110 NM_LH = 0x04,
16111 NM_SH = 0x05,
16112 NM_LHU = 0x06,
16113 NM_LWU = 0x07,
16114 NM_LW = 0x08,
16115 NM_SW = 0x09,
16116 NM_LWC1 = 0x0a,
16117 NM_SWC1 = 0x0b,
16118 NM_LDC1 = 0x0e,
16119 NM_SDC1 = 0x0f,
16122 /* P.LS.S9 instruction pool */
16123 enum {
16124 NM_P_LS_S0 = 0x00,
16125 NM_P_LS_S1 = 0x01,
16126 NM_P_LS_E0 = 0x02,
16127 NM_P_LS_WM = 0x04,
16128 NM_P_LS_UAWM = 0x05,
16131 /* P.BAL instruction pool */
16132 enum {
16133 NM_BC = 0x00,
16134 NM_BALC = 0x01,
16137 /* P.J instruction pool */
16138 enum {
16139 NM_JALRC = 0x00,
16140 NM_JALRC_HB = 0x01,
16141 NM_P_BALRSC = 0x08,
16144 /* P.BR1 instruction pool */
16145 enum {
16146 NM_BEQC = 0x00,
16147 NM_P_BR3A = 0x01,
16148 NM_BGEC = 0x02,
16149 NM_BGEUC = 0x03,
16152 /* P.BR2 instruction pool */
16153 enum {
16154 NM_BNEC = 0x00,
16155 NM_BLTC = 0x02,
16156 NM_BLTUC = 0x03,
16159 /* P.BRI instruction pool */
16160 enum {
16161 NM_BEQIC = 0x00,
16162 NM_BBEQZC = 0x01,
16163 NM_BGEIC = 0x02,
16164 NM_BGEIUC = 0x03,
16165 NM_BNEIC = 0x04,
16166 NM_BBNEZC = 0x05,
16167 NM_BLTIC = 0x06,
16168 NM_BLTIUC = 0x07,
16171 /* P16.SHIFT instruction pool */
16172 enum {
16173 NM_SLL16 = 0x00,
16174 NM_SRL16 = 0x01,
16177 /* POOL16C instruction pool */
16178 enum {
16179 NM_POOL16C_0 = 0x00,
16180 NM_LWXS16 = 0x01,
16183 /* P16.A1 instruction pool */
16184 enum {
16185 NM_ADDIUR1SP = 0x01,
16188 /* P16.A2 instruction pool */
16189 enum {
16190 NM_ADDIUR2 = 0x00,
16191 NM_P_ADDIURS5 = 0x01,
16194 /* P16.ADDU instruction pool */
16195 enum {
16196 NM_ADDU16 = 0x00,
16197 NM_SUBU16 = 0x01,
16200 /* P16.SR instruction pool */
16201 enum {
16202 NM_SAVE16 = 0x00,
16203 NM_RESTORE_JRC16 = 0x01,
16206 /* P16.4X4 instruction pool */
16207 enum {
16208 NM_ADDU4X4 = 0x00,
16209 NM_MUL4X4 = 0x01,
16212 /* P16.LB instruction pool */
16213 enum {
16214 NM_LB16 = 0x00,
16215 NM_SB16 = 0x01,
16216 NM_LBU16 = 0x02,
16219 /* P16.LH instruction pool */
16220 enum {
16221 NM_LH16 = 0x00,
16222 NM_SH16 = 0x01,
16223 NM_LHU16 = 0x02,
16226 /* P.RI instruction pool */
16227 enum {
16228 NM_SIGRIE = 0x00,
16229 NM_P_SYSCALL = 0x01,
16230 NM_BREAK = 0x02,
16231 NM_SDBBP = 0x03,
16234 /* POOL32A0 instruction pool */
16235 enum {
16236 NM_P_TRAP = 0x00,
16237 NM_SEB = 0x01,
16238 NM_SLLV = 0x02,
16239 NM_MUL = 0x03,
16240 NM_MFC0 = 0x06,
16241 NM_MFHC0 = 0x07,
16242 NM_SEH = 0x09,
16243 NM_SRLV = 0x0a,
16244 NM_MUH = 0x0b,
16245 NM_MTC0 = 0x0e,
16246 NM_MTHC0 = 0x0f,
16247 NM_SRAV = 0x12,
16248 NM_MULU = 0x13,
16249 NM_ROTRV = 0x1a,
16250 NM_MUHU = 0x1b,
16251 NM_ADD = 0x22,
16252 NM_DIV = 0x23,
16253 NM_ADDU = 0x2a,
16254 NM_MOD = 0x2b,
16255 NM_SUB = 0x32,
16256 NM_DIVU = 0x33,
16257 NM_RDHWR = 0x38,
16258 NM_SUBU = 0x3a,
16259 NM_MODU = 0x3b,
16260 NM_P_CMOVE = 0x42,
16261 NM_FORK = 0x45,
16262 NM_MFTR = 0x46,
16263 NM_MFHTR = 0x47,
16264 NM_AND = 0x4a,
16265 NM_YIELD = 0x4d,
16266 NM_MTTR = 0x4e,
16267 NM_MTHTR = 0x4f,
16268 NM_OR = 0x52,
16269 NM_D_E_MT_VPE = 0x56,
16270 NM_NOR = 0x5a,
16271 NM_XOR = 0x62,
16272 NM_SLT = 0x6a,
16273 NM_P_SLTU = 0x72,
16274 NM_SOV = 0x7a,
16277 /* POOL32A5 instruction pool */
16278 enum {
16279 NM_CMP_EQ_PH = 0x00,
16280 NM_CMP_LT_PH = 0x08,
16281 NM_CMP_LE_PH = 0x10,
16282 NM_CMPGU_EQ_QB = 0x18,
16283 NM_CMPGU_LT_QB = 0x20,
16284 NM_CMPGU_LE_QB = 0x28,
16285 NM_CMPGDU_EQ_QB = 0x30,
16286 NM_CMPGDU_LT_QB = 0x38,
16287 NM_CMPGDU_LE_QB = 0x40,
16288 NM_CMPU_EQ_QB = 0x48,
16289 NM_CMPU_LT_QB = 0x50,
16290 NM_CMPU_LE_QB = 0x58,
16291 NM_ADDQ_S_W = 0x60,
16292 NM_SUBQ_S_W = 0x68,
16293 NM_ADDSC = 0x70,
16294 NM_ADDWC = 0x78,
16296 NM_ADDQ_S_PH = 0x01,
16297 NM_ADDQH_R_PH = 0x09,
16298 NM_ADDQH_R_W = 0x11,
16299 NM_ADDU_S_QB = 0x19,
16300 NM_ADDU_S_PH = 0x21,
16301 NM_ADDUH_R_QB = 0x29,
16302 NM_SHRAV_R_PH = 0x31,
16303 NM_SHRAV_R_QB = 0x39,
16304 NM_SUBQ_S_PH = 0x41,
16305 NM_SUBQH_R_PH = 0x49,
16306 NM_SUBQH_R_W = 0x51,
16307 NM_SUBU_S_QB = 0x59,
16308 NM_SUBU_S_PH = 0x61,
16309 NM_SUBUH_R_QB = 0x69,
16310 NM_SHLLV_S_PH = 0x71,
16311 NM_PRECR_SRA_R_PH_W = 0x79,
16313 NM_MULEU_S_PH_QBL = 0x12,
16314 NM_MULEU_S_PH_QBR = 0x1a,
16315 NM_MULQ_RS_PH = 0x22,
16316 NM_MULQ_S_PH = 0x2a,
16317 NM_MULQ_RS_W = 0x32,
16318 NM_MULQ_S_W = 0x3a,
16319 NM_APPEND = 0x42,
16320 NM_MODSUB = 0x52,
16321 NM_SHRAV_R_W = 0x5a,
16322 NM_SHRLV_PH = 0x62,
16323 NM_SHRLV_QB = 0x6a,
16324 NM_SHLLV_QB = 0x72,
16325 NM_SHLLV_S_W = 0x7a,
16327 NM_SHILO = 0x03,
16329 NM_MULEQ_S_W_PHL = 0x04,
16330 NM_MULEQ_S_W_PHR = 0x0c,
16332 NM_MUL_S_PH = 0x05,
16333 NM_PRECR_QB_PH = 0x0d,
16334 NM_PRECRQ_QB_PH = 0x15,
16335 NM_PRECRQ_PH_W = 0x1d,
16336 NM_PRECRQ_RS_PH_W = 0x25,
16337 NM_PRECRQU_S_QB_PH = 0x2d,
16338 NM_PACKRL_PH = 0x35,
16339 NM_PICK_QB = 0x3d,
16340 NM_PICK_PH = 0x45,
16342 NM_SHRA_R_W = 0x5e,
16343 NM_SHRA_R_PH = 0x66,
16344 NM_SHLL_S_PH = 0x76,
16345 NM_SHLL_S_W = 0x7e,
16347 NM_REPL_PH = 0x07
16350 /* POOL32A7 instruction pool */
16351 enum {
16352 NM_P_LSX = 0x00,
16353 NM_LSA = 0x01,
16354 NM_EXTW = 0x03,
16355 NM_POOL32AXF = 0x07,
16358 /* P.SR instruction pool */
16359 enum {
16360 NM_PP_SR = 0x00,
16361 NM_P_SR_F = 0x01,
16364 /* P.SHIFT instruction pool */
16365 enum {
16366 NM_P_SLL = 0x00,
16367 NM_SRL = 0x02,
16368 NM_SRA = 0x04,
16369 NM_ROTR = 0x06,
16372 /* P.ROTX instruction pool */
16373 enum {
16374 NM_ROTX = 0x00,
16377 /* P.INS instruction pool */
16378 enum {
16379 NM_INS = 0x00,
16382 /* P.EXT instruction pool */
16383 enum {
16384 NM_EXT = 0x00,
16387 /* POOL32F_0 (fmt) instruction pool */
16388 enum {
16389 NM_RINT_S = 0x04,
16390 NM_RINT_D = 0x44,
16391 NM_ADD_S = 0x06,
16392 NM_SELEQZ_S = 0x07,
16393 NM_SELEQZ_D = 0x47,
16394 NM_CLASS_S = 0x0c,
16395 NM_CLASS_D = 0x4c,
16396 NM_SUB_S = 0x0e,
16397 NM_SELNEZ_S = 0x0f,
16398 NM_SELNEZ_D = 0x4f,
16399 NM_MUL_S = 0x16,
16400 NM_SEL_S = 0x17,
16401 NM_SEL_D = 0x57,
16402 NM_DIV_S = 0x1e,
16403 NM_ADD_D = 0x26,
16404 NM_SUB_D = 0x2e,
16405 NM_MUL_D = 0x36,
16406 NM_MADDF_S = 0x37,
16407 NM_MADDF_D = 0x77,
16408 NM_DIV_D = 0x3e,
16409 NM_MSUBF_S = 0x3f,
16410 NM_MSUBF_D = 0x7f,
16413 /* POOL32F_3 instruction pool */
16414 enum {
16415 NM_MIN_FMT = 0x00,
16416 NM_MAX_FMT = 0x01,
16417 NM_MINA_FMT = 0x04,
16418 NM_MAXA_FMT = 0x05,
16419 NM_POOL32FXF = 0x07,
16422 /* POOL32F_5 instruction pool */
16423 enum {
16424 NM_CMP_CONDN_S = 0x00,
16425 NM_CMP_CONDN_D = 0x02,
16428 /* P.GP.LH instruction pool */
16429 enum {
16430 NM_LHGP = 0x00,
16431 NM_LHUGP = 0x01,
16434 /* P.GP.SH instruction pool */
16435 enum {
16436 NM_SHGP = 0x00,
16439 /* P.GP.CP1 instruction pool */
16440 enum {
16441 NM_LWC1GP = 0x00,
16442 NM_SWC1GP = 0x01,
16443 NM_LDC1GP = 0x02,
16444 NM_SDC1GP = 0x03,
16447 /* P.LS.S0 instruction pool */
16448 enum {
16449 NM_LBS9 = 0x00,
16450 NM_LHS9 = 0x04,
16451 NM_LWS9 = 0x08,
16452 NM_LDS9 = 0x0c,
16454 NM_SBS9 = 0x01,
16455 NM_SHS9 = 0x05,
16456 NM_SWS9 = 0x09,
16457 NM_SDS9 = 0x0d,
16459 NM_LBUS9 = 0x02,
16460 NM_LHUS9 = 0x06,
16461 NM_LWC1S9 = 0x0a,
16462 NM_LDC1S9 = 0x0e,
16464 NM_P_PREFS9 = 0x03,
16465 NM_LWUS9 = 0x07,
16466 NM_SWC1S9 = 0x0b,
16467 NM_SDC1S9 = 0x0f,
16470 /* P.LS.S1 instruction pool */
16471 enum {
16472 NM_ASET_ACLR = 0x02,
16473 NM_UALH = 0x04,
16474 NM_UASH = 0x05,
16475 NM_CACHE = 0x07,
16476 NM_P_LL = 0x0a,
16477 NM_P_SC = 0x0b,
16480 /* P.LS.WM instruction pool */
16481 enum {
16482 NM_LWM = 0x00,
16483 NM_SWM = 0x01,
16486 /* P.LS.UAWM instruction pool */
16487 enum {
16488 NM_UALWM = 0x00,
16489 NM_UASWM = 0x01,
16492 /* P.BR3A instruction pool */
16493 enum {
16494 NM_BC1EQZC = 0x00,
16495 NM_BC1NEZC = 0x01,
16496 NM_BC2EQZC = 0x02,
16497 NM_BC2NEZC = 0x03,
16498 NM_BPOSGE32C = 0x04,
16501 /* P16.RI instruction pool */
16502 enum {
16503 NM_P16_SYSCALL = 0x01,
16504 NM_BREAK16 = 0x02,
16505 NM_SDBBP16 = 0x03,
16508 /* POOL16C_0 instruction pool */
16509 enum {
16510 NM_POOL16C_00 = 0x00,
16513 /* P16.JRC instruction pool */
16514 enum {
16515 NM_JRC = 0x00,
16516 NM_JALRC16 = 0x01,
16519 /* P.SYSCALL instruction pool */
16520 enum {
16521 NM_SYSCALL = 0x00,
16522 NM_HYPCALL = 0x01,
16525 /* P.TRAP instruction pool */
16526 enum {
16527 NM_TEQ = 0x00,
16528 NM_TNE = 0x01,
16531 /* P.CMOVE instruction pool */
16532 enum {
16533 NM_MOVZ = 0x00,
16534 NM_MOVN = 0x01,
16537 /* POOL32Axf instruction pool */
16538 enum {
16539 NM_POOL32AXF_1 = 0x01,
16540 NM_POOL32AXF_2 = 0x02,
16541 NM_POOL32AXF_4 = 0x04,
16542 NM_POOL32AXF_5 = 0x05,
16543 NM_POOL32AXF_7 = 0x07,
16546 /* POOL32Axf_1 instruction pool */
16547 enum {
16548 NM_POOL32AXF_1_0 = 0x00,
16549 NM_POOL32AXF_1_1 = 0x01,
16550 NM_POOL32AXF_1_3 = 0x03,
16551 NM_POOL32AXF_1_4 = 0x04,
16552 NM_POOL32AXF_1_5 = 0x05,
16553 NM_POOL32AXF_1_7 = 0x07,
16556 /* POOL32Axf_2 instruction pool */
16557 enum {
16558 NM_POOL32AXF_2_0_7 = 0x00,
16559 NM_POOL32AXF_2_8_15 = 0x01,
16560 NM_POOL32AXF_2_16_23 = 0x02,
16561 NM_POOL32AXF_2_24_31 = 0x03,
16564 /* POOL32Axf_7 instruction pool */
16565 enum {
16566 NM_SHRA_R_QB = 0x0,
16567 NM_SHRL_PH = 0x1,
16568 NM_REPL_QB = 0x2,
16571 /* POOL32Axf_1_0 instruction pool */
16572 enum {
16573 NM_MFHI = 0x0,
16574 NM_MFLO = 0x1,
16575 NM_MTHI = 0x2,
16576 NM_MTLO = 0x3,
16579 /* POOL32Axf_1_1 instruction pool */
16580 enum {
16581 NM_MTHLIP = 0x0,
16582 NM_SHILOV = 0x1,
16585 /* POOL32Axf_1_3 instruction pool */
16586 enum {
16587 NM_RDDSP = 0x0,
16588 NM_WRDSP = 0x1,
16589 NM_EXTP = 0x2,
16590 NM_EXTPDP = 0x3,
16593 /* POOL32Axf_1_4 instruction pool */
16594 enum {
16595 NM_SHLL_QB = 0x0,
16596 NM_SHRL_QB = 0x1,
16599 /* POOL32Axf_1_5 instruction pool */
16600 enum {
16601 NM_MAQ_S_W_PHR = 0x0,
16602 NM_MAQ_S_W_PHL = 0x1,
16603 NM_MAQ_SA_W_PHR = 0x2,
16604 NM_MAQ_SA_W_PHL = 0x3,
16607 /* POOL32Axf_1_7 instruction pool */
16608 enum {
16609 NM_EXTR_W = 0x0,
16610 NM_EXTR_R_W = 0x1,
16611 NM_EXTR_RS_W = 0x2,
16612 NM_EXTR_S_H = 0x3,
16615 /* POOL32Axf_2_0_7 instruction pool */
16616 enum {
16617 NM_DPA_W_PH = 0x0,
16618 NM_DPAQ_S_W_PH = 0x1,
16619 NM_DPS_W_PH = 0x2,
16620 NM_DPSQ_S_W_PH = 0x3,
16621 NM_BALIGN = 0x4,
16622 NM_MADD = 0x5,
16623 NM_MULT = 0x6,
16624 NM_EXTRV_W = 0x7,
16627 /* POOL32Axf_2_8_15 instruction pool */
16628 enum {
16629 NM_DPAX_W_PH = 0x0,
16630 NM_DPAQ_SA_L_W = 0x1,
16631 NM_DPSX_W_PH = 0x2,
16632 NM_DPSQ_SA_L_W = 0x3,
16633 NM_MADDU = 0x5,
16634 NM_MULTU = 0x6,
16635 NM_EXTRV_R_W = 0x7,
16638 /* POOL32Axf_2_16_23 instruction pool */
16639 enum {
16640 NM_DPAU_H_QBL = 0x0,
16641 NM_DPAQX_S_W_PH = 0x1,
16642 NM_DPSU_H_QBL = 0x2,
16643 NM_DPSQX_S_W_PH = 0x3,
16644 NM_EXTPV = 0x4,
16645 NM_MSUB = 0x5,
16646 NM_MULSA_W_PH = 0x6,
16647 NM_EXTRV_RS_W = 0x7,
16650 /* POOL32Axf_2_24_31 instruction pool */
16651 enum {
16652 NM_DPAU_H_QBR = 0x0,
16653 NM_DPAQX_SA_W_PH = 0x1,
16654 NM_DPSU_H_QBR = 0x2,
16655 NM_DPSQX_SA_W_PH = 0x3,
16656 NM_EXTPDPV = 0x4,
16657 NM_MSUBU = 0x5,
16658 NM_MULSAQ_S_W_PH = 0x6,
16659 NM_EXTRV_S_H = 0x7,
16662 /* POOL32Axf_{4, 5} instruction pool */
16663 enum {
16664 NM_CLO = 0x25,
16665 NM_CLZ = 0x2d,
16667 NM_TLBP = 0x01,
16668 NM_TLBR = 0x09,
16669 NM_TLBWI = 0x11,
16670 NM_TLBWR = 0x19,
16671 NM_TLBINV = 0x03,
16672 NM_TLBINVF = 0x0b,
16673 NM_DI = 0x23,
16674 NM_EI = 0x2b,
16675 NM_RDPGPR = 0x70,
16676 NM_WRPGPR = 0x78,
16677 NM_WAIT = 0x61,
16678 NM_DERET = 0x71,
16679 NM_ERETX = 0x79,
16681 /* nanoMIPS DSP instructions */
16682 NM_ABSQ_S_QB = 0x00,
16683 NM_ABSQ_S_PH = 0x08,
16684 NM_ABSQ_S_W = 0x10,
16685 NM_PRECEQ_W_PHL = 0x28,
16686 NM_PRECEQ_W_PHR = 0x30,
16687 NM_PRECEQU_PH_QBL = 0x38,
16688 NM_PRECEQU_PH_QBR = 0x48,
16689 NM_PRECEU_PH_QBL = 0x58,
16690 NM_PRECEU_PH_QBR = 0x68,
16691 NM_PRECEQU_PH_QBLA = 0x39,
16692 NM_PRECEQU_PH_QBRA = 0x49,
16693 NM_PRECEU_PH_QBLA = 0x59,
16694 NM_PRECEU_PH_QBRA = 0x69,
16695 NM_REPLV_PH = 0x01,
16696 NM_REPLV_QB = 0x09,
16697 NM_BITREV = 0x18,
16698 NM_INSV = 0x20,
16699 NM_RADDU_W_QB = 0x78,
16701 NM_BITSWAP = 0x05,
16702 NM_WSBH = 0x3d,
16705 /* PP.SR instruction pool */
16706 enum {
16707 NM_SAVE = 0x00,
16708 NM_RESTORE = 0x02,
16709 NM_RESTORE_JRC = 0x03,
16712 /* P.SR.F instruction pool */
16713 enum {
16714 NM_SAVEF = 0x00,
16715 NM_RESTOREF = 0x01,
16718 /* P16.SYSCALL instruction pool */
16719 enum {
16720 NM_SYSCALL16 = 0x00,
16721 NM_HYPCALL16 = 0x01,
16724 /* POOL16C_00 instruction pool */
16725 enum {
16726 NM_NOT16 = 0x00,
16727 NM_XOR16 = 0x01,
16728 NM_AND16 = 0x02,
16729 NM_OR16 = 0x03,
16732 /* PP.LSX and PP.LSXS instruction pool */
16733 enum {
16734 NM_LBX = 0x00,
16735 NM_LHX = 0x04,
16736 NM_LWX = 0x08,
16737 NM_LDX = 0x0c,
16739 NM_SBX = 0x01,
16740 NM_SHX = 0x05,
16741 NM_SWX = 0x09,
16742 NM_SDX = 0x0d,
16744 NM_LBUX = 0x02,
16745 NM_LHUX = 0x06,
16746 NM_LWC1X = 0x0a,
16747 NM_LDC1X = 0x0e,
16749 NM_LWUX = 0x07,
16750 NM_SWC1X = 0x0b,
16751 NM_SDC1X = 0x0f,
16753 NM_LHXS = 0x04,
16754 NM_LWXS = 0x08,
16755 NM_LDXS = 0x0c,
16757 NM_SHXS = 0x05,
16758 NM_SWXS = 0x09,
16759 NM_SDXS = 0x0d,
16761 NM_LHUXS = 0x06,
16762 NM_LWC1XS = 0x0a,
16763 NM_LDC1XS = 0x0e,
16765 NM_LWUXS = 0x07,
16766 NM_SWC1XS = 0x0b,
16767 NM_SDC1XS = 0x0f,
16770 /* ERETx instruction pool */
16771 enum {
16772 NM_ERET = 0x00,
16773 NM_ERETNC = 0x01,
16776 /* POOL32FxF_{0, 1} insturction pool */
16777 enum {
16778 NM_CFC1 = 0x40,
16779 NM_CTC1 = 0x60,
16780 NM_MFC1 = 0x80,
16781 NM_MTC1 = 0xa0,
16782 NM_MFHC1 = 0xc0,
16783 NM_MTHC1 = 0xe0,
16785 NM_CVT_S_PL = 0x84,
16786 NM_CVT_S_PU = 0xa4,
16788 NM_CVT_L_S = 0x004,
16789 NM_CVT_L_D = 0x104,
16790 NM_CVT_W_S = 0x024,
16791 NM_CVT_W_D = 0x124,
16793 NM_RSQRT_S = 0x008,
16794 NM_RSQRT_D = 0x108,
16796 NM_SQRT_S = 0x028,
16797 NM_SQRT_D = 0x128,
16799 NM_RECIP_S = 0x048,
16800 NM_RECIP_D = 0x148,
16802 NM_FLOOR_L_S = 0x00c,
16803 NM_FLOOR_L_D = 0x10c,
16805 NM_FLOOR_W_S = 0x02c,
16806 NM_FLOOR_W_D = 0x12c,
16808 NM_CEIL_L_S = 0x04c,
16809 NM_CEIL_L_D = 0x14c,
16810 NM_CEIL_W_S = 0x06c,
16811 NM_CEIL_W_D = 0x16c,
16812 NM_TRUNC_L_S = 0x08c,
16813 NM_TRUNC_L_D = 0x18c,
16814 NM_TRUNC_W_S = 0x0ac,
16815 NM_TRUNC_W_D = 0x1ac,
16816 NM_ROUND_L_S = 0x0cc,
16817 NM_ROUND_L_D = 0x1cc,
16818 NM_ROUND_W_S = 0x0ec,
16819 NM_ROUND_W_D = 0x1ec,
16821 NM_MOV_S = 0x01,
16822 NM_MOV_D = 0x81,
16823 NM_ABS_S = 0x0d,
16824 NM_ABS_D = 0x8d,
16825 NM_NEG_S = 0x2d,
16826 NM_NEG_D = 0xad,
16827 NM_CVT_D_S = 0x04d,
16828 NM_CVT_D_W = 0x0cd,
16829 NM_CVT_D_L = 0x14d,
16830 NM_CVT_S_D = 0x06d,
16831 NM_CVT_S_W = 0x0ed,
16832 NM_CVT_S_L = 0x16d,
16835 /* P.LL instruction pool */
16836 enum {
16837 NM_LL = 0x00,
16838 NM_LLWP = 0x01,
16841 /* P.SC instruction pool */
16842 enum {
16843 NM_SC = 0x00,
16844 NM_SCWP = 0x01,
16847 /* P.DVP instruction pool */
16848 enum {
16849 NM_DVP = 0x00,
16850 NM_EVP = 0x01,
16856 * nanoMIPS decoding engine
16861 /* extraction utilities */
16863 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
16864 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
16865 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
16866 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
16867 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
16868 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
16870 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
16871 static inline int decode_gpr_gpr3(int r)
16873 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
16875 return map[r & 0x7];
16878 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
16879 static inline int decode_gpr_gpr3_src_store(int r)
16881 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
16883 return map[r & 0x7];
16886 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
16887 static inline int decode_gpr_gpr4(int r)
16889 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
16890 16, 17, 18, 19, 20, 21, 22, 23 };
16892 return map[r & 0xf];
16895 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
16896 static inline int decode_gpr_gpr4_zero(int r)
16898 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
16899 16, 17, 18, 19, 20, 21, 22, 23 };
16901 return map[r & 0xf];
16905 /* extraction utilities */
16907 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
16908 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
16909 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
16910 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
16911 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
16912 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
16915 static void gen_adjust_sp(DisasContext *ctx, int u)
16917 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
16920 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
16921 uint8_t gp, uint16_t u)
16923 int counter = 0;
16924 TCGv va = tcg_temp_new();
16925 TCGv t0 = tcg_temp_new();
16927 while (counter != count) {
16928 bool use_gp = gp && (counter == count - 1);
16929 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
16930 int this_offset = -((counter + 1) << 2);
16931 gen_base_offset_addr(ctx, va, 29, this_offset);
16932 gen_load_gpr(t0, this_rt);
16933 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
16934 (MO_TEUL | ctx->default_tcg_memop_mask));
16935 counter++;
16938 /* adjust stack pointer */
16939 gen_adjust_sp(ctx, -u);
16941 tcg_temp_free(t0);
16942 tcg_temp_free(va);
16945 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
16946 uint8_t gp, uint16_t u)
16948 int counter = 0;
16949 TCGv va = tcg_temp_new();
16950 TCGv t0 = tcg_temp_new();
16952 while (counter != count) {
16953 bool use_gp = gp && (counter == count - 1);
16954 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
16955 int this_offset = u - ((counter + 1) << 2);
16956 gen_base_offset_addr(ctx, va, 29, this_offset);
16957 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
16958 ctx->default_tcg_memop_mask);
16959 tcg_gen_ext32s_tl(t0, t0);
16960 gen_store_gpr(t0, this_rt);
16961 counter++;
16964 /* adjust stack pointer */
16965 gen_adjust_sp(ctx, u);
16967 tcg_temp_free(t0);
16968 tcg_temp_free(va);
16971 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
16973 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
16974 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
16976 switch (extract32(ctx->opcode, 2, 2)) {
16977 case NM_NOT16:
16978 gen_logic(ctx, OPC_NOR, rt, rs, 0);
16979 break;
16980 case NM_AND16:
16981 gen_logic(ctx, OPC_AND, rt, rt, rs);
16982 break;
16983 case NM_XOR16:
16984 gen_logic(ctx, OPC_XOR, rt, rt, rs);
16985 break;
16986 case NM_OR16:
16987 gen_logic(ctx, OPC_OR, rt, rt, rs);
16988 break;
16992 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
16994 int rt = extract32(ctx->opcode, 21, 5);
16995 int rs = extract32(ctx->opcode, 16, 5);
16996 int rd = extract32(ctx->opcode, 11, 5);
16998 switch (extract32(ctx->opcode, 3, 7)) {
16999 case NM_P_TRAP:
17000 switch (extract32(ctx->opcode, 10, 1)) {
17001 case NM_TEQ:
17002 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17003 break;
17004 case NM_TNE:
17005 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17006 break;
17008 break;
17009 case NM_RDHWR:
17010 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17011 break;
17012 case NM_SEB:
17013 gen_bshfl(ctx, OPC_SEB, rs, rt);
17014 break;
17015 case NM_SEH:
17016 gen_bshfl(ctx, OPC_SEH, rs, rt);
17017 break;
17018 case NM_SLLV:
17019 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17020 break;
17021 case NM_SRLV:
17022 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17023 break;
17024 case NM_SRAV:
17025 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17026 break;
17027 case NM_ROTRV:
17028 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17029 break;
17030 case NM_ADD:
17031 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17032 break;
17033 case NM_ADDU:
17034 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17035 break;
17036 case NM_SUB:
17037 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17038 break;
17039 case NM_SUBU:
17040 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17041 break;
17042 case NM_P_CMOVE:
17043 switch (extract32(ctx->opcode, 10, 1)) {
17044 case NM_MOVZ:
17045 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17046 break;
17047 case NM_MOVN:
17048 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17049 break;
17051 break;
17052 case NM_AND:
17053 gen_logic(ctx, OPC_AND, rd, rs, rt);
17054 break;
17055 case NM_OR:
17056 gen_logic(ctx, OPC_OR, rd, rs, rt);
17057 break;
17058 case NM_NOR:
17059 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17060 break;
17061 case NM_XOR:
17062 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17063 break;
17064 case NM_SLT:
17065 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17066 break;
17067 case NM_P_SLTU:
17068 if (rd == 0) {
17069 /* P_DVP */
17070 #ifndef CONFIG_USER_ONLY
17071 TCGv t0 = tcg_temp_new();
17072 switch (extract32(ctx->opcode, 10, 1)) {
17073 case NM_DVP:
17074 if (ctx->vp) {
17075 check_cp0_enabled(ctx);
17076 gen_helper_dvp(t0, cpu_env);
17077 gen_store_gpr(t0, rt);
17079 break;
17080 case NM_EVP:
17081 if (ctx->vp) {
17082 check_cp0_enabled(ctx);
17083 gen_helper_evp(t0, cpu_env);
17084 gen_store_gpr(t0, rt);
17086 break;
17088 tcg_temp_free(t0);
17089 #endif
17090 } else {
17091 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
17093 break;
17094 case NM_SOV:
17096 TCGv t0 = tcg_temp_new();
17097 TCGv t1 = tcg_temp_new();
17098 TCGv t2 = tcg_temp_new();
17100 gen_load_gpr(t1, rs);
17101 gen_load_gpr(t2, rt);
17102 tcg_gen_add_tl(t0, t1, t2);
17103 tcg_gen_ext32s_tl(t0, t0);
17104 tcg_gen_xor_tl(t1, t1, t2);
17105 tcg_gen_xor_tl(t2, t0, t2);
17106 tcg_gen_andc_tl(t1, t2, t1);
17108 /* operands of same sign, result different sign */
17109 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
17110 gen_store_gpr(t0, rd);
17112 tcg_temp_free(t0);
17113 tcg_temp_free(t1);
17114 tcg_temp_free(t2);
17116 break;
17117 case NM_MUL:
17118 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
17119 break;
17120 case NM_MUH:
17121 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
17122 break;
17123 case NM_MULU:
17124 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
17125 break;
17126 case NM_MUHU:
17127 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
17128 break;
17129 case NM_DIV:
17130 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
17131 break;
17132 case NM_MOD:
17133 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
17134 break;
17135 case NM_DIVU:
17136 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
17137 break;
17138 case NM_MODU:
17139 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
17140 break;
17141 #ifndef CONFIG_USER_ONLY
17142 case NM_MFC0:
17143 check_cp0_enabled(ctx);
17144 if (rt == 0) {
17145 /* Treat as NOP. */
17146 break;
17148 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
17149 break;
17150 case NM_MTC0:
17151 check_cp0_enabled(ctx);
17153 TCGv t0 = tcg_temp_new();
17155 gen_load_gpr(t0, rt);
17156 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
17157 tcg_temp_free(t0);
17159 break;
17160 case NM_D_E_MT_VPE:
17162 uint8_t sc = extract32(ctx->opcode, 10, 1);
17163 TCGv t0 = tcg_temp_new();
17165 switch (sc) {
17166 case 0:
17167 if (rs == 1) {
17168 /* DMT */
17169 check_cp0_mt(ctx);
17170 gen_helper_dmt(t0);
17171 gen_store_gpr(t0, rt);
17172 } else if (rs == 0) {
17173 /* DVPE */
17174 check_cp0_mt(ctx);
17175 gen_helper_dvpe(t0, cpu_env);
17176 gen_store_gpr(t0, rt);
17177 } else {
17178 generate_exception_end(ctx, EXCP_RI);
17180 break;
17181 case 1:
17182 if (rs == 1) {
17183 /* EMT */
17184 check_cp0_mt(ctx);
17185 gen_helper_emt(t0);
17186 gen_store_gpr(t0, rt);
17187 } else if (rs == 0) {
17188 /* EVPE */
17189 check_cp0_mt(ctx);
17190 gen_helper_evpe(t0, cpu_env);
17191 gen_store_gpr(t0, rt);
17192 } else {
17193 generate_exception_end(ctx, EXCP_RI);
17195 break;
17198 tcg_temp_free(t0);
17200 break;
17201 case NM_FORK:
17202 check_mt(ctx);
17204 TCGv t0 = tcg_temp_new();
17205 TCGv t1 = tcg_temp_new();
17207 gen_load_gpr(t0, rt);
17208 gen_load_gpr(t1, rs);
17209 gen_helper_fork(t0, t1);
17210 tcg_temp_free(t0);
17211 tcg_temp_free(t1);
17213 break;
17214 case NM_MFTR:
17215 case NM_MFHTR:
17216 check_cp0_enabled(ctx);
17217 if (rd == 0) {
17218 /* Treat as NOP. */
17219 return;
17221 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17222 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17223 break;
17224 case NM_MTTR:
17225 case NM_MTHTR:
17226 check_cp0_enabled(ctx);
17227 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17228 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17229 break;
17230 case NM_YIELD:
17231 check_mt(ctx);
17233 TCGv t0 = tcg_temp_new();
17235 gen_load_gpr(t0, rs);
17236 gen_helper_yield(t0, cpu_env, t0);
17237 gen_store_gpr(t0, rt);
17238 tcg_temp_free(t0);
17240 break;
17241 #endif
17242 default:
17243 generate_exception_end(ctx, EXCP_RI);
17244 break;
17248 /* dsp */
17249 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
17250 int ret, int v1, int v2)
17252 TCGv_i32 t0;
17253 TCGv v0_t;
17254 TCGv v1_t;
17256 t0 = tcg_temp_new_i32();
17258 v0_t = tcg_temp_new();
17259 v1_t = tcg_temp_new();
17261 tcg_gen_movi_i32(t0, v2 >> 3);
17263 gen_load_gpr(v0_t, ret);
17264 gen_load_gpr(v1_t, v1);
17266 switch (opc) {
17267 case NM_MAQ_S_W_PHR:
17268 check_dsp(ctx);
17269 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
17270 break;
17271 case NM_MAQ_S_W_PHL:
17272 check_dsp(ctx);
17273 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
17274 break;
17275 case NM_MAQ_SA_W_PHR:
17276 check_dsp(ctx);
17277 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
17278 break;
17279 case NM_MAQ_SA_W_PHL:
17280 check_dsp(ctx);
17281 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
17282 break;
17283 default:
17284 generate_exception_end(ctx, EXCP_RI);
17285 break;
17288 tcg_temp_free_i32(t0);
17290 tcg_temp_free(v0_t);
17291 tcg_temp_free(v1_t);
17295 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
17296 int ret, int v1, int v2)
17298 int16_t imm;
17299 TCGv t0 = tcg_temp_new();
17300 TCGv t1 = tcg_temp_new();
17301 TCGv v0_t = tcg_temp_new();
17303 gen_load_gpr(v0_t, v1);
17305 switch (opc) {
17306 case NM_POOL32AXF_1_0:
17307 check_dsp(ctx);
17308 switch (extract32(ctx->opcode, 12, 2)) {
17309 case NM_MFHI:
17310 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
17311 break;
17312 case NM_MFLO:
17313 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
17314 break;
17315 case NM_MTHI:
17316 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
17317 break;
17318 case NM_MTLO:
17319 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
17320 break;
17322 break;
17323 case NM_POOL32AXF_1_1:
17324 check_dsp(ctx);
17325 switch (extract32(ctx->opcode, 12, 2)) {
17326 case NM_MTHLIP:
17327 tcg_gen_movi_tl(t0, v2);
17328 gen_helper_mthlip(t0, v0_t, cpu_env);
17329 break;
17330 case NM_SHILOV:
17331 tcg_gen_movi_tl(t0, v2 >> 3);
17332 gen_helper_shilo(t0, v0_t, cpu_env);
17333 break;
17334 default:
17335 generate_exception_end(ctx, EXCP_RI);
17336 break;
17338 break;
17339 case NM_POOL32AXF_1_3:
17340 check_dsp(ctx);
17341 imm = extract32(ctx->opcode, 14, 7);
17342 switch (extract32(ctx->opcode, 12, 2)) {
17343 case NM_RDDSP:
17344 tcg_gen_movi_tl(t0, imm);
17345 gen_helper_rddsp(t0, t0, cpu_env);
17346 gen_store_gpr(t0, ret);
17347 break;
17348 case NM_WRDSP:
17349 gen_load_gpr(t0, ret);
17350 tcg_gen_movi_tl(t1, imm);
17351 gen_helper_wrdsp(t0, t1, cpu_env);
17352 break;
17353 case NM_EXTP:
17354 tcg_gen_movi_tl(t0, v2 >> 3);
17355 tcg_gen_movi_tl(t1, v1);
17356 gen_helper_extp(t0, t0, t1, cpu_env);
17357 gen_store_gpr(t0, ret);
17358 break;
17359 case NM_EXTPDP:
17360 tcg_gen_movi_tl(t0, v2 >> 3);
17361 tcg_gen_movi_tl(t1, v1);
17362 gen_helper_extpdp(t0, t0, t1, cpu_env);
17363 gen_store_gpr(t0, ret);
17364 break;
17366 break;
17367 case NM_POOL32AXF_1_4:
17368 check_dsp(ctx);
17369 tcg_gen_movi_tl(t0, v2 >> 2);
17370 switch (extract32(ctx->opcode, 12, 1)) {
17371 case NM_SHLL_QB:
17372 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
17373 gen_store_gpr(t0, ret);
17374 break;
17375 case NM_SHRL_QB:
17376 gen_helper_shrl_qb(t0, t0, v0_t);
17377 gen_store_gpr(t0, ret);
17378 break;
17380 break;
17381 case NM_POOL32AXF_1_5:
17382 opc = extract32(ctx->opcode, 12, 2);
17383 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
17384 break;
17385 case NM_POOL32AXF_1_7:
17386 check_dsp(ctx);
17387 tcg_gen_movi_tl(t0, v2 >> 3);
17388 tcg_gen_movi_tl(t1, v1);
17389 switch (extract32(ctx->opcode, 12, 2)) {
17390 case NM_EXTR_W:
17391 gen_helper_extr_w(t0, t0, t1, cpu_env);
17392 gen_store_gpr(t0, ret);
17393 break;
17394 case NM_EXTR_R_W:
17395 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
17396 gen_store_gpr(t0, ret);
17397 break;
17398 case NM_EXTR_RS_W:
17399 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
17400 gen_store_gpr(t0, ret);
17401 break;
17402 case NM_EXTR_S_H:
17403 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
17404 gen_store_gpr(t0, ret);
17405 break;
17407 break;
17408 default:
17409 generate_exception_end(ctx, EXCP_RI);
17410 break;
17413 tcg_temp_free(t0);
17414 tcg_temp_free(t1);
17415 tcg_temp_free(v0_t);
17418 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
17419 TCGv v0, TCGv v1, int rd)
17421 TCGv_i32 t0;
17423 t0 = tcg_temp_new_i32();
17425 tcg_gen_movi_i32(t0, rd >> 3);
17427 switch (opc) {
17428 case NM_POOL32AXF_2_0_7:
17429 switch (extract32(ctx->opcode, 9, 3)) {
17430 case NM_DPA_W_PH:
17431 check_dspr2(ctx);
17432 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
17433 break;
17434 case NM_DPAQ_S_W_PH:
17435 check_dsp(ctx);
17436 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
17437 break;
17438 case NM_DPS_W_PH:
17439 check_dspr2(ctx);
17440 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
17441 break;
17442 case NM_DPSQ_S_W_PH:
17443 check_dsp(ctx);
17444 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
17445 break;
17446 default:
17447 generate_exception_end(ctx, EXCP_RI);
17448 break;
17450 break;
17451 case NM_POOL32AXF_2_8_15:
17452 switch (extract32(ctx->opcode, 9, 3)) {
17453 case NM_DPAX_W_PH:
17454 check_dspr2(ctx);
17455 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
17456 break;
17457 case NM_DPAQ_SA_L_W:
17458 check_dsp(ctx);
17459 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
17460 break;
17461 case NM_DPSX_W_PH:
17462 check_dspr2(ctx);
17463 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
17464 break;
17465 case NM_DPSQ_SA_L_W:
17466 check_dsp(ctx);
17467 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
17468 break;
17469 default:
17470 generate_exception_end(ctx, EXCP_RI);
17471 break;
17473 break;
17474 case NM_POOL32AXF_2_16_23:
17475 switch (extract32(ctx->opcode, 9, 3)) {
17476 case NM_DPAU_H_QBL:
17477 check_dsp(ctx);
17478 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
17479 break;
17480 case NM_DPAQX_S_W_PH:
17481 check_dspr2(ctx);
17482 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
17483 break;
17484 case NM_DPSU_H_QBL:
17485 check_dsp(ctx);
17486 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
17487 break;
17488 case NM_DPSQX_S_W_PH:
17489 check_dspr2(ctx);
17490 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
17491 break;
17492 case NM_MULSA_W_PH:
17493 check_dspr2(ctx);
17494 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
17495 break;
17496 default:
17497 generate_exception_end(ctx, EXCP_RI);
17498 break;
17500 break;
17501 case NM_POOL32AXF_2_24_31:
17502 switch (extract32(ctx->opcode, 9, 3)) {
17503 case NM_DPAU_H_QBR:
17504 check_dsp(ctx);
17505 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
17506 break;
17507 case NM_DPAQX_SA_W_PH:
17508 check_dspr2(ctx);
17509 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
17510 break;
17511 case NM_DPSU_H_QBR:
17512 check_dsp(ctx);
17513 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
17514 break;
17515 case NM_DPSQX_SA_W_PH:
17516 check_dspr2(ctx);
17517 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
17518 break;
17519 case NM_MULSAQ_S_W_PH:
17520 check_dsp(ctx);
17521 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
17522 break;
17523 default:
17524 generate_exception_end(ctx, EXCP_RI);
17525 break;
17527 break;
17528 default:
17529 generate_exception_end(ctx, EXCP_RI);
17530 break;
17533 tcg_temp_free_i32(t0);
17536 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
17537 int rt, int rs, int rd)
17539 int ret = rt;
17540 TCGv t0 = tcg_temp_new();
17541 TCGv t1 = tcg_temp_new();
17542 TCGv v0_t = tcg_temp_new();
17543 TCGv v1_t = tcg_temp_new();
17545 gen_load_gpr(v0_t, rt);
17546 gen_load_gpr(v1_t, rs);
17548 switch (opc) {
17549 case NM_POOL32AXF_2_0_7:
17550 switch (extract32(ctx->opcode, 9, 3)) {
17551 case NM_DPA_W_PH:
17552 case NM_DPAQ_S_W_PH:
17553 case NM_DPS_W_PH:
17554 case NM_DPSQ_S_W_PH:
17555 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17556 break;
17557 case NM_BALIGN:
17558 check_dspr2(ctx);
17559 if (rt != 0) {
17560 gen_load_gpr(t0, rs);
17561 rd &= 3;
17562 if (rd != 0 && rd != 2) {
17563 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
17564 tcg_gen_ext32u_tl(t0, t0);
17565 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
17566 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
17568 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
17570 break;
17571 case NM_MADD:
17572 check_dsp(ctx);
17574 int acc = extract32(ctx->opcode, 14, 2);
17575 TCGv_i64 t2 = tcg_temp_new_i64();
17576 TCGv_i64 t3 = tcg_temp_new_i64();
17578 gen_load_gpr(t0, rt);
17579 gen_load_gpr(t1, rs);
17580 tcg_gen_ext_tl_i64(t2, t0);
17581 tcg_gen_ext_tl_i64(t3, t1);
17582 tcg_gen_mul_i64(t2, t2, t3);
17583 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17584 tcg_gen_add_i64(t2, t2, t3);
17585 tcg_temp_free_i64(t3);
17586 gen_move_low32(cpu_LO[acc], t2);
17587 gen_move_high32(cpu_HI[acc], t2);
17588 tcg_temp_free_i64(t2);
17590 break;
17591 case NM_MULT:
17592 check_dsp(ctx);
17594 int acc = extract32(ctx->opcode, 14, 2);
17595 TCGv_i32 t2 = tcg_temp_new_i32();
17596 TCGv_i32 t3 = tcg_temp_new_i32();
17598 gen_load_gpr(t0, rs);
17599 gen_load_gpr(t1, rt);
17600 tcg_gen_trunc_tl_i32(t2, t0);
17601 tcg_gen_trunc_tl_i32(t3, t1);
17602 tcg_gen_muls2_i32(t2, t3, t2, t3);
17603 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
17604 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
17605 tcg_temp_free_i32(t2);
17606 tcg_temp_free_i32(t3);
17608 break;
17609 case NM_EXTRV_W:
17610 check_dsp(ctx);
17611 gen_load_gpr(v1_t, rs);
17612 tcg_gen_movi_tl(t0, rd >> 3);
17613 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
17614 gen_store_gpr(t0, ret);
17615 break;
17617 break;
17618 case NM_POOL32AXF_2_8_15:
17619 switch (extract32(ctx->opcode, 9, 3)) {
17620 case NM_DPAX_W_PH:
17621 case NM_DPAQ_SA_L_W:
17622 case NM_DPSX_W_PH:
17623 case NM_DPSQ_SA_L_W:
17624 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17625 break;
17626 case NM_MADDU:
17627 check_dsp(ctx);
17629 int acc = extract32(ctx->opcode, 14, 2);
17630 TCGv_i64 t2 = tcg_temp_new_i64();
17631 TCGv_i64 t3 = tcg_temp_new_i64();
17633 gen_load_gpr(t0, rs);
17634 gen_load_gpr(t1, rt);
17635 tcg_gen_ext32u_tl(t0, t0);
17636 tcg_gen_ext32u_tl(t1, t1);
17637 tcg_gen_extu_tl_i64(t2, t0);
17638 tcg_gen_extu_tl_i64(t3, t1);
17639 tcg_gen_mul_i64(t2, t2, t3);
17640 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17641 tcg_gen_add_i64(t2, t2, t3);
17642 tcg_temp_free_i64(t3);
17643 gen_move_low32(cpu_LO[acc], t2);
17644 gen_move_high32(cpu_HI[acc], t2);
17645 tcg_temp_free_i64(t2);
17647 break;
17648 case NM_MULTU:
17649 check_dsp(ctx);
17651 int acc = extract32(ctx->opcode, 14, 2);
17652 TCGv_i32 t2 = tcg_temp_new_i32();
17653 TCGv_i32 t3 = tcg_temp_new_i32();
17655 gen_load_gpr(t0, rs);
17656 gen_load_gpr(t1, rt);
17657 tcg_gen_trunc_tl_i32(t2, t0);
17658 tcg_gen_trunc_tl_i32(t3, t1);
17659 tcg_gen_mulu2_i32(t2, t3, t2, t3);
17660 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
17661 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
17662 tcg_temp_free_i32(t2);
17663 tcg_temp_free_i32(t3);
17665 break;
17666 case NM_EXTRV_R_W:
17667 check_dsp(ctx);
17668 tcg_gen_movi_tl(t0, rd >> 3);
17669 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
17670 gen_store_gpr(t0, ret);
17671 break;
17672 default:
17673 generate_exception_end(ctx, EXCP_RI);
17674 break;
17676 break;
17677 case NM_POOL32AXF_2_16_23:
17678 switch (extract32(ctx->opcode, 9, 3)) {
17679 case NM_DPAU_H_QBL:
17680 case NM_DPAQX_S_W_PH:
17681 case NM_DPSU_H_QBL:
17682 case NM_DPSQX_S_W_PH:
17683 case NM_MULSA_W_PH:
17684 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17685 break;
17686 case NM_EXTPV:
17687 check_dsp(ctx);
17688 tcg_gen_movi_tl(t0, rd >> 3);
17689 gen_helper_extp(t0, t0, v1_t, cpu_env);
17690 gen_store_gpr(t0, ret);
17691 break;
17692 case NM_MSUB:
17693 check_dsp(ctx);
17695 int acc = extract32(ctx->opcode, 14, 2);
17696 TCGv_i64 t2 = tcg_temp_new_i64();
17697 TCGv_i64 t3 = tcg_temp_new_i64();
17699 gen_load_gpr(t0, rs);
17700 gen_load_gpr(t1, rt);
17701 tcg_gen_ext_tl_i64(t2, t0);
17702 tcg_gen_ext_tl_i64(t3, t1);
17703 tcg_gen_mul_i64(t2, t2, t3);
17704 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17705 tcg_gen_sub_i64(t2, t3, t2);
17706 tcg_temp_free_i64(t3);
17707 gen_move_low32(cpu_LO[acc], t2);
17708 gen_move_high32(cpu_HI[acc], t2);
17709 tcg_temp_free_i64(t2);
17711 break;
17712 case NM_EXTRV_RS_W:
17713 check_dsp(ctx);
17714 tcg_gen_movi_tl(t0, rd >> 3);
17715 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
17716 gen_store_gpr(t0, ret);
17717 break;
17719 break;
17720 case NM_POOL32AXF_2_24_31:
17721 switch (extract32(ctx->opcode, 9, 3)) {
17722 case NM_DPAU_H_QBR:
17723 case NM_DPAQX_SA_W_PH:
17724 case NM_DPSU_H_QBR:
17725 case NM_DPSQX_SA_W_PH:
17726 case NM_MULSAQ_S_W_PH:
17727 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17728 break;
17729 case NM_EXTPDPV:
17730 check_dsp(ctx);
17731 tcg_gen_movi_tl(t0, rd >> 3);
17732 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
17733 gen_store_gpr(t0, ret);
17734 break;
17735 case NM_MSUBU:
17736 check_dsp(ctx);
17738 int acc = extract32(ctx->opcode, 14, 2);
17739 TCGv_i64 t2 = tcg_temp_new_i64();
17740 TCGv_i64 t3 = tcg_temp_new_i64();
17742 gen_load_gpr(t0, rs);
17743 gen_load_gpr(t1, rt);
17744 tcg_gen_ext32u_tl(t0, t0);
17745 tcg_gen_ext32u_tl(t1, t1);
17746 tcg_gen_extu_tl_i64(t2, t0);
17747 tcg_gen_extu_tl_i64(t3, t1);
17748 tcg_gen_mul_i64(t2, t2, t3);
17749 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17750 tcg_gen_sub_i64(t2, t3, t2);
17751 tcg_temp_free_i64(t3);
17752 gen_move_low32(cpu_LO[acc], t2);
17753 gen_move_high32(cpu_HI[acc], t2);
17754 tcg_temp_free_i64(t2);
17756 break;
17757 case NM_EXTRV_S_H:
17758 check_dsp(ctx);
17759 tcg_gen_movi_tl(t0, rd >> 3);
17760 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
17761 gen_store_gpr(t0, ret);
17762 break;
17764 break;
17765 default:
17766 generate_exception_end(ctx, EXCP_RI);
17767 break;
17770 tcg_temp_free(t0);
17771 tcg_temp_free(t1);
17773 tcg_temp_free(v0_t);
17774 tcg_temp_free(v1_t);
17778 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17780 int rt = extract32(ctx->opcode, 21, 5);
17781 int rs = extract32(ctx->opcode, 16, 5);
17782 int rd = extract32(ctx->opcode, 11, 5);
17784 switch (extract32(ctx->opcode, 6, 3)) {
17785 case NM_POOL32AXF_1:
17787 int32_t op1 = extract32(ctx->opcode, 9, 3);
17788 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
17790 break;
17791 case NM_POOL32AXF_2:
17793 int32_t op1 = extract32(ctx->opcode, 12, 2);
17794 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
17796 break;
17797 case NM_POOL32AXF_4:
17798 break;
17799 case NM_POOL32AXF_5:
17800 switch (extract32(ctx->opcode, 9, 7)) {
17801 #ifndef CONFIG_USER_ONLY
17802 case NM_TLBP:
17803 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
17804 break;
17805 case NM_TLBR:
17806 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
17807 break;
17808 case NM_TLBWI:
17809 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
17810 break;
17811 case NM_TLBWR:
17812 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
17813 break;
17814 case NM_TLBINV:
17815 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
17816 break;
17817 case NM_TLBINVF:
17818 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
17819 break;
17820 case NM_DI:
17821 check_cp0_enabled(ctx);
17823 TCGv t0 = tcg_temp_new();
17825 save_cpu_state(ctx, 1);
17826 gen_helper_di(t0, cpu_env);
17827 gen_store_gpr(t0, rt);
17828 /* Stop translation as we may have switched the execution mode */
17829 ctx->base.is_jmp = DISAS_STOP;
17830 tcg_temp_free(t0);
17832 break;
17833 case NM_EI:
17834 check_cp0_enabled(ctx);
17836 TCGv t0 = tcg_temp_new();
17838 save_cpu_state(ctx, 1);
17839 gen_helper_ei(t0, cpu_env);
17840 gen_store_gpr(t0, rt);
17841 /* Stop translation as we may have switched the execution mode */
17842 ctx->base.is_jmp = DISAS_STOP;
17843 tcg_temp_free(t0);
17845 break;
17846 case NM_RDPGPR:
17847 gen_load_srsgpr(rs, rt);
17848 break;
17849 case NM_WRPGPR:
17850 gen_store_srsgpr(rs, rt);
17851 break;
17852 case NM_WAIT:
17853 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
17854 break;
17855 case NM_DERET:
17856 gen_cp0(env, ctx, OPC_DERET, 0, 0);
17857 break;
17858 case NM_ERETX:
17859 gen_cp0(env, ctx, OPC_ERET, 0, 0);
17860 break;
17861 #endif
17862 default:
17863 generate_exception_end(ctx, EXCP_RI);
17864 break;
17866 break;
17867 case NM_POOL32AXF_7:
17868 break;
17869 default:
17870 generate_exception_end(ctx, EXCP_RI);
17871 break;
17875 /* Immediate Value Compact Branches */
17876 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
17877 int rt, int32_t imm, int32_t offset)
17879 TCGCond cond;
17880 int bcond_compute = 0;
17881 TCGv t0 = tcg_temp_new();
17882 TCGv t1 = tcg_temp_new();
17884 gen_load_gpr(t0, rt);
17885 tcg_gen_movi_tl(t1, imm);
17886 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
17888 /* Load needed operands and calculate btarget */
17889 switch (opc) {
17890 case NM_BEQIC:
17891 if (rt == 0 && imm == 0) {
17892 /* Unconditional branch */
17893 } else if (rt == 0 && imm != 0) {
17894 /* Treat as NOP */
17895 goto out;
17896 } else {
17897 bcond_compute = 1;
17898 cond = TCG_COND_EQ;
17900 break;
17901 case NM_BBEQZC:
17902 case NM_BBNEZC:
17903 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
17904 generate_exception_end(ctx, EXCP_RI);
17905 goto out;
17906 } else if (rt == 0 && opc == NM_BBEQZC) {
17907 /* Unconditional branch */
17908 } else if (rt == 0 && opc == NM_BBNEZC) {
17909 /* Treat as NOP */
17910 goto out;
17911 } else {
17912 tcg_gen_shri_tl(t0, t0, imm);
17913 tcg_gen_andi_tl(t0, t0, 1);
17914 tcg_gen_movi_tl(t1, 0);
17915 bcond_compute = 1;
17916 if (opc == NM_BBEQZC) {
17917 cond = TCG_COND_EQ;
17918 } else {
17919 cond = TCG_COND_NE;
17922 break;
17923 case NM_BNEIC:
17924 if (rt == 0 && imm == 0) {
17925 /* Treat as NOP */
17926 goto out;
17927 } else if (rt == 0 && imm != 0) {
17928 /* Unconditional branch */
17929 } else {
17930 bcond_compute = 1;
17931 cond = TCG_COND_NE;
17933 break;
17934 case NM_BGEIC:
17935 if (rt == 0 && imm == 0) {
17936 /* Unconditional branch */
17937 } else {
17938 bcond_compute = 1;
17939 cond = TCG_COND_GE;
17941 break;
17942 case NM_BLTIC:
17943 bcond_compute = 1;
17944 cond = TCG_COND_LT;
17945 break;
17946 case NM_BGEIUC:
17947 if (rt == 0 && imm == 0) {
17948 /* Unconditional branch */
17949 } else {
17950 bcond_compute = 1;
17951 cond = TCG_COND_GEU;
17953 break;
17954 case NM_BLTIUC:
17955 bcond_compute = 1;
17956 cond = TCG_COND_LTU;
17957 break;
17958 default:
17959 MIPS_INVAL("Immediate Value Compact branch");
17960 generate_exception_end(ctx, EXCP_RI);
17961 goto out;
17964 if (bcond_compute == 0) {
17965 /* Uncoditional compact branch */
17966 gen_goto_tb(ctx, 0, ctx->btarget);
17967 } else {
17968 /* Conditional compact branch */
17969 TCGLabel *fs = gen_new_label();
17971 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
17973 gen_goto_tb(ctx, 1, ctx->btarget);
17974 gen_set_label(fs);
17976 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
17979 out:
17980 tcg_temp_free(t0);
17981 tcg_temp_free(t1);
17984 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
17985 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
17986 int rt)
17988 TCGv t0 = tcg_temp_new();
17989 TCGv t1 = tcg_temp_new();
17991 /* load rs */
17992 gen_load_gpr(t0, rs);
17994 /* link */
17995 if (rt != 0) {
17996 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
17999 /* calculate btarget */
18000 tcg_gen_shli_tl(t0, t0, 1);
18001 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
18002 gen_op_addr_add(ctx, btarget, t1, t0);
18004 /* unconditional branch to register */
18005 tcg_gen_mov_tl(cpu_PC, btarget);
18006 tcg_gen_lookup_and_goto_ptr();
18008 tcg_temp_free(t0);
18009 tcg_temp_free(t1);
18012 /* nanoMIPS Branches */
18013 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
18014 int rs, int rt, int32_t offset)
18016 int bcond_compute = 0;
18017 TCGv t0 = tcg_temp_new();
18018 TCGv t1 = tcg_temp_new();
18020 /* Load needed operands and calculate btarget */
18021 switch (opc) {
18022 /* compact branch */
18023 case OPC_BGEC:
18024 case OPC_BLTC:
18025 gen_load_gpr(t0, rs);
18026 gen_load_gpr(t1, rt);
18027 bcond_compute = 1;
18028 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18029 break;
18030 case OPC_BGEUC:
18031 case OPC_BLTUC:
18032 if (rs == 0 || rs == rt) {
18033 /* OPC_BLEZALC, OPC_BGEZALC */
18034 /* OPC_BGTZALC, OPC_BLTZALC */
18035 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
18037 gen_load_gpr(t0, rs);
18038 gen_load_gpr(t1, rt);
18039 bcond_compute = 1;
18040 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18041 break;
18042 case OPC_BC:
18043 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18044 break;
18045 case OPC_BEQZC:
18046 if (rs != 0) {
18047 /* OPC_BEQZC, OPC_BNEZC */
18048 gen_load_gpr(t0, rs);
18049 bcond_compute = 1;
18050 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18051 } else {
18052 /* OPC_JIC, OPC_JIALC */
18053 TCGv tbase = tcg_temp_new();
18054 TCGv toffset = tcg_temp_new();
18056 gen_load_gpr(tbase, rt);
18057 tcg_gen_movi_tl(toffset, offset);
18058 gen_op_addr_add(ctx, btarget, tbase, toffset);
18059 tcg_temp_free(tbase);
18060 tcg_temp_free(toffset);
18062 break;
18063 default:
18064 MIPS_INVAL("Compact branch/jump");
18065 generate_exception_end(ctx, EXCP_RI);
18066 goto out;
18069 if (bcond_compute == 0) {
18070 /* Uncoditional compact branch */
18071 switch (opc) {
18072 case OPC_BC:
18073 gen_goto_tb(ctx, 0, ctx->btarget);
18074 break;
18075 default:
18076 MIPS_INVAL("Compact branch/jump");
18077 generate_exception_end(ctx, EXCP_RI);
18078 goto out;
18080 } else {
18081 /* Conditional compact branch */
18082 TCGLabel *fs = gen_new_label();
18084 switch (opc) {
18085 case OPC_BGEUC:
18086 if (rs == 0 && rt != 0) {
18087 /* OPC_BLEZALC */
18088 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18089 } else if (rs != 0 && rt != 0 && rs == rt) {
18090 /* OPC_BGEZALC */
18091 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18092 } else {
18093 /* OPC_BGEUC */
18094 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
18096 break;
18097 case OPC_BLTUC:
18098 if (rs == 0 && rt != 0) {
18099 /* OPC_BGTZALC */
18100 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18101 } else if (rs != 0 && rt != 0 && rs == rt) {
18102 /* OPC_BLTZALC */
18103 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
18104 } else {
18105 /* OPC_BLTUC */
18106 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
18108 break;
18109 case OPC_BGEC:
18110 if (rs == 0 && rt != 0) {
18111 /* OPC_BLEZC */
18112 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18113 } else if (rs != 0 && rt != 0 && rs == rt) {
18114 /* OPC_BGEZC */
18115 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18116 } else {
18117 /* OPC_BGEC */
18118 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
18120 break;
18121 case OPC_BLTC:
18122 if (rs == 0 && rt != 0) {
18123 /* OPC_BGTZC */
18124 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18125 } else if (rs != 0 && rt != 0 && rs == rt) {
18126 /* OPC_BLTZC */
18127 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
18128 } else {
18129 /* OPC_BLTC */
18130 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
18132 break;
18133 case OPC_BEQZC:
18134 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
18135 break;
18136 default:
18137 MIPS_INVAL("Compact conditional branch/jump");
18138 generate_exception_end(ctx, EXCP_RI);
18139 goto out;
18142 /* Generating branch here as compact branches don't have delay slot */
18143 gen_goto_tb(ctx, 1, ctx->btarget);
18144 gen_set_label(fs);
18146 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
18149 out:
18150 tcg_temp_free(t0);
18151 tcg_temp_free(t1);
18155 /* nanoMIPS CP1 Branches */
18156 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
18157 int32_t ft, int32_t offset)
18159 target_ulong btarget;
18160 TCGv_i64 t0 = tcg_temp_new_i64();
18162 gen_load_fpr64(ctx, t0, ft);
18163 tcg_gen_andi_i64(t0, t0, 1);
18165 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18167 switch (op) {
18168 case NM_BC1EQZC:
18169 tcg_gen_xori_i64(t0, t0, 1);
18170 ctx->hflags |= MIPS_HFLAG_BC;
18171 break;
18172 case NM_BC1NEZC:
18173 /* t0 already set */
18174 ctx->hflags |= MIPS_HFLAG_BC;
18175 break;
18176 default:
18177 MIPS_INVAL("cp1 cond branch");
18178 generate_exception_end(ctx, EXCP_RI);
18179 goto out;
18182 tcg_gen_trunc_i64_tl(bcond, t0);
18184 ctx->btarget = btarget;
18186 out:
18187 tcg_temp_free_i64(t0);
18191 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
18193 TCGv t0, t1;
18194 t0 = tcg_temp_new();
18195 t1 = tcg_temp_new();
18197 gen_load_gpr(t0, rs);
18198 gen_load_gpr(t1, rt);
18200 if ((extract32(ctx->opcode, 6, 1)) == 1) {
18201 /* PP.LSXS instructions require shifting */
18202 switch (extract32(ctx->opcode, 7, 4)) {
18203 case NM_LHXS:
18204 case NM_SHXS:
18205 case NM_LHUXS:
18206 tcg_gen_shli_tl(t0, t0, 1);
18207 break;
18208 case NM_LWXS:
18209 case NM_SWXS:
18210 case NM_LWC1XS:
18211 case NM_SWC1XS:
18212 tcg_gen_shli_tl(t0, t0, 2);
18213 break;
18214 case NM_LDC1XS:
18215 case NM_SDC1XS:
18216 tcg_gen_shli_tl(t0, t0, 3);
18217 break;
18220 gen_op_addr_add(ctx, t0, t0, t1);
18222 switch (extract32(ctx->opcode, 7, 4)) {
18223 case NM_LBX:
18224 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18225 MO_SB);
18226 gen_store_gpr(t0, rd);
18227 break;
18228 case NM_LHX:
18229 /*case NM_LHXS:*/
18230 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18231 MO_TESW);
18232 gen_store_gpr(t0, rd);
18233 break;
18234 case NM_LWX:
18235 /*case NM_LWXS:*/
18236 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18237 MO_TESL);
18238 gen_store_gpr(t0, rd);
18239 break;
18240 case NM_LBUX:
18241 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18242 MO_UB);
18243 gen_store_gpr(t0, rd);
18244 break;
18245 case NM_LHUX:
18246 /*case NM_LHUXS:*/
18247 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18248 MO_TEUW);
18249 gen_store_gpr(t0, rd);
18250 break;
18251 case NM_SBX:
18252 gen_load_gpr(t1, rd);
18253 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18254 MO_8);
18255 break;
18256 case NM_SHX:
18257 /*case NM_SHXS:*/
18258 gen_load_gpr(t1, rd);
18259 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18260 MO_TEUW);
18261 break;
18262 case NM_SWX:
18263 /*case NM_SWXS:*/
18264 gen_load_gpr(t1, rd);
18265 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18266 MO_TEUL);
18267 break;
18268 case NM_LWC1X:
18269 /*case NM_LWC1XS:*/
18270 case NM_LDC1X:
18271 /*case NM_LDC1XS:*/
18272 case NM_SWC1X:
18273 /*case NM_SWC1XS:*/
18274 case NM_SDC1X:
18275 /*case NM_SDC1XS:*/
18276 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
18277 check_cp1_enabled(ctx);
18278 switch (extract32(ctx->opcode, 7, 4)) {
18279 case NM_LWC1X:
18280 /*case NM_LWC1XS:*/
18281 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
18282 break;
18283 case NM_LDC1X:
18284 /*case NM_LDC1XS:*/
18285 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
18286 break;
18287 case NM_SWC1X:
18288 /*case NM_SWC1XS:*/
18289 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
18290 break;
18291 case NM_SDC1X:
18292 /*case NM_SDC1XS:*/
18293 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
18294 break;
18296 } else {
18297 generate_exception_err(ctx, EXCP_CpU, 1);
18299 break;
18300 default:
18301 generate_exception_end(ctx, EXCP_RI);
18302 break;
18305 tcg_temp_free(t0);
18306 tcg_temp_free(t1);
18309 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
18311 int rt, rs, rd;
18313 rt = extract32(ctx->opcode, 21, 5);
18314 rs = extract32(ctx->opcode, 16, 5);
18315 rd = extract32(ctx->opcode, 11, 5);
18317 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
18318 generate_exception_end(ctx, EXCP_RI);
18319 return;
18321 check_cp1_enabled(ctx);
18322 switch (extract32(ctx->opcode, 0, 3)) {
18323 case NM_POOL32F_0:
18324 switch (extract32(ctx->opcode, 3, 7)) {
18325 case NM_RINT_S:
18326 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
18327 break;
18328 case NM_RINT_D:
18329 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
18330 break;
18331 case NM_CLASS_S:
18332 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
18333 break;
18334 case NM_CLASS_D:
18335 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
18336 break;
18337 case NM_ADD_S:
18338 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
18339 break;
18340 case NM_ADD_D:
18341 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
18342 break;
18343 case NM_SUB_S:
18344 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
18345 break;
18346 case NM_SUB_D:
18347 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
18348 break;
18349 case NM_MUL_S:
18350 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
18351 break;
18352 case NM_MUL_D:
18353 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
18354 break;
18355 case NM_DIV_S:
18356 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
18357 break;
18358 case NM_DIV_D:
18359 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
18360 break;
18361 case NM_SELEQZ_S:
18362 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
18363 break;
18364 case NM_SELEQZ_D:
18365 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
18366 break;
18367 case NM_SELNEZ_S:
18368 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
18369 break;
18370 case NM_SELNEZ_D:
18371 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
18372 break;
18373 case NM_SEL_S:
18374 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
18375 break;
18376 case NM_SEL_D:
18377 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
18378 break;
18379 case NM_MADDF_S:
18380 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
18381 break;
18382 case NM_MADDF_D:
18383 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
18384 break;
18385 case NM_MSUBF_S:
18386 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
18387 break;
18388 case NM_MSUBF_D:
18389 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
18390 break;
18391 default:
18392 generate_exception_end(ctx, EXCP_RI);
18393 break;
18395 break;
18396 case NM_POOL32F_3:
18397 switch (extract32(ctx->opcode, 3, 3)) {
18398 case NM_MIN_FMT:
18399 switch (extract32(ctx->opcode, 9, 1)) {
18400 case FMT_SDPS_S:
18401 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
18402 break;
18403 case FMT_SDPS_D:
18404 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
18405 break;
18407 break;
18408 case NM_MAX_FMT:
18409 switch (extract32(ctx->opcode, 9, 1)) {
18410 case FMT_SDPS_S:
18411 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
18412 break;
18413 case FMT_SDPS_D:
18414 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
18415 break;
18417 break;
18418 case NM_MINA_FMT:
18419 switch (extract32(ctx->opcode, 9, 1)) {
18420 case FMT_SDPS_S:
18421 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
18422 break;
18423 case FMT_SDPS_D:
18424 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
18425 break;
18427 break;
18428 case NM_MAXA_FMT:
18429 switch (extract32(ctx->opcode, 9, 1)) {
18430 case FMT_SDPS_S:
18431 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
18432 break;
18433 case FMT_SDPS_D:
18434 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
18435 break;
18437 break;
18438 case NM_POOL32FXF:
18439 switch (extract32(ctx->opcode, 6, 8)) {
18440 case NM_CFC1:
18441 gen_cp1(ctx, OPC_CFC1, rt, rs);
18442 break;
18443 case NM_CTC1:
18444 gen_cp1(ctx, OPC_CTC1, rt, rs);
18445 break;
18446 case NM_MFC1:
18447 gen_cp1(ctx, OPC_MFC1, rt, rs);
18448 break;
18449 case NM_MTC1:
18450 gen_cp1(ctx, OPC_MTC1, rt, rs);
18451 break;
18452 case NM_MFHC1:
18453 gen_cp1(ctx, OPC_MFHC1, rt, rs);
18454 break;
18455 case NM_MTHC1:
18456 gen_cp1(ctx, OPC_MTHC1, rt, rs);
18457 break;
18458 case NM_CVT_S_PL:
18459 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
18460 break;
18461 case NM_CVT_S_PU:
18462 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
18463 break;
18464 default:
18465 switch (extract32(ctx->opcode, 6, 9)) {
18466 case NM_CVT_L_S:
18467 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
18468 break;
18469 case NM_CVT_L_D:
18470 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
18471 break;
18472 case NM_CVT_W_S:
18473 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
18474 break;
18475 case NM_CVT_W_D:
18476 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
18477 break;
18478 case NM_RSQRT_S:
18479 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
18480 break;
18481 case NM_RSQRT_D:
18482 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
18483 break;
18484 case NM_SQRT_S:
18485 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
18486 break;
18487 case NM_SQRT_D:
18488 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
18489 break;
18490 case NM_RECIP_S:
18491 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
18492 break;
18493 case NM_RECIP_D:
18494 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
18495 break;
18496 case NM_FLOOR_L_S:
18497 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
18498 break;
18499 case NM_FLOOR_L_D:
18500 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
18501 break;
18502 case NM_FLOOR_W_S:
18503 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
18504 break;
18505 case NM_FLOOR_W_D:
18506 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
18507 break;
18508 case NM_CEIL_L_S:
18509 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
18510 break;
18511 case NM_CEIL_L_D:
18512 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
18513 break;
18514 case NM_CEIL_W_S:
18515 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
18516 break;
18517 case NM_CEIL_W_D:
18518 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
18519 break;
18520 case NM_TRUNC_L_S:
18521 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
18522 break;
18523 case NM_TRUNC_L_D:
18524 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
18525 break;
18526 case NM_TRUNC_W_S:
18527 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
18528 break;
18529 case NM_TRUNC_W_D:
18530 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
18531 break;
18532 case NM_ROUND_L_S:
18533 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
18534 break;
18535 case NM_ROUND_L_D:
18536 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
18537 break;
18538 case NM_ROUND_W_S:
18539 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
18540 break;
18541 case NM_ROUND_W_D:
18542 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
18543 break;
18544 case NM_MOV_S:
18545 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
18546 break;
18547 case NM_MOV_D:
18548 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
18549 break;
18550 case NM_ABS_S:
18551 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
18552 break;
18553 case NM_ABS_D:
18554 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
18555 break;
18556 case NM_NEG_S:
18557 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
18558 break;
18559 case NM_NEG_D:
18560 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
18561 break;
18562 case NM_CVT_D_S:
18563 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
18564 break;
18565 case NM_CVT_D_W:
18566 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
18567 break;
18568 case NM_CVT_D_L:
18569 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
18570 break;
18571 case NM_CVT_S_D:
18572 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
18573 break;
18574 case NM_CVT_S_W:
18575 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
18576 break;
18577 case NM_CVT_S_L:
18578 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
18579 break;
18580 default:
18581 generate_exception_end(ctx, EXCP_RI);
18582 break;
18584 break;
18586 break;
18588 break;
18589 case NM_POOL32F_5:
18590 switch (extract32(ctx->opcode, 3, 3)) {
18591 case NM_CMP_CONDN_S:
18592 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
18593 break;
18594 case NM_CMP_CONDN_D:
18595 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
18596 break;
18597 default:
18598 generate_exception_end(ctx, EXCP_RI);
18599 break;
18601 break;
18602 default:
18603 generate_exception_end(ctx, EXCP_RI);
18604 break;
18608 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
18609 int rd, int rs, int rt)
18611 int ret = rd;
18612 TCGv t0 = tcg_temp_new();
18613 TCGv v1_t = tcg_temp_new();
18614 TCGv v2_t = tcg_temp_new();
18616 gen_load_gpr(v1_t, rs);
18617 gen_load_gpr(v2_t, rt);
18619 switch (opc) {
18620 case NM_CMP_EQ_PH:
18621 check_dsp(ctx);
18622 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
18623 break;
18624 case NM_CMP_LT_PH:
18625 check_dsp(ctx);
18626 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
18627 break;
18628 case NM_CMP_LE_PH:
18629 check_dsp(ctx);
18630 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
18631 break;
18632 case NM_CMPU_EQ_QB:
18633 check_dsp(ctx);
18634 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
18635 break;
18636 case NM_CMPU_LT_QB:
18637 check_dsp(ctx);
18638 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
18639 break;
18640 case NM_CMPU_LE_QB:
18641 check_dsp(ctx);
18642 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
18643 break;
18644 case NM_CMPGU_EQ_QB:
18645 check_dsp(ctx);
18646 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
18647 gen_store_gpr(v1_t, ret);
18648 break;
18649 case NM_CMPGU_LT_QB:
18650 check_dsp(ctx);
18651 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
18652 gen_store_gpr(v1_t, ret);
18653 break;
18654 case NM_CMPGU_LE_QB:
18655 check_dsp(ctx);
18656 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
18657 gen_store_gpr(v1_t, ret);
18658 break;
18659 case NM_CMPGDU_EQ_QB:
18660 check_dspr2(ctx);
18661 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
18662 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
18663 gen_store_gpr(v1_t, ret);
18664 break;
18665 case NM_CMPGDU_LT_QB:
18666 check_dspr2(ctx);
18667 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
18668 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
18669 gen_store_gpr(v1_t, ret);
18670 break;
18671 case NM_CMPGDU_LE_QB:
18672 check_dspr2(ctx);
18673 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
18674 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
18675 gen_store_gpr(v1_t, ret);
18676 break;
18677 case NM_PACKRL_PH:
18678 check_dsp(ctx);
18679 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
18680 gen_store_gpr(v1_t, ret);
18681 break;
18682 case NM_PICK_QB:
18683 check_dsp(ctx);
18684 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
18685 gen_store_gpr(v1_t, ret);
18686 break;
18687 case NM_PICK_PH:
18688 check_dsp(ctx);
18689 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
18690 gen_store_gpr(v1_t, ret);
18691 break;
18692 case NM_ADDQ_S_W:
18693 check_dsp(ctx);
18694 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
18695 gen_store_gpr(v1_t, ret);
18696 break;
18697 case NM_SUBQ_S_W:
18698 check_dsp(ctx);
18699 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
18700 gen_store_gpr(v1_t, ret);
18701 break;
18702 case NM_ADDSC:
18703 check_dsp(ctx);
18704 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
18705 gen_store_gpr(v1_t, ret);
18706 break;
18707 case NM_ADDWC:
18708 check_dsp(ctx);
18709 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
18710 gen_store_gpr(v1_t, ret);
18711 break;
18712 case NM_ADDQ_S_PH:
18713 check_dsp(ctx);
18714 switch (extract32(ctx->opcode, 10, 1)) {
18715 case 0:
18716 /* ADDQ_PH */
18717 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
18718 gen_store_gpr(v1_t, ret);
18719 break;
18720 case 1:
18721 /* ADDQ_S_PH */
18722 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
18723 gen_store_gpr(v1_t, ret);
18724 break;
18726 break;
18727 case NM_ADDQH_R_PH:
18728 check_dspr2(ctx);
18729 switch (extract32(ctx->opcode, 10, 1)) {
18730 case 0:
18731 /* ADDQH_PH */
18732 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
18733 gen_store_gpr(v1_t, ret);
18734 break;
18735 case 1:
18736 /* ADDQH_R_PH */
18737 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
18738 gen_store_gpr(v1_t, ret);
18739 break;
18741 break;
18742 case NM_ADDQH_R_W:
18743 check_dspr2(ctx);
18744 switch (extract32(ctx->opcode, 10, 1)) {
18745 case 0:
18746 /* ADDQH_W */
18747 gen_helper_addqh_w(v1_t, v1_t, v2_t);
18748 gen_store_gpr(v1_t, ret);
18749 break;
18750 case 1:
18751 /* ADDQH_R_W */
18752 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
18753 gen_store_gpr(v1_t, ret);
18754 break;
18756 break;
18757 case NM_ADDU_S_QB:
18758 check_dsp(ctx);
18759 switch (extract32(ctx->opcode, 10, 1)) {
18760 case 0:
18761 /* ADDU_QB */
18762 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
18763 gen_store_gpr(v1_t, ret);
18764 break;
18765 case 1:
18766 /* ADDU_S_QB */
18767 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
18768 gen_store_gpr(v1_t, ret);
18769 break;
18771 break;
18772 case NM_ADDU_S_PH:
18773 check_dspr2(ctx);
18774 switch (extract32(ctx->opcode, 10, 1)) {
18775 case 0:
18776 /* ADDU_PH */
18777 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
18778 gen_store_gpr(v1_t, ret);
18779 break;
18780 case 1:
18781 /* ADDU_S_PH */
18782 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
18783 gen_store_gpr(v1_t, ret);
18784 break;
18786 break;
18787 case NM_ADDUH_R_QB:
18788 check_dspr2(ctx);
18789 switch (extract32(ctx->opcode, 10, 1)) {
18790 case 0:
18791 /* ADDUH_QB */
18792 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
18793 gen_store_gpr(v1_t, ret);
18794 break;
18795 case 1:
18796 /* ADDUH_R_QB */
18797 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
18798 gen_store_gpr(v1_t, ret);
18799 break;
18801 break;
18802 case NM_SHRAV_R_PH:
18803 check_dsp(ctx);
18804 switch (extract32(ctx->opcode, 10, 1)) {
18805 case 0:
18806 /* SHRAV_PH */
18807 gen_helper_shra_ph(v1_t, v1_t, v2_t);
18808 gen_store_gpr(v1_t, ret);
18809 break;
18810 case 1:
18811 /* SHRAV_R_PH */
18812 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
18813 gen_store_gpr(v1_t, ret);
18814 break;
18816 break;
18817 case NM_SHRAV_R_QB:
18818 check_dspr2(ctx);
18819 switch (extract32(ctx->opcode, 10, 1)) {
18820 case 0:
18821 /* SHRAV_QB */
18822 gen_helper_shra_qb(v1_t, v1_t, v2_t);
18823 gen_store_gpr(v1_t, ret);
18824 break;
18825 case 1:
18826 /* SHRAV_R_QB */
18827 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
18828 gen_store_gpr(v1_t, ret);
18829 break;
18831 break;
18832 case NM_SUBQ_S_PH:
18833 check_dsp(ctx);
18834 switch (extract32(ctx->opcode, 10, 1)) {
18835 case 0:
18836 /* SUBQ_PH */
18837 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
18838 gen_store_gpr(v1_t, ret);
18839 break;
18840 case 1:
18841 /* SUBQ_S_PH */
18842 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
18843 gen_store_gpr(v1_t, ret);
18844 break;
18846 break;
18847 case NM_SUBQH_R_PH:
18848 check_dspr2(ctx);
18849 switch (extract32(ctx->opcode, 10, 1)) {
18850 case 0:
18851 /* SUBQH_PH */
18852 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
18853 gen_store_gpr(v1_t, ret);
18854 break;
18855 case 1:
18856 /* SUBQH_R_PH */
18857 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
18858 gen_store_gpr(v1_t, ret);
18859 break;
18861 break;
18862 case NM_SUBQH_R_W:
18863 check_dspr2(ctx);
18864 switch (extract32(ctx->opcode, 10, 1)) {
18865 case 0:
18866 /* SUBQH_W */
18867 gen_helper_subqh_w(v1_t, v1_t, v2_t);
18868 gen_store_gpr(v1_t, ret);
18869 break;
18870 case 1:
18871 /* SUBQH_R_W */
18872 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
18873 gen_store_gpr(v1_t, ret);
18874 break;
18876 break;
18877 case NM_SUBU_S_QB:
18878 check_dsp(ctx);
18879 switch (extract32(ctx->opcode, 10, 1)) {
18880 case 0:
18881 /* SUBU_QB */
18882 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
18883 gen_store_gpr(v1_t, ret);
18884 break;
18885 case 1:
18886 /* SUBU_S_QB */
18887 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
18888 gen_store_gpr(v1_t, ret);
18889 break;
18891 break;
18892 case NM_SUBU_S_PH:
18893 check_dspr2(ctx);
18894 switch (extract32(ctx->opcode, 10, 1)) {
18895 case 0:
18896 /* SUBU_PH */
18897 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
18898 gen_store_gpr(v1_t, ret);
18899 break;
18900 case 1:
18901 /* SUBU_S_PH */
18902 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
18903 gen_store_gpr(v1_t, ret);
18904 break;
18906 break;
18907 case NM_SUBUH_R_QB:
18908 check_dspr2(ctx);
18909 switch (extract32(ctx->opcode, 10, 1)) {
18910 case 0:
18911 /* SUBUH_QB */
18912 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
18913 gen_store_gpr(v1_t, ret);
18914 break;
18915 case 1:
18916 /* SUBUH_R_QB */
18917 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
18918 gen_store_gpr(v1_t, ret);
18919 break;
18921 break;
18922 case NM_SHLLV_S_PH:
18923 check_dsp(ctx);
18924 switch (extract32(ctx->opcode, 10, 1)) {
18925 case 0:
18926 /* SHLLV_PH */
18927 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
18928 gen_store_gpr(v1_t, ret);
18929 break;
18930 case 1:
18931 /* SHLLV_S_PH */
18932 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
18933 gen_store_gpr(v1_t, ret);
18934 break;
18936 break;
18937 case NM_PRECR_SRA_R_PH_W:
18938 check_dspr2(ctx);
18939 switch (extract32(ctx->opcode, 10, 1)) {
18940 case 0:
18941 /* PRECR_SRA_PH_W */
18943 TCGv_i32 sa_t = tcg_const_i32(rd);
18944 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
18945 cpu_gpr[rt]);
18946 gen_store_gpr(v1_t, rt);
18947 tcg_temp_free_i32(sa_t);
18949 break;
18950 case 1:
18951 /* PRECR_SRA_R_PH_W */
18953 TCGv_i32 sa_t = tcg_const_i32(rd);
18954 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
18955 cpu_gpr[rt]);
18956 gen_store_gpr(v1_t, rt);
18957 tcg_temp_free_i32(sa_t);
18959 break;
18961 break;
18962 case NM_MULEU_S_PH_QBL:
18963 check_dsp(ctx);
18964 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
18965 gen_store_gpr(v1_t, ret);
18966 break;
18967 case NM_MULEU_S_PH_QBR:
18968 check_dsp(ctx);
18969 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
18970 gen_store_gpr(v1_t, ret);
18971 break;
18972 case NM_MULQ_RS_PH:
18973 check_dsp(ctx);
18974 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
18975 gen_store_gpr(v1_t, ret);
18976 break;
18977 case NM_MULQ_S_PH:
18978 check_dspr2(ctx);
18979 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
18980 gen_store_gpr(v1_t, ret);
18981 break;
18982 case NM_MULQ_RS_W:
18983 check_dspr2(ctx);
18984 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
18985 gen_store_gpr(v1_t, ret);
18986 break;
18987 case NM_MULQ_S_W:
18988 check_dspr2(ctx);
18989 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
18990 gen_store_gpr(v1_t, ret);
18991 break;
18992 case NM_APPEND:
18993 check_dspr2(ctx);
18994 gen_load_gpr(t0, rs);
18995 if (rd != 0) {
18996 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
18998 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
18999 break;
19000 case NM_MODSUB:
19001 check_dsp(ctx);
19002 gen_helper_modsub(v1_t, v1_t, v2_t);
19003 gen_store_gpr(v1_t, ret);
19004 break;
19005 case NM_SHRAV_R_W:
19006 check_dsp(ctx);
19007 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
19008 gen_store_gpr(v1_t, ret);
19009 break;
19010 case NM_SHRLV_PH:
19011 check_dspr2(ctx);
19012 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
19013 gen_store_gpr(v1_t, ret);
19014 break;
19015 case NM_SHRLV_QB:
19016 check_dsp(ctx);
19017 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
19018 gen_store_gpr(v1_t, ret);
19019 break;
19020 case NM_SHLLV_QB:
19021 check_dsp(ctx);
19022 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
19023 gen_store_gpr(v1_t, ret);
19024 break;
19025 case NM_SHLLV_S_W:
19026 check_dsp(ctx);
19027 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
19028 gen_store_gpr(v1_t, ret);
19029 break;
19030 case NM_SHILO:
19031 check_dsp(ctx);
19033 TCGv tv0 = tcg_temp_new();
19034 TCGv tv1 = tcg_temp_new();
19035 int16_t imm = extract32(ctx->opcode, 16, 7);
19037 tcg_gen_movi_tl(tv0, rd >> 3);
19038 tcg_gen_movi_tl(tv1, imm);
19039 gen_helper_shilo(tv0, tv1, cpu_env);
19041 break;
19042 case NM_MULEQ_S_W_PHL:
19043 check_dsp(ctx);
19044 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
19045 gen_store_gpr(v1_t, ret);
19046 break;
19047 case NM_MULEQ_S_W_PHR:
19048 check_dsp(ctx);
19049 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
19050 gen_store_gpr(v1_t, ret);
19051 break;
19052 case NM_MUL_S_PH:
19053 check_dspr2(ctx);
19054 switch (extract32(ctx->opcode, 10, 1)) {
19055 case 0:
19056 /* MUL_PH */
19057 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
19058 gen_store_gpr(v1_t, ret);
19059 break;
19060 case 1:
19061 /* MUL_S_PH */
19062 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
19063 gen_store_gpr(v1_t, ret);
19064 break;
19066 break;
19067 case NM_PRECR_QB_PH:
19068 check_dspr2(ctx);
19069 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
19070 gen_store_gpr(v1_t, ret);
19071 break;
19072 case NM_PRECRQ_QB_PH:
19073 check_dsp(ctx);
19074 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
19075 gen_store_gpr(v1_t, ret);
19076 break;
19077 case NM_PRECRQ_PH_W:
19078 check_dsp(ctx);
19079 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
19080 gen_store_gpr(v1_t, ret);
19081 break;
19082 case NM_PRECRQ_RS_PH_W:
19083 check_dsp(ctx);
19084 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
19085 gen_store_gpr(v1_t, ret);
19086 break;
19087 case NM_PRECRQU_S_QB_PH:
19088 check_dsp(ctx);
19089 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
19090 gen_store_gpr(v1_t, ret);
19091 break;
19092 case NM_SHRA_R_W:
19093 check_dsp(ctx);
19094 tcg_gen_movi_tl(t0, rd);
19095 gen_helper_shra_r_w(v1_t, t0, v1_t);
19096 gen_store_gpr(v1_t, rt);
19097 break;
19098 case NM_SHRA_R_PH:
19099 check_dsp(ctx);
19100 tcg_gen_movi_tl(t0, rd >> 1);
19101 switch (extract32(ctx->opcode, 10, 1)) {
19102 case 0:
19103 /* SHRA_PH */
19104 gen_helper_shra_ph(v1_t, t0, v1_t);
19105 break;
19106 gen_store_gpr(v1_t, rt);
19107 case 1:
19108 /* SHRA_R_PH */
19109 gen_helper_shra_r_ph(v1_t, t0, v1_t);
19110 gen_store_gpr(v1_t, rt);
19111 break;
19113 break;
19114 case NM_SHLL_S_PH:
19115 check_dsp(ctx);
19116 tcg_gen_movi_tl(t0, rd >> 1);
19117 switch (extract32(ctx->opcode, 10, 2)) {
19118 case 0:
19119 /* SHLL_PH */
19120 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
19121 gen_store_gpr(v1_t, rt);
19122 break;
19123 case 2:
19124 /* SHLL_S_PH */
19125 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
19126 gen_store_gpr(v1_t, rt);
19127 break;
19128 default:
19129 generate_exception_end(ctx, EXCP_RI);
19130 break;
19132 break;
19133 case NM_SHLL_S_W:
19134 check_dsp(ctx);
19135 tcg_gen_movi_tl(t0, rd);
19136 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
19137 gen_store_gpr(v1_t, rt);
19138 break;
19139 case NM_REPL_PH:
19140 check_dsp(ctx);
19142 int16_t imm;
19143 imm = sextract32(ctx->opcode, 11, 11);
19144 imm = (int16_t)(imm << 6) >> 6;
19145 if (rt != 0) {
19146 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
19149 break;
19150 default:
19151 generate_exception_end(ctx, EXCP_RI);
19152 break;
19156 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
19158 uint16_t insn;
19159 uint32_t op;
19160 int rt, rs, rd;
19161 int offset;
19162 int imm;
19164 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
19165 ctx->opcode = (ctx->opcode << 16) | insn;
19167 rt = extract32(ctx->opcode, 21, 5);
19168 rs = extract32(ctx->opcode, 16, 5);
19169 rd = extract32(ctx->opcode, 11, 5);
19171 op = extract32(ctx->opcode, 26, 6);
19172 switch (op) {
19173 case NM_P_ADDIU:
19174 if (rt == 0) {
19175 /* P.RI */
19176 switch (extract32(ctx->opcode, 19, 2)) {
19177 case NM_SIGRIE:
19178 default:
19179 generate_exception_end(ctx, EXCP_RI);
19180 break;
19181 case NM_P_SYSCALL:
19182 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
19183 generate_exception_end(ctx, EXCP_SYSCALL);
19184 } else {
19185 generate_exception_end(ctx, EXCP_RI);
19187 break;
19188 case NM_BREAK:
19189 generate_exception_end(ctx, EXCP_BREAK);
19190 break;
19191 case NM_SDBBP:
19192 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
19193 gen_helper_do_semihosting(cpu_env);
19194 } else {
19195 if (ctx->hflags & MIPS_HFLAG_SBRI) {
19196 generate_exception_end(ctx, EXCP_RI);
19197 } else {
19198 generate_exception_end(ctx, EXCP_DBp);
19201 break;
19203 } else {
19204 /* NM_ADDIU */
19205 imm = extract32(ctx->opcode, 0, 16);
19206 if (rs != 0) {
19207 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
19208 } else {
19209 tcg_gen_movi_tl(cpu_gpr[rt], imm);
19211 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19213 break;
19214 case NM_ADDIUPC:
19215 if (rt != 0) {
19216 offset = sextract32(ctx->opcode, 0, 1) << 21 |
19217 extract32(ctx->opcode, 1, 20) << 1;
19218 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
19219 tcg_gen_movi_tl(cpu_gpr[rt], addr);
19221 break;
19222 case NM_POOL32A:
19223 switch (ctx->opcode & 0x07) {
19224 case NM_POOL32A0:
19225 gen_pool32a0_nanomips_insn(env, ctx);
19226 break;
19227 case NM_POOL32A5:
19229 int32_t op1 = extract32(ctx->opcode, 3, 7);
19230 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
19232 break;
19233 case NM_POOL32A7:
19234 switch (extract32(ctx->opcode, 3, 3)) {
19235 case NM_P_LSX:
19236 gen_p_lsx(ctx, rd, rs, rt);
19237 break;
19238 case NM_LSA:
19239 /* In nanoMIPS, the shift field directly encodes the shift
19240 * amount, meaning that the supported shift values are in
19241 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
19242 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
19243 extract32(ctx->opcode, 9, 2) - 1);
19244 break;
19245 case NM_EXTW:
19246 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
19247 break;
19248 case NM_POOL32AXF:
19249 gen_pool32axf_nanomips_insn(env, ctx);
19250 break;
19251 default:
19252 generate_exception_end(ctx, EXCP_RI);
19253 break;
19255 break;
19256 default:
19257 generate_exception_end(ctx, EXCP_RI);
19258 break;
19260 break;
19261 case NM_P_GP_W:
19262 switch (ctx->opcode & 0x03) {
19263 case NM_ADDIUGP_W:
19264 if (rt != 0) {
19265 offset = extract32(ctx->opcode, 0, 21);
19266 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
19268 break;
19269 case NM_LWGP:
19270 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
19271 break;
19272 case NM_SWGP:
19273 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
19274 break;
19275 default:
19276 generate_exception_end(ctx, EXCP_RI);
19277 break;
19279 break;
19280 case NM_P48I:
19282 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
19283 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
19284 switch (extract32(ctx->opcode, 16, 5)) {
19285 case NM_LI48:
19286 if (rt != 0) {
19287 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
19289 break;
19290 case NM_ADDIU48:
19291 if (rt != 0) {
19292 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
19293 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19295 break;
19296 case NM_ADDIUGP48:
19297 if (rt != 0) {
19298 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
19300 break;
19301 case NM_ADDIUPC48:
19302 if (rt != 0) {
19303 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19304 addr_off);
19306 tcg_gen_movi_tl(cpu_gpr[rt], addr);
19308 break;
19309 case NM_LWPC48:
19310 if (rt != 0) {
19311 TCGv t0;
19312 t0 = tcg_temp_new();
19314 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19315 addr_off);
19317 tcg_gen_movi_tl(t0, addr);
19318 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
19319 tcg_temp_free(t0);
19321 break;
19322 case NM_SWPC48:
19324 TCGv t0, t1;
19325 t0 = tcg_temp_new();
19326 t1 = tcg_temp_new();
19328 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19329 addr_off);
19331 tcg_gen_movi_tl(t0, addr);
19332 gen_load_gpr(t1, rt);
19334 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
19336 tcg_temp_free(t0);
19337 tcg_temp_free(t1);
19339 break;
19340 default:
19341 generate_exception_end(ctx, EXCP_RI);
19342 break;
19344 return 6;
19346 case NM_P_U12:
19347 switch (extract32(ctx->opcode, 12, 4)) {
19348 case NM_ORI:
19349 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
19350 break;
19351 case NM_XORI:
19352 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
19353 break;
19354 case NM_ANDI:
19355 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
19356 break;
19357 case NM_P_SR:
19358 switch (extract32(ctx->opcode, 20, 1)) {
19359 case NM_PP_SR:
19360 switch (ctx->opcode & 3) {
19361 case NM_SAVE:
19362 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
19363 extract32(ctx->opcode, 2, 1),
19364 extract32(ctx->opcode, 3, 9) << 3);
19365 break;
19366 case NM_RESTORE:
19367 case NM_RESTORE_JRC:
19368 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
19369 extract32(ctx->opcode, 2, 1),
19370 extract32(ctx->opcode, 3, 9) << 3);
19371 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
19372 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
19374 break;
19375 default:
19376 generate_exception_end(ctx, EXCP_RI);
19377 break;
19379 break;
19380 case NM_P_SR_F:
19381 generate_exception_end(ctx, EXCP_RI);
19382 break;
19384 break;
19385 case NM_SLTI:
19386 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
19387 break;
19388 case NM_SLTIU:
19389 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
19390 break;
19391 case NM_SEQI:
19393 TCGv t0 = tcg_temp_new();
19395 imm = extract32(ctx->opcode, 0, 12);
19396 gen_load_gpr(t0, rs);
19397 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
19398 gen_store_gpr(t0, rt);
19400 tcg_temp_free(t0);
19402 break;
19403 case NM_ADDIUNEG:
19404 imm = (int16_t) extract32(ctx->opcode, 0, 12);
19405 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
19406 break;
19407 case NM_P_SHIFT:
19409 int shift = extract32(ctx->opcode, 0, 5);
19410 switch (extract32(ctx->opcode, 5, 4)) {
19411 case NM_P_SLL:
19412 if (rt == 0 && shift == 0) {
19413 /* NOP */
19414 } else if (rt == 0 && shift == 3) {
19415 /* EHB - treat as NOP */
19416 } else if (rt == 0 && shift == 5) {
19417 /* PAUSE - treat as NOP */
19418 } else if (rt == 0 && shift == 6) {
19419 /* SYNC */
19420 gen_sync(extract32(ctx->opcode, 16, 5));
19421 } else {
19422 /* SLL */
19423 gen_shift_imm(ctx, OPC_SLL, rt, rs,
19424 extract32(ctx->opcode, 0, 5));
19426 break;
19427 case NM_SRL:
19428 gen_shift_imm(ctx, OPC_SRL, rt, rs,
19429 extract32(ctx->opcode, 0, 5));
19430 break;
19431 case NM_SRA:
19432 gen_shift_imm(ctx, OPC_SRA, rt, rs,
19433 extract32(ctx->opcode, 0, 5));
19434 break;
19435 case NM_ROTR:
19436 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
19437 extract32(ctx->opcode, 0, 5));
19438 break;
19441 break;
19442 case NM_P_ROTX:
19443 if (rt != 0) {
19444 TCGv t0 = tcg_temp_new();
19445 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
19446 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
19447 << 1);
19448 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
19450 gen_load_gpr(t0, rs);
19451 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
19452 tcg_temp_free(t0);
19454 tcg_temp_free_i32(shift);
19455 tcg_temp_free_i32(shiftx);
19456 tcg_temp_free_i32(stripe);
19458 break;
19459 case NM_P_INS:
19460 switch (((ctx->opcode >> 10) & 2) |
19461 (extract32(ctx->opcode, 5, 1))) {
19462 case NM_INS:
19463 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
19464 extract32(ctx->opcode, 6, 5));
19465 break;
19466 default:
19467 generate_exception_end(ctx, EXCP_RI);
19468 break;
19470 break;
19471 case NM_P_EXT:
19472 switch (((ctx->opcode >> 10) & 2) |
19473 (extract32(ctx->opcode, 5, 1))) {
19474 case NM_EXT:
19475 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
19476 extract32(ctx->opcode, 6, 5));
19477 break;
19478 default:
19479 generate_exception_end(ctx, EXCP_RI);
19480 break;
19482 break;
19483 default:
19484 generate_exception_end(ctx, EXCP_RI);
19485 break;
19487 break;
19488 case NM_POOL32F:
19489 gen_pool32f_nanomips_insn(ctx);
19490 break;
19491 case NM_POOL32S:
19492 break;
19493 case NM_P_LUI:
19494 switch (extract32(ctx->opcode, 1, 1)) {
19495 case NM_LUI:
19496 if (rt != 0) {
19497 tcg_gen_movi_tl(cpu_gpr[rt],
19498 sextract32(ctx->opcode, 0, 1) << 31 |
19499 extract32(ctx->opcode, 2, 10) << 21 |
19500 extract32(ctx->opcode, 12, 9) << 12);
19502 break;
19503 case NM_ALUIPC:
19504 if (rt != 0) {
19505 offset = sextract32(ctx->opcode, 0, 1) << 31 |
19506 extract32(ctx->opcode, 2, 10) << 21 |
19507 extract32(ctx->opcode, 12, 9) << 12;
19508 target_long addr;
19509 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
19510 tcg_gen_movi_tl(cpu_gpr[rt], addr);
19512 break;
19514 break;
19515 case NM_P_GP_BH:
19517 uint32_t u = extract32(ctx->opcode, 0, 18);
19519 switch (extract32(ctx->opcode, 18, 3)) {
19520 case NM_LBGP:
19521 gen_ld(ctx, OPC_LB, rt, 28, u);
19522 break;
19523 case NM_SBGP:
19524 gen_st(ctx, OPC_SB, rt, 28, u);
19525 break;
19526 case NM_LBUGP:
19527 gen_ld(ctx, OPC_LBU, rt, 28, u);
19528 break;
19529 case NM_ADDIUGP_B:
19530 if (rt != 0) {
19531 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
19533 break;
19534 case NM_P_GP_LH:
19535 u &= ~1;
19536 switch (ctx->opcode & 1) {
19537 case NM_LHGP:
19538 gen_ld(ctx, OPC_LH, rt, 28, u);
19539 break;
19540 case NM_LHUGP:
19541 gen_ld(ctx, OPC_LHU, rt, 28, u);
19542 break;
19544 break;
19545 case NM_P_GP_SH:
19546 u &= ~1;
19547 switch (ctx->opcode & 1) {
19548 case NM_SHGP:
19549 gen_st(ctx, OPC_SH, rt, 28, u);
19550 break;
19551 default:
19552 generate_exception_end(ctx, EXCP_RI);
19553 break;
19555 break;
19556 case NM_P_GP_CP1:
19557 u &= ~0x3;
19558 switch (ctx->opcode & 0x3) {
19559 case NM_LWC1GP:
19560 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
19561 break;
19562 case NM_LDC1GP:
19563 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
19564 break;
19565 case NM_SWC1GP:
19566 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
19567 break;
19568 case NM_SDC1GP:
19569 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
19570 break;
19572 break;
19573 default:
19574 generate_exception_end(ctx, EXCP_RI);
19575 break;
19578 break;
19579 case NM_P_LS_U12:
19581 uint32_t u = extract32(ctx->opcode, 0, 12);
19583 switch (extract32(ctx->opcode, 12, 4)) {
19584 case NM_P_PREFU12:
19585 if (rt == 31) {
19586 /* SYNCI */
19587 /* Break the TB to be able to sync copied instructions
19588 immediately */
19589 ctx->base.is_jmp = DISAS_STOP;
19590 } else {
19591 /* PREF */
19592 /* Treat as NOP. */
19594 break;
19595 case NM_LB:
19596 gen_ld(ctx, OPC_LB, rt, rs, u);
19597 break;
19598 case NM_LH:
19599 gen_ld(ctx, OPC_LH, rt, rs, u);
19600 break;
19601 case NM_LW:
19602 gen_ld(ctx, OPC_LW, rt, rs, u);
19603 break;
19604 case NM_LBU:
19605 gen_ld(ctx, OPC_LBU, rt, rs, u);
19606 break;
19607 case NM_LHU:
19608 gen_ld(ctx, OPC_LHU, rt, rs, u);
19609 break;
19610 case NM_SB:
19611 gen_st(ctx, OPC_SB, rt, rs, u);
19612 break;
19613 case NM_SH:
19614 gen_st(ctx, OPC_SH, rt, rs, u);
19615 break;
19616 case NM_SW:
19617 gen_st(ctx, OPC_SW, rt, rs, u);
19618 break;
19619 case NM_LWC1:
19620 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
19621 break;
19622 case NM_LDC1:
19623 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
19624 break;
19625 case NM_SWC1:
19626 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
19627 break;
19628 case NM_SDC1:
19629 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
19630 break;
19631 default:
19632 generate_exception_end(ctx, EXCP_RI);
19633 break;
19636 break;
19637 case NM_P_LS_S9:
19639 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
19640 extract32(ctx->opcode, 0, 8);
19642 switch (extract32(ctx->opcode, 8, 3)) {
19643 case NM_P_LS_S0:
19644 switch (extract32(ctx->opcode, 11, 4)) {
19645 case NM_LBS9:
19646 gen_ld(ctx, OPC_LB, rt, rs, s);
19647 break;
19648 case NM_LHS9:
19649 gen_ld(ctx, OPC_LH, rt, rs, s);
19650 break;
19651 case NM_LWS9:
19652 gen_ld(ctx, OPC_LW, rt, rs, s);
19653 break;
19654 case NM_LBUS9:
19655 gen_ld(ctx, OPC_LBU, rt, rs, s);
19656 break;
19657 case NM_LHUS9:
19658 gen_ld(ctx, OPC_LHU, rt, rs, s);
19659 break;
19660 case NM_SBS9:
19661 gen_st(ctx, OPC_SB, rt, rs, s);
19662 break;
19663 case NM_SHS9:
19664 gen_st(ctx, OPC_SH, rt, rs, s);
19665 break;
19666 case NM_SWS9:
19667 gen_st(ctx, OPC_SW, rt, rs, s);
19668 break;
19669 case NM_LWC1S9:
19670 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
19671 break;
19672 case NM_LDC1S9:
19673 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
19674 break;
19675 case NM_SWC1S9:
19676 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
19677 break;
19678 case NM_SDC1S9:
19679 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
19680 break;
19681 case NM_P_PREFS9:
19682 if (rt == 31) {
19683 /* SYNCI */
19684 /* Break the TB to be able to sync copied instructions
19685 immediately */
19686 ctx->base.is_jmp = DISAS_STOP;
19687 } else {
19688 /* PREF */
19689 /* Treat as NOP. */
19691 break;
19692 default:
19693 generate_exception_end(ctx, EXCP_RI);
19694 break;
19696 break;
19697 case NM_P_LS_S1:
19698 switch (extract32(ctx->opcode, 11, 4)) {
19699 case NM_UALH:
19700 case NM_UASH:
19702 TCGv t0 = tcg_temp_new();
19703 TCGv t1 = tcg_temp_new();
19705 gen_base_offset_addr(ctx, t0, rs, s);
19707 switch (extract32(ctx->opcode, 11, 4)) {
19708 case NM_UALH:
19709 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
19710 MO_UNALN);
19711 gen_store_gpr(t0, rt);
19712 break;
19713 case NM_UASH:
19714 gen_load_gpr(t1, rt);
19715 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
19716 MO_UNALN);
19717 break;
19719 tcg_temp_free(t0);
19720 tcg_temp_free(t1);
19722 break;
19723 case NM_P_LL:
19724 switch (ctx->opcode & 0x03) {
19725 case NM_LL:
19726 gen_ld(ctx, OPC_LL, rt, rs, s);
19727 break;
19728 case NM_LLWP:
19729 check_xnp(ctx);
19730 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
19731 break;
19733 break;
19734 case NM_P_SC:
19735 switch (ctx->opcode & 0x03) {
19736 case NM_SC:
19737 gen_st_cond(ctx, OPC_SC, rt, rs, s);
19738 break;
19739 case NM_SCWP:
19740 check_xnp(ctx);
19741 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
19742 break;
19744 break;
19745 case NM_CACHE:
19746 check_cp0_enabled(ctx);
19747 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
19748 gen_cache_operation(ctx, rt, rs, s);
19750 break;
19752 break;
19753 case NM_P_LS_WM:
19754 case NM_P_LS_UAWM:
19756 int count = extract32(ctx->opcode, 12, 3);
19757 int counter = 0;
19759 offset = sextract32(ctx->opcode, 15, 1) << 8 |
19760 extract32(ctx->opcode, 0, 8);
19761 TCGv va = tcg_temp_new();
19762 TCGv t1 = tcg_temp_new();
19763 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
19764 NM_P_LS_UAWM ? MO_UNALN : 0;
19766 count = (count == 0) ? 8 : count;
19767 while (counter != count) {
19768 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
19769 int this_offset = offset + (counter << 2);
19771 gen_base_offset_addr(ctx, va, rs, this_offset);
19773 switch (extract32(ctx->opcode, 11, 1)) {
19774 case NM_LWM:
19775 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
19776 memop | MO_TESL);
19777 gen_store_gpr(t1, this_rt);
19778 if ((this_rt == rs) &&
19779 (counter != (count - 1))) {
19780 /* UNPREDICTABLE */
19782 break;
19783 case NM_SWM:
19784 this_rt = (rt == 0) ? 0 : this_rt;
19785 gen_load_gpr(t1, this_rt);
19786 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
19787 memop | MO_TEUL);
19788 break;
19790 counter++;
19792 tcg_temp_free(va);
19793 tcg_temp_free(t1);
19795 break;
19796 default:
19797 generate_exception_end(ctx, EXCP_RI);
19798 break;
19801 break;
19802 case NM_MOVE_BALC:
19804 TCGv t0 = tcg_temp_new();
19805 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
19806 extract32(ctx->opcode, 1, 20) << 1;
19807 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
19808 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
19809 extract32(ctx->opcode, 21, 3));
19810 gen_load_gpr(t0, rt);
19811 tcg_gen_mov_tl(cpu_gpr[rd], t0);
19812 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
19813 tcg_temp_free(t0);
19815 break;
19816 case NM_P_BAL:
19818 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
19819 extract32(ctx->opcode, 1, 24) << 1;
19821 if ((extract32(ctx->opcode, 25, 1)) == 0) {
19822 /* BC */
19823 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
19824 } else {
19825 /* BALC */
19826 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
19829 break;
19830 case NM_P_J:
19831 switch (extract32(ctx->opcode, 12, 4)) {
19832 case NM_JALRC:
19833 case NM_JALRC_HB:
19834 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
19835 break;
19836 case NM_P_BALRSC:
19837 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
19838 break;
19839 default:
19840 generate_exception_end(ctx, EXCP_RI);
19841 break;
19843 break;
19844 case NM_P_BR1:
19846 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
19847 extract32(ctx->opcode, 1, 13) << 1;
19848 switch (extract32(ctx->opcode, 14, 2)) {
19849 case NM_BEQC:
19850 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
19851 break;
19852 case NM_P_BR3A:
19853 s = sextract32(ctx->opcode, 0, 1) << 14 |
19854 extract32(ctx->opcode, 1, 13) << 1;
19855 check_cp1_enabled(ctx);
19856 switch (extract32(ctx->opcode, 16, 5)) {
19857 case NM_BC1EQZC:
19858 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
19859 break;
19860 case NM_BC1NEZC:
19861 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
19862 break;
19863 case NM_BPOSGE32C:
19864 check_dspr2(ctx);
19866 int32_t imm = extract32(ctx->opcode, 1, 13) |
19867 extract32(ctx->opcode, 0, 1) << 13;
19869 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
19870 imm);
19872 break;
19873 default:
19874 generate_exception_end(ctx, EXCP_RI);
19875 break;
19877 break;
19878 case NM_BGEC:
19879 if (rs == rt) {
19880 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
19881 } else {
19882 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
19884 break;
19885 case NM_BGEUC:
19886 if (rs == rt || rt == 0) {
19887 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
19888 } else if (rs == 0) {
19889 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
19890 } else {
19891 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
19893 break;
19896 break;
19897 case NM_P_BR2:
19899 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
19900 extract32(ctx->opcode, 1, 13) << 1;
19901 switch (extract32(ctx->opcode, 14, 2)) {
19902 case NM_BNEC:
19903 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
19904 break;
19905 case NM_BLTC:
19906 if (rs != 0 && rt != 0 && rs == rt) {
19907 /* NOP */
19908 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
19909 } else {
19910 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
19912 break;
19913 case NM_BLTUC:
19914 if (rs == 0 || rs == rt) {
19915 /* NOP */
19916 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
19917 } else {
19918 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
19920 break;
19921 default:
19922 generate_exception_end(ctx, EXCP_RI);
19923 break;
19926 break;
19927 case NM_P_BRI:
19929 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
19930 extract32(ctx->opcode, 1, 10) << 1;
19931 uint32_t u = extract32(ctx->opcode, 11, 7);
19933 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
19934 rt, u, s);
19936 break;
19937 default:
19938 generate_exception_end(ctx, EXCP_RI);
19939 break;
19941 return 4;
19944 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
19946 uint32_t op;
19947 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
19948 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
19949 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
19950 int offset;
19951 int imm;
19953 /* make sure instructions are on a halfword boundary */
19954 if (ctx->base.pc_next & 0x1) {
19955 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
19956 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
19957 tcg_temp_free(tmp);
19958 generate_exception_end(ctx, EXCP_AdEL);
19959 return 2;
19962 op = extract32(ctx->opcode, 10, 6);
19963 switch (op) {
19964 case NM_P16_MV:
19965 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
19966 if (rt != 0) {
19967 /* MOVE */
19968 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
19969 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
19970 } else {
19971 /* P16.RI */
19972 switch (extract32(ctx->opcode, 3, 2)) {
19973 case NM_P16_SYSCALL:
19974 if (extract32(ctx->opcode, 2, 1) == 0) {
19975 generate_exception_end(ctx, EXCP_SYSCALL);
19976 } else {
19977 generate_exception_end(ctx, EXCP_RI);
19979 break;
19980 case NM_BREAK16:
19981 generate_exception_end(ctx, EXCP_BREAK);
19982 break;
19983 case NM_SDBBP16:
19984 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
19985 gen_helper_do_semihosting(cpu_env);
19986 } else {
19987 if (ctx->hflags & MIPS_HFLAG_SBRI) {
19988 generate_exception_end(ctx, EXCP_RI);
19989 } else {
19990 generate_exception_end(ctx, EXCP_DBp);
19993 break;
19994 default:
19995 generate_exception_end(ctx, EXCP_RI);
19996 break;
19999 break;
20000 case NM_P16_SHIFT:
20002 int shift = extract32(ctx->opcode, 0, 3);
20003 uint32_t opc = 0;
20004 shift = (shift == 0) ? 8 : shift;
20006 switch (extract32(ctx->opcode, 3, 1)) {
20007 case NM_SLL16:
20008 opc = OPC_SLL;
20009 break;
20010 case NM_SRL16:
20011 opc = OPC_SRL;
20012 break;
20014 gen_shift_imm(ctx, opc, rt, rs, shift);
20016 break;
20017 case NM_P16C:
20018 switch (ctx->opcode & 1) {
20019 case NM_POOL16C_0:
20020 gen_pool16c_nanomips_insn(ctx);
20021 break;
20022 case NM_LWXS16:
20023 gen_ldxs(ctx, rt, rs, rd);
20024 break;
20026 break;
20027 case NM_P16_A1:
20028 switch (extract32(ctx->opcode, 6, 1)) {
20029 case NM_ADDIUR1SP:
20030 imm = extract32(ctx->opcode, 0, 6) << 2;
20031 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
20032 break;
20033 default:
20034 generate_exception_end(ctx, EXCP_RI);
20035 break;
20037 break;
20038 case NM_P16_A2:
20039 switch (extract32(ctx->opcode, 3, 1)) {
20040 case NM_ADDIUR2:
20041 imm = extract32(ctx->opcode, 0, 3) << 2;
20042 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
20043 break;
20044 case NM_P_ADDIURS5:
20045 rt = extract32(ctx->opcode, 5, 5);
20046 if (rt != 0) {
20047 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
20048 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
20049 (extract32(ctx->opcode, 0, 3));
20050 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
20052 break;
20054 break;
20055 case NM_P16_ADDU:
20056 switch (ctx->opcode & 0x1) {
20057 case NM_ADDU16:
20058 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
20059 break;
20060 case NM_SUBU16:
20061 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
20062 break;
20064 break;
20065 case NM_P16_4X4:
20066 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20067 extract32(ctx->opcode, 5, 3);
20068 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20069 extract32(ctx->opcode, 0, 3);
20070 rt = decode_gpr_gpr4(rt);
20071 rs = decode_gpr_gpr4(rs);
20072 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
20073 (extract32(ctx->opcode, 3, 1))) {
20074 case NM_ADDU4X4:
20075 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
20076 break;
20077 case NM_MUL4X4:
20078 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
20079 break;
20080 default:
20081 generate_exception_end(ctx, EXCP_RI);
20082 break;
20084 break;
20085 case NM_LI16:
20087 int imm = extract32(ctx->opcode, 0, 7);
20088 imm = (imm == 0x7f ? -1 : imm);
20089 if (rt != 0) {
20090 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20093 break;
20094 case NM_ANDI16:
20096 uint32_t u = extract32(ctx->opcode, 0, 4);
20097 u = (u == 12) ? 0xff :
20098 (u == 13) ? 0xffff : u;
20099 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
20101 break;
20102 case NM_P16_LB:
20103 offset = extract32(ctx->opcode, 0, 2);
20104 switch (extract32(ctx->opcode, 2, 2)) {
20105 case NM_LB16:
20106 gen_ld(ctx, OPC_LB, rt, rs, offset);
20107 break;
20108 case NM_SB16:
20109 rt = decode_gpr_gpr3_src_store(
20110 NANOMIPS_EXTRACT_RD(ctx->opcode));
20111 gen_st(ctx, OPC_SB, rt, rs, offset);
20112 break;
20113 case NM_LBU16:
20114 gen_ld(ctx, OPC_LBU, rt, rs, offset);
20115 break;
20116 default:
20117 generate_exception_end(ctx, EXCP_RI);
20118 break;
20120 break;
20121 case NM_P16_LH:
20122 offset = extract32(ctx->opcode, 1, 2) << 1;
20123 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
20124 case NM_LH16:
20125 gen_ld(ctx, OPC_LH, rt, rs, offset);
20126 break;
20127 case NM_SH16:
20128 rt = decode_gpr_gpr3_src_store(
20129 NANOMIPS_EXTRACT_RD(ctx->opcode));
20130 gen_st(ctx, OPC_SH, rt, rs, offset);
20131 break;
20132 case NM_LHU16:
20133 gen_ld(ctx, OPC_LHU, rt, rs, offset);
20134 break;
20135 default:
20136 generate_exception_end(ctx, EXCP_RI);
20137 break;
20139 break;
20140 case NM_LW16:
20141 offset = extract32(ctx->opcode, 0, 4) << 2;
20142 gen_ld(ctx, OPC_LW, rt, rs, offset);
20143 break;
20144 case NM_LWSP16:
20145 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20146 offset = extract32(ctx->opcode, 0, 5) << 2;
20147 gen_ld(ctx, OPC_LW, rt, 29, offset);
20148 break;
20149 case NM_LW4X4:
20150 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20151 extract32(ctx->opcode, 5, 3);
20152 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20153 extract32(ctx->opcode, 0, 3);
20154 offset = (extract32(ctx->opcode, 3, 1) << 3) |
20155 (extract32(ctx->opcode, 8, 1) << 2);
20156 rt = decode_gpr_gpr4(rt);
20157 rs = decode_gpr_gpr4(rs);
20158 gen_ld(ctx, OPC_LW, rt, rs, offset);
20159 break;
20160 case NM_SW4X4:
20161 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20162 extract32(ctx->opcode, 5, 3);
20163 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20164 extract32(ctx->opcode, 0, 3);
20165 offset = (extract32(ctx->opcode, 3, 1) << 3) |
20166 (extract32(ctx->opcode, 8, 1) << 2);
20167 rt = decode_gpr_gpr4_zero(rt);
20168 rs = decode_gpr_gpr4(rs);
20169 gen_st(ctx, OPC_SW, rt, rs, offset);
20170 break;
20171 case NM_LWGP16:
20172 offset = extract32(ctx->opcode, 0, 7) << 2;
20173 gen_ld(ctx, OPC_LW, rt, 28, offset);
20174 break;
20175 case NM_SWSP16:
20176 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20177 offset = extract32(ctx->opcode, 0, 5) << 2;
20178 gen_st(ctx, OPC_SW, rt, 29, offset);
20179 break;
20180 case NM_SW16:
20181 rt = decode_gpr_gpr3_src_store(
20182 NANOMIPS_EXTRACT_RD(ctx->opcode));
20183 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
20184 offset = extract32(ctx->opcode, 0, 4) << 2;
20185 gen_st(ctx, OPC_SW, rt, rs, offset);
20186 break;
20187 case NM_SWGP16:
20188 rt = decode_gpr_gpr3_src_store(
20189 NANOMIPS_EXTRACT_RD(ctx->opcode));
20190 offset = extract32(ctx->opcode, 0, 7) << 2;
20191 gen_st(ctx, OPC_SW, rt, 28, offset);
20192 break;
20193 case NM_BC16:
20194 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
20195 (sextract32(ctx->opcode, 0, 1) << 10) |
20196 (extract32(ctx->opcode, 1, 9) << 1));
20197 break;
20198 case NM_BALC16:
20199 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
20200 (sextract32(ctx->opcode, 0, 1) << 10) |
20201 (extract32(ctx->opcode, 1, 9) << 1));
20202 break;
20203 case NM_BEQZC16:
20204 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
20205 (sextract32(ctx->opcode, 0, 1) << 7) |
20206 (extract32(ctx->opcode, 1, 6) << 1));
20207 break;
20208 case NM_BNEZC16:
20209 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
20210 (sextract32(ctx->opcode, 0, 1) << 7) |
20211 (extract32(ctx->opcode, 1, 6) << 1));
20212 break;
20213 case NM_P16_BR:
20214 switch (ctx->opcode & 0xf) {
20215 case 0:
20216 /* P16.JRC */
20217 switch (extract32(ctx->opcode, 4, 1)) {
20218 case NM_JRC:
20219 gen_compute_branch_nm(ctx, OPC_JR, 2,
20220 extract32(ctx->opcode, 5, 5), 0, 0);
20221 break;
20222 case NM_JALRC16:
20223 gen_compute_branch_nm(ctx, OPC_JALR, 2,
20224 extract32(ctx->opcode, 5, 5), 31, 0);
20225 break;
20227 break;
20228 default:
20230 /* P16.BRI */
20231 uint32_t opc = extract32(ctx->opcode, 4, 3) <
20232 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
20233 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
20234 extract32(ctx->opcode, 0, 4) << 1);
20236 break;
20238 break;
20239 case NM_P16_SR:
20241 int count = extract32(ctx->opcode, 0, 4);
20242 int u = extract32(ctx->opcode, 4, 4) << 4;
20244 rt = 30 + extract32(ctx->opcode, 9, 1);
20245 switch (extract32(ctx->opcode, 8, 1)) {
20246 case NM_SAVE16:
20247 gen_save(ctx, rt, count, 0, u);
20248 break;
20249 case NM_RESTORE_JRC16:
20250 gen_restore(ctx, rt, count, 0, u);
20251 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20252 break;
20255 break;
20256 case NM_MOVEP:
20257 case NM_MOVEPREV:
20259 static const int gpr2reg1[] = {4, 5, 6, 7};
20260 static const int gpr2reg2[] = {5, 6, 7, 8};
20261 int re;
20262 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
20263 extract32(ctx->opcode, 8, 1);
20264 int r1 = gpr2reg1[rd2];
20265 int r2 = gpr2reg2[rd2];
20266 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
20267 extract32(ctx->opcode, 0, 3);
20268 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
20269 extract32(ctx->opcode, 5, 3);
20270 TCGv t0 = tcg_temp_new();
20271 TCGv t1 = tcg_temp_new();
20272 if (op == NM_MOVEP) {
20273 rd = r1;
20274 re = r2;
20275 rs = decode_gpr_gpr4_zero(r3);
20276 rt = decode_gpr_gpr4_zero(r4);
20277 } else {
20278 rd = decode_gpr_gpr4(r3);
20279 re = decode_gpr_gpr4(r4);
20280 rs = r1;
20281 rt = r2;
20283 gen_load_gpr(t0, rs);
20284 gen_load_gpr(t1, rt);
20285 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20286 tcg_gen_mov_tl(cpu_gpr[re], t1);
20287 tcg_temp_free(t0);
20288 tcg_temp_free(t1);
20290 break;
20291 default:
20292 return decode_nanomips_32_48_opc(env, ctx);
20295 return 2;
20299 /* SmartMIPS extension to MIPS32 */
20301 #if defined(TARGET_MIPS64)
20303 /* MDMX extension to MIPS64 */
20305 #endif
20307 /* MIPSDSP functions. */
20308 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
20309 int rd, int base, int offset)
20311 TCGv t0;
20313 check_dsp(ctx);
20314 t0 = tcg_temp_new();
20316 if (base == 0) {
20317 gen_load_gpr(t0, offset);
20318 } else if (offset == 0) {
20319 gen_load_gpr(t0, base);
20320 } else {
20321 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
20324 switch (opc) {
20325 case OPC_LBUX:
20326 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
20327 gen_store_gpr(t0, rd);
20328 break;
20329 case OPC_LHX:
20330 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
20331 gen_store_gpr(t0, rd);
20332 break;
20333 case OPC_LWX:
20334 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
20335 gen_store_gpr(t0, rd);
20336 break;
20337 #if defined(TARGET_MIPS64)
20338 case OPC_LDX:
20339 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
20340 gen_store_gpr(t0, rd);
20341 break;
20342 #endif
20344 tcg_temp_free(t0);
20347 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
20348 int ret, int v1, int v2)
20350 TCGv v1_t;
20351 TCGv v2_t;
20353 if (ret == 0) {
20354 /* Treat as NOP. */
20355 return;
20358 v1_t = tcg_temp_new();
20359 v2_t = tcg_temp_new();
20361 gen_load_gpr(v1_t, v1);
20362 gen_load_gpr(v2_t, v2);
20364 switch (op1) {
20365 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
20366 case OPC_MULT_G_2E:
20367 check_dspr2(ctx);
20368 switch (op2) {
20369 case OPC_ADDUH_QB:
20370 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
20371 break;
20372 case OPC_ADDUH_R_QB:
20373 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
20374 break;
20375 case OPC_ADDQH_PH:
20376 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
20377 break;
20378 case OPC_ADDQH_R_PH:
20379 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
20380 break;
20381 case OPC_ADDQH_W:
20382 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
20383 break;
20384 case OPC_ADDQH_R_W:
20385 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
20386 break;
20387 case OPC_SUBUH_QB:
20388 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
20389 break;
20390 case OPC_SUBUH_R_QB:
20391 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
20392 break;
20393 case OPC_SUBQH_PH:
20394 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
20395 break;
20396 case OPC_SUBQH_R_PH:
20397 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
20398 break;
20399 case OPC_SUBQH_W:
20400 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
20401 break;
20402 case OPC_SUBQH_R_W:
20403 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
20404 break;
20406 break;
20407 case OPC_ABSQ_S_PH_DSP:
20408 switch (op2) {
20409 case OPC_ABSQ_S_QB:
20410 check_dspr2(ctx);
20411 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
20412 break;
20413 case OPC_ABSQ_S_PH:
20414 check_dsp(ctx);
20415 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
20416 break;
20417 case OPC_ABSQ_S_W:
20418 check_dsp(ctx);
20419 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
20420 break;
20421 case OPC_PRECEQ_W_PHL:
20422 check_dsp(ctx);
20423 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
20424 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
20425 break;
20426 case OPC_PRECEQ_W_PHR:
20427 check_dsp(ctx);
20428 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
20429 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
20430 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
20431 break;
20432 case OPC_PRECEQU_PH_QBL:
20433 check_dsp(ctx);
20434 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
20435 break;
20436 case OPC_PRECEQU_PH_QBR:
20437 check_dsp(ctx);
20438 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
20439 break;
20440 case OPC_PRECEQU_PH_QBLA:
20441 check_dsp(ctx);
20442 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
20443 break;
20444 case OPC_PRECEQU_PH_QBRA:
20445 check_dsp(ctx);
20446 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
20447 break;
20448 case OPC_PRECEU_PH_QBL:
20449 check_dsp(ctx);
20450 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
20451 break;
20452 case OPC_PRECEU_PH_QBR:
20453 check_dsp(ctx);
20454 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
20455 break;
20456 case OPC_PRECEU_PH_QBLA:
20457 check_dsp(ctx);
20458 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
20459 break;
20460 case OPC_PRECEU_PH_QBRA:
20461 check_dsp(ctx);
20462 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
20463 break;
20465 break;
20466 case OPC_ADDU_QB_DSP:
20467 switch (op2) {
20468 case OPC_ADDQ_PH:
20469 check_dsp(ctx);
20470 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20471 break;
20472 case OPC_ADDQ_S_PH:
20473 check_dsp(ctx);
20474 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20475 break;
20476 case OPC_ADDQ_S_W:
20477 check_dsp(ctx);
20478 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20479 break;
20480 case OPC_ADDU_QB:
20481 check_dsp(ctx);
20482 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20483 break;
20484 case OPC_ADDU_S_QB:
20485 check_dsp(ctx);
20486 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20487 break;
20488 case OPC_ADDU_PH:
20489 check_dspr2(ctx);
20490 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20491 break;
20492 case OPC_ADDU_S_PH:
20493 check_dspr2(ctx);
20494 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20495 break;
20496 case OPC_SUBQ_PH:
20497 check_dsp(ctx);
20498 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20499 break;
20500 case OPC_SUBQ_S_PH:
20501 check_dsp(ctx);
20502 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20503 break;
20504 case OPC_SUBQ_S_W:
20505 check_dsp(ctx);
20506 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20507 break;
20508 case OPC_SUBU_QB:
20509 check_dsp(ctx);
20510 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20511 break;
20512 case OPC_SUBU_S_QB:
20513 check_dsp(ctx);
20514 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20515 break;
20516 case OPC_SUBU_PH:
20517 check_dspr2(ctx);
20518 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20519 break;
20520 case OPC_SUBU_S_PH:
20521 check_dspr2(ctx);
20522 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20523 break;
20524 case OPC_ADDSC:
20525 check_dsp(ctx);
20526 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20527 break;
20528 case OPC_ADDWC:
20529 check_dsp(ctx);
20530 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20531 break;
20532 case OPC_MODSUB:
20533 check_dsp(ctx);
20534 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
20535 break;
20536 case OPC_RADDU_W_QB:
20537 check_dsp(ctx);
20538 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
20539 break;
20541 break;
20542 case OPC_CMPU_EQ_QB_DSP:
20543 switch (op2) {
20544 case OPC_PRECR_QB_PH:
20545 check_dspr2(ctx);
20546 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
20547 break;
20548 case OPC_PRECRQ_QB_PH:
20549 check_dsp(ctx);
20550 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
20551 break;
20552 case OPC_PRECR_SRA_PH_W:
20553 check_dspr2(ctx);
20555 TCGv_i32 sa_t = tcg_const_i32(v2);
20556 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
20557 cpu_gpr[ret]);
20558 tcg_temp_free_i32(sa_t);
20559 break;
20561 case OPC_PRECR_SRA_R_PH_W:
20562 check_dspr2(ctx);
20564 TCGv_i32 sa_t = tcg_const_i32(v2);
20565 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
20566 cpu_gpr[ret]);
20567 tcg_temp_free_i32(sa_t);
20568 break;
20570 case OPC_PRECRQ_PH_W:
20571 check_dsp(ctx);
20572 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
20573 break;
20574 case OPC_PRECRQ_RS_PH_W:
20575 check_dsp(ctx);
20576 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20577 break;
20578 case OPC_PRECRQU_S_QB_PH:
20579 check_dsp(ctx);
20580 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20581 break;
20583 break;
20584 #ifdef TARGET_MIPS64
20585 case OPC_ABSQ_S_QH_DSP:
20586 switch (op2) {
20587 case OPC_PRECEQ_L_PWL:
20588 check_dsp(ctx);
20589 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
20590 break;
20591 case OPC_PRECEQ_L_PWR:
20592 check_dsp(ctx);
20593 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
20594 break;
20595 case OPC_PRECEQ_PW_QHL:
20596 check_dsp(ctx);
20597 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
20598 break;
20599 case OPC_PRECEQ_PW_QHR:
20600 check_dsp(ctx);
20601 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
20602 break;
20603 case OPC_PRECEQ_PW_QHLA:
20604 check_dsp(ctx);
20605 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
20606 break;
20607 case OPC_PRECEQ_PW_QHRA:
20608 check_dsp(ctx);
20609 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
20610 break;
20611 case OPC_PRECEQU_QH_OBL:
20612 check_dsp(ctx);
20613 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
20614 break;
20615 case OPC_PRECEQU_QH_OBR:
20616 check_dsp(ctx);
20617 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
20618 break;
20619 case OPC_PRECEQU_QH_OBLA:
20620 check_dsp(ctx);
20621 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
20622 break;
20623 case OPC_PRECEQU_QH_OBRA:
20624 check_dsp(ctx);
20625 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
20626 break;
20627 case OPC_PRECEU_QH_OBL:
20628 check_dsp(ctx);
20629 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
20630 break;
20631 case OPC_PRECEU_QH_OBR:
20632 check_dsp(ctx);
20633 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
20634 break;
20635 case OPC_PRECEU_QH_OBLA:
20636 check_dsp(ctx);
20637 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
20638 break;
20639 case OPC_PRECEU_QH_OBRA:
20640 check_dsp(ctx);
20641 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
20642 break;
20643 case OPC_ABSQ_S_OB:
20644 check_dspr2(ctx);
20645 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
20646 break;
20647 case OPC_ABSQ_S_PW:
20648 check_dsp(ctx);
20649 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
20650 break;
20651 case OPC_ABSQ_S_QH:
20652 check_dsp(ctx);
20653 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
20654 break;
20656 break;
20657 case OPC_ADDU_OB_DSP:
20658 switch (op2) {
20659 case OPC_RADDU_L_OB:
20660 check_dsp(ctx);
20661 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
20662 break;
20663 case OPC_SUBQ_PW:
20664 check_dsp(ctx);
20665 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20666 break;
20667 case OPC_SUBQ_S_PW:
20668 check_dsp(ctx);
20669 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20670 break;
20671 case OPC_SUBQ_QH:
20672 check_dsp(ctx);
20673 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20674 break;
20675 case OPC_SUBQ_S_QH:
20676 check_dsp(ctx);
20677 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20678 break;
20679 case OPC_SUBU_OB:
20680 check_dsp(ctx);
20681 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20682 break;
20683 case OPC_SUBU_S_OB:
20684 check_dsp(ctx);
20685 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20686 break;
20687 case OPC_SUBU_QH:
20688 check_dspr2(ctx);
20689 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20690 break;
20691 case OPC_SUBU_S_QH:
20692 check_dspr2(ctx);
20693 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20694 break;
20695 case OPC_SUBUH_OB:
20696 check_dspr2(ctx);
20697 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
20698 break;
20699 case OPC_SUBUH_R_OB:
20700 check_dspr2(ctx);
20701 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
20702 break;
20703 case OPC_ADDQ_PW:
20704 check_dsp(ctx);
20705 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20706 break;
20707 case OPC_ADDQ_S_PW:
20708 check_dsp(ctx);
20709 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20710 break;
20711 case OPC_ADDQ_QH:
20712 check_dsp(ctx);
20713 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20714 break;
20715 case OPC_ADDQ_S_QH:
20716 check_dsp(ctx);
20717 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20718 break;
20719 case OPC_ADDU_OB:
20720 check_dsp(ctx);
20721 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20722 break;
20723 case OPC_ADDU_S_OB:
20724 check_dsp(ctx);
20725 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20726 break;
20727 case OPC_ADDU_QH:
20728 check_dspr2(ctx);
20729 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20730 break;
20731 case OPC_ADDU_S_QH:
20732 check_dspr2(ctx);
20733 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20734 break;
20735 case OPC_ADDUH_OB:
20736 check_dspr2(ctx);
20737 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
20738 break;
20739 case OPC_ADDUH_R_OB:
20740 check_dspr2(ctx);
20741 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
20742 break;
20744 break;
20745 case OPC_CMPU_EQ_OB_DSP:
20746 switch (op2) {
20747 case OPC_PRECR_OB_QH:
20748 check_dspr2(ctx);
20749 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
20750 break;
20751 case OPC_PRECR_SRA_QH_PW:
20752 check_dspr2(ctx);
20754 TCGv_i32 ret_t = tcg_const_i32(ret);
20755 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
20756 tcg_temp_free_i32(ret_t);
20757 break;
20759 case OPC_PRECR_SRA_R_QH_PW:
20760 check_dspr2(ctx);
20762 TCGv_i32 sa_v = tcg_const_i32(ret);
20763 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
20764 tcg_temp_free_i32(sa_v);
20765 break;
20767 case OPC_PRECRQ_OB_QH:
20768 check_dsp(ctx);
20769 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
20770 break;
20771 case OPC_PRECRQ_PW_L:
20772 check_dsp(ctx);
20773 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
20774 break;
20775 case OPC_PRECRQ_QH_PW:
20776 check_dsp(ctx);
20777 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
20778 break;
20779 case OPC_PRECRQ_RS_QH_PW:
20780 check_dsp(ctx);
20781 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20782 break;
20783 case OPC_PRECRQU_S_OB_QH:
20784 check_dsp(ctx);
20785 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20786 break;
20788 break;
20789 #endif
20792 tcg_temp_free(v1_t);
20793 tcg_temp_free(v2_t);
20796 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
20797 int ret, int v1, int v2)
20799 uint32_t op2;
20800 TCGv t0;
20801 TCGv v1_t;
20802 TCGv v2_t;
20804 if (ret == 0) {
20805 /* Treat as NOP. */
20806 return;
20809 t0 = tcg_temp_new();
20810 v1_t = tcg_temp_new();
20811 v2_t = tcg_temp_new();
20813 tcg_gen_movi_tl(t0, v1);
20814 gen_load_gpr(v1_t, v1);
20815 gen_load_gpr(v2_t, v2);
20817 switch (opc) {
20818 case OPC_SHLL_QB_DSP:
20820 op2 = MASK_SHLL_QB(ctx->opcode);
20821 switch (op2) {
20822 case OPC_SHLL_QB:
20823 check_dsp(ctx);
20824 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
20825 break;
20826 case OPC_SHLLV_QB:
20827 check_dsp(ctx);
20828 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20829 break;
20830 case OPC_SHLL_PH:
20831 check_dsp(ctx);
20832 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
20833 break;
20834 case OPC_SHLLV_PH:
20835 check_dsp(ctx);
20836 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20837 break;
20838 case OPC_SHLL_S_PH:
20839 check_dsp(ctx);
20840 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
20841 break;
20842 case OPC_SHLLV_S_PH:
20843 check_dsp(ctx);
20844 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20845 break;
20846 case OPC_SHLL_S_W:
20847 check_dsp(ctx);
20848 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
20849 break;
20850 case OPC_SHLLV_S_W:
20851 check_dsp(ctx);
20852 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20853 break;
20854 case OPC_SHRL_QB:
20855 check_dsp(ctx);
20856 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
20857 break;
20858 case OPC_SHRLV_QB:
20859 check_dsp(ctx);
20860 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
20861 break;
20862 case OPC_SHRL_PH:
20863 check_dspr2(ctx);
20864 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
20865 break;
20866 case OPC_SHRLV_PH:
20867 check_dspr2(ctx);
20868 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
20869 break;
20870 case OPC_SHRA_QB:
20871 check_dspr2(ctx);
20872 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
20873 break;
20874 case OPC_SHRA_R_QB:
20875 check_dspr2(ctx);
20876 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
20877 break;
20878 case OPC_SHRAV_QB:
20879 check_dspr2(ctx);
20880 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
20881 break;
20882 case OPC_SHRAV_R_QB:
20883 check_dspr2(ctx);
20884 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
20885 break;
20886 case OPC_SHRA_PH:
20887 check_dsp(ctx);
20888 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
20889 break;
20890 case OPC_SHRA_R_PH:
20891 check_dsp(ctx);
20892 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
20893 break;
20894 case OPC_SHRAV_PH:
20895 check_dsp(ctx);
20896 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
20897 break;
20898 case OPC_SHRAV_R_PH:
20899 check_dsp(ctx);
20900 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
20901 break;
20902 case OPC_SHRA_R_W:
20903 check_dsp(ctx);
20904 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
20905 break;
20906 case OPC_SHRAV_R_W:
20907 check_dsp(ctx);
20908 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
20909 break;
20910 default: /* Invalid */
20911 MIPS_INVAL("MASK SHLL.QB");
20912 generate_exception_end(ctx, EXCP_RI);
20913 break;
20915 break;
20917 #ifdef TARGET_MIPS64
20918 case OPC_SHLL_OB_DSP:
20919 op2 = MASK_SHLL_OB(ctx->opcode);
20920 switch (op2) {
20921 case OPC_SHLL_PW:
20922 check_dsp(ctx);
20923 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
20924 break;
20925 case OPC_SHLLV_PW:
20926 check_dsp(ctx);
20927 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
20928 break;
20929 case OPC_SHLL_S_PW:
20930 check_dsp(ctx);
20931 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
20932 break;
20933 case OPC_SHLLV_S_PW:
20934 check_dsp(ctx);
20935 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
20936 break;
20937 case OPC_SHLL_OB:
20938 check_dsp(ctx);
20939 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
20940 break;
20941 case OPC_SHLLV_OB:
20942 check_dsp(ctx);
20943 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
20944 break;
20945 case OPC_SHLL_QH:
20946 check_dsp(ctx);
20947 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
20948 break;
20949 case OPC_SHLLV_QH:
20950 check_dsp(ctx);
20951 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
20952 break;
20953 case OPC_SHLL_S_QH:
20954 check_dsp(ctx);
20955 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
20956 break;
20957 case OPC_SHLLV_S_QH:
20958 check_dsp(ctx);
20959 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
20960 break;
20961 case OPC_SHRA_OB:
20962 check_dspr2(ctx);
20963 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
20964 break;
20965 case OPC_SHRAV_OB:
20966 check_dspr2(ctx);
20967 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
20968 break;
20969 case OPC_SHRA_R_OB:
20970 check_dspr2(ctx);
20971 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
20972 break;
20973 case OPC_SHRAV_R_OB:
20974 check_dspr2(ctx);
20975 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
20976 break;
20977 case OPC_SHRA_PW:
20978 check_dsp(ctx);
20979 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
20980 break;
20981 case OPC_SHRAV_PW:
20982 check_dsp(ctx);
20983 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
20984 break;
20985 case OPC_SHRA_R_PW:
20986 check_dsp(ctx);
20987 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
20988 break;
20989 case OPC_SHRAV_R_PW:
20990 check_dsp(ctx);
20991 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
20992 break;
20993 case OPC_SHRA_QH:
20994 check_dsp(ctx);
20995 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
20996 break;
20997 case OPC_SHRAV_QH:
20998 check_dsp(ctx);
20999 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
21000 break;
21001 case OPC_SHRA_R_QH:
21002 check_dsp(ctx);
21003 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
21004 break;
21005 case OPC_SHRAV_R_QH:
21006 check_dsp(ctx);
21007 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
21008 break;
21009 case OPC_SHRL_OB:
21010 check_dsp(ctx);
21011 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
21012 break;
21013 case OPC_SHRLV_OB:
21014 check_dsp(ctx);
21015 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
21016 break;
21017 case OPC_SHRL_QH:
21018 check_dspr2(ctx);
21019 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
21020 break;
21021 case OPC_SHRLV_QH:
21022 check_dspr2(ctx);
21023 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
21024 break;
21025 default: /* Invalid */
21026 MIPS_INVAL("MASK SHLL.OB");
21027 generate_exception_end(ctx, EXCP_RI);
21028 break;
21030 break;
21031 #endif
21034 tcg_temp_free(t0);
21035 tcg_temp_free(v1_t);
21036 tcg_temp_free(v2_t);
21039 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
21040 int ret, int v1, int v2, int check_ret)
21042 TCGv_i32 t0;
21043 TCGv v1_t;
21044 TCGv v2_t;
21046 if ((ret == 0) && (check_ret == 1)) {
21047 /* Treat as NOP. */
21048 return;
21051 t0 = tcg_temp_new_i32();
21052 v1_t = tcg_temp_new();
21053 v2_t = tcg_temp_new();
21055 tcg_gen_movi_i32(t0, ret);
21056 gen_load_gpr(v1_t, v1);
21057 gen_load_gpr(v2_t, v2);
21059 switch (op1) {
21060 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
21061 * the same mask and op1. */
21062 case OPC_MULT_G_2E:
21063 check_dspr2(ctx);
21064 switch (op2) {
21065 case OPC_MUL_PH:
21066 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21067 break;
21068 case OPC_MUL_S_PH:
21069 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21070 break;
21071 case OPC_MULQ_S_W:
21072 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21073 break;
21074 case OPC_MULQ_RS_W:
21075 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21076 break;
21078 break;
21079 case OPC_DPA_W_PH_DSP:
21080 switch (op2) {
21081 case OPC_DPAU_H_QBL:
21082 check_dsp(ctx);
21083 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
21084 break;
21085 case OPC_DPAU_H_QBR:
21086 check_dsp(ctx);
21087 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
21088 break;
21089 case OPC_DPSU_H_QBL:
21090 check_dsp(ctx);
21091 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
21092 break;
21093 case OPC_DPSU_H_QBR:
21094 check_dsp(ctx);
21095 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
21096 break;
21097 case OPC_DPA_W_PH:
21098 check_dspr2(ctx);
21099 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
21100 break;
21101 case OPC_DPAX_W_PH:
21102 check_dspr2(ctx);
21103 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
21104 break;
21105 case OPC_DPAQ_S_W_PH:
21106 check_dsp(ctx);
21107 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21108 break;
21109 case OPC_DPAQX_S_W_PH:
21110 check_dspr2(ctx);
21111 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
21112 break;
21113 case OPC_DPAQX_SA_W_PH:
21114 check_dspr2(ctx);
21115 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
21116 break;
21117 case OPC_DPS_W_PH:
21118 check_dspr2(ctx);
21119 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
21120 break;
21121 case OPC_DPSX_W_PH:
21122 check_dspr2(ctx);
21123 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
21124 break;
21125 case OPC_DPSQ_S_W_PH:
21126 check_dsp(ctx);
21127 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21128 break;
21129 case OPC_DPSQX_S_W_PH:
21130 check_dspr2(ctx);
21131 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
21132 break;
21133 case OPC_DPSQX_SA_W_PH:
21134 check_dspr2(ctx);
21135 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
21136 break;
21137 case OPC_MULSAQ_S_W_PH:
21138 check_dsp(ctx);
21139 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21140 break;
21141 case OPC_DPAQ_SA_L_W:
21142 check_dsp(ctx);
21143 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
21144 break;
21145 case OPC_DPSQ_SA_L_W:
21146 check_dsp(ctx);
21147 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
21148 break;
21149 case OPC_MAQ_S_W_PHL:
21150 check_dsp(ctx);
21151 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
21152 break;
21153 case OPC_MAQ_S_W_PHR:
21154 check_dsp(ctx);
21155 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
21156 break;
21157 case OPC_MAQ_SA_W_PHL:
21158 check_dsp(ctx);
21159 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
21160 break;
21161 case OPC_MAQ_SA_W_PHR:
21162 check_dsp(ctx);
21163 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
21164 break;
21165 case OPC_MULSA_W_PH:
21166 check_dspr2(ctx);
21167 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
21168 break;
21170 break;
21171 #ifdef TARGET_MIPS64
21172 case OPC_DPAQ_W_QH_DSP:
21174 int ac = ret & 0x03;
21175 tcg_gen_movi_i32(t0, ac);
21177 switch (op2) {
21178 case OPC_DMADD:
21179 check_dsp(ctx);
21180 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
21181 break;
21182 case OPC_DMADDU:
21183 check_dsp(ctx);
21184 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
21185 break;
21186 case OPC_DMSUB:
21187 check_dsp(ctx);
21188 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
21189 break;
21190 case OPC_DMSUBU:
21191 check_dsp(ctx);
21192 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
21193 break;
21194 case OPC_DPA_W_QH:
21195 check_dspr2(ctx);
21196 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
21197 break;
21198 case OPC_DPAQ_S_W_QH:
21199 check_dsp(ctx);
21200 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21201 break;
21202 case OPC_DPAQ_SA_L_PW:
21203 check_dsp(ctx);
21204 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
21205 break;
21206 case OPC_DPAU_H_OBL:
21207 check_dsp(ctx);
21208 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
21209 break;
21210 case OPC_DPAU_H_OBR:
21211 check_dsp(ctx);
21212 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
21213 break;
21214 case OPC_DPS_W_QH:
21215 check_dspr2(ctx);
21216 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
21217 break;
21218 case OPC_DPSQ_S_W_QH:
21219 check_dsp(ctx);
21220 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21221 break;
21222 case OPC_DPSQ_SA_L_PW:
21223 check_dsp(ctx);
21224 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
21225 break;
21226 case OPC_DPSU_H_OBL:
21227 check_dsp(ctx);
21228 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
21229 break;
21230 case OPC_DPSU_H_OBR:
21231 check_dsp(ctx);
21232 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
21233 break;
21234 case OPC_MAQ_S_L_PWL:
21235 check_dsp(ctx);
21236 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
21237 break;
21238 case OPC_MAQ_S_L_PWR:
21239 check_dsp(ctx);
21240 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
21241 break;
21242 case OPC_MAQ_S_W_QHLL:
21243 check_dsp(ctx);
21244 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
21245 break;
21246 case OPC_MAQ_SA_W_QHLL:
21247 check_dsp(ctx);
21248 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
21249 break;
21250 case OPC_MAQ_S_W_QHLR:
21251 check_dsp(ctx);
21252 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
21253 break;
21254 case OPC_MAQ_SA_W_QHLR:
21255 check_dsp(ctx);
21256 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
21257 break;
21258 case OPC_MAQ_S_W_QHRL:
21259 check_dsp(ctx);
21260 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
21261 break;
21262 case OPC_MAQ_SA_W_QHRL:
21263 check_dsp(ctx);
21264 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
21265 break;
21266 case OPC_MAQ_S_W_QHRR:
21267 check_dsp(ctx);
21268 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
21269 break;
21270 case OPC_MAQ_SA_W_QHRR:
21271 check_dsp(ctx);
21272 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
21273 break;
21274 case OPC_MULSAQ_S_L_PW:
21275 check_dsp(ctx);
21276 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
21277 break;
21278 case OPC_MULSAQ_S_W_QH:
21279 check_dsp(ctx);
21280 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21281 break;
21284 break;
21285 #endif
21286 case OPC_ADDU_QB_DSP:
21287 switch (op2) {
21288 case OPC_MULEU_S_PH_QBL:
21289 check_dsp(ctx);
21290 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21291 break;
21292 case OPC_MULEU_S_PH_QBR:
21293 check_dsp(ctx);
21294 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21295 break;
21296 case OPC_MULQ_RS_PH:
21297 check_dsp(ctx);
21298 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21299 break;
21300 case OPC_MULEQ_S_W_PHL:
21301 check_dsp(ctx);
21302 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21303 break;
21304 case OPC_MULEQ_S_W_PHR:
21305 check_dsp(ctx);
21306 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21307 break;
21308 case OPC_MULQ_S_PH:
21309 check_dspr2(ctx);
21310 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21311 break;
21313 break;
21314 #ifdef TARGET_MIPS64
21315 case OPC_ADDU_OB_DSP:
21316 switch (op2) {
21317 case OPC_MULEQ_S_PW_QHL:
21318 check_dsp(ctx);
21319 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21320 break;
21321 case OPC_MULEQ_S_PW_QHR:
21322 check_dsp(ctx);
21323 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21324 break;
21325 case OPC_MULEU_S_QH_OBL:
21326 check_dsp(ctx);
21327 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21328 break;
21329 case OPC_MULEU_S_QH_OBR:
21330 check_dsp(ctx);
21331 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21332 break;
21333 case OPC_MULQ_RS_QH:
21334 check_dsp(ctx);
21335 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21336 break;
21338 break;
21339 #endif
21342 tcg_temp_free_i32(t0);
21343 tcg_temp_free(v1_t);
21344 tcg_temp_free(v2_t);
21347 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
21348 int ret, int val)
21350 int16_t imm;
21351 TCGv t0;
21352 TCGv val_t;
21354 if (ret == 0) {
21355 /* Treat as NOP. */
21356 return;
21359 t0 = tcg_temp_new();
21360 val_t = tcg_temp_new();
21361 gen_load_gpr(val_t, val);
21363 switch (op1) {
21364 case OPC_ABSQ_S_PH_DSP:
21365 switch (op2) {
21366 case OPC_BITREV:
21367 check_dsp(ctx);
21368 gen_helper_bitrev(cpu_gpr[ret], val_t);
21369 break;
21370 case OPC_REPL_QB:
21371 check_dsp(ctx);
21373 target_long result;
21374 imm = (ctx->opcode >> 16) & 0xFF;
21375 result = (uint32_t)imm << 24 |
21376 (uint32_t)imm << 16 |
21377 (uint32_t)imm << 8 |
21378 (uint32_t)imm;
21379 result = (int32_t)result;
21380 tcg_gen_movi_tl(cpu_gpr[ret], result);
21382 break;
21383 case OPC_REPLV_QB:
21384 check_dsp(ctx);
21385 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
21386 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
21387 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21388 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21389 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21390 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21391 break;
21392 case OPC_REPL_PH:
21393 check_dsp(ctx);
21395 imm = (ctx->opcode >> 16) & 0x03FF;
21396 imm = (int16_t)(imm << 6) >> 6;
21397 tcg_gen_movi_tl(cpu_gpr[ret], \
21398 (target_long)((int32_t)imm << 16 | \
21399 (uint16_t)imm));
21401 break;
21402 case OPC_REPLV_PH:
21403 check_dsp(ctx);
21404 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
21405 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21406 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21407 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21408 break;
21410 break;
21411 #ifdef TARGET_MIPS64
21412 case OPC_ABSQ_S_QH_DSP:
21413 switch (op2) {
21414 case OPC_REPL_OB:
21415 check_dsp(ctx);
21417 target_long temp;
21419 imm = (ctx->opcode >> 16) & 0xFF;
21420 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
21421 temp = (temp << 16) | temp;
21422 temp = (temp << 32) | temp;
21423 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21424 break;
21426 case OPC_REPL_PW:
21427 check_dsp(ctx);
21429 target_long temp;
21431 imm = (ctx->opcode >> 16) & 0x03FF;
21432 imm = (int16_t)(imm << 6) >> 6;
21433 temp = ((target_long)imm << 32) \
21434 | ((target_long)imm & 0xFFFFFFFF);
21435 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21436 break;
21438 case OPC_REPL_QH:
21439 check_dsp(ctx);
21441 target_long temp;
21443 imm = (ctx->opcode >> 16) & 0x03FF;
21444 imm = (int16_t)(imm << 6) >> 6;
21446 temp = ((uint64_t)(uint16_t)imm << 48) |
21447 ((uint64_t)(uint16_t)imm << 32) |
21448 ((uint64_t)(uint16_t)imm << 16) |
21449 (uint64_t)(uint16_t)imm;
21450 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21451 break;
21453 case OPC_REPLV_OB:
21454 check_dsp(ctx);
21455 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
21456 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
21457 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21458 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21459 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21460 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21461 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21462 break;
21463 case OPC_REPLV_PW:
21464 check_dsp(ctx);
21465 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
21466 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21467 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21468 break;
21469 case OPC_REPLV_QH:
21470 check_dsp(ctx);
21471 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
21472 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21473 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21474 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21475 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21476 break;
21478 break;
21479 #endif
21481 tcg_temp_free(t0);
21482 tcg_temp_free(val_t);
21485 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
21486 uint32_t op1, uint32_t op2,
21487 int ret, int v1, int v2, int check_ret)
21489 TCGv t1;
21490 TCGv v1_t;
21491 TCGv v2_t;
21493 if ((ret == 0) && (check_ret == 1)) {
21494 /* Treat as NOP. */
21495 return;
21498 t1 = tcg_temp_new();
21499 v1_t = tcg_temp_new();
21500 v2_t = tcg_temp_new();
21502 gen_load_gpr(v1_t, v1);
21503 gen_load_gpr(v2_t, v2);
21505 switch (op1) {
21506 case OPC_CMPU_EQ_QB_DSP:
21507 switch (op2) {
21508 case OPC_CMPU_EQ_QB:
21509 check_dsp(ctx);
21510 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
21511 break;
21512 case OPC_CMPU_LT_QB:
21513 check_dsp(ctx);
21514 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
21515 break;
21516 case OPC_CMPU_LE_QB:
21517 check_dsp(ctx);
21518 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
21519 break;
21520 case OPC_CMPGU_EQ_QB:
21521 check_dsp(ctx);
21522 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
21523 break;
21524 case OPC_CMPGU_LT_QB:
21525 check_dsp(ctx);
21526 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
21527 break;
21528 case OPC_CMPGU_LE_QB:
21529 check_dsp(ctx);
21530 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
21531 break;
21532 case OPC_CMPGDU_EQ_QB:
21533 check_dspr2(ctx);
21534 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
21535 tcg_gen_mov_tl(cpu_gpr[ret], t1);
21536 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
21537 tcg_gen_shli_tl(t1, t1, 24);
21538 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
21539 break;
21540 case OPC_CMPGDU_LT_QB:
21541 check_dspr2(ctx);
21542 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
21543 tcg_gen_mov_tl(cpu_gpr[ret], t1);
21544 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
21545 tcg_gen_shli_tl(t1, t1, 24);
21546 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
21547 break;
21548 case OPC_CMPGDU_LE_QB:
21549 check_dspr2(ctx);
21550 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
21551 tcg_gen_mov_tl(cpu_gpr[ret], t1);
21552 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
21553 tcg_gen_shli_tl(t1, t1, 24);
21554 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
21555 break;
21556 case OPC_CMP_EQ_PH:
21557 check_dsp(ctx);
21558 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
21559 break;
21560 case OPC_CMP_LT_PH:
21561 check_dsp(ctx);
21562 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
21563 break;
21564 case OPC_CMP_LE_PH:
21565 check_dsp(ctx);
21566 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
21567 break;
21568 case OPC_PICK_QB:
21569 check_dsp(ctx);
21570 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21571 break;
21572 case OPC_PICK_PH:
21573 check_dsp(ctx);
21574 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21575 break;
21576 case OPC_PACKRL_PH:
21577 check_dsp(ctx);
21578 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
21579 break;
21581 break;
21582 #ifdef TARGET_MIPS64
21583 case OPC_CMPU_EQ_OB_DSP:
21584 switch (op2) {
21585 case OPC_CMP_EQ_PW:
21586 check_dsp(ctx);
21587 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
21588 break;
21589 case OPC_CMP_LT_PW:
21590 check_dsp(ctx);
21591 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
21592 break;
21593 case OPC_CMP_LE_PW:
21594 check_dsp(ctx);
21595 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
21596 break;
21597 case OPC_CMP_EQ_QH:
21598 check_dsp(ctx);
21599 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
21600 break;
21601 case OPC_CMP_LT_QH:
21602 check_dsp(ctx);
21603 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
21604 break;
21605 case OPC_CMP_LE_QH:
21606 check_dsp(ctx);
21607 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
21608 break;
21609 case OPC_CMPGDU_EQ_OB:
21610 check_dspr2(ctx);
21611 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21612 break;
21613 case OPC_CMPGDU_LT_OB:
21614 check_dspr2(ctx);
21615 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21616 break;
21617 case OPC_CMPGDU_LE_OB:
21618 check_dspr2(ctx);
21619 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21620 break;
21621 case OPC_CMPGU_EQ_OB:
21622 check_dsp(ctx);
21623 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
21624 break;
21625 case OPC_CMPGU_LT_OB:
21626 check_dsp(ctx);
21627 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
21628 break;
21629 case OPC_CMPGU_LE_OB:
21630 check_dsp(ctx);
21631 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
21632 break;
21633 case OPC_CMPU_EQ_OB:
21634 check_dsp(ctx);
21635 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
21636 break;
21637 case OPC_CMPU_LT_OB:
21638 check_dsp(ctx);
21639 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
21640 break;
21641 case OPC_CMPU_LE_OB:
21642 check_dsp(ctx);
21643 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
21644 break;
21645 case OPC_PACKRL_PW:
21646 check_dsp(ctx);
21647 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
21648 break;
21649 case OPC_PICK_OB:
21650 check_dsp(ctx);
21651 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21652 break;
21653 case OPC_PICK_PW:
21654 check_dsp(ctx);
21655 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21656 break;
21657 case OPC_PICK_QH:
21658 check_dsp(ctx);
21659 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21660 break;
21662 break;
21663 #endif
21666 tcg_temp_free(t1);
21667 tcg_temp_free(v1_t);
21668 tcg_temp_free(v2_t);
21671 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
21672 uint32_t op1, int rt, int rs, int sa)
21674 TCGv t0;
21676 check_dspr2(ctx);
21678 if (rt == 0) {
21679 /* Treat as NOP. */
21680 return;
21683 t0 = tcg_temp_new();
21684 gen_load_gpr(t0, rs);
21686 switch (op1) {
21687 case OPC_APPEND_DSP:
21688 switch (MASK_APPEND(ctx->opcode)) {
21689 case OPC_APPEND:
21690 if (sa != 0) {
21691 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
21693 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21694 break;
21695 case OPC_PREPEND:
21696 if (sa != 0) {
21697 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
21698 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
21699 tcg_gen_shli_tl(t0, t0, 32 - sa);
21700 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
21702 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21703 break;
21704 case OPC_BALIGN:
21705 sa &= 3;
21706 if (sa != 0 && sa != 2) {
21707 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
21708 tcg_gen_ext32u_tl(t0, t0);
21709 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
21710 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
21712 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21713 break;
21714 default: /* Invalid */
21715 MIPS_INVAL("MASK APPEND");
21716 generate_exception_end(ctx, EXCP_RI);
21717 break;
21719 break;
21720 #ifdef TARGET_MIPS64
21721 case OPC_DAPPEND_DSP:
21722 switch (MASK_DAPPEND(ctx->opcode)) {
21723 case OPC_DAPPEND:
21724 if (sa != 0) {
21725 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
21727 break;
21728 case OPC_PREPENDD:
21729 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
21730 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
21731 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
21732 break;
21733 case OPC_PREPENDW:
21734 if (sa != 0) {
21735 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
21736 tcg_gen_shli_tl(t0, t0, 64 - sa);
21737 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
21739 break;
21740 case OPC_DBALIGN:
21741 sa &= 7;
21742 if (sa != 0 && sa != 2 && sa != 4) {
21743 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
21744 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
21745 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
21747 break;
21748 default: /* Invalid */
21749 MIPS_INVAL("MASK DAPPEND");
21750 generate_exception_end(ctx, EXCP_RI);
21751 break;
21753 break;
21754 #endif
21756 tcg_temp_free(t0);
21759 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
21760 int ret, int v1, int v2, int check_ret)
21763 TCGv t0;
21764 TCGv t1;
21765 TCGv v1_t;
21766 TCGv v2_t;
21767 int16_t imm;
21769 if ((ret == 0) && (check_ret == 1)) {
21770 /* Treat as NOP. */
21771 return;
21774 t0 = tcg_temp_new();
21775 t1 = tcg_temp_new();
21776 v1_t = tcg_temp_new();
21777 v2_t = tcg_temp_new();
21779 gen_load_gpr(v1_t, v1);
21780 gen_load_gpr(v2_t, v2);
21782 switch (op1) {
21783 case OPC_EXTR_W_DSP:
21784 check_dsp(ctx);
21785 switch (op2) {
21786 case OPC_EXTR_W:
21787 tcg_gen_movi_tl(t0, v2);
21788 tcg_gen_movi_tl(t1, v1);
21789 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
21790 break;
21791 case OPC_EXTR_R_W:
21792 tcg_gen_movi_tl(t0, v2);
21793 tcg_gen_movi_tl(t1, v1);
21794 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
21795 break;
21796 case OPC_EXTR_RS_W:
21797 tcg_gen_movi_tl(t0, v2);
21798 tcg_gen_movi_tl(t1, v1);
21799 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
21800 break;
21801 case OPC_EXTR_S_H:
21802 tcg_gen_movi_tl(t0, v2);
21803 tcg_gen_movi_tl(t1, v1);
21804 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
21805 break;
21806 case OPC_EXTRV_S_H:
21807 tcg_gen_movi_tl(t0, v2);
21808 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
21809 break;
21810 case OPC_EXTRV_W:
21811 tcg_gen_movi_tl(t0, v2);
21812 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
21813 break;
21814 case OPC_EXTRV_R_W:
21815 tcg_gen_movi_tl(t0, v2);
21816 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
21817 break;
21818 case OPC_EXTRV_RS_W:
21819 tcg_gen_movi_tl(t0, v2);
21820 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
21821 break;
21822 case OPC_EXTP:
21823 tcg_gen_movi_tl(t0, v2);
21824 tcg_gen_movi_tl(t1, v1);
21825 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
21826 break;
21827 case OPC_EXTPV:
21828 tcg_gen_movi_tl(t0, v2);
21829 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
21830 break;
21831 case OPC_EXTPDP:
21832 tcg_gen_movi_tl(t0, v2);
21833 tcg_gen_movi_tl(t1, v1);
21834 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
21835 break;
21836 case OPC_EXTPDPV:
21837 tcg_gen_movi_tl(t0, v2);
21838 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
21839 break;
21840 case OPC_SHILO:
21841 imm = (ctx->opcode >> 20) & 0x3F;
21842 tcg_gen_movi_tl(t0, ret);
21843 tcg_gen_movi_tl(t1, imm);
21844 gen_helper_shilo(t0, t1, cpu_env);
21845 break;
21846 case OPC_SHILOV:
21847 tcg_gen_movi_tl(t0, ret);
21848 gen_helper_shilo(t0, v1_t, cpu_env);
21849 break;
21850 case OPC_MTHLIP:
21851 tcg_gen_movi_tl(t0, ret);
21852 gen_helper_mthlip(t0, v1_t, cpu_env);
21853 break;
21854 case OPC_WRDSP:
21855 imm = (ctx->opcode >> 11) & 0x3FF;
21856 tcg_gen_movi_tl(t0, imm);
21857 gen_helper_wrdsp(v1_t, t0, cpu_env);
21858 break;
21859 case OPC_RDDSP:
21860 imm = (ctx->opcode >> 16) & 0x03FF;
21861 tcg_gen_movi_tl(t0, imm);
21862 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
21863 break;
21865 break;
21866 #ifdef TARGET_MIPS64
21867 case OPC_DEXTR_W_DSP:
21868 check_dsp(ctx);
21869 switch (op2) {
21870 case OPC_DMTHLIP:
21871 tcg_gen_movi_tl(t0, ret);
21872 gen_helper_dmthlip(v1_t, t0, cpu_env);
21873 break;
21874 case OPC_DSHILO:
21876 int shift = (ctx->opcode >> 19) & 0x7F;
21877 int ac = (ctx->opcode >> 11) & 0x03;
21878 tcg_gen_movi_tl(t0, shift);
21879 tcg_gen_movi_tl(t1, ac);
21880 gen_helper_dshilo(t0, t1, cpu_env);
21881 break;
21883 case OPC_DSHILOV:
21885 int ac = (ctx->opcode >> 11) & 0x03;
21886 tcg_gen_movi_tl(t0, ac);
21887 gen_helper_dshilo(v1_t, t0, cpu_env);
21888 break;
21890 case OPC_DEXTP:
21891 tcg_gen_movi_tl(t0, v2);
21892 tcg_gen_movi_tl(t1, v1);
21894 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
21895 break;
21896 case OPC_DEXTPV:
21897 tcg_gen_movi_tl(t0, v2);
21898 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
21899 break;
21900 case OPC_DEXTPDP:
21901 tcg_gen_movi_tl(t0, v2);
21902 tcg_gen_movi_tl(t1, v1);
21903 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
21904 break;
21905 case OPC_DEXTPDPV:
21906 tcg_gen_movi_tl(t0, v2);
21907 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
21908 break;
21909 case OPC_DEXTR_L:
21910 tcg_gen_movi_tl(t0, v2);
21911 tcg_gen_movi_tl(t1, v1);
21912 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
21913 break;
21914 case OPC_DEXTR_R_L:
21915 tcg_gen_movi_tl(t0, v2);
21916 tcg_gen_movi_tl(t1, v1);
21917 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
21918 break;
21919 case OPC_DEXTR_RS_L:
21920 tcg_gen_movi_tl(t0, v2);
21921 tcg_gen_movi_tl(t1, v1);
21922 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
21923 break;
21924 case OPC_DEXTR_W:
21925 tcg_gen_movi_tl(t0, v2);
21926 tcg_gen_movi_tl(t1, v1);
21927 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
21928 break;
21929 case OPC_DEXTR_R_W:
21930 tcg_gen_movi_tl(t0, v2);
21931 tcg_gen_movi_tl(t1, v1);
21932 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
21933 break;
21934 case OPC_DEXTR_RS_W:
21935 tcg_gen_movi_tl(t0, v2);
21936 tcg_gen_movi_tl(t1, v1);
21937 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
21938 break;
21939 case OPC_DEXTR_S_H:
21940 tcg_gen_movi_tl(t0, v2);
21941 tcg_gen_movi_tl(t1, v1);
21942 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
21943 break;
21944 case OPC_DEXTRV_S_H:
21945 tcg_gen_movi_tl(t0, v2);
21946 tcg_gen_movi_tl(t1, v1);
21947 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
21948 break;
21949 case OPC_DEXTRV_L:
21950 tcg_gen_movi_tl(t0, v2);
21951 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
21952 break;
21953 case OPC_DEXTRV_R_L:
21954 tcg_gen_movi_tl(t0, v2);
21955 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
21956 break;
21957 case OPC_DEXTRV_RS_L:
21958 tcg_gen_movi_tl(t0, v2);
21959 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
21960 break;
21961 case OPC_DEXTRV_W:
21962 tcg_gen_movi_tl(t0, v2);
21963 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
21964 break;
21965 case OPC_DEXTRV_R_W:
21966 tcg_gen_movi_tl(t0, v2);
21967 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
21968 break;
21969 case OPC_DEXTRV_RS_W:
21970 tcg_gen_movi_tl(t0, v2);
21971 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
21972 break;
21974 break;
21975 #endif
21978 tcg_temp_free(t0);
21979 tcg_temp_free(t1);
21980 tcg_temp_free(v1_t);
21981 tcg_temp_free(v2_t);
21984 /* End MIPSDSP functions. */
21986 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
21988 int rs, rt, rd, sa;
21989 uint32_t op1, op2;
21991 rs = (ctx->opcode >> 21) & 0x1f;
21992 rt = (ctx->opcode >> 16) & 0x1f;
21993 rd = (ctx->opcode >> 11) & 0x1f;
21994 sa = (ctx->opcode >> 6) & 0x1f;
21996 op1 = MASK_SPECIAL(ctx->opcode);
21997 switch (op1) {
21998 case OPC_LSA:
21999 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
22000 break;
22001 case OPC_MULT:
22002 case OPC_MULTU:
22003 case OPC_DIV:
22004 case OPC_DIVU:
22005 op2 = MASK_R6_MULDIV(ctx->opcode);
22006 switch (op2) {
22007 case R6_OPC_MUL:
22008 case R6_OPC_MUH:
22009 case R6_OPC_MULU:
22010 case R6_OPC_MUHU:
22011 case R6_OPC_DIV:
22012 case R6_OPC_MOD:
22013 case R6_OPC_DIVU:
22014 case R6_OPC_MODU:
22015 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22016 break;
22017 default:
22018 MIPS_INVAL("special_r6 muldiv");
22019 generate_exception_end(ctx, EXCP_RI);
22020 break;
22022 break;
22023 case OPC_SELEQZ:
22024 case OPC_SELNEZ:
22025 gen_cond_move(ctx, op1, rd, rs, rt);
22026 break;
22027 case R6_OPC_CLO:
22028 case R6_OPC_CLZ:
22029 if (rt == 0 && sa == 1) {
22030 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22031 We need additionally to check other fields */
22032 gen_cl(ctx, op1, rd, rs);
22033 } else {
22034 generate_exception_end(ctx, EXCP_RI);
22036 break;
22037 case R6_OPC_SDBBP:
22038 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
22039 gen_helper_do_semihosting(cpu_env);
22040 } else {
22041 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22042 generate_exception_end(ctx, EXCP_RI);
22043 } else {
22044 generate_exception_end(ctx, EXCP_DBp);
22047 break;
22048 #if defined(TARGET_MIPS64)
22049 case OPC_DLSA:
22050 check_mips_64(ctx);
22051 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
22052 break;
22053 case R6_OPC_DCLO:
22054 case R6_OPC_DCLZ:
22055 if (rt == 0 && sa == 1) {
22056 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22057 We need additionally to check other fields */
22058 check_mips_64(ctx);
22059 gen_cl(ctx, op1, rd, rs);
22060 } else {
22061 generate_exception_end(ctx, EXCP_RI);
22063 break;
22064 case OPC_DMULT:
22065 case OPC_DMULTU:
22066 case OPC_DDIV:
22067 case OPC_DDIVU:
22069 op2 = MASK_R6_MULDIV(ctx->opcode);
22070 switch (op2) {
22071 case R6_OPC_DMUL:
22072 case R6_OPC_DMUH:
22073 case R6_OPC_DMULU:
22074 case R6_OPC_DMUHU:
22075 case R6_OPC_DDIV:
22076 case R6_OPC_DMOD:
22077 case R6_OPC_DDIVU:
22078 case R6_OPC_DMODU:
22079 check_mips_64(ctx);
22080 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22081 break;
22082 default:
22083 MIPS_INVAL("special_r6 muldiv");
22084 generate_exception_end(ctx, EXCP_RI);
22085 break;
22087 break;
22088 #endif
22089 default: /* Invalid */
22090 MIPS_INVAL("special_r6");
22091 generate_exception_end(ctx, EXCP_RI);
22092 break;
22096 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
22098 int rs, rt, rd, sa;
22099 uint32_t op1;
22101 rs = (ctx->opcode >> 21) & 0x1f;
22102 rt = (ctx->opcode >> 16) & 0x1f;
22103 rd = (ctx->opcode >> 11) & 0x1f;
22104 sa = (ctx->opcode >> 6) & 0x1f;
22106 op1 = MASK_SPECIAL(ctx->opcode);
22107 switch (op1) {
22108 case OPC_MOVN: /* Conditional move */
22109 case OPC_MOVZ:
22110 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
22111 INSN_LOONGSON2E | INSN_LOONGSON2F);
22112 gen_cond_move(ctx, op1, rd, rs, rt);
22113 break;
22114 case OPC_MFHI: /* Move from HI/LO */
22115 case OPC_MFLO:
22116 gen_HILO(ctx, op1, rs & 3, rd);
22117 break;
22118 case OPC_MTHI:
22119 case OPC_MTLO: /* Move to HI/LO */
22120 gen_HILO(ctx, op1, rd & 3, rs);
22121 break;
22122 case OPC_MOVCI:
22123 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
22124 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
22125 check_cp1_enabled(ctx);
22126 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
22127 (ctx->opcode >> 16) & 1);
22128 } else {
22129 generate_exception_err(ctx, EXCP_CpU, 1);
22131 break;
22132 case OPC_MULT:
22133 case OPC_MULTU:
22134 if (sa) {
22135 check_insn(ctx, INSN_VR54XX);
22136 op1 = MASK_MUL_VR54XX(ctx->opcode);
22137 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
22138 } else {
22139 gen_muldiv(ctx, op1, rd & 3, rs, rt);
22141 break;
22142 case OPC_DIV:
22143 case OPC_DIVU:
22144 gen_muldiv(ctx, op1, 0, rs, rt);
22145 break;
22146 #if defined(TARGET_MIPS64)
22147 case OPC_DMULT:
22148 case OPC_DMULTU:
22149 case OPC_DDIV:
22150 case OPC_DDIVU:
22151 check_insn(ctx, ISA_MIPS3);
22152 check_mips_64(ctx);
22153 gen_muldiv(ctx, op1, 0, rs, rt);
22154 break;
22155 #endif
22156 case OPC_JR:
22157 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
22158 break;
22159 case OPC_SPIM:
22160 #ifdef MIPS_STRICT_STANDARD
22161 MIPS_INVAL("SPIM");
22162 generate_exception_end(ctx, EXCP_RI);
22163 #else
22164 /* Implemented as RI exception for now. */
22165 MIPS_INVAL("spim (unofficial)");
22166 generate_exception_end(ctx, EXCP_RI);
22167 #endif
22168 break;
22169 default: /* Invalid */
22170 MIPS_INVAL("special_legacy");
22171 generate_exception_end(ctx, EXCP_RI);
22172 break;
22176 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
22178 int rs, rt, rd, sa;
22179 uint32_t op1;
22181 rs = (ctx->opcode >> 21) & 0x1f;
22182 rt = (ctx->opcode >> 16) & 0x1f;
22183 rd = (ctx->opcode >> 11) & 0x1f;
22184 sa = (ctx->opcode >> 6) & 0x1f;
22186 op1 = MASK_SPECIAL(ctx->opcode);
22187 switch (op1) {
22188 case OPC_SLL: /* Shift with immediate */
22189 if (sa == 5 && rd == 0 &&
22190 rs == 0 && rt == 0) { /* PAUSE */
22191 if ((ctx->insn_flags & ISA_MIPS32R6) &&
22192 (ctx->hflags & MIPS_HFLAG_BMASK)) {
22193 generate_exception_end(ctx, EXCP_RI);
22194 break;
22197 /* Fallthrough */
22198 case OPC_SRA:
22199 gen_shift_imm(ctx, op1, rd, rt, sa);
22200 break;
22201 case OPC_SRL:
22202 switch ((ctx->opcode >> 21) & 0x1f) {
22203 case 1:
22204 /* rotr is decoded as srl on non-R2 CPUs */
22205 if (ctx->insn_flags & ISA_MIPS32R2) {
22206 op1 = OPC_ROTR;
22208 /* Fallthrough */
22209 case 0:
22210 gen_shift_imm(ctx, op1, rd, rt, sa);
22211 break;
22212 default:
22213 generate_exception_end(ctx, EXCP_RI);
22214 break;
22216 break;
22217 case OPC_ADD:
22218 case OPC_ADDU:
22219 case OPC_SUB:
22220 case OPC_SUBU:
22221 gen_arith(ctx, op1, rd, rs, rt);
22222 break;
22223 case OPC_SLLV: /* Shifts */
22224 case OPC_SRAV:
22225 gen_shift(ctx, op1, rd, rs, rt);
22226 break;
22227 case OPC_SRLV:
22228 switch ((ctx->opcode >> 6) & 0x1f) {
22229 case 1:
22230 /* rotrv is decoded as srlv on non-R2 CPUs */
22231 if (ctx->insn_flags & ISA_MIPS32R2) {
22232 op1 = OPC_ROTRV;
22234 /* Fallthrough */
22235 case 0:
22236 gen_shift(ctx, op1, rd, rs, rt);
22237 break;
22238 default:
22239 generate_exception_end(ctx, EXCP_RI);
22240 break;
22242 break;
22243 case OPC_SLT: /* Set on less than */
22244 case OPC_SLTU:
22245 gen_slt(ctx, op1, rd, rs, rt);
22246 break;
22247 case OPC_AND: /* Logic*/
22248 case OPC_OR:
22249 case OPC_NOR:
22250 case OPC_XOR:
22251 gen_logic(ctx, op1, rd, rs, rt);
22252 break;
22253 case OPC_JALR:
22254 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
22255 break;
22256 case OPC_TGE: /* Traps */
22257 case OPC_TGEU:
22258 case OPC_TLT:
22259 case OPC_TLTU:
22260 case OPC_TEQ:
22261 case OPC_TNE:
22262 check_insn(ctx, ISA_MIPS2);
22263 gen_trap(ctx, op1, rs, rt, -1);
22264 break;
22265 case OPC_LSA: /* OPC_PMON */
22266 if ((ctx->insn_flags & ISA_MIPS32R6) ||
22267 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
22268 decode_opc_special_r6(env, ctx);
22269 } else {
22270 /* Pmon entry point, also R4010 selsl */
22271 #ifdef MIPS_STRICT_STANDARD
22272 MIPS_INVAL("PMON / selsl");
22273 generate_exception_end(ctx, EXCP_RI);
22274 #else
22275 gen_helper_0e0i(pmon, sa);
22276 #endif
22278 break;
22279 case OPC_SYSCALL:
22280 generate_exception_end(ctx, EXCP_SYSCALL);
22281 break;
22282 case OPC_BREAK:
22283 generate_exception_end(ctx, EXCP_BREAK);
22284 break;
22285 case OPC_SYNC:
22286 check_insn(ctx, ISA_MIPS2);
22287 gen_sync(extract32(ctx->opcode, 6, 5));
22288 break;
22290 #if defined(TARGET_MIPS64)
22291 /* MIPS64 specific opcodes */
22292 case OPC_DSLL:
22293 case OPC_DSRA:
22294 case OPC_DSLL32:
22295 case OPC_DSRA32:
22296 check_insn(ctx, ISA_MIPS3);
22297 check_mips_64(ctx);
22298 gen_shift_imm(ctx, op1, rd, rt, sa);
22299 break;
22300 case OPC_DSRL:
22301 switch ((ctx->opcode >> 21) & 0x1f) {
22302 case 1:
22303 /* drotr is decoded as dsrl on non-R2 CPUs */
22304 if (ctx->insn_flags & ISA_MIPS32R2) {
22305 op1 = OPC_DROTR;
22307 /* Fallthrough */
22308 case 0:
22309 check_insn(ctx, ISA_MIPS3);
22310 check_mips_64(ctx);
22311 gen_shift_imm(ctx, op1, rd, rt, sa);
22312 break;
22313 default:
22314 generate_exception_end(ctx, EXCP_RI);
22315 break;
22317 break;
22318 case OPC_DSRL32:
22319 switch ((ctx->opcode >> 21) & 0x1f) {
22320 case 1:
22321 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
22322 if (ctx->insn_flags & ISA_MIPS32R2) {
22323 op1 = OPC_DROTR32;
22325 /* Fallthrough */
22326 case 0:
22327 check_insn(ctx, ISA_MIPS3);
22328 check_mips_64(ctx);
22329 gen_shift_imm(ctx, op1, rd, rt, sa);
22330 break;
22331 default:
22332 generate_exception_end(ctx, EXCP_RI);
22333 break;
22335 break;
22336 case OPC_DADD:
22337 case OPC_DADDU:
22338 case OPC_DSUB:
22339 case OPC_DSUBU:
22340 check_insn(ctx, ISA_MIPS3);
22341 check_mips_64(ctx);
22342 gen_arith(ctx, op1, rd, rs, rt);
22343 break;
22344 case OPC_DSLLV:
22345 case OPC_DSRAV:
22346 check_insn(ctx, ISA_MIPS3);
22347 check_mips_64(ctx);
22348 gen_shift(ctx, op1, rd, rs, rt);
22349 break;
22350 case OPC_DSRLV:
22351 switch ((ctx->opcode >> 6) & 0x1f) {
22352 case 1:
22353 /* drotrv is decoded as dsrlv on non-R2 CPUs */
22354 if (ctx->insn_flags & ISA_MIPS32R2) {
22355 op1 = OPC_DROTRV;
22357 /* Fallthrough */
22358 case 0:
22359 check_insn(ctx, ISA_MIPS3);
22360 check_mips_64(ctx);
22361 gen_shift(ctx, op1, rd, rs, rt);
22362 break;
22363 default:
22364 generate_exception_end(ctx, EXCP_RI);
22365 break;
22367 break;
22368 case OPC_DLSA:
22369 if ((ctx->insn_flags & ISA_MIPS32R6) ||
22370 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
22371 decode_opc_special_r6(env, ctx);
22373 break;
22374 #endif
22375 default:
22376 if (ctx->insn_flags & ISA_MIPS32R6) {
22377 decode_opc_special_r6(env, ctx);
22378 } else {
22379 decode_opc_special_legacy(env, ctx);
22384 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
22386 int rs, rt, rd;
22387 uint32_t op1;
22389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
22391 rs = (ctx->opcode >> 21) & 0x1f;
22392 rt = (ctx->opcode >> 16) & 0x1f;
22393 rd = (ctx->opcode >> 11) & 0x1f;
22395 op1 = MASK_SPECIAL2(ctx->opcode);
22396 switch (op1) {
22397 case OPC_MADD: /* Multiply and add/sub */
22398 case OPC_MADDU:
22399 case OPC_MSUB:
22400 case OPC_MSUBU:
22401 check_insn(ctx, ISA_MIPS32);
22402 gen_muldiv(ctx, op1, rd & 3, rs, rt);
22403 break;
22404 case OPC_MUL:
22405 gen_arith(ctx, op1, rd, rs, rt);
22406 break;
22407 case OPC_DIV_G_2F:
22408 case OPC_DIVU_G_2F:
22409 case OPC_MULT_G_2F:
22410 case OPC_MULTU_G_2F:
22411 case OPC_MOD_G_2F:
22412 case OPC_MODU_G_2F:
22413 check_insn(ctx, INSN_LOONGSON2F);
22414 gen_loongson_integer(ctx, op1, rd, rs, rt);
22415 break;
22416 case OPC_CLO:
22417 case OPC_CLZ:
22418 check_insn(ctx, ISA_MIPS32);
22419 gen_cl(ctx, op1, rd, rs);
22420 break;
22421 case OPC_SDBBP:
22422 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
22423 gen_helper_do_semihosting(cpu_env);
22424 } else {
22425 /* XXX: not clear which exception should be raised
22426 * when in debug mode...
22428 check_insn(ctx, ISA_MIPS32);
22429 generate_exception_end(ctx, EXCP_DBp);
22431 break;
22432 #if defined(TARGET_MIPS64)
22433 case OPC_DCLO:
22434 case OPC_DCLZ:
22435 check_insn(ctx, ISA_MIPS64);
22436 check_mips_64(ctx);
22437 gen_cl(ctx, op1, rd, rs);
22438 break;
22439 case OPC_DMULT_G_2F:
22440 case OPC_DMULTU_G_2F:
22441 case OPC_DDIV_G_2F:
22442 case OPC_DDIVU_G_2F:
22443 case OPC_DMOD_G_2F:
22444 case OPC_DMODU_G_2F:
22445 check_insn(ctx, INSN_LOONGSON2F);
22446 gen_loongson_integer(ctx, op1, rd, rs, rt);
22447 break;
22448 #endif
22449 default: /* Invalid */
22450 MIPS_INVAL("special2_legacy");
22451 generate_exception_end(ctx, EXCP_RI);
22452 break;
22456 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
22458 int rs, rt, rd, sa;
22459 uint32_t op1, op2;
22460 int16_t imm;
22462 rs = (ctx->opcode >> 21) & 0x1f;
22463 rt = (ctx->opcode >> 16) & 0x1f;
22464 rd = (ctx->opcode >> 11) & 0x1f;
22465 sa = (ctx->opcode >> 6) & 0x1f;
22466 imm = (int16_t)ctx->opcode >> 7;
22468 op1 = MASK_SPECIAL3(ctx->opcode);
22469 switch (op1) {
22470 case R6_OPC_PREF:
22471 if (rt >= 24) {
22472 /* hint codes 24-31 are reserved and signal RI */
22473 generate_exception_end(ctx, EXCP_RI);
22475 /* Treat as NOP. */
22476 break;
22477 case R6_OPC_CACHE:
22478 check_cp0_enabled(ctx);
22479 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22480 gen_cache_operation(ctx, rt, rs, imm);
22482 break;
22483 case R6_OPC_SC:
22484 gen_st_cond(ctx, op1, rt, rs, imm);
22485 break;
22486 case R6_OPC_LL:
22487 gen_ld(ctx, op1, rt, rs, imm);
22488 break;
22489 case OPC_BSHFL:
22491 if (rd == 0) {
22492 /* Treat as NOP. */
22493 break;
22495 op2 = MASK_BSHFL(ctx->opcode);
22496 switch (op2) {
22497 case OPC_ALIGN:
22498 case OPC_ALIGN_END:
22499 gen_align(ctx, 32, rd, rs, rt, sa & 3);
22500 break;
22501 case OPC_BITSWAP:
22502 gen_bitswap(ctx, op2, rd, rt);
22503 break;
22506 break;
22507 #if defined(TARGET_MIPS64)
22508 case R6_OPC_SCD:
22509 gen_st_cond(ctx, op1, rt, rs, imm);
22510 break;
22511 case R6_OPC_LLD:
22512 gen_ld(ctx, op1, rt, rs, imm);
22513 break;
22514 case OPC_DBSHFL:
22515 check_mips_64(ctx);
22517 if (rd == 0) {
22518 /* Treat as NOP. */
22519 break;
22521 op2 = MASK_DBSHFL(ctx->opcode);
22522 switch (op2) {
22523 case OPC_DALIGN:
22524 case OPC_DALIGN_END:
22525 gen_align(ctx, 64, rd, rs, rt, sa & 7);
22526 break;
22527 case OPC_DBITSWAP:
22528 gen_bitswap(ctx, op2, rd, rt);
22529 break;
22533 break;
22534 #endif
22535 default: /* Invalid */
22536 MIPS_INVAL("special3_r6");
22537 generate_exception_end(ctx, EXCP_RI);
22538 break;
22542 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
22544 int rs, rt, rd;
22545 uint32_t op1, op2;
22547 rs = (ctx->opcode >> 21) & 0x1f;
22548 rt = (ctx->opcode >> 16) & 0x1f;
22549 rd = (ctx->opcode >> 11) & 0x1f;
22551 op1 = MASK_SPECIAL3(ctx->opcode);
22552 switch (op1) {
22553 case OPC_DIV_G_2E:
22554 case OPC_DIVU_G_2E:
22555 case OPC_MOD_G_2E:
22556 case OPC_MODU_G_2E:
22557 case OPC_MULT_G_2E:
22558 case OPC_MULTU_G_2E:
22559 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22560 * the same mask and op1. */
22561 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
22562 op2 = MASK_ADDUH_QB(ctx->opcode);
22563 switch (op2) {
22564 case OPC_ADDUH_QB:
22565 case OPC_ADDUH_R_QB:
22566 case OPC_ADDQH_PH:
22567 case OPC_ADDQH_R_PH:
22568 case OPC_ADDQH_W:
22569 case OPC_ADDQH_R_W:
22570 case OPC_SUBUH_QB:
22571 case OPC_SUBUH_R_QB:
22572 case OPC_SUBQH_PH:
22573 case OPC_SUBQH_R_PH:
22574 case OPC_SUBQH_W:
22575 case OPC_SUBQH_R_W:
22576 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22577 break;
22578 case OPC_MUL_PH:
22579 case OPC_MUL_S_PH:
22580 case OPC_MULQ_S_W:
22581 case OPC_MULQ_RS_W:
22582 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
22583 break;
22584 default:
22585 MIPS_INVAL("MASK ADDUH.QB");
22586 generate_exception_end(ctx, EXCP_RI);
22587 break;
22589 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
22590 gen_loongson_integer(ctx, op1, rd, rs, rt);
22591 } else {
22592 generate_exception_end(ctx, EXCP_RI);
22594 break;
22595 case OPC_LX_DSP:
22596 op2 = MASK_LX(ctx->opcode);
22597 switch (op2) {
22598 #if defined(TARGET_MIPS64)
22599 case OPC_LDX:
22600 #endif
22601 case OPC_LBUX:
22602 case OPC_LHX:
22603 case OPC_LWX:
22604 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
22605 break;
22606 default: /* Invalid */
22607 MIPS_INVAL("MASK LX");
22608 generate_exception_end(ctx, EXCP_RI);
22609 break;
22611 break;
22612 case OPC_ABSQ_S_PH_DSP:
22613 op2 = MASK_ABSQ_S_PH(ctx->opcode);
22614 switch (op2) {
22615 case OPC_ABSQ_S_QB:
22616 case OPC_ABSQ_S_PH:
22617 case OPC_ABSQ_S_W:
22618 case OPC_PRECEQ_W_PHL:
22619 case OPC_PRECEQ_W_PHR:
22620 case OPC_PRECEQU_PH_QBL:
22621 case OPC_PRECEQU_PH_QBR:
22622 case OPC_PRECEQU_PH_QBLA:
22623 case OPC_PRECEQU_PH_QBRA:
22624 case OPC_PRECEU_PH_QBL:
22625 case OPC_PRECEU_PH_QBR:
22626 case OPC_PRECEU_PH_QBLA:
22627 case OPC_PRECEU_PH_QBRA:
22628 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22629 break;
22630 case OPC_BITREV:
22631 case OPC_REPL_QB:
22632 case OPC_REPLV_QB:
22633 case OPC_REPL_PH:
22634 case OPC_REPLV_PH:
22635 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
22636 break;
22637 default:
22638 MIPS_INVAL("MASK ABSQ_S.PH");
22639 generate_exception_end(ctx, EXCP_RI);
22640 break;
22642 break;
22643 case OPC_ADDU_QB_DSP:
22644 op2 = MASK_ADDU_QB(ctx->opcode);
22645 switch (op2) {
22646 case OPC_ADDQ_PH:
22647 case OPC_ADDQ_S_PH:
22648 case OPC_ADDQ_S_W:
22649 case OPC_ADDU_QB:
22650 case OPC_ADDU_S_QB:
22651 case OPC_ADDU_PH:
22652 case OPC_ADDU_S_PH:
22653 case OPC_SUBQ_PH:
22654 case OPC_SUBQ_S_PH:
22655 case OPC_SUBQ_S_W:
22656 case OPC_SUBU_QB:
22657 case OPC_SUBU_S_QB:
22658 case OPC_SUBU_PH:
22659 case OPC_SUBU_S_PH:
22660 case OPC_ADDSC:
22661 case OPC_ADDWC:
22662 case OPC_MODSUB:
22663 case OPC_RADDU_W_QB:
22664 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22665 break;
22666 case OPC_MULEU_S_PH_QBL:
22667 case OPC_MULEU_S_PH_QBR:
22668 case OPC_MULQ_RS_PH:
22669 case OPC_MULEQ_S_W_PHL:
22670 case OPC_MULEQ_S_W_PHR:
22671 case OPC_MULQ_S_PH:
22672 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
22673 break;
22674 default: /* Invalid */
22675 MIPS_INVAL("MASK ADDU.QB");
22676 generate_exception_end(ctx, EXCP_RI);
22677 break;
22680 break;
22681 case OPC_CMPU_EQ_QB_DSP:
22682 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
22683 switch (op2) {
22684 case OPC_PRECR_SRA_PH_W:
22685 case OPC_PRECR_SRA_R_PH_W:
22686 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
22687 break;
22688 case OPC_PRECR_QB_PH:
22689 case OPC_PRECRQ_QB_PH:
22690 case OPC_PRECRQ_PH_W:
22691 case OPC_PRECRQ_RS_PH_W:
22692 case OPC_PRECRQU_S_QB_PH:
22693 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22694 break;
22695 case OPC_CMPU_EQ_QB:
22696 case OPC_CMPU_LT_QB:
22697 case OPC_CMPU_LE_QB:
22698 case OPC_CMP_EQ_PH:
22699 case OPC_CMP_LT_PH:
22700 case OPC_CMP_LE_PH:
22701 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
22702 break;
22703 case OPC_CMPGU_EQ_QB:
22704 case OPC_CMPGU_LT_QB:
22705 case OPC_CMPGU_LE_QB:
22706 case OPC_CMPGDU_EQ_QB:
22707 case OPC_CMPGDU_LT_QB:
22708 case OPC_CMPGDU_LE_QB:
22709 case OPC_PICK_QB:
22710 case OPC_PICK_PH:
22711 case OPC_PACKRL_PH:
22712 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
22713 break;
22714 default: /* Invalid */
22715 MIPS_INVAL("MASK CMPU.EQ.QB");
22716 generate_exception_end(ctx, EXCP_RI);
22717 break;
22719 break;
22720 case OPC_SHLL_QB_DSP:
22721 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
22722 break;
22723 case OPC_DPA_W_PH_DSP:
22724 op2 = MASK_DPA_W_PH(ctx->opcode);
22725 switch (op2) {
22726 case OPC_DPAU_H_QBL:
22727 case OPC_DPAU_H_QBR:
22728 case OPC_DPSU_H_QBL:
22729 case OPC_DPSU_H_QBR:
22730 case OPC_DPA_W_PH:
22731 case OPC_DPAX_W_PH:
22732 case OPC_DPAQ_S_W_PH:
22733 case OPC_DPAQX_S_W_PH:
22734 case OPC_DPAQX_SA_W_PH:
22735 case OPC_DPS_W_PH:
22736 case OPC_DPSX_W_PH:
22737 case OPC_DPSQ_S_W_PH:
22738 case OPC_DPSQX_S_W_PH:
22739 case OPC_DPSQX_SA_W_PH:
22740 case OPC_MULSAQ_S_W_PH:
22741 case OPC_DPAQ_SA_L_W:
22742 case OPC_DPSQ_SA_L_W:
22743 case OPC_MAQ_S_W_PHL:
22744 case OPC_MAQ_S_W_PHR:
22745 case OPC_MAQ_SA_W_PHL:
22746 case OPC_MAQ_SA_W_PHR:
22747 case OPC_MULSA_W_PH:
22748 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
22749 break;
22750 default: /* Invalid */
22751 MIPS_INVAL("MASK DPAW.PH");
22752 generate_exception_end(ctx, EXCP_RI);
22753 break;
22755 break;
22756 case OPC_INSV_DSP:
22757 op2 = MASK_INSV(ctx->opcode);
22758 switch (op2) {
22759 case OPC_INSV:
22760 check_dsp(ctx);
22762 TCGv t0, t1;
22764 if (rt == 0) {
22765 break;
22768 t0 = tcg_temp_new();
22769 t1 = tcg_temp_new();
22771 gen_load_gpr(t0, rt);
22772 gen_load_gpr(t1, rs);
22774 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
22776 tcg_temp_free(t0);
22777 tcg_temp_free(t1);
22778 break;
22780 default: /* Invalid */
22781 MIPS_INVAL("MASK INSV");
22782 generate_exception_end(ctx, EXCP_RI);
22783 break;
22785 break;
22786 case OPC_APPEND_DSP:
22787 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
22788 break;
22789 case OPC_EXTR_W_DSP:
22790 op2 = MASK_EXTR_W(ctx->opcode);
22791 switch (op2) {
22792 case OPC_EXTR_W:
22793 case OPC_EXTR_R_W:
22794 case OPC_EXTR_RS_W:
22795 case OPC_EXTR_S_H:
22796 case OPC_EXTRV_S_H:
22797 case OPC_EXTRV_W:
22798 case OPC_EXTRV_R_W:
22799 case OPC_EXTRV_RS_W:
22800 case OPC_EXTP:
22801 case OPC_EXTPV:
22802 case OPC_EXTPDP:
22803 case OPC_EXTPDPV:
22804 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
22805 break;
22806 case OPC_RDDSP:
22807 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
22808 break;
22809 case OPC_SHILO:
22810 case OPC_SHILOV:
22811 case OPC_MTHLIP:
22812 case OPC_WRDSP:
22813 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
22814 break;
22815 default: /* Invalid */
22816 MIPS_INVAL("MASK EXTR.W");
22817 generate_exception_end(ctx, EXCP_RI);
22818 break;
22820 break;
22821 #if defined(TARGET_MIPS64)
22822 case OPC_DDIV_G_2E:
22823 case OPC_DDIVU_G_2E:
22824 case OPC_DMULT_G_2E:
22825 case OPC_DMULTU_G_2E:
22826 case OPC_DMOD_G_2E:
22827 case OPC_DMODU_G_2E:
22828 check_insn(ctx, INSN_LOONGSON2E);
22829 gen_loongson_integer(ctx, op1, rd, rs, rt);
22830 break;
22831 case OPC_ABSQ_S_QH_DSP:
22832 op2 = MASK_ABSQ_S_QH(ctx->opcode);
22833 switch (op2) {
22834 case OPC_PRECEQ_L_PWL:
22835 case OPC_PRECEQ_L_PWR:
22836 case OPC_PRECEQ_PW_QHL:
22837 case OPC_PRECEQ_PW_QHR:
22838 case OPC_PRECEQ_PW_QHLA:
22839 case OPC_PRECEQ_PW_QHRA:
22840 case OPC_PRECEQU_QH_OBL:
22841 case OPC_PRECEQU_QH_OBR:
22842 case OPC_PRECEQU_QH_OBLA:
22843 case OPC_PRECEQU_QH_OBRA:
22844 case OPC_PRECEU_QH_OBL:
22845 case OPC_PRECEU_QH_OBR:
22846 case OPC_PRECEU_QH_OBLA:
22847 case OPC_PRECEU_QH_OBRA:
22848 case OPC_ABSQ_S_OB:
22849 case OPC_ABSQ_S_PW:
22850 case OPC_ABSQ_S_QH:
22851 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22852 break;
22853 case OPC_REPL_OB:
22854 case OPC_REPL_PW:
22855 case OPC_REPL_QH:
22856 case OPC_REPLV_OB:
22857 case OPC_REPLV_PW:
22858 case OPC_REPLV_QH:
22859 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
22860 break;
22861 default: /* Invalid */
22862 MIPS_INVAL("MASK ABSQ_S.QH");
22863 generate_exception_end(ctx, EXCP_RI);
22864 break;
22866 break;
22867 case OPC_ADDU_OB_DSP:
22868 op2 = MASK_ADDU_OB(ctx->opcode);
22869 switch (op2) {
22870 case OPC_RADDU_L_OB:
22871 case OPC_SUBQ_PW:
22872 case OPC_SUBQ_S_PW:
22873 case OPC_SUBQ_QH:
22874 case OPC_SUBQ_S_QH:
22875 case OPC_SUBU_OB:
22876 case OPC_SUBU_S_OB:
22877 case OPC_SUBU_QH:
22878 case OPC_SUBU_S_QH:
22879 case OPC_SUBUH_OB:
22880 case OPC_SUBUH_R_OB:
22881 case OPC_ADDQ_PW:
22882 case OPC_ADDQ_S_PW:
22883 case OPC_ADDQ_QH:
22884 case OPC_ADDQ_S_QH:
22885 case OPC_ADDU_OB:
22886 case OPC_ADDU_S_OB:
22887 case OPC_ADDU_QH:
22888 case OPC_ADDU_S_QH:
22889 case OPC_ADDUH_OB:
22890 case OPC_ADDUH_R_OB:
22891 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22892 break;
22893 case OPC_MULEQ_S_PW_QHL:
22894 case OPC_MULEQ_S_PW_QHR:
22895 case OPC_MULEU_S_QH_OBL:
22896 case OPC_MULEU_S_QH_OBR:
22897 case OPC_MULQ_RS_QH:
22898 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
22899 break;
22900 default: /* Invalid */
22901 MIPS_INVAL("MASK ADDU.OB");
22902 generate_exception_end(ctx, EXCP_RI);
22903 break;
22905 break;
22906 case OPC_CMPU_EQ_OB_DSP:
22907 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
22908 switch (op2) {
22909 case OPC_PRECR_SRA_QH_PW:
22910 case OPC_PRECR_SRA_R_QH_PW:
22911 /* Return value is rt. */
22912 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
22913 break;
22914 case OPC_PRECR_OB_QH:
22915 case OPC_PRECRQ_OB_QH:
22916 case OPC_PRECRQ_PW_L:
22917 case OPC_PRECRQ_QH_PW:
22918 case OPC_PRECRQ_RS_QH_PW:
22919 case OPC_PRECRQU_S_OB_QH:
22920 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22921 break;
22922 case OPC_CMPU_EQ_OB:
22923 case OPC_CMPU_LT_OB:
22924 case OPC_CMPU_LE_OB:
22925 case OPC_CMP_EQ_QH:
22926 case OPC_CMP_LT_QH:
22927 case OPC_CMP_LE_QH:
22928 case OPC_CMP_EQ_PW:
22929 case OPC_CMP_LT_PW:
22930 case OPC_CMP_LE_PW:
22931 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
22932 break;
22933 case OPC_CMPGDU_EQ_OB:
22934 case OPC_CMPGDU_LT_OB:
22935 case OPC_CMPGDU_LE_OB:
22936 case OPC_CMPGU_EQ_OB:
22937 case OPC_CMPGU_LT_OB:
22938 case OPC_CMPGU_LE_OB:
22939 case OPC_PACKRL_PW:
22940 case OPC_PICK_OB:
22941 case OPC_PICK_PW:
22942 case OPC_PICK_QH:
22943 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
22944 break;
22945 default: /* Invalid */
22946 MIPS_INVAL("MASK CMPU_EQ.OB");
22947 generate_exception_end(ctx, EXCP_RI);
22948 break;
22950 break;
22951 case OPC_DAPPEND_DSP:
22952 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
22953 break;
22954 case OPC_DEXTR_W_DSP:
22955 op2 = MASK_DEXTR_W(ctx->opcode);
22956 switch (op2) {
22957 case OPC_DEXTP:
22958 case OPC_DEXTPDP:
22959 case OPC_DEXTPDPV:
22960 case OPC_DEXTPV:
22961 case OPC_DEXTR_L:
22962 case OPC_DEXTR_R_L:
22963 case OPC_DEXTR_RS_L:
22964 case OPC_DEXTR_W:
22965 case OPC_DEXTR_R_W:
22966 case OPC_DEXTR_RS_W:
22967 case OPC_DEXTR_S_H:
22968 case OPC_DEXTRV_L:
22969 case OPC_DEXTRV_R_L:
22970 case OPC_DEXTRV_RS_L:
22971 case OPC_DEXTRV_S_H:
22972 case OPC_DEXTRV_W:
22973 case OPC_DEXTRV_R_W:
22974 case OPC_DEXTRV_RS_W:
22975 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
22976 break;
22977 case OPC_DMTHLIP:
22978 case OPC_DSHILO:
22979 case OPC_DSHILOV:
22980 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
22981 break;
22982 default: /* Invalid */
22983 MIPS_INVAL("MASK EXTR.W");
22984 generate_exception_end(ctx, EXCP_RI);
22985 break;
22987 break;
22988 case OPC_DPAQ_W_QH_DSP:
22989 op2 = MASK_DPAQ_W_QH(ctx->opcode);
22990 switch (op2) {
22991 case OPC_DPAU_H_OBL:
22992 case OPC_DPAU_H_OBR:
22993 case OPC_DPSU_H_OBL:
22994 case OPC_DPSU_H_OBR:
22995 case OPC_DPA_W_QH:
22996 case OPC_DPAQ_S_W_QH:
22997 case OPC_DPS_W_QH:
22998 case OPC_DPSQ_S_W_QH:
22999 case OPC_MULSAQ_S_W_QH:
23000 case OPC_DPAQ_SA_L_PW:
23001 case OPC_DPSQ_SA_L_PW:
23002 case OPC_MULSAQ_S_L_PW:
23003 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23004 break;
23005 case OPC_MAQ_S_W_QHLL:
23006 case OPC_MAQ_S_W_QHLR:
23007 case OPC_MAQ_S_W_QHRL:
23008 case OPC_MAQ_S_W_QHRR:
23009 case OPC_MAQ_SA_W_QHLL:
23010 case OPC_MAQ_SA_W_QHLR:
23011 case OPC_MAQ_SA_W_QHRL:
23012 case OPC_MAQ_SA_W_QHRR:
23013 case OPC_MAQ_S_L_PWL:
23014 case OPC_MAQ_S_L_PWR:
23015 case OPC_DMADD:
23016 case OPC_DMADDU:
23017 case OPC_DMSUB:
23018 case OPC_DMSUBU:
23019 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23020 break;
23021 default: /* Invalid */
23022 MIPS_INVAL("MASK DPAQ.W.QH");
23023 generate_exception_end(ctx, EXCP_RI);
23024 break;
23026 break;
23027 case OPC_DINSV_DSP:
23028 op2 = MASK_INSV(ctx->opcode);
23029 switch (op2) {
23030 case OPC_DINSV:
23032 TCGv t0, t1;
23034 if (rt == 0) {
23035 break;
23037 check_dsp(ctx);
23039 t0 = tcg_temp_new();
23040 t1 = tcg_temp_new();
23042 gen_load_gpr(t0, rt);
23043 gen_load_gpr(t1, rs);
23045 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
23047 tcg_temp_free(t0);
23048 tcg_temp_free(t1);
23049 break;
23051 default: /* Invalid */
23052 MIPS_INVAL("MASK DINSV");
23053 generate_exception_end(ctx, EXCP_RI);
23054 break;
23056 break;
23057 case OPC_SHLL_OB_DSP:
23058 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23059 break;
23060 #endif
23061 default: /* Invalid */
23062 MIPS_INVAL("special3_legacy");
23063 generate_exception_end(ctx, EXCP_RI);
23064 break;
23068 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
23070 int rs, rt, rd, sa;
23071 uint32_t op1, op2;
23072 int16_t imm;
23074 rs = (ctx->opcode >> 21) & 0x1f;
23075 rt = (ctx->opcode >> 16) & 0x1f;
23076 rd = (ctx->opcode >> 11) & 0x1f;
23077 sa = (ctx->opcode >> 6) & 0x1f;
23078 imm = sextract32(ctx->opcode, 7, 9);
23080 op1 = MASK_SPECIAL3(ctx->opcode);
23083 * EVA loads and stores overlap Loongson 2E instructions decoded by
23084 * decode_opc_special3_legacy(), so be careful to allow their decoding when
23085 * EVA is absent.
23087 if (ctx->eva) {
23088 switch (op1) {
23089 case OPC_LWLE:
23090 case OPC_LWRE:
23091 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23092 /* fall through */
23093 case OPC_LBUE:
23094 case OPC_LHUE:
23095 case OPC_LBE:
23096 case OPC_LHE:
23097 case OPC_LLE:
23098 case OPC_LWE:
23099 check_cp0_enabled(ctx);
23100 gen_ld(ctx, op1, rt, rs, imm);
23101 return;
23102 case OPC_SWLE:
23103 case OPC_SWRE:
23104 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23105 /* fall through */
23106 case OPC_SBE:
23107 case OPC_SHE:
23108 case OPC_SWE:
23109 check_cp0_enabled(ctx);
23110 gen_st(ctx, op1, rt, rs, imm);
23111 return;
23112 case OPC_SCE:
23113 check_cp0_enabled(ctx);
23114 gen_st_cond(ctx, op1, rt, rs, imm);
23115 return;
23116 case OPC_CACHEE:
23117 check_cp0_enabled(ctx);
23118 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23119 gen_cache_operation(ctx, rt, rs, imm);
23121 /* Treat as NOP. */
23122 return;
23123 case OPC_PREFE:
23124 check_cp0_enabled(ctx);
23125 /* Treat as NOP. */
23126 return;
23130 switch (op1) {
23131 case OPC_EXT:
23132 case OPC_INS:
23133 check_insn(ctx, ISA_MIPS32R2);
23134 gen_bitops(ctx, op1, rt, rs, sa, rd);
23135 break;
23136 case OPC_BSHFL:
23137 op2 = MASK_BSHFL(ctx->opcode);
23138 switch (op2) {
23139 case OPC_ALIGN:
23140 case OPC_ALIGN_END:
23141 case OPC_BITSWAP:
23142 check_insn(ctx, ISA_MIPS32R6);
23143 decode_opc_special3_r6(env, ctx);
23144 break;
23145 default:
23146 check_insn(ctx, ISA_MIPS32R2);
23147 gen_bshfl(ctx, op2, rt, rd);
23148 break;
23150 break;
23151 #if defined(TARGET_MIPS64)
23152 case OPC_DEXTM:
23153 case OPC_DEXTU:
23154 case OPC_DEXT:
23155 case OPC_DINSM:
23156 case OPC_DINSU:
23157 case OPC_DINS:
23158 check_insn(ctx, ISA_MIPS64R2);
23159 check_mips_64(ctx);
23160 gen_bitops(ctx, op1, rt, rs, sa, rd);
23161 break;
23162 case OPC_DBSHFL:
23163 op2 = MASK_DBSHFL(ctx->opcode);
23164 switch (op2) {
23165 case OPC_DALIGN:
23166 case OPC_DALIGN_END:
23167 case OPC_DBITSWAP:
23168 check_insn(ctx, ISA_MIPS32R6);
23169 decode_opc_special3_r6(env, ctx);
23170 break;
23171 default:
23172 check_insn(ctx, ISA_MIPS64R2);
23173 check_mips_64(ctx);
23174 op2 = MASK_DBSHFL(ctx->opcode);
23175 gen_bshfl(ctx, op2, rt, rd);
23176 break;
23178 break;
23179 #endif
23180 case OPC_RDHWR:
23181 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
23182 break;
23183 case OPC_FORK:
23184 check_mt(ctx);
23186 TCGv t0 = tcg_temp_new();
23187 TCGv t1 = tcg_temp_new();
23189 gen_load_gpr(t0, rt);
23190 gen_load_gpr(t1, rs);
23191 gen_helper_fork(t0, t1);
23192 tcg_temp_free(t0);
23193 tcg_temp_free(t1);
23195 break;
23196 case OPC_YIELD:
23197 check_mt(ctx);
23199 TCGv t0 = tcg_temp_new();
23201 gen_load_gpr(t0, rs);
23202 gen_helper_yield(t0, cpu_env, t0);
23203 gen_store_gpr(t0, rd);
23204 tcg_temp_free(t0);
23206 break;
23207 default:
23208 if (ctx->insn_flags & ISA_MIPS32R6) {
23209 decode_opc_special3_r6(env, ctx);
23210 } else {
23211 decode_opc_special3_legacy(env, ctx);
23216 /* MIPS SIMD Architecture (MSA) */
23217 static inline int check_msa_access(DisasContext *ctx)
23219 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
23220 !(ctx->hflags & MIPS_HFLAG_F64))) {
23221 generate_exception_end(ctx, EXCP_RI);
23222 return 0;
23225 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
23226 if (ctx->insn_flags & ASE_MSA) {
23227 generate_exception_end(ctx, EXCP_MSADIS);
23228 return 0;
23229 } else {
23230 generate_exception_end(ctx, EXCP_RI);
23231 return 0;
23234 return 1;
23237 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
23239 /* generates tcg ops to check if any element is 0 */
23240 /* Note this function only works with MSA_WRLEN = 128 */
23241 uint64_t eval_zero_or_big = 0;
23242 uint64_t eval_big = 0;
23243 TCGv_i64 t0 = tcg_temp_new_i64();
23244 TCGv_i64 t1 = tcg_temp_new_i64();
23245 switch (df) {
23246 case DF_BYTE:
23247 eval_zero_or_big = 0x0101010101010101ULL;
23248 eval_big = 0x8080808080808080ULL;
23249 break;
23250 case DF_HALF:
23251 eval_zero_or_big = 0x0001000100010001ULL;
23252 eval_big = 0x8000800080008000ULL;
23253 break;
23254 case DF_WORD:
23255 eval_zero_or_big = 0x0000000100000001ULL;
23256 eval_big = 0x8000000080000000ULL;
23257 break;
23258 case DF_DOUBLE:
23259 eval_zero_or_big = 0x0000000000000001ULL;
23260 eval_big = 0x8000000000000000ULL;
23261 break;
23263 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
23264 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
23265 tcg_gen_andi_i64(t0, t0, eval_big);
23266 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
23267 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
23268 tcg_gen_andi_i64(t1, t1, eval_big);
23269 tcg_gen_or_i64(t0, t0, t1);
23270 /* if all bits are zero then all elements are not zero */
23271 /* if some bit is non-zero then some element is zero */
23272 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
23273 tcg_gen_trunc_i64_tl(tresult, t0);
23274 tcg_temp_free_i64(t0);
23275 tcg_temp_free_i64(t1);
23278 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
23280 uint8_t df = (ctx->opcode >> 21) & 0x3;
23281 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
23282 int64_t s16 = (int16_t)ctx->opcode;
23284 check_msa_access(ctx);
23286 if (ctx->hflags & MIPS_HFLAG_BMASK) {
23287 generate_exception_end(ctx, EXCP_RI);
23288 return;
23290 switch (op1) {
23291 case OPC_BZ_V:
23292 case OPC_BNZ_V:
23294 TCGv_i64 t0 = tcg_temp_new_i64();
23295 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
23296 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
23297 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
23298 tcg_gen_trunc_i64_tl(bcond, t0);
23299 tcg_temp_free_i64(t0);
23301 break;
23302 case OPC_BZ_B:
23303 case OPC_BZ_H:
23304 case OPC_BZ_W:
23305 case OPC_BZ_D:
23306 gen_check_zero_element(bcond, df, wt);
23307 break;
23308 case OPC_BNZ_B:
23309 case OPC_BNZ_H:
23310 case OPC_BNZ_W:
23311 case OPC_BNZ_D:
23312 gen_check_zero_element(bcond, df, wt);
23313 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
23314 break;
23317 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
23319 ctx->hflags |= MIPS_HFLAG_BC;
23320 ctx->hflags |= MIPS_HFLAG_BDS32;
23323 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
23325 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
23326 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
23327 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23328 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23330 TCGv_i32 twd = tcg_const_i32(wd);
23331 TCGv_i32 tws = tcg_const_i32(ws);
23332 TCGv_i32 ti8 = tcg_const_i32(i8);
23334 switch (MASK_MSA_I8(ctx->opcode)) {
23335 case OPC_ANDI_B:
23336 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
23337 break;
23338 case OPC_ORI_B:
23339 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
23340 break;
23341 case OPC_NORI_B:
23342 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
23343 break;
23344 case OPC_XORI_B:
23345 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
23346 break;
23347 case OPC_BMNZI_B:
23348 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
23349 break;
23350 case OPC_BMZI_B:
23351 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
23352 break;
23353 case OPC_BSELI_B:
23354 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
23355 break;
23356 case OPC_SHF_B:
23357 case OPC_SHF_H:
23358 case OPC_SHF_W:
23360 uint8_t df = (ctx->opcode >> 24) & 0x3;
23361 if (df == DF_DOUBLE) {
23362 generate_exception_end(ctx, EXCP_RI);
23363 } else {
23364 TCGv_i32 tdf = tcg_const_i32(df);
23365 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
23366 tcg_temp_free_i32(tdf);
23369 break;
23370 default:
23371 MIPS_INVAL("MSA instruction");
23372 generate_exception_end(ctx, EXCP_RI);
23373 break;
23376 tcg_temp_free_i32(twd);
23377 tcg_temp_free_i32(tws);
23378 tcg_temp_free_i32(ti8);
23381 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
23383 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
23384 uint8_t df = (ctx->opcode >> 21) & 0x3;
23385 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
23386 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
23387 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23388 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23390 TCGv_i32 tdf = tcg_const_i32(df);
23391 TCGv_i32 twd = tcg_const_i32(wd);
23392 TCGv_i32 tws = tcg_const_i32(ws);
23393 TCGv_i32 timm = tcg_temp_new_i32();
23394 tcg_gen_movi_i32(timm, u5);
23396 switch (MASK_MSA_I5(ctx->opcode)) {
23397 case OPC_ADDVI_df:
23398 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
23399 break;
23400 case OPC_SUBVI_df:
23401 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
23402 break;
23403 case OPC_MAXI_S_df:
23404 tcg_gen_movi_i32(timm, s5);
23405 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
23406 break;
23407 case OPC_MAXI_U_df:
23408 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
23409 break;
23410 case OPC_MINI_S_df:
23411 tcg_gen_movi_i32(timm, s5);
23412 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
23413 break;
23414 case OPC_MINI_U_df:
23415 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
23416 break;
23417 case OPC_CEQI_df:
23418 tcg_gen_movi_i32(timm, s5);
23419 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
23420 break;
23421 case OPC_CLTI_S_df:
23422 tcg_gen_movi_i32(timm, s5);
23423 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
23424 break;
23425 case OPC_CLTI_U_df:
23426 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
23427 break;
23428 case OPC_CLEI_S_df:
23429 tcg_gen_movi_i32(timm, s5);
23430 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
23431 break;
23432 case OPC_CLEI_U_df:
23433 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
23434 break;
23435 case OPC_LDI_df:
23437 int32_t s10 = sextract32(ctx->opcode, 11, 10);
23438 tcg_gen_movi_i32(timm, s10);
23439 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
23441 break;
23442 default:
23443 MIPS_INVAL("MSA instruction");
23444 generate_exception_end(ctx, EXCP_RI);
23445 break;
23448 tcg_temp_free_i32(tdf);
23449 tcg_temp_free_i32(twd);
23450 tcg_temp_free_i32(tws);
23451 tcg_temp_free_i32(timm);
23454 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
23456 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
23457 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
23458 uint32_t df = 0, m = 0;
23459 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23460 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23462 TCGv_i32 tdf;
23463 TCGv_i32 tm;
23464 TCGv_i32 twd;
23465 TCGv_i32 tws;
23467 if ((dfm & 0x40) == 0x00) {
23468 m = dfm & 0x3f;
23469 df = DF_DOUBLE;
23470 } else if ((dfm & 0x60) == 0x40) {
23471 m = dfm & 0x1f;
23472 df = DF_WORD;
23473 } else if ((dfm & 0x70) == 0x60) {
23474 m = dfm & 0x0f;
23475 df = DF_HALF;
23476 } else if ((dfm & 0x78) == 0x70) {
23477 m = dfm & 0x7;
23478 df = DF_BYTE;
23479 } else {
23480 generate_exception_end(ctx, EXCP_RI);
23481 return;
23484 tdf = tcg_const_i32(df);
23485 tm = tcg_const_i32(m);
23486 twd = tcg_const_i32(wd);
23487 tws = tcg_const_i32(ws);
23489 switch (MASK_MSA_BIT(ctx->opcode)) {
23490 case OPC_SLLI_df:
23491 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
23492 break;
23493 case OPC_SRAI_df:
23494 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
23495 break;
23496 case OPC_SRLI_df:
23497 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
23498 break;
23499 case OPC_BCLRI_df:
23500 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
23501 break;
23502 case OPC_BSETI_df:
23503 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
23504 break;
23505 case OPC_BNEGI_df:
23506 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
23507 break;
23508 case OPC_BINSLI_df:
23509 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
23510 break;
23511 case OPC_BINSRI_df:
23512 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
23513 break;
23514 case OPC_SAT_S_df:
23515 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
23516 break;
23517 case OPC_SAT_U_df:
23518 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
23519 break;
23520 case OPC_SRARI_df:
23521 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
23522 break;
23523 case OPC_SRLRI_df:
23524 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
23525 break;
23526 default:
23527 MIPS_INVAL("MSA instruction");
23528 generate_exception_end(ctx, EXCP_RI);
23529 break;
23532 tcg_temp_free_i32(tdf);
23533 tcg_temp_free_i32(tm);
23534 tcg_temp_free_i32(twd);
23535 tcg_temp_free_i32(tws);
23538 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
23540 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
23541 uint8_t df = (ctx->opcode >> 21) & 0x3;
23542 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
23543 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23544 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23546 TCGv_i32 tdf = tcg_const_i32(df);
23547 TCGv_i32 twd = tcg_const_i32(wd);
23548 TCGv_i32 tws = tcg_const_i32(ws);
23549 TCGv_i32 twt = tcg_const_i32(wt);
23551 switch (MASK_MSA_3R(ctx->opcode)) {
23552 case OPC_SLL_df:
23553 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
23554 break;
23555 case OPC_ADDV_df:
23556 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
23557 break;
23558 case OPC_CEQ_df:
23559 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
23560 break;
23561 case OPC_ADD_A_df:
23562 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
23563 break;
23564 case OPC_SUBS_S_df:
23565 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
23566 break;
23567 case OPC_MULV_df:
23568 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
23569 break;
23570 case OPC_SLD_df:
23571 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
23572 break;
23573 case OPC_VSHF_df:
23574 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
23575 break;
23576 case OPC_SRA_df:
23577 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
23578 break;
23579 case OPC_SUBV_df:
23580 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
23581 break;
23582 case OPC_ADDS_A_df:
23583 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
23584 break;
23585 case OPC_SUBS_U_df:
23586 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
23587 break;
23588 case OPC_MADDV_df:
23589 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
23590 break;
23591 case OPC_SPLAT_df:
23592 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
23593 break;
23594 case OPC_SRAR_df:
23595 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
23596 break;
23597 case OPC_SRL_df:
23598 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
23599 break;
23600 case OPC_MAX_S_df:
23601 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
23602 break;
23603 case OPC_CLT_S_df:
23604 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
23605 break;
23606 case OPC_ADDS_S_df:
23607 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
23608 break;
23609 case OPC_SUBSUS_U_df:
23610 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
23611 break;
23612 case OPC_MSUBV_df:
23613 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
23614 break;
23615 case OPC_PCKEV_df:
23616 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
23617 break;
23618 case OPC_SRLR_df:
23619 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
23620 break;
23621 case OPC_BCLR_df:
23622 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
23623 break;
23624 case OPC_MAX_U_df:
23625 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
23626 break;
23627 case OPC_CLT_U_df:
23628 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
23629 break;
23630 case OPC_ADDS_U_df:
23631 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
23632 break;
23633 case OPC_SUBSUU_S_df:
23634 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
23635 break;
23636 case OPC_PCKOD_df:
23637 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
23638 break;
23639 case OPC_BSET_df:
23640 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
23641 break;
23642 case OPC_MIN_S_df:
23643 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
23644 break;
23645 case OPC_CLE_S_df:
23646 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
23647 break;
23648 case OPC_AVE_S_df:
23649 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
23650 break;
23651 case OPC_ASUB_S_df:
23652 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
23653 break;
23654 case OPC_DIV_S_df:
23655 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
23656 break;
23657 case OPC_ILVL_df:
23658 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
23659 break;
23660 case OPC_BNEG_df:
23661 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
23662 break;
23663 case OPC_MIN_U_df:
23664 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
23665 break;
23666 case OPC_CLE_U_df:
23667 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
23668 break;
23669 case OPC_AVE_U_df:
23670 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
23671 break;
23672 case OPC_ASUB_U_df:
23673 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
23674 break;
23675 case OPC_DIV_U_df:
23676 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
23677 break;
23678 case OPC_ILVR_df:
23679 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
23680 break;
23681 case OPC_BINSL_df:
23682 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
23683 break;
23684 case OPC_MAX_A_df:
23685 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
23686 break;
23687 case OPC_AVER_S_df:
23688 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
23689 break;
23690 case OPC_MOD_S_df:
23691 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
23692 break;
23693 case OPC_ILVEV_df:
23694 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
23695 break;
23696 case OPC_BINSR_df:
23697 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
23698 break;
23699 case OPC_MIN_A_df:
23700 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
23701 break;
23702 case OPC_AVER_U_df:
23703 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
23704 break;
23705 case OPC_MOD_U_df:
23706 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
23707 break;
23708 case OPC_ILVOD_df:
23709 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
23710 break;
23712 case OPC_DOTP_S_df:
23713 case OPC_DOTP_U_df:
23714 case OPC_DPADD_S_df:
23715 case OPC_DPADD_U_df:
23716 case OPC_DPSUB_S_df:
23717 case OPC_HADD_S_df:
23718 case OPC_DPSUB_U_df:
23719 case OPC_HADD_U_df:
23720 case OPC_HSUB_S_df:
23721 case OPC_HSUB_U_df:
23722 if (df == DF_BYTE) {
23723 generate_exception_end(ctx, EXCP_RI);
23724 break;
23726 switch (MASK_MSA_3R(ctx->opcode)) {
23727 case OPC_DOTP_S_df:
23728 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
23729 break;
23730 case OPC_DOTP_U_df:
23731 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
23732 break;
23733 case OPC_DPADD_S_df:
23734 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
23735 break;
23736 case OPC_DPADD_U_df:
23737 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
23738 break;
23739 case OPC_DPSUB_S_df:
23740 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
23741 break;
23742 case OPC_HADD_S_df:
23743 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
23744 break;
23745 case OPC_DPSUB_U_df:
23746 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
23747 break;
23748 case OPC_HADD_U_df:
23749 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
23750 break;
23751 case OPC_HSUB_S_df:
23752 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
23753 break;
23754 case OPC_HSUB_U_df:
23755 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
23756 break;
23758 break;
23759 default:
23760 MIPS_INVAL("MSA instruction");
23761 generate_exception_end(ctx, EXCP_RI);
23762 break;
23764 tcg_temp_free_i32(twd);
23765 tcg_temp_free_i32(tws);
23766 tcg_temp_free_i32(twt);
23767 tcg_temp_free_i32(tdf);
23770 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
23772 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
23773 uint8_t source = (ctx->opcode >> 11) & 0x1f;
23774 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
23775 TCGv telm = tcg_temp_new();
23776 TCGv_i32 tsr = tcg_const_i32(source);
23777 TCGv_i32 tdt = tcg_const_i32(dest);
23779 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
23780 case OPC_CTCMSA:
23781 gen_load_gpr(telm, source);
23782 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
23783 break;
23784 case OPC_CFCMSA:
23785 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
23786 gen_store_gpr(telm, dest);
23787 break;
23788 case OPC_MOVE_V:
23789 gen_helper_msa_move_v(cpu_env, tdt, tsr);
23790 break;
23791 default:
23792 MIPS_INVAL("MSA instruction");
23793 generate_exception_end(ctx, EXCP_RI);
23794 break;
23797 tcg_temp_free(telm);
23798 tcg_temp_free_i32(tdt);
23799 tcg_temp_free_i32(tsr);
23802 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
23803 uint32_t n)
23805 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
23806 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23807 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23809 TCGv_i32 tws = tcg_const_i32(ws);
23810 TCGv_i32 twd = tcg_const_i32(wd);
23811 TCGv_i32 tn = tcg_const_i32(n);
23812 TCGv_i32 tdf = tcg_const_i32(df);
23814 switch (MASK_MSA_ELM(ctx->opcode)) {
23815 case OPC_SLDI_df:
23816 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
23817 break;
23818 case OPC_SPLATI_df:
23819 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
23820 break;
23821 case OPC_INSVE_df:
23822 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
23823 break;
23824 case OPC_COPY_S_df:
23825 case OPC_COPY_U_df:
23826 case OPC_INSERT_df:
23827 #if !defined(TARGET_MIPS64)
23828 /* Double format valid only for MIPS64 */
23829 if (df == DF_DOUBLE) {
23830 generate_exception_end(ctx, EXCP_RI);
23831 break;
23833 #endif
23834 switch (MASK_MSA_ELM(ctx->opcode)) {
23835 case OPC_COPY_S_df:
23836 if (likely(wd != 0)) {
23837 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
23839 break;
23840 case OPC_COPY_U_df:
23841 if (likely(wd != 0)) {
23842 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
23844 break;
23845 case OPC_INSERT_df:
23846 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
23847 break;
23849 break;
23850 default:
23851 MIPS_INVAL("MSA instruction");
23852 generate_exception_end(ctx, EXCP_RI);
23854 tcg_temp_free_i32(twd);
23855 tcg_temp_free_i32(tws);
23856 tcg_temp_free_i32(tn);
23857 tcg_temp_free_i32(tdf);
23860 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
23862 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
23863 uint32_t df = 0, n = 0;
23865 if ((dfn & 0x30) == 0x00) {
23866 n = dfn & 0x0f;
23867 df = DF_BYTE;
23868 } else if ((dfn & 0x38) == 0x20) {
23869 n = dfn & 0x07;
23870 df = DF_HALF;
23871 } else if ((dfn & 0x3c) == 0x30) {
23872 n = dfn & 0x03;
23873 df = DF_WORD;
23874 } else if ((dfn & 0x3e) == 0x38) {
23875 n = dfn & 0x01;
23876 df = DF_DOUBLE;
23877 } else if (dfn == 0x3E) {
23878 /* CTCMSA, CFCMSA, MOVE.V */
23879 gen_msa_elm_3e(env, ctx);
23880 return;
23881 } else {
23882 generate_exception_end(ctx, EXCP_RI);
23883 return;
23886 gen_msa_elm_df(env, ctx, df, n);
23889 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
23891 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
23892 uint8_t df = (ctx->opcode >> 21) & 0x1;
23893 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
23894 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23895 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23897 TCGv_i32 twd = tcg_const_i32(wd);
23898 TCGv_i32 tws = tcg_const_i32(ws);
23899 TCGv_i32 twt = tcg_const_i32(wt);
23900 TCGv_i32 tdf = tcg_temp_new_i32();
23902 /* adjust df value for floating-point instruction */
23903 tcg_gen_movi_i32(tdf, df + 2);
23905 switch (MASK_MSA_3RF(ctx->opcode)) {
23906 case OPC_FCAF_df:
23907 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
23908 break;
23909 case OPC_FADD_df:
23910 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
23911 break;
23912 case OPC_FCUN_df:
23913 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
23914 break;
23915 case OPC_FSUB_df:
23916 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
23917 break;
23918 case OPC_FCOR_df:
23919 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
23920 break;
23921 case OPC_FCEQ_df:
23922 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
23923 break;
23924 case OPC_FMUL_df:
23925 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
23926 break;
23927 case OPC_FCUNE_df:
23928 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
23929 break;
23930 case OPC_FCUEQ_df:
23931 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
23932 break;
23933 case OPC_FDIV_df:
23934 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
23935 break;
23936 case OPC_FCNE_df:
23937 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
23938 break;
23939 case OPC_FCLT_df:
23940 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
23941 break;
23942 case OPC_FMADD_df:
23943 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
23944 break;
23945 case OPC_MUL_Q_df:
23946 tcg_gen_movi_i32(tdf, df + 1);
23947 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
23948 break;
23949 case OPC_FCULT_df:
23950 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
23951 break;
23952 case OPC_FMSUB_df:
23953 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
23954 break;
23955 case OPC_MADD_Q_df:
23956 tcg_gen_movi_i32(tdf, df + 1);
23957 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
23958 break;
23959 case OPC_FCLE_df:
23960 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
23961 break;
23962 case OPC_MSUB_Q_df:
23963 tcg_gen_movi_i32(tdf, df + 1);
23964 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
23965 break;
23966 case OPC_FCULE_df:
23967 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
23968 break;
23969 case OPC_FEXP2_df:
23970 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
23971 break;
23972 case OPC_FSAF_df:
23973 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
23974 break;
23975 case OPC_FEXDO_df:
23976 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
23977 break;
23978 case OPC_FSUN_df:
23979 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
23980 break;
23981 case OPC_FSOR_df:
23982 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
23983 break;
23984 case OPC_FSEQ_df:
23985 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
23986 break;
23987 case OPC_FTQ_df:
23988 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
23989 break;
23990 case OPC_FSUNE_df:
23991 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
23992 break;
23993 case OPC_FSUEQ_df:
23994 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
23995 break;
23996 case OPC_FSNE_df:
23997 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
23998 break;
23999 case OPC_FSLT_df:
24000 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
24001 break;
24002 case OPC_FMIN_df:
24003 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
24004 break;
24005 case OPC_MULR_Q_df:
24006 tcg_gen_movi_i32(tdf, df + 1);
24007 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
24008 break;
24009 case OPC_FSULT_df:
24010 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
24011 break;
24012 case OPC_FMIN_A_df:
24013 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
24014 break;
24015 case OPC_MADDR_Q_df:
24016 tcg_gen_movi_i32(tdf, df + 1);
24017 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
24018 break;
24019 case OPC_FSLE_df:
24020 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
24021 break;
24022 case OPC_FMAX_df:
24023 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
24024 break;
24025 case OPC_MSUBR_Q_df:
24026 tcg_gen_movi_i32(tdf, df + 1);
24027 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
24028 break;
24029 case OPC_FSULE_df:
24030 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
24031 break;
24032 case OPC_FMAX_A_df:
24033 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
24034 break;
24035 default:
24036 MIPS_INVAL("MSA instruction");
24037 generate_exception_end(ctx, EXCP_RI);
24038 break;
24041 tcg_temp_free_i32(twd);
24042 tcg_temp_free_i32(tws);
24043 tcg_temp_free_i32(twt);
24044 tcg_temp_free_i32(tdf);
24047 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
24049 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24050 (op & (0x7 << 18)))
24051 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24052 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24053 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24054 uint8_t df = (ctx->opcode >> 16) & 0x3;
24055 TCGv_i32 twd = tcg_const_i32(wd);
24056 TCGv_i32 tws = tcg_const_i32(ws);
24057 TCGv_i32 twt = tcg_const_i32(wt);
24058 TCGv_i32 tdf = tcg_const_i32(df);
24060 switch (MASK_MSA_2R(ctx->opcode)) {
24061 case OPC_FILL_df:
24062 #if !defined(TARGET_MIPS64)
24063 /* Double format valid only for MIPS64 */
24064 if (df == DF_DOUBLE) {
24065 generate_exception_end(ctx, EXCP_RI);
24066 break;
24068 #endif
24069 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
24070 break;
24071 case OPC_PCNT_df:
24072 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
24073 break;
24074 case OPC_NLOC_df:
24075 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
24076 break;
24077 case OPC_NLZC_df:
24078 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
24079 break;
24080 default:
24081 MIPS_INVAL("MSA instruction");
24082 generate_exception_end(ctx, EXCP_RI);
24083 break;
24086 tcg_temp_free_i32(twd);
24087 tcg_temp_free_i32(tws);
24088 tcg_temp_free_i32(twt);
24089 tcg_temp_free_i32(tdf);
24092 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
24094 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24095 (op & (0xf << 17)))
24096 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24097 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24098 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24099 uint8_t df = (ctx->opcode >> 16) & 0x1;
24100 TCGv_i32 twd = tcg_const_i32(wd);
24101 TCGv_i32 tws = tcg_const_i32(ws);
24102 TCGv_i32 twt = tcg_const_i32(wt);
24103 /* adjust df value for floating-point instruction */
24104 TCGv_i32 tdf = tcg_const_i32(df + 2);
24106 switch (MASK_MSA_2RF(ctx->opcode)) {
24107 case OPC_FCLASS_df:
24108 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
24109 break;
24110 case OPC_FTRUNC_S_df:
24111 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
24112 break;
24113 case OPC_FTRUNC_U_df:
24114 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
24115 break;
24116 case OPC_FSQRT_df:
24117 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
24118 break;
24119 case OPC_FRSQRT_df:
24120 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
24121 break;
24122 case OPC_FRCP_df:
24123 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
24124 break;
24125 case OPC_FRINT_df:
24126 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
24127 break;
24128 case OPC_FLOG2_df:
24129 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
24130 break;
24131 case OPC_FEXUPL_df:
24132 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
24133 break;
24134 case OPC_FEXUPR_df:
24135 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
24136 break;
24137 case OPC_FFQL_df:
24138 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
24139 break;
24140 case OPC_FFQR_df:
24141 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
24142 break;
24143 case OPC_FTINT_S_df:
24144 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
24145 break;
24146 case OPC_FTINT_U_df:
24147 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
24148 break;
24149 case OPC_FFINT_S_df:
24150 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
24151 break;
24152 case OPC_FFINT_U_df:
24153 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
24154 break;
24157 tcg_temp_free_i32(twd);
24158 tcg_temp_free_i32(tws);
24159 tcg_temp_free_i32(twt);
24160 tcg_temp_free_i32(tdf);
24163 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
24165 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
24166 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24167 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24168 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24169 TCGv_i32 twd = tcg_const_i32(wd);
24170 TCGv_i32 tws = tcg_const_i32(ws);
24171 TCGv_i32 twt = tcg_const_i32(wt);
24173 switch (MASK_MSA_VEC(ctx->opcode)) {
24174 case OPC_AND_V:
24175 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
24176 break;
24177 case OPC_OR_V:
24178 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
24179 break;
24180 case OPC_NOR_V:
24181 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
24182 break;
24183 case OPC_XOR_V:
24184 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
24185 break;
24186 case OPC_BMNZ_V:
24187 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
24188 break;
24189 case OPC_BMZ_V:
24190 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
24191 break;
24192 case OPC_BSEL_V:
24193 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
24194 break;
24195 default:
24196 MIPS_INVAL("MSA instruction");
24197 generate_exception_end(ctx, EXCP_RI);
24198 break;
24201 tcg_temp_free_i32(twd);
24202 tcg_temp_free_i32(tws);
24203 tcg_temp_free_i32(twt);
24206 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
24208 switch (MASK_MSA_VEC(ctx->opcode)) {
24209 case OPC_AND_V:
24210 case OPC_OR_V:
24211 case OPC_NOR_V:
24212 case OPC_XOR_V:
24213 case OPC_BMNZ_V:
24214 case OPC_BMZ_V:
24215 case OPC_BSEL_V:
24216 gen_msa_vec_v(env, ctx);
24217 break;
24218 case OPC_MSA_2R:
24219 gen_msa_2r(env, ctx);
24220 break;
24221 case OPC_MSA_2RF:
24222 gen_msa_2rf(env, ctx);
24223 break;
24224 default:
24225 MIPS_INVAL("MSA instruction");
24226 generate_exception_end(ctx, EXCP_RI);
24227 break;
24231 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
24233 uint32_t opcode = ctx->opcode;
24234 check_insn(ctx, ASE_MSA);
24235 check_msa_access(ctx);
24237 switch (MASK_MSA_MINOR(opcode)) {
24238 case OPC_MSA_I8_00:
24239 case OPC_MSA_I8_01:
24240 case OPC_MSA_I8_02:
24241 gen_msa_i8(env, ctx);
24242 break;
24243 case OPC_MSA_I5_06:
24244 case OPC_MSA_I5_07:
24245 gen_msa_i5(env, ctx);
24246 break;
24247 case OPC_MSA_BIT_09:
24248 case OPC_MSA_BIT_0A:
24249 gen_msa_bit(env, ctx);
24250 break;
24251 case OPC_MSA_3R_0D:
24252 case OPC_MSA_3R_0E:
24253 case OPC_MSA_3R_0F:
24254 case OPC_MSA_3R_10:
24255 case OPC_MSA_3R_11:
24256 case OPC_MSA_3R_12:
24257 case OPC_MSA_3R_13:
24258 case OPC_MSA_3R_14:
24259 case OPC_MSA_3R_15:
24260 gen_msa_3r(env, ctx);
24261 break;
24262 case OPC_MSA_ELM:
24263 gen_msa_elm(env, ctx);
24264 break;
24265 case OPC_MSA_3RF_1A:
24266 case OPC_MSA_3RF_1B:
24267 case OPC_MSA_3RF_1C:
24268 gen_msa_3rf(env, ctx);
24269 break;
24270 case OPC_MSA_VEC:
24271 gen_msa_vec(env, ctx);
24272 break;
24273 case OPC_LD_B:
24274 case OPC_LD_H:
24275 case OPC_LD_W:
24276 case OPC_LD_D:
24277 case OPC_ST_B:
24278 case OPC_ST_H:
24279 case OPC_ST_W:
24280 case OPC_ST_D:
24282 int32_t s10 = sextract32(ctx->opcode, 16, 10);
24283 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
24284 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24285 uint8_t df = (ctx->opcode >> 0) & 0x3;
24287 TCGv_i32 twd = tcg_const_i32(wd);
24288 TCGv taddr = tcg_temp_new();
24289 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
24291 switch (MASK_MSA_MINOR(opcode)) {
24292 case OPC_LD_B:
24293 gen_helper_msa_ld_b(cpu_env, twd, taddr);
24294 break;
24295 case OPC_LD_H:
24296 gen_helper_msa_ld_h(cpu_env, twd, taddr);
24297 break;
24298 case OPC_LD_W:
24299 gen_helper_msa_ld_w(cpu_env, twd, taddr);
24300 break;
24301 case OPC_LD_D:
24302 gen_helper_msa_ld_d(cpu_env, twd, taddr);
24303 break;
24304 case OPC_ST_B:
24305 gen_helper_msa_st_b(cpu_env, twd, taddr);
24306 break;
24307 case OPC_ST_H:
24308 gen_helper_msa_st_h(cpu_env, twd, taddr);
24309 break;
24310 case OPC_ST_W:
24311 gen_helper_msa_st_w(cpu_env, twd, taddr);
24312 break;
24313 case OPC_ST_D:
24314 gen_helper_msa_st_d(cpu_env, twd, taddr);
24315 break;
24318 tcg_temp_free_i32(twd);
24319 tcg_temp_free(taddr);
24321 break;
24322 default:
24323 MIPS_INVAL("MSA instruction");
24324 generate_exception_end(ctx, EXCP_RI);
24325 break;
24330 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
24332 int32_t offset;
24333 int rs, rt, rd, sa;
24334 uint32_t op, op1;
24335 int16_t imm;
24337 /* make sure instructions are on a word boundary */
24338 if (ctx->base.pc_next & 0x3) {
24339 env->CP0_BadVAddr = ctx->base.pc_next;
24340 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
24341 return;
24344 /* Handle blikely not taken case */
24345 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
24346 TCGLabel *l1 = gen_new_label();
24348 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
24349 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
24350 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
24351 gen_set_label(l1);
24354 op = MASK_OP_MAJOR(ctx->opcode);
24355 rs = (ctx->opcode >> 21) & 0x1f;
24356 rt = (ctx->opcode >> 16) & 0x1f;
24357 rd = (ctx->opcode >> 11) & 0x1f;
24358 sa = (ctx->opcode >> 6) & 0x1f;
24359 imm = (int16_t)ctx->opcode;
24360 switch (op) {
24361 case OPC_SPECIAL:
24362 decode_opc_special(env, ctx);
24363 break;
24364 case OPC_SPECIAL2:
24365 decode_opc_special2_legacy(env, ctx);
24366 break;
24367 case OPC_SPECIAL3:
24368 decode_opc_special3(env, ctx);
24369 break;
24370 case OPC_REGIMM:
24371 op1 = MASK_REGIMM(ctx->opcode);
24372 switch (op1) {
24373 case OPC_BLTZL: /* REGIMM branches */
24374 case OPC_BGEZL:
24375 case OPC_BLTZALL:
24376 case OPC_BGEZALL:
24377 check_insn(ctx, ISA_MIPS2);
24378 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24379 /* Fallthrough */
24380 case OPC_BLTZ:
24381 case OPC_BGEZ:
24382 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24383 break;
24384 case OPC_BLTZAL:
24385 case OPC_BGEZAL:
24386 if (ctx->insn_flags & ISA_MIPS32R6) {
24387 if (rs == 0) {
24388 /* OPC_NAL, OPC_BAL */
24389 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
24390 } else {
24391 generate_exception_end(ctx, EXCP_RI);
24393 } else {
24394 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24396 break;
24397 case OPC_TGEI: /* REGIMM traps */
24398 case OPC_TGEIU:
24399 case OPC_TLTI:
24400 case OPC_TLTIU:
24401 case OPC_TEQI:
24403 case OPC_TNEI:
24404 check_insn(ctx, ISA_MIPS2);
24405 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24406 gen_trap(ctx, op1, rs, -1, imm);
24407 break;
24408 case OPC_SIGRIE:
24409 check_insn(ctx, ISA_MIPS32R6);
24410 generate_exception_end(ctx, EXCP_RI);
24411 break;
24412 case OPC_SYNCI:
24413 check_insn(ctx, ISA_MIPS32R2);
24414 /* Break the TB to be able to sync copied instructions
24415 immediately */
24416 ctx->base.is_jmp = DISAS_STOP;
24417 break;
24418 case OPC_BPOSGE32: /* MIPS DSP branch */
24419 #if defined(TARGET_MIPS64)
24420 case OPC_BPOSGE64:
24421 #endif
24422 check_dsp(ctx);
24423 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
24424 break;
24425 #if defined(TARGET_MIPS64)
24426 case OPC_DAHI:
24427 check_insn(ctx, ISA_MIPS32R6);
24428 check_mips_64(ctx);
24429 if (rs != 0) {
24430 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24432 break;
24433 case OPC_DATI:
24434 check_insn(ctx, ISA_MIPS32R6);
24435 check_mips_64(ctx);
24436 if (rs != 0) {
24437 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24439 break;
24440 #endif
24441 default: /* Invalid */
24442 MIPS_INVAL("regimm");
24443 generate_exception_end(ctx, EXCP_RI);
24444 break;
24446 break;
24447 case OPC_CP0:
24448 check_cp0_enabled(ctx);
24449 op1 = MASK_CP0(ctx->opcode);
24450 switch (op1) {
24451 case OPC_MFC0:
24452 case OPC_MTC0:
24453 case OPC_MFTR:
24454 case OPC_MTTR:
24455 case OPC_MFHC0:
24456 case OPC_MTHC0:
24457 #if defined(TARGET_MIPS64)
24458 case OPC_DMFC0:
24459 case OPC_DMTC0:
24460 #endif
24461 #ifndef CONFIG_USER_ONLY
24462 gen_cp0(env, ctx, op1, rt, rd);
24463 #endif /* !CONFIG_USER_ONLY */
24464 break;
24465 case OPC_C0:
24466 case OPC_C0_1:
24467 case OPC_C0_2:
24468 case OPC_C0_3:
24469 case OPC_C0_4:
24470 case OPC_C0_5:
24471 case OPC_C0_6:
24472 case OPC_C0_7:
24473 case OPC_C0_8:
24474 case OPC_C0_9:
24475 case OPC_C0_A:
24476 case OPC_C0_B:
24477 case OPC_C0_C:
24478 case OPC_C0_D:
24479 case OPC_C0_E:
24480 case OPC_C0_F:
24481 #ifndef CONFIG_USER_ONLY
24482 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
24483 #endif /* !CONFIG_USER_ONLY */
24484 break;
24485 case OPC_MFMC0:
24486 #ifndef CONFIG_USER_ONLY
24488 uint32_t op2;
24489 TCGv t0 = tcg_temp_new();
24491 op2 = MASK_MFMC0(ctx->opcode);
24492 switch (op2) {
24493 case OPC_DMT:
24494 check_cp0_mt(ctx);
24495 gen_helper_dmt(t0);
24496 gen_store_gpr(t0, rt);
24497 break;
24498 case OPC_EMT:
24499 check_cp0_mt(ctx);
24500 gen_helper_emt(t0);
24501 gen_store_gpr(t0, rt);
24502 break;
24503 case OPC_DVPE:
24504 check_cp0_mt(ctx);
24505 gen_helper_dvpe(t0, cpu_env);
24506 gen_store_gpr(t0, rt);
24507 break;
24508 case OPC_EVPE:
24509 check_cp0_mt(ctx);
24510 gen_helper_evpe(t0, cpu_env);
24511 gen_store_gpr(t0, rt);
24512 break;
24513 case OPC_DVP:
24514 check_insn(ctx, ISA_MIPS32R6);
24515 if (ctx->vp) {
24516 gen_helper_dvp(t0, cpu_env);
24517 gen_store_gpr(t0, rt);
24519 break;
24520 case OPC_EVP:
24521 check_insn(ctx, ISA_MIPS32R6);
24522 if (ctx->vp) {
24523 gen_helper_evp(t0, cpu_env);
24524 gen_store_gpr(t0, rt);
24526 break;
24527 case OPC_DI:
24528 check_insn(ctx, ISA_MIPS32R2);
24529 save_cpu_state(ctx, 1);
24530 gen_helper_di(t0, cpu_env);
24531 gen_store_gpr(t0, rt);
24532 /* Stop translation as we may have switched
24533 the execution mode. */
24534 ctx->base.is_jmp = DISAS_STOP;
24535 break;
24536 case OPC_EI:
24537 check_insn(ctx, ISA_MIPS32R2);
24538 save_cpu_state(ctx, 1);
24539 gen_helper_ei(t0, cpu_env);
24540 gen_store_gpr(t0, rt);
24541 /* DISAS_STOP isn't sufficient, we need to ensure we break
24542 out of translated code to check for pending interrupts */
24543 gen_save_pc(ctx->base.pc_next + 4);
24544 ctx->base.is_jmp = DISAS_EXIT;
24545 break;
24546 default: /* Invalid */
24547 MIPS_INVAL("mfmc0");
24548 generate_exception_end(ctx, EXCP_RI);
24549 break;
24551 tcg_temp_free(t0);
24553 #endif /* !CONFIG_USER_ONLY */
24554 break;
24555 case OPC_RDPGPR:
24556 check_insn(ctx, ISA_MIPS32R2);
24557 gen_load_srsgpr(rt, rd);
24558 break;
24559 case OPC_WRPGPR:
24560 check_insn(ctx, ISA_MIPS32R2);
24561 gen_store_srsgpr(rt, rd);
24562 break;
24563 default:
24564 MIPS_INVAL("cp0");
24565 generate_exception_end(ctx, EXCP_RI);
24566 break;
24568 break;
24569 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
24570 if (ctx->insn_flags & ISA_MIPS32R6) {
24571 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
24572 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24573 } else {
24574 /* OPC_ADDI */
24575 /* Arithmetic with immediate opcode */
24576 gen_arith_imm(ctx, op, rt, rs, imm);
24578 break;
24579 case OPC_ADDIU:
24580 gen_arith_imm(ctx, op, rt, rs, imm);
24581 break;
24582 case OPC_SLTI: /* Set on less than with immediate opcode */
24583 case OPC_SLTIU:
24584 gen_slt_imm(ctx, op, rt, rs, imm);
24585 break;
24586 case OPC_ANDI: /* Arithmetic with immediate opcode */
24587 case OPC_LUI: /* OPC_AUI */
24588 case OPC_ORI:
24589 case OPC_XORI:
24590 gen_logic_imm(ctx, op, rt, rs, imm);
24591 break;
24592 case OPC_J: /* Jump */
24593 case OPC_JAL:
24594 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
24595 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
24596 break;
24597 /* Branch */
24598 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
24599 if (ctx->insn_flags & ISA_MIPS32R6) {
24600 if (rt == 0) {
24601 generate_exception_end(ctx, EXCP_RI);
24602 break;
24604 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
24605 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24606 } else {
24607 /* OPC_BLEZL */
24608 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24610 break;
24611 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
24612 if (ctx->insn_flags & ISA_MIPS32R6) {
24613 if (rt == 0) {
24614 generate_exception_end(ctx, EXCP_RI);
24615 break;
24617 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
24618 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24619 } else {
24620 /* OPC_BGTZL */
24621 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24623 break;
24624 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
24625 if (rt == 0) {
24626 /* OPC_BLEZ */
24627 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24628 } else {
24629 check_insn(ctx, ISA_MIPS32R6);
24630 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
24631 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24633 break;
24634 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
24635 if (rt == 0) {
24636 /* OPC_BGTZ */
24637 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24638 } else {
24639 check_insn(ctx, ISA_MIPS32R6);
24640 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
24641 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24643 break;
24644 case OPC_BEQL:
24645 case OPC_BNEL:
24646 check_insn(ctx, ISA_MIPS2);
24647 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24648 /* Fallthrough */
24649 case OPC_BEQ:
24650 case OPC_BNE:
24651 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24652 break;
24653 case OPC_LL: /* Load and stores */
24654 check_insn(ctx, ISA_MIPS2);
24655 /* Fallthrough */
24656 case OPC_LWL:
24657 case OPC_LWR:
24658 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24659 /* Fallthrough */
24660 case OPC_LB:
24661 case OPC_LH:
24662 case OPC_LW:
24663 case OPC_LWPC:
24664 case OPC_LBU:
24665 case OPC_LHU:
24666 gen_ld(ctx, op, rt, rs, imm);
24667 break;
24668 case OPC_SWL:
24669 case OPC_SWR:
24670 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24671 /* fall through */
24672 case OPC_SB:
24673 case OPC_SH:
24674 case OPC_SW:
24675 gen_st(ctx, op, rt, rs, imm);
24676 break;
24677 case OPC_SC:
24678 check_insn(ctx, ISA_MIPS2);
24679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24680 gen_st_cond(ctx, op, rt, rs, imm);
24681 break;
24682 case OPC_CACHE:
24683 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24684 check_cp0_enabled(ctx);
24685 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
24686 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24687 gen_cache_operation(ctx, rt, rs, imm);
24689 /* Treat as NOP. */
24690 break;
24691 case OPC_PREF:
24692 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24693 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24694 /* Treat as NOP. */
24695 break;
24697 /* Floating point (COP1). */
24698 case OPC_LWC1:
24699 case OPC_LDC1:
24700 case OPC_SWC1:
24701 case OPC_SDC1:
24702 gen_cop1_ldst(ctx, op, rt, rs, imm);
24703 break;
24705 case OPC_CP1:
24706 op1 = MASK_CP1(ctx->opcode);
24708 switch (op1) {
24709 case OPC_MFHC1:
24710 case OPC_MTHC1:
24711 check_cp1_enabled(ctx);
24712 check_insn(ctx, ISA_MIPS32R2);
24713 /* fall through */
24714 case OPC_MFC1:
24715 case OPC_CFC1:
24716 case OPC_MTC1:
24717 case OPC_CTC1:
24718 check_cp1_enabled(ctx);
24719 gen_cp1(ctx, op1, rt, rd);
24720 break;
24721 #if defined(TARGET_MIPS64)
24722 case OPC_DMFC1:
24723 case OPC_DMTC1:
24724 check_cp1_enabled(ctx);
24725 check_insn(ctx, ISA_MIPS3);
24726 check_mips_64(ctx);
24727 gen_cp1(ctx, op1, rt, rd);
24728 break;
24729 #endif
24730 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
24731 check_cp1_enabled(ctx);
24732 if (ctx->insn_flags & ISA_MIPS32R6) {
24733 /* OPC_BC1EQZ */
24734 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
24735 rt, imm << 2, 4);
24736 } else {
24737 /* OPC_BC1ANY2 */
24738 check_cop1x(ctx);
24739 check_insn(ctx, ASE_MIPS3D);
24740 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
24741 (rt >> 2) & 0x7, imm << 2);
24743 break;
24744 case OPC_BC1NEZ:
24745 check_cp1_enabled(ctx);
24746 check_insn(ctx, ISA_MIPS32R6);
24747 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
24748 rt, imm << 2, 4);
24749 break;
24750 case OPC_BC1ANY4:
24751 check_cp1_enabled(ctx);
24752 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24753 check_cop1x(ctx);
24754 check_insn(ctx, ASE_MIPS3D);
24755 /* fall through */
24756 case OPC_BC1:
24757 check_cp1_enabled(ctx);
24758 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24759 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
24760 (rt >> 2) & 0x7, imm << 2);
24761 break;
24762 case OPC_PS_FMT:
24763 check_ps(ctx);
24764 /* fall through */
24765 case OPC_S_FMT:
24766 case OPC_D_FMT:
24767 check_cp1_enabled(ctx);
24768 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
24769 (imm >> 8) & 0x7);
24770 break;
24771 case OPC_W_FMT:
24772 case OPC_L_FMT:
24774 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
24775 check_cp1_enabled(ctx);
24776 if (ctx->insn_flags & ISA_MIPS32R6) {
24777 switch (r6_op) {
24778 case R6_OPC_CMP_AF_S:
24779 case R6_OPC_CMP_UN_S:
24780 case R6_OPC_CMP_EQ_S:
24781 case R6_OPC_CMP_UEQ_S:
24782 case R6_OPC_CMP_LT_S:
24783 case R6_OPC_CMP_ULT_S:
24784 case R6_OPC_CMP_LE_S:
24785 case R6_OPC_CMP_ULE_S:
24786 case R6_OPC_CMP_SAF_S:
24787 case R6_OPC_CMP_SUN_S:
24788 case R6_OPC_CMP_SEQ_S:
24789 case R6_OPC_CMP_SEUQ_S:
24790 case R6_OPC_CMP_SLT_S:
24791 case R6_OPC_CMP_SULT_S:
24792 case R6_OPC_CMP_SLE_S:
24793 case R6_OPC_CMP_SULE_S:
24794 case R6_OPC_CMP_OR_S:
24795 case R6_OPC_CMP_UNE_S:
24796 case R6_OPC_CMP_NE_S:
24797 case R6_OPC_CMP_SOR_S:
24798 case R6_OPC_CMP_SUNE_S:
24799 case R6_OPC_CMP_SNE_S:
24800 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
24801 break;
24802 case R6_OPC_CMP_AF_D:
24803 case R6_OPC_CMP_UN_D:
24804 case R6_OPC_CMP_EQ_D:
24805 case R6_OPC_CMP_UEQ_D:
24806 case R6_OPC_CMP_LT_D:
24807 case R6_OPC_CMP_ULT_D:
24808 case R6_OPC_CMP_LE_D:
24809 case R6_OPC_CMP_ULE_D:
24810 case R6_OPC_CMP_SAF_D:
24811 case R6_OPC_CMP_SUN_D:
24812 case R6_OPC_CMP_SEQ_D:
24813 case R6_OPC_CMP_SEUQ_D:
24814 case R6_OPC_CMP_SLT_D:
24815 case R6_OPC_CMP_SULT_D:
24816 case R6_OPC_CMP_SLE_D:
24817 case R6_OPC_CMP_SULE_D:
24818 case R6_OPC_CMP_OR_D:
24819 case R6_OPC_CMP_UNE_D:
24820 case R6_OPC_CMP_NE_D:
24821 case R6_OPC_CMP_SOR_D:
24822 case R6_OPC_CMP_SUNE_D:
24823 case R6_OPC_CMP_SNE_D:
24824 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
24825 break;
24826 default:
24827 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
24828 rt, rd, sa, (imm >> 8) & 0x7);
24830 break;
24832 } else {
24833 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
24834 (imm >> 8) & 0x7);
24836 break;
24838 case OPC_BZ_V:
24839 case OPC_BNZ_V:
24840 case OPC_BZ_B:
24841 case OPC_BZ_H:
24842 case OPC_BZ_W:
24843 case OPC_BZ_D:
24844 case OPC_BNZ_B:
24845 case OPC_BNZ_H:
24846 case OPC_BNZ_W:
24847 case OPC_BNZ_D:
24848 check_insn(ctx, ASE_MSA);
24849 gen_msa_branch(env, ctx, op1);
24850 break;
24851 default:
24852 MIPS_INVAL("cp1");
24853 generate_exception_end(ctx, EXCP_RI);
24854 break;
24856 break;
24858 /* Compact branches [R6] and COP2 [non-R6] */
24859 case OPC_BC: /* OPC_LWC2 */
24860 case OPC_BALC: /* OPC_SWC2 */
24861 if (ctx->insn_flags & ISA_MIPS32R6) {
24862 /* OPC_BC, OPC_BALC */
24863 gen_compute_compact_branch(ctx, op, 0, 0,
24864 sextract32(ctx->opcode << 2, 0, 28));
24865 } else {
24866 /* OPC_LWC2, OPC_SWC2 */
24867 /* COP2: Not implemented. */
24868 generate_exception_err(ctx, EXCP_CpU, 2);
24870 break;
24871 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
24872 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
24873 if (ctx->insn_flags & ISA_MIPS32R6) {
24874 if (rs != 0) {
24875 /* OPC_BEQZC, OPC_BNEZC */
24876 gen_compute_compact_branch(ctx, op, rs, 0,
24877 sextract32(ctx->opcode << 2, 0, 23));
24878 } else {
24879 /* OPC_JIC, OPC_JIALC */
24880 gen_compute_compact_branch(ctx, op, 0, rt, imm);
24882 } else {
24883 /* OPC_LWC2, OPC_SWC2 */
24884 /* COP2: Not implemented. */
24885 generate_exception_err(ctx, EXCP_CpU, 2);
24887 break;
24888 case OPC_CP2:
24889 check_insn(ctx, INSN_LOONGSON2F);
24890 /* Note that these instructions use different fields. */
24891 gen_loongson_multimedia(ctx, sa, rd, rt);
24892 break;
24894 case OPC_CP3:
24895 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24896 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
24897 check_cp1_enabled(ctx);
24898 op1 = MASK_CP3(ctx->opcode);
24899 switch (op1) {
24900 case OPC_LUXC1:
24901 case OPC_SUXC1:
24902 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
24903 /* Fallthrough */
24904 case OPC_LWXC1:
24905 case OPC_LDXC1:
24906 case OPC_SWXC1:
24907 case OPC_SDXC1:
24908 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
24909 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
24910 break;
24911 case OPC_PREFX:
24912 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
24913 /* Treat as NOP. */
24914 break;
24915 case OPC_ALNV_PS:
24916 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
24917 /* Fallthrough */
24918 case OPC_MADD_S:
24919 case OPC_MADD_D:
24920 case OPC_MADD_PS:
24921 case OPC_MSUB_S:
24922 case OPC_MSUB_D:
24923 case OPC_MSUB_PS:
24924 case OPC_NMADD_S:
24925 case OPC_NMADD_D:
24926 case OPC_NMADD_PS:
24927 case OPC_NMSUB_S:
24928 case OPC_NMSUB_D:
24929 case OPC_NMSUB_PS:
24930 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
24931 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
24932 break;
24933 default:
24934 MIPS_INVAL("cp3");
24935 generate_exception_end(ctx, EXCP_RI);
24936 break;
24938 } else {
24939 generate_exception_err(ctx, EXCP_CpU, 1);
24941 break;
24943 #if defined(TARGET_MIPS64)
24944 /* MIPS64 opcodes */
24945 case OPC_LDL:
24946 case OPC_LDR:
24947 case OPC_LLD:
24948 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24949 /* fall through */
24950 case OPC_LWU:
24951 case OPC_LD:
24952 check_insn(ctx, ISA_MIPS3);
24953 check_mips_64(ctx);
24954 gen_ld(ctx, op, rt, rs, imm);
24955 break;
24956 case OPC_SDL:
24957 case OPC_SDR:
24958 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24959 /* fall through */
24960 case OPC_SD:
24961 check_insn(ctx, ISA_MIPS3);
24962 check_mips_64(ctx);
24963 gen_st(ctx, op, rt, rs, imm);
24964 break;
24965 case OPC_SCD:
24966 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24967 check_insn(ctx, ISA_MIPS3);
24968 check_mips_64(ctx);
24969 gen_st_cond(ctx, op, rt, rs, imm);
24970 break;
24971 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
24972 if (ctx->insn_flags & ISA_MIPS32R6) {
24973 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
24974 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24975 } else {
24976 /* OPC_DADDI */
24977 check_insn(ctx, ISA_MIPS3);
24978 check_mips_64(ctx);
24979 gen_arith_imm(ctx, op, rt, rs, imm);
24981 break;
24982 case OPC_DADDIU:
24983 check_insn(ctx, ISA_MIPS3);
24984 check_mips_64(ctx);
24985 gen_arith_imm(ctx, op, rt, rs, imm);
24986 break;
24987 #else
24988 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
24989 if (ctx->insn_flags & ISA_MIPS32R6) {
24990 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24991 } else {
24992 MIPS_INVAL("major opcode");
24993 generate_exception_end(ctx, EXCP_RI);
24995 break;
24996 #endif
24997 case OPC_DAUI: /* OPC_JALX */
24998 if (ctx->insn_flags & ISA_MIPS32R6) {
24999 #if defined(TARGET_MIPS64)
25000 /* OPC_DAUI */
25001 check_mips_64(ctx);
25002 if (rs == 0) {
25003 generate_exception(ctx, EXCP_RI);
25004 } else if (rt != 0) {
25005 TCGv t0 = tcg_temp_new();
25006 gen_load_gpr(t0, rs);
25007 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25008 tcg_temp_free(t0);
25010 #else
25011 generate_exception_end(ctx, EXCP_RI);
25012 MIPS_INVAL("major opcode");
25013 #endif
25014 } else {
25015 /* OPC_JALX */
25016 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25017 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25018 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25020 break;
25021 case OPC_MSA: /* OPC_MDMX */
25022 /* MDMX: Not implemented. */
25023 gen_msa(env, ctx);
25024 break;
25025 case OPC_PCREL:
25026 check_insn(ctx, ISA_MIPS32R6);
25027 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
25028 break;
25029 default: /* Invalid */
25030 MIPS_INVAL("major opcode");
25031 generate_exception_end(ctx, EXCP_RI);
25032 break;
25036 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
25038 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25039 CPUMIPSState *env = cs->env_ptr;
25041 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
25042 ctx->saved_pc = -1;
25043 ctx->insn_flags = env->insn_flags;
25044 ctx->CP0_Config1 = env->CP0_Config1;
25045 ctx->CP0_Config3 = env->CP0_Config3;
25046 ctx->CP0_Config5 = env->CP0_Config5;
25047 ctx->btarget = 0;
25048 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25049 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25050 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25051 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25052 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25053 ctx->PAMask = env->PAMask;
25054 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25055 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25056 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25057 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25058 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
25059 /* Restore delay slot state from the tb context. */
25060 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25061 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25062 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
25063 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
25064 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25065 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25066 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25067 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25068 restore_cpu_state(env, ctx);
25069 #ifdef CONFIG_USER_ONLY
25070 ctx->mem_idx = MIPS_HFLAG_UM;
25071 #else
25072 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
25073 #endif
25074 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
25075 MO_UNALN : MO_ALIGN;
25077 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25078 ctx->hflags);
25081 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25085 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25087 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25089 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25090 ctx->btarget);
25093 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25094 const CPUBreakpoint *bp)
25096 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25098 save_cpu_state(ctx, 1);
25099 ctx->base.is_jmp = DISAS_NORETURN;
25100 gen_helper_raise_exception_debug(cpu_env);
25101 /* The address covered by the breakpoint must be included in
25102 [tb->pc, tb->pc + tb->size) in order to for it to be
25103 properly cleared -- thus we increment the PC here so that
25104 the logic setting tb->size below does the right thing. */
25105 ctx->base.pc_next += 4;
25106 return true;
25109 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25111 CPUMIPSState *env = cs->env_ptr;
25112 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25113 int insn_bytes;
25114 int is_slot;
25116 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
25117 if (ctx->insn_flags & ISA_NANOMIPS32) {
25118 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25119 insn_bytes = decode_nanomips_opc(env, ctx);
25120 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
25121 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
25122 insn_bytes = 4;
25123 decode_opc(env, ctx);
25124 } else if (ctx->insn_flags & ASE_MICROMIPS) {
25125 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25126 insn_bytes = decode_micromips_opc(env, ctx);
25127 } else if (ctx->insn_flags & ASE_MIPS16) {
25128 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25129 insn_bytes = decode_mips16_opc(env, ctx);
25130 } else {
25131 generate_exception_end(ctx, EXCP_RI);
25132 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25133 return;
25136 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25137 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25138 MIPS_HFLAG_FBNSLOT))) {
25139 /* force to generate branch as there is neither delay nor
25140 forbidden slot */
25141 is_slot = 1;
25143 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25144 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
25145 /* Force to generate branch as microMIPS R6 doesn't restrict
25146 branches in the forbidden slot. */
25147 is_slot = 1;
25150 if (is_slot) {
25151 gen_branch(ctx, insn_bytes);
25153 ctx->base.pc_next += insn_bytes;
25155 if (ctx->base.is_jmp != DISAS_NEXT) {
25156 return;
25158 /* Execute a branch and its delay slot as a single instruction.
25159 This is what GDB expects and is consistent with what the
25160 hardware does (e.g. if a delay slot instruction faults, the
25161 reported PC is the PC of the branch). */
25162 if (ctx->base.singlestep_enabled &&
25163 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25164 ctx->base.is_jmp = DISAS_TOO_MANY;
25166 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25167 ctx->base.is_jmp = DISAS_TOO_MANY;
25171 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25173 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25175 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25176 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
25177 gen_helper_raise_exception_debug(cpu_env);
25178 } else {
25179 switch (ctx->base.is_jmp) {
25180 case DISAS_STOP:
25181 gen_save_pc(ctx->base.pc_next);
25182 tcg_gen_lookup_and_goto_ptr();
25183 break;
25184 case DISAS_NEXT:
25185 case DISAS_TOO_MANY:
25186 save_cpu_state(ctx, 0);
25187 gen_goto_tb(ctx, 0, ctx->base.pc_next);
25188 break;
25189 case DISAS_EXIT:
25190 tcg_gen_exit_tb(NULL, 0);
25191 break;
25192 case DISAS_NORETURN:
25193 break;
25194 default:
25195 g_assert_not_reached();
25200 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25202 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25203 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25206 static const TranslatorOps mips_tr_ops = {
25207 .init_disas_context = mips_tr_init_disas_context,
25208 .tb_start = mips_tr_tb_start,
25209 .insn_start = mips_tr_insn_start,
25210 .breakpoint_check = mips_tr_breakpoint_check,
25211 .translate_insn = mips_tr_translate_insn,
25212 .tb_stop = mips_tr_tb_stop,
25213 .disas_log = mips_tr_disas_log,
25216 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
25218 DisasContext ctx;
25220 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
25223 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
25224 int flags)
25226 int i;
25227 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
25229 #define printfpr(fp) \
25230 do { \
25231 if (is_fpu64) \
25232 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
25233 " fd:%13g fs:%13g psu: %13g\n", \
25234 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
25235 (double)(fp)->fd, \
25236 (double)(fp)->fs[FP_ENDIAN_IDX], \
25237 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
25238 else { \
25239 fpr_t tmp; \
25240 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
25241 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
25242 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
25243 " fd:%13g fs:%13g psu:%13g\n", \
25244 tmp.w[FP_ENDIAN_IDX], tmp.d, \
25245 (double)tmp.fd, \
25246 (double)tmp.fs[FP_ENDIAN_IDX], \
25247 (double)tmp.fs[!FP_ENDIAN_IDX]); \
25249 } while(0)
25252 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
25253 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
25254 get_float_exception_flags(&env->active_fpu.fp_status));
25255 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
25256 fpu_fprintf(f, "%3s: ", fregnames[i]);
25257 printfpr(&env->active_fpu.fpr[i]);
25260 #undef printfpr
25263 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
25264 int flags)
25266 MIPSCPU *cpu = MIPS_CPU(cs);
25267 CPUMIPSState *env = &cpu->env;
25268 int i;
25270 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
25271 " LO=0x" TARGET_FMT_lx " ds %04x "
25272 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
25273 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
25274 env->hflags, env->btarget, env->bcond);
25275 for (i = 0; i < 32; i++) {
25276 if ((i & 3) == 0)
25277 cpu_fprintf(f, "GPR%02d:", i);
25278 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
25279 if ((i & 3) == 3)
25280 cpu_fprintf(f, "\n");
25283 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
25284 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
25285 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
25286 PRIx64 "\n",
25287 env->CP0_Config0, env->CP0_Config1, env->lladdr);
25288 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
25289 env->CP0_Config2, env->CP0_Config3);
25290 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
25291 env->CP0_Config4, env->CP0_Config5);
25292 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
25293 fpu_dump_state(env, f, cpu_fprintf, flags);
25297 void mips_tcg_init(void)
25299 int i;
25301 cpu_gpr[0] = NULL;
25302 for (i = 1; i < 32; i++)
25303 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
25304 offsetof(CPUMIPSState, active_tc.gpr[i]),
25305 regnames[i]);
25307 for (i = 0; i < 32; i++) {
25308 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
25309 msa_wr_d[i * 2] =
25310 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
25311 /* The scalar floating-point unit (FPU) registers are mapped on
25312 * the MSA vector registers. */
25313 fpu_f64[i] = msa_wr_d[i * 2];
25314 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
25315 msa_wr_d[i * 2 + 1] =
25316 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
25319 cpu_PC = tcg_global_mem_new(cpu_env,
25320 offsetof(CPUMIPSState, active_tc.PC), "PC");
25321 for (i = 0; i < MIPS_DSP_ACC; i++) {
25322 cpu_HI[i] = tcg_global_mem_new(cpu_env,
25323 offsetof(CPUMIPSState, active_tc.HI[i]),
25324 regnames_HI[i]);
25325 cpu_LO[i] = tcg_global_mem_new(cpu_env,
25326 offsetof(CPUMIPSState, active_tc.LO[i]),
25327 regnames_LO[i]);
25329 cpu_dspctrl = tcg_global_mem_new(cpu_env,
25330 offsetof(CPUMIPSState, active_tc.DSPControl),
25331 "DSPControl");
25332 bcond = tcg_global_mem_new(cpu_env,
25333 offsetof(CPUMIPSState, bcond), "bcond");
25334 btarget = tcg_global_mem_new(cpu_env,
25335 offsetof(CPUMIPSState, btarget), "btarget");
25336 hflags = tcg_global_mem_new_i32(cpu_env,
25337 offsetof(CPUMIPSState, hflags), "hflags");
25339 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
25340 offsetof(CPUMIPSState, active_fpu.fcr0),
25341 "fcr0");
25342 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
25343 offsetof(CPUMIPSState, active_fpu.fcr31),
25344 "fcr31");
25347 #include "translate_init.inc.c"
25349 void cpu_mips_realize_env(CPUMIPSState *env)
25351 env->exception_base = (int32_t)0xBFC00000;
25353 #ifndef CONFIG_USER_ONLY
25354 mmu_init(env, env->cpu_model);
25355 #endif
25356 fpu_init(env, env->cpu_model);
25357 mvp_init(env, env->cpu_model);
25360 bool cpu_supports_cps_smp(const char *cpu_type)
25362 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
25363 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
25366 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
25368 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
25369 return (mcc->cpu_def->insn_flags & isa) != 0;
25372 void cpu_set_exception_base(int vp_index, target_ulong address)
25374 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
25375 vp->env.exception_base = address;
25378 void cpu_state_reset(CPUMIPSState *env)
25380 MIPSCPU *cpu = mips_env_get_cpu(env);
25381 CPUState *cs = CPU(cpu);
25383 /* Reset registers to their default values */
25384 env->CP0_PRid = env->cpu_model->CP0_PRid;
25385 env->CP0_Config0 = env->cpu_model->CP0_Config0;
25386 #ifdef TARGET_WORDS_BIGENDIAN
25387 env->CP0_Config0 |= (1 << CP0C0_BE);
25388 #endif
25389 env->CP0_Config1 = env->cpu_model->CP0_Config1;
25390 env->CP0_Config2 = env->cpu_model->CP0_Config2;
25391 env->CP0_Config3 = env->cpu_model->CP0_Config3;
25392 env->CP0_Config4 = env->cpu_model->CP0_Config4;
25393 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
25394 env->CP0_Config5 = env->cpu_model->CP0_Config5;
25395 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
25396 env->CP0_Config6 = env->cpu_model->CP0_Config6;
25397 env->CP0_Config7 = env->cpu_model->CP0_Config7;
25398 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
25399 << env->cpu_model->CP0_LLAddr_shift;
25400 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
25401 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
25402 env->CCRes = env->cpu_model->CCRes;
25403 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
25404 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
25405 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
25406 env->current_tc = 0;
25407 env->SEGBITS = env->cpu_model->SEGBITS;
25408 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
25409 #if defined(TARGET_MIPS64)
25410 if (env->cpu_model->insn_flags & ISA_MIPS3) {
25411 env->SEGMask |= 3ULL << 62;
25413 #endif
25414 env->PABITS = env->cpu_model->PABITS;
25415 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
25416 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
25417 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
25418 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
25419 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
25420 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
25421 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
25422 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
25423 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
25424 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
25425 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
25426 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
25427 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
25428 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
25429 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
25430 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
25431 env->msair = env->cpu_model->MSAIR;
25432 env->insn_flags = env->cpu_model->insn_flags;
25434 #if defined(CONFIG_USER_ONLY)
25435 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
25436 # ifdef TARGET_MIPS64
25437 /* Enable 64-bit register mode. */
25438 env->CP0_Status |= (1 << CP0St_PX);
25439 # endif
25440 # ifdef TARGET_ABI_MIPSN64
25441 /* Enable 64-bit address mode. */
25442 env->CP0_Status |= (1 << CP0St_UX);
25443 # endif
25444 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
25445 hardware registers. */
25446 env->CP0_HWREna |= 0x0000000F;
25447 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
25448 env->CP0_Status |= (1 << CP0St_CU1);
25450 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
25451 env->CP0_Status |= (1 << CP0St_MX);
25453 # if defined(TARGET_MIPS64)
25454 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
25455 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
25456 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
25457 env->CP0_Status |= (1 << CP0St_FR);
25459 # endif
25460 #else
25461 if (env->hflags & MIPS_HFLAG_BMASK) {
25462 /* If the exception was raised from a delay slot,
25463 come back to the jump. */
25464 env->CP0_ErrorEPC = (env->active_tc.PC
25465 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
25466 } else {
25467 env->CP0_ErrorEPC = env->active_tc.PC;
25469 env->active_tc.PC = env->exception_base;
25470 env->CP0_Random = env->tlb->nb_tlb - 1;
25471 env->tlb->tlb_in_use = env->tlb->nb_tlb;
25472 env->CP0_Wired = 0;
25473 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
25474 env->CP0_EBase = (cs->cpu_index & 0x3FF);
25475 if (mips_um_ksegs_enabled()) {
25476 env->CP0_EBase |= 0x40000000;
25477 } else {
25478 env->CP0_EBase |= (int32_t)0x80000000;
25480 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
25481 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
25483 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
25484 0x3ff : 0xff;
25485 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
25486 /* vectored interrupts not implemented, timer on int 7,
25487 no performance counters. */
25488 env->CP0_IntCtl = 0xe0000000;
25490 int i;
25492 for (i = 0; i < 7; i++) {
25493 env->CP0_WatchLo[i] = 0;
25494 env->CP0_WatchHi[i] = 0x80000000;
25496 env->CP0_WatchLo[7] = 0;
25497 env->CP0_WatchHi[7] = 0;
25499 /* Count register increments in debug mode, EJTAG version 1 */
25500 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
25502 cpu_mips_store_count(env, 1);
25504 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
25505 int i;
25507 /* Only TC0 on VPE 0 starts as active. */
25508 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
25509 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
25510 env->tcs[i].CP0_TCHalt = 1;
25512 env->active_tc.CP0_TCHalt = 1;
25513 cs->halted = 1;
25515 if (cs->cpu_index == 0) {
25516 /* VPE0 starts up enabled. */
25517 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
25518 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
25520 /* TC0 starts up unhalted. */
25521 cs->halted = 0;
25522 env->active_tc.CP0_TCHalt = 0;
25523 env->tcs[0].CP0_TCHalt = 0;
25524 /* With thread 0 active. */
25525 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
25526 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
25531 * Configure default legacy segmentation control. We use this regardless of
25532 * whether segmentation control is presented to the guest.
25534 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
25535 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
25536 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
25537 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
25538 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
25539 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
25540 (2 << CP0SC_C);
25541 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
25542 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
25543 (3 << CP0SC_C)) << 16;
25544 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
25545 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
25546 (1 << CP0SC_EU) | (2 << CP0SC_C);
25547 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
25548 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
25549 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
25550 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
25551 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
25552 #endif
25553 if ((env->insn_flags & ISA_MIPS32R6) &&
25554 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
25555 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
25556 env->CP0_Status |= (1 << CP0St_FR);
25559 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
25560 /* microMIPS on reset when Config3.ISA is 3 */
25561 env->hflags |= MIPS_HFLAG_M16;
25564 /* MSA */
25565 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
25566 msa_reset(env);
25569 compute_hflags(env);
25570 restore_fp_status(env);
25571 restore_pamask(env);
25572 cs->exception_index = EXCP_NONE;
25574 if (semihosting_get_argc()) {
25575 /* UHI interface can be used to obtain argc and argv */
25576 env->active_tc.gpr[4] = -1;
25580 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
25581 target_ulong *data)
25583 env->active_tc.PC = data[0];
25584 env->hflags &= ~MIPS_HFLAG_BMASK;
25585 env->hflags |= data[1];
25586 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
25587 case MIPS_HFLAG_BR:
25588 break;
25589 case MIPS_HFLAG_BC:
25590 case MIPS_HFLAG_BL:
25591 case MIPS_HFLAG_B:
25592 env->btarget = data[2];
25593 break;