target/mips: Add bit encoding for MXU accumulate add/sub 2-bit pattern 'aptn2'
[qemu/ar7.git] / target / mips / translate.c
blob4ccb1a93fa81d45e4302ba77316ffda9c51c30eb
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
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 (010.00 to 010.11) */
467 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
468 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
469 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
470 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
473 /* DBSHFL opcodes */
474 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
476 enum {
477 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
478 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
479 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
480 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
481 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
482 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
483 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
484 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
485 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
486 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
487 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
490 /* MIPS DSP REGIMM opcodes */
491 enum {
492 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
493 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
496 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
497 /* MIPS DSP Load */
498 enum {
499 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
500 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
501 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
502 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
505 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
506 enum {
507 /* MIPS DSP Arithmetic Sub-class */
508 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
509 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
511 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
515 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
522 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
523 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
524 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
525 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
526 /* MIPS DSP Multiply Sub-class insns */
527 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
529 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
530 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
535 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
536 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
537 enum {
538 /* MIPS DSP Arithmetic Sub-class */
539 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
551 /* MIPS DSP Multiply Sub-class insns */
552 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
553 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
554 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
555 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
558 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
559 enum {
560 /* MIPS DSP Arithmetic Sub-class */
561 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
574 /* DSP Bit/Manipulation Sub-class */
575 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
578 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
582 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583 enum {
584 /* MIPS DSP Arithmetic Sub-class */
585 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
592 /* DSP Compare-Pick Sub-class */
593 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
610 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
611 enum {
612 /* MIPS DSP GPR-Based Shift Sub-class */
613 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
637 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
638 enum {
639 /* MIPS DSP Multiply Sub-class insns */
640 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
654 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
664 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
665 enum {
666 /* DSP Bit/Manipulation Sub-class */
667 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
670 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Append Sub-class */
673 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
674 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
675 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
678 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
679 enum {
680 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
681 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
693 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
694 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
695 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
696 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
697 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
700 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701 enum {
702 /* MIPS DSP Arithmetic Sub-class */
703 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
720 /* DSP Bit/Manipulation Sub-class */
721 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
724 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
729 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
730 enum {
731 /* MIPS DSP Multiply Sub-class insns */
732 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
733 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
734 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
735 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
737 /* MIPS DSP Arithmetic Sub-class */
738 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
761 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
762 enum {
763 /* DSP Compare-Pick Sub-class */
764 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
783 /* MIPS DSP Arithmetic Sub-class */
784 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
787 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
794 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
795 enum {
796 /* DSP Append Sub-class */
797 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
798 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
799 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
800 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
803 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804 enum {
805 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
806 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
807 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
829 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
830 enum {
831 /* DSP Bit/Manipulation Sub-class */
832 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
835 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
836 enum {
837 /* MIPS DSP Multiply Sub-class insns */
838 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
866 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
867 enum {
868 /* MIPS DSP GPR-Based Shift Sub-class */
869 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
897 /* Coprocessor 0 (rs field) */
898 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
900 enum {
901 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
902 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
903 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
904 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
905 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
906 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
907 OPC_MFTR = (0x08 << 21) | OPC_CP0,
908 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
909 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
910 OPC_MTTR = (0x0C << 21) | OPC_CP0,
911 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
912 OPC_C0 = (0x10 << 21) | OPC_CP0,
913 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
914 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
915 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
916 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
917 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
918 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
919 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
920 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
921 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
922 OPC_C0_A = (0x1A << 21) | OPC_CP0,
923 OPC_C0_B = (0x1B << 21) | OPC_CP0,
924 OPC_C0_C = (0x1C << 21) | OPC_CP0,
925 OPC_C0_D = (0x1D << 21) | OPC_CP0,
926 OPC_C0_E = (0x1E << 21) | OPC_CP0,
927 OPC_C0_F = (0x1F << 21) | OPC_CP0,
930 /* MFMC0 opcodes */
931 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
933 enum {
934 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
935 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
936 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
937 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
938 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
939 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
940 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
941 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
944 /* Coprocessor 0 (with rs == C0) */
945 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
947 enum {
948 OPC_TLBR = 0x01 | OPC_C0,
949 OPC_TLBWI = 0x02 | OPC_C0,
950 OPC_TLBINV = 0x03 | OPC_C0,
951 OPC_TLBINVF = 0x04 | OPC_C0,
952 OPC_TLBWR = 0x06 | OPC_C0,
953 OPC_TLBP = 0x08 | OPC_C0,
954 OPC_RFE = 0x10 | OPC_C0,
955 OPC_ERET = 0x18 | OPC_C0,
956 OPC_DERET = 0x1F | OPC_C0,
957 OPC_WAIT = 0x20 | OPC_C0,
960 /* Coprocessor 1 (rs field) */
961 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
963 /* Values for the fmt field in FP instructions */
964 enum {
965 /* 0 - 15 are reserved */
966 FMT_S = 16, /* single fp */
967 FMT_D = 17, /* double fp */
968 FMT_E = 18, /* extended fp */
969 FMT_Q = 19, /* quad fp */
970 FMT_W = 20, /* 32-bit fixed */
971 FMT_L = 21, /* 64-bit fixed */
972 FMT_PS = 22, /* paired single fp */
973 /* 23 - 31 are reserved */
976 enum {
977 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
978 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
979 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
980 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
981 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
982 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
983 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
984 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
985 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
986 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
987 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
988 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
989 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
990 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
991 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
992 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
993 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
994 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
995 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
996 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
997 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
998 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
999 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1000 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1001 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1002 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1003 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1004 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1005 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1006 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1009 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1010 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1012 enum {
1013 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1014 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1015 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1016 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1019 enum {
1020 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1021 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1024 enum {
1025 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1026 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1029 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1031 enum {
1032 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1033 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1034 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1035 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1036 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1037 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1038 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1039 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1040 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1041 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1042 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1045 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1047 enum {
1048 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1049 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1050 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1051 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1057 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1059 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1060 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1067 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1068 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1069 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1070 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1071 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1072 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1073 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1075 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1076 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1077 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1078 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1079 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1080 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1081 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1084 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1085 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1086 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1087 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1088 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1091 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1092 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1093 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1094 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1098 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1099 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1100 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1101 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1106 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1107 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1108 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1112 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1113 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1114 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1115 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1116 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1117 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1120 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1121 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1122 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1123 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1127 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1128 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1129 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1130 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1131 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1134 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1135 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1136 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1137 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1138 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1142 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1144 enum {
1145 OPC_LWXC1 = 0x00 | OPC_CP3,
1146 OPC_LDXC1 = 0x01 | OPC_CP3,
1147 OPC_LUXC1 = 0x05 | OPC_CP3,
1148 OPC_SWXC1 = 0x08 | OPC_CP3,
1149 OPC_SDXC1 = 0x09 | OPC_CP3,
1150 OPC_SUXC1 = 0x0D | OPC_CP3,
1151 OPC_PREFX = 0x0F | OPC_CP3,
1152 OPC_ALNV_PS = 0x1E | OPC_CP3,
1153 OPC_MADD_S = 0x20 | OPC_CP3,
1154 OPC_MADD_D = 0x21 | OPC_CP3,
1155 OPC_MADD_PS = 0x26 | OPC_CP3,
1156 OPC_MSUB_S = 0x28 | OPC_CP3,
1157 OPC_MSUB_D = 0x29 | OPC_CP3,
1158 OPC_MSUB_PS = 0x2E | OPC_CP3,
1159 OPC_NMADD_S = 0x30 | OPC_CP3,
1160 OPC_NMADD_D = 0x31 | OPC_CP3,
1161 OPC_NMADD_PS= 0x36 | OPC_CP3,
1162 OPC_NMSUB_S = 0x38 | OPC_CP3,
1163 OPC_NMSUB_D = 0x39 | OPC_CP3,
1164 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1167 /* MSA Opcodes */
1168 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1169 enum {
1170 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1171 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1172 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1173 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1174 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1175 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1176 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1177 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1178 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1179 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1180 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1181 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1182 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1183 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1184 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1185 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1186 OPC_MSA_ELM = 0x19 | OPC_MSA,
1187 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1188 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1189 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1190 OPC_MSA_VEC = 0x1E | OPC_MSA,
1192 /* MI10 instruction */
1193 OPC_LD_B = (0x20) | OPC_MSA,
1194 OPC_LD_H = (0x21) | OPC_MSA,
1195 OPC_LD_W = (0x22) | OPC_MSA,
1196 OPC_LD_D = (0x23) | OPC_MSA,
1197 OPC_ST_B = (0x24) | OPC_MSA,
1198 OPC_ST_H = (0x25) | OPC_MSA,
1199 OPC_ST_W = (0x26) | OPC_MSA,
1200 OPC_ST_D = (0x27) | OPC_MSA,
1203 enum {
1204 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1205 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1206 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1207 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1208 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1209 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1210 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1211 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1212 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1213 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1214 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1215 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1216 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1218 /* I8 instruction */
1219 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1220 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1221 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1222 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1223 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1225 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1226 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1228 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1230 /* VEC/2R/2RF instruction */
1231 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1232 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1233 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1234 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1235 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1236 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1237 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1239 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1240 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1242 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1243 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1244 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1245 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1246 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1248 /* 2RF instruction df(bit 16) = _w, _d */
1249 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1250 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1251 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1252 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1253 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1254 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1255 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1256 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1257 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1258 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1259 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1260 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1261 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1262 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1263 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1264 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1266 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1267 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1268 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1269 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1270 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1272 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1274 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1275 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1276 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1277 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1278 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1279 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1280 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1281 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1282 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1283 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1284 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1285 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1286 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1287 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1288 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1289 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1290 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1292 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1293 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1294 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1295 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1296 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1297 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1298 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1299 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1300 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1301 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1302 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1303 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1304 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1305 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1306 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1307 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1308 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1309 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1310 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1311 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1312 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1313 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1314 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1315 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1316 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1317 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1318 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1319 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1320 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1321 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1322 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1323 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1324 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1325 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1326 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1327 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1328 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1329 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1331 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1332 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1333 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1334 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1335 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1336 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 /* 3RF instruction _df(bit 21) = _w, _d */
1343 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1346 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1347 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1348 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1356 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1361 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1362 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1363 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1364 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1365 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1366 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1369 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1372 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1373 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1374 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1375 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1378 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1381 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1385 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1386 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1387 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1388 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1389 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1390 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1391 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1392 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1393 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1394 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1395 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1396 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1397 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1402 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1403 * ============================================
1405 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1406 * instructions set. It is designed to fit the needs of signal, graphical and
1407 * video processing applications. MXU instruction set is used in Xburst family
1408 * of microprocessors by Ingenic.
1410 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1411 * the control register.
1413 * The notation used in MXU assembler mnemonics:
1415 * XRa, XRb, XRc, XRd - MXU registers
1416 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1417 * s12 - a subfield of an instruction code
1418 * strd2 - a subfield of an instruction code
1419 * eptn2 - a subfield of an instruction code
1420 * eptn3 - a subfield of an instruction code
1421 * optn2 - a subfield of an instruction code
1422 * optn3 - a subfield of an instruction code
1423 * sft4 - a subfield of an instruction code
1425 * Load/Store instructions Multiplication instructions
1426 * ----------------------- ---------------------------
1428 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1429 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1430 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1431 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1432 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1433 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1434 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1435 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1436 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1437 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1438 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1439 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1440 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1441 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1442 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1443 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1444 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1445 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1446 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1447 * S16SDI XRa, Rb, s10, eptn2
1448 * S8LDD XRa, Rb, s8, eptn3
1449 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1450 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1451 * S8SDI XRa, Rb, s8, eptn3
1452 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1453 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1454 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1455 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1456 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1457 * S32CPS XRa, XRb, XRc
1458 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1459 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1460 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1461 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1462 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1463 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1464 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1465 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1466 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1467 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1468 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1469 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1470 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1471 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1472 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1473 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1474 * Q8SLT XRa, XRb, XRc
1475 * Q8SLTU XRa, XRb, XRc
1476 * Q8MOVZ XRa, XRb, XRc Shift instructions
1477 * Q8MOVN XRa, XRb, XRc ------------------
1479 * D32SLL XRa, XRb, XRc, XRd, sft4
1480 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1481 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1482 * D32SARL XRa, XRb, XRc, sft4
1483 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1484 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1485 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1486 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1487 * Q16SLL XRa, XRb, XRc, XRd, sft4
1488 * Q16SLR XRa, XRb, XRc, XRd, sft4
1489 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1490 * ------------------------- Q16SLLV XRa, XRb, Rb
1491 * Q16SLRV XRa, XRb, Rb
1492 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1493 * S32ALN XRa, XRb, XRc, Rb
1494 * S32ALNI XRa, XRb, XRc, s3
1495 * S32LUI XRa, s8, optn3 Move instructions
1496 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1497 * S32EXTRV XRa, XRb, Rs, Rt
1498 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1499 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1502 * bits
1503 * 05..00
1505 * ┌─ 000000 ─ OPC_MXU_S32MADD
1506 * ├─ 000001 ─ OPC_MXU_S32MADDU
1507 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1508 * │
1509 * │ 20..18
1510 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1511 * │ ├─ 001 ─ OPC_MXU_S32MIN
1512 * │ ├─ 010 ─ OPC_MXU_D16MAX
1513 * │ ├─ 011 ─ OPC_MXU_D16MIN
1514 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1515 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1516 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1517 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1518 * ├─ 000100 ─ OPC_MXU_S32MSUB
1519 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1520 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1521 * │ ├─ 001 ─ OPC_MXU_D16SLT
1522 * │ ├─ 010 ─ OPC_MXU_D16AVG
1523 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1524 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1525 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1526 * │ └─ 111 ─ OPC_MXU_Q8ADD
1527 * │
1528 * │ 20..18
1529 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1530 * │ ├─ 010 ─ OPC_MXU_D16CPS
1531 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1532 * │ └─ 110 ─ OPC_MXU_Q16SAT
1533 * ├─ 001000 ─ OPC_MXU_D16MUL
1534 * │ 25..24
1535 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1536 * │ └─ 01 ─ OPC_MXU_D16MULE
1537 * ├─ 001010 ─ OPC_MXU_D16MAC
1538 * ├─ 001011 ─ OPC_MXU_D16MACF
1539 * ├─ 001100 ─ OPC_MXU_D16MADL
1540 * ├─ 001101 ─ OPC_MXU_S16MAD
1541 * ├─ 001110 ─ OPC_MXU_Q16ADD
1542 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1543 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1544 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1545 * │
1546 * │ 23
1547 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1548 * │ └─ 1 ─ OPC_MXU_S32STDR
1549 * │
1550 * │ 13..10
1551 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1552 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1553 * │
1554 * │ 13..10
1555 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1556 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1557 * │
1558 * │ 23
1559 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1560 * │ └─ 1 ─ OPC_MXU_S32LDIR
1561 * │
1562 * │ 23
1563 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1564 * │ └─ 1 ─ OPC_MXU_S32SDIR
1565 * │
1566 * │ 13..10
1567 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1568 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1569 * │
1570 * │ 13..10
1571 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1572 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1573 * ├─ 011000 ─ OPC_MXU_D32ADD
1574 * │ 23..22
1575 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1576 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1577 * │ └─ 10 ─ OPC_MXU_D32ASUM
1578 * ├─ 011010 ─ <not assigned>
1579 * │ 23..22
1580 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1581 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1582 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1583 * │
1584 * │ 23..22
1585 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1586 * │ ├─ 01 ─ OPC_MXU_D8SUM
1587 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1588 * ├─ 011110 ─ <not assigned>
1589 * ├─ 011111 ─ <not assigned>
1590 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1591 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1592 * ├─ 100010 ─ OPC_MXU_S8LDD
1593 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1594 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1595 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1596 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1597 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1598 * │
1599 * │ 20..18
1600 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1601 * │ ├─ 001 ─ OPC_MXU_S32ALN
1602 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1603 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1604 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1605 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1606 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1607 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1608 * ├─ 101110 ─ OPC_MXU_S32M2I
1609 * ├─ 101111 ─ OPC_MXU_S32I2M
1610 * ├─ 110000 ─ OPC_MXU_D32SLL
1611 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1612 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1613 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1614 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1615 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1616 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1617 * ├─ 110110 ─ OPC_MXU__POOL17 ─┴─ 101 ─ OPC_MXU_Q16SARV
1618 * │
1619 * ├─ 110111 ─ OPC_MXU_Q16SAR
1620 * │ 23..22
1621 * ├─ 111000 ─ OPC_MXU__POOL18 ─┬─ 00 ─ OPC_MXU_Q8MUL
1622 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1623 * │
1624 * │ 20..18
1625 * ├─ 111001 ─ OPC_MXU__POOL19 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1626 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1627 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1628 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1629 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1630 * │ └─ 101 ─ OPC_MXU_S32MOV
1631 * │
1632 * │ 23..22
1633 * ├─ 111010 ─ OPC_MXU__POOL20 ─┬─ 00 ─ OPC_MXU_Q8MAC
1634 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1635 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1636 * ├─ 111100 ─ OPC_MXU_Q8MADL
1637 * ├─ 111101 ─ OPC_MXU_S32SFL
1638 * ├─ 111110 ─ OPC_MXU_Q8SAD
1639 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1642 * Compiled after:
1644 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1645 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1648 enum {
1649 OPC_MXU_S32MADD = 0x00,
1650 OPC_MXU_S32MADDU = 0x01,
1651 /* not assigned 0x02 */
1652 OPC_MXU__POOL00 = 0x03,
1653 OPC_MXU_S32MSUB = 0x04,
1654 OPC_MXU_S32MSUBU = 0x05,
1655 OPC_MXU__POOL01 = 0x06,
1656 OPC_MXU__POOL02 = 0x07,
1657 OPC_MXU_D16MUL = 0x08,
1658 OPC_MXU__POOL03 = 0x09,
1659 OPC_MXU_D16MAC = 0x0A,
1660 OPC_MXU_D16MACF = 0x0B,
1661 OPC_MXU_D16MADL = 0x0C,
1662 OPC_MXU_S16MAD = 0x0D,
1663 OPC_MXU_Q16ADD = 0x0E,
1664 OPC_MXU_D16MACE = 0x0F,
1665 OPC_MXU__POOL04 = 0x10,
1666 OPC_MXU__POOL05 = 0x11,
1667 OPC_MXU__POOL06 = 0x12,
1668 OPC_MXU__POOL07 = 0x13,
1669 OPC_MXU__POOL08 = 0x14,
1670 OPC_MXU__POOL09 = 0x15,
1671 OPC_MXU__POOL10 = 0x16,
1672 OPC_MXU__POOL11 = 0x17,
1673 OPC_MXU_D32ADD = 0x18,
1674 OPC_MXU__POOL12 = 0x19,
1675 /* not assigned 0x1A */
1676 OPC_MXU__POOL13 = 0x1B,
1677 OPC_MXU__POOL14 = 0x1C,
1678 OPC_MXU_Q8ACCE = 0x1D,
1679 /* not assigned 0x1E */
1680 /* not assigned 0x1F */
1681 /* not assigned 0x20 */
1682 /* not assigned 0x21 */
1683 OPC_MXU_S8LDD = 0x22,
1684 OPC_MXU_S8STD = 0x23,
1685 OPC_MXU_S8LDI = 0x24,
1686 OPC_MXU_S8SDI = 0x25,
1687 OPC_MXU__POOL15 = 0x26,
1688 OPC_MXU__POOL16 = 0x27,
1689 OPC_MXU_LXB = 0x28,
1690 /* not assigned 0x29 */
1691 OPC_MXU_S16LDD = 0x2A,
1692 OPC_MXU_S16STD = 0x2B,
1693 OPC_MXU_S16LDI = 0x2C,
1694 OPC_MXU_S16SDI = 0x2D,
1695 OPC_MXU_S32M2I = 0x2E,
1696 OPC_MXU_S32I2M = 0x2F,
1697 OPC_MXU_D32SLL = 0x30,
1698 OPC_MXU_D32SLR = 0x31,
1699 OPC_MXU_D32SARL = 0x32,
1700 OPC_MXU_D32SAR = 0x33,
1701 OPC_MXU_Q16SLL = 0x34,
1702 OPC_MXU_Q16SLR = 0x35,
1703 OPC_MXU__POOL17 = 0x36,
1704 OPC_MXU_Q16SAR = 0x37,
1705 OPC_MXU__POOL18 = 0x38,
1706 OPC_MXU__POOL19 = 0x39,
1707 OPC_MXU__POOL20 = 0x3A,
1708 OPC_MXU_Q16SCOP = 0x3B,
1709 OPC_MXU_Q8MADL = 0x3C,
1710 OPC_MXU_S32SFL = 0x3D,
1711 OPC_MXU_Q8SAD = 0x3E,
1712 /* not assigned 0x3F */
1717 * MXU pool 00
1719 enum {
1720 OPC_MXU_S32MAX = 0x00,
1721 OPC_MXU_S32MIN = 0x01,
1722 OPC_MXU_D16MAX = 0x02,
1723 OPC_MXU_D16MIN = 0x03,
1724 OPC_MXU_Q8MAX = 0x04,
1725 OPC_MXU_Q8MIN = 0x05,
1726 OPC_MXU_Q8SLT = 0x06,
1727 OPC_MXU_Q8SLTU = 0x07,
1731 * MXU pool 01
1733 enum {
1734 OPC_MXU_S32SLT = 0x00,
1735 OPC_MXU_D16SLT = 0x01,
1736 OPC_MXU_D16AVG = 0x02,
1737 OPC_MXU_D16AVGR = 0x03,
1738 OPC_MXU_Q8AVG = 0x04,
1739 OPC_MXU_Q8AVGR = 0x05,
1740 OPC_MXU_Q8ADD = 0x07,
1744 * MXU pool 02
1746 enum {
1747 OPC_MXU_S32CPS = 0x00,
1748 OPC_MXU_D16CPS = 0x02,
1749 OPC_MXU_Q8ABD = 0x04,
1750 OPC_MXU_Q16SAT = 0x06,
1754 * MXU pool 03
1756 enum {
1757 OPC_MXU_D16MULF = 0x00,
1758 OPC_MXU_D16MULE = 0x01,
1762 * MXU pool 04
1764 enum {
1765 OPC_MXU_S32LDD = 0x00,
1766 OPC_MXU_S32LDDR = 0x01,
1770 * MXU pool 05
1772 enum {
1773 OPC_MXU_S32STD = 0x00,
1774 OPC_MXU_S32STDR = 0x01,
1778 * MXU pool 06
1780 enum {
1781 OPC_MXU_S32LDDV = 0x00,
1782 OPC_MXU_S32LDDVR = 0x01,
1786 * MXU pool 07
1788 enum {
1789 OPC_MXU_S32STDV = 0x00,
1790 OPC_MXU_S32STDVR = 0x01,
1794 * MXU pool 08
1796 enum {
1797 OPC_MXU_S32LDI = 0x00,
1798 OPC_MXU_S32LDIR = 0x01,
1802 * MXU pool 09
1804 enum {
1805 OPC_MXU_S32SDI = 0x00,
1806 OPC_MXU_S32SDIR = 0x01,
1810 * MXU pool 10
1812 enum {
1813 OPC_MXU_S32LDIV = 0x00,
1814 OPC_MXU_S32LDIVR = 0x01,
1818 * MXU pool 11
1820 enum {
1821 OPC_MXU_S32SDIV = 0x00,
1822 OPC_MXU_S32SDIVR = 0x01,
1826 * MXU pool 12
1828 enum {
1829 OPC_MXU_D32ACC = 0x00,
1830 OPC_MXU_D32ACCM = 0x01,
1831 OPC_MXU_D32ASUM = 0x02,
1835 * MXU pool 13
1837 enum {
1838 OPC_MXU_Q16ACC = 0x00,
1839 OPC_MXU_Q16ACCM = 0x01,
1840 OPC_MXU_Q16ASUM = 0x02,
1844 * MXU pool 14
1846 enum {
1847 OPC_MXU_Q8ADDE = 0x00,
1848 OPC_MXU_D8SUM = 0x01,
1849 OPC_MXU_D8SUMC = 0x02,
1853 * MXU pool 15
1855 enum {
1856 OPC_MXU_S32MUL = 0x00,
1857 OPC_MXU_S32MULU = 0x01,
1858 OPC_MXU_S32EXTR = 0x02,
1859 OPC_MXU_S32EXTRV = 0x03,
1863 * MXU pool 16
1865 enum {
1866 OPC_MXU_D32SARW = 0x00,
1867 OPC_MXU_S32ALN = 0x01,
1868 OPC_MXU_S32ALNI = 0x02,
1869 OPC_MXU_S32NOR = 0x03,
1870 OPC_MXU_S32AND = 0x04,
1871 OPC_MXU_S32OR = 0x05,
1872 OPC_MXU_S32XOR = 0x06,
1873 OPC_MXU_S32LUI = 0x07,
1877 * MXU pool 17
1879 enum {
1880 OPC_MXU_D32SLLV = 0x00,
1881 OPC_MXU_D32SLRV = 0x01,
1882 OPC_MXU_D32SARV = 0x03,
1883 OPC_MXU_Q16SLLV = 0x04,
1884 OPC_MXU_Q16SLRV = 0x05,
1885 OPC_MXU_Q16SARV = 0x07,
1889 * MXU pool 18
1891 enum {
1892 OPC_MXU_Q8MUL = 0x00,
1893 OPC_MXU_Q8MULSU = 0x01,
1897 * MXU pool 19
1899 enum {
1900 OPC_MXU_Q8MOVZ = 0x00,
1901 OPC_MXU_Q8MOVN = 0x01,
1902 OPC_MXU_D16MOVZ = 0x02,
1903 OPC_MXU_D16MOVN = 0x03,
1904 OPC_MXU_S32MOVZ = 0x04,
1905 OPC_MXU_S32MOVN = 0x05,
1909 * MXU pool 20
1911 enum {
1912 OPC_MXU_Q8MAC = 0x00,
1913 OPC_MXU_Q8MACSU = 0x01,
1917 * Overview of the TX79-specific instruction set
1918 * =============================================
1920 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1921 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1922 * instructions and certain multimedia instructions (MMIs). These MMIs
1923 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1924 * or sixteen 8-bit paths.
1926 * Reference:
1928 * The Toshiba TX System RISC TX79 Core Architecture manual,
1929 * https://wiki.qemu.org/File:C790.pdf
1931 * Three-Operand Multiply and Multiply-Add (4 instructions)
1932 * --------------------------------------------------------
1933 * MADD [rd,] rs, rt Multiply/Add
1934 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1935 * MULT [rd,] rs, rt Multiply (3-operand)
1936 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1938 * Multiply Instructions for Pipeline 1 (10 instructions)
1939 * ------------------------------------------------------
1940 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1941 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1942 * DIV1 rs, rt Divide Pipeline 1
1943 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1944 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1945 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1946 * MFHI1 rd Move From HI1 Register
1947 * MFLO1 rd Move From LO1 Register
1948 * MTHI1 rs Move To HI1 Register
1949 * MTLO1 rs Move To LO1 Register
1951 * Arithmetic (19 instructions)
1952 * ----------------------------
1953 * PADDB rd, rs, rt Parallel Add Byte
1954 * PSUBB rd, rs, rt Parallel Subtract Byte
1955 * PADDH rd, rs, rt Parallel Add Halfword
1956 * PSUBH rd, rs, rt Parallel Subtract Halfword
1957 * PADDW rd, rs, rt Parallel Add Word
1958 * PSUBW rd, rs, rt Parallel Subtract Word
1959 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1960 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1961 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1962 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1963 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1964 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1965 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1966 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1967 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1968 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1969 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1970 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1971 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1973 * Min/Max (4 instructions)
1974 * ------------------------
1975 * PMAXH rd, rs, rt Parallel Maximum Halfword
1976 * PMINH rd, rs, rt Parallel Minimum Halfword
1977 * PMAXW rd, rs, rt Parallel Maximum Word
1978 * PMINW rd, rs, rt Parallel Minimum Word
1980 * Absolute (2 instructions)
1981 * -------------------------
1982 * PABSH rd, rt Parallel Absolute Halfword
1983 * PABSW rd, rt Parallel Absolute Word
1985 * Logical (4 instructions)
1986 * ------------------------
1987 * PAND rd, rs, rt Parallel AND
1988 * POR rd, rs, rt Parallel OR
1989 * PXOR rd, rs, rt Parallel XOR
1990 * PNOR rd, rs, rt Parallel NOR
1992 * Shift (9 instructions)
1993 * ----------------------
1994 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
1995 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
1996 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
1997 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
1998 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
1999 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2000 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2001 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2002 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2004 * Compare (6 instructions)
2005 * ------------------------
2006 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2007 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2008 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2009 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2010 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2011 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2013 * LZC (1 instruction)
2014 * -------------------
2015 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2017 * Quadword Load and Store (2 instructions)
2018 * ----------------------------------------
2019 * LQ rt, offset(base) Load Quadword
2020 * SQ rt, offset(base) Store Quadword
2022 * Multiply and Divide (19 instructions)
2023 * -------------------------------------
2024 * PMULTW rd, rs, rt Parallel Multiply Word
2025 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2026 * PDIVW rs, rt Parallel Divide Word
2027 * PDIVUW rs, rt Parallel Divide Unsigned Word
2028 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2029 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2030 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2031 * PMULTH rd, rs, rt Parallel Multiply Halfword
2032 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2033 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2034 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2035 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2036 * PDIVBW rs, rt Parallel Divide Broadcast Word
2037 * PMFHI rd Parallel Move From HI Register
2038 * PMFLO rd Parallel Move From LO Register
2039 * PMTHI rs Parallel Move To HI Register
2040 * PMTLO rs Parallel Move To LO Register
2041 * PMFHL rd Parallel Move From HI/LO Register
2042 * PMTHL rs Parallel Move To HI/LO Register
2044 * Pack/Extend (11 instructions)
2045 * -----------------------------
2046 * PPAC5 rd, rt Parallel Pack to 5 bits
2047 * PPACB rd, rs, rt Parallel Pack to Byte
2048 * PPACH rd, rs, rt Parallel Pack to Halfword
2049 * PPACW rd, rs, rt Parallel Pack to Word
2050 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2051 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2052 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2053 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2054 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2055 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2056 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2058 * Others (16 instructions)
2059 * ------------------------
2060 * PCPYH rd, rt Parallel Copy Halfword
2061 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2062 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2063 * PREVH rd, rt Parallel Reverse Halfword
2064 * PINTH rd, rs, rt Parallel Interleave Halfword
2065 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2066 * PEXEH rd, rt Parallel Exchange Even Halfword
2067 * PEXCH rd, rt Parallel Exchange Center Halfword
2068 * PEXEW rd, rt Parallel Exchange Even Word
2069 * PEXCW rd, rt Parallel Exchange Center Word
2070 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2071 * MFSA rd Move from Shift Amount Register
2072 * MTSA rs Move to Shift Amount Register
2073 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2074 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2075 * PROT3W rd, rt Parallel Rotate 3 Words
2077 * The TX79-specific Multimedia Instruction encodings
2078 * ==================================================
2080 * TX79 Multimedia Instruction encoding table keys:
2082 * * This code is reserved for future use. An attempt to execute it
2083 * causes a Reserved Instruction exception.
2084 * % This code indicates an instruction class. The instruction word
2085 * must be further decoded by examining additional tables that show
2086 * the values for other instruction fields.
2087 * # This code is reserved for the unsupported instructions DMULT,
2088 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2089 * to execute it causes a Reserved Instruction exception.
2091 * TX79 Multimedia Instructions encoded by opcode field (MMI, LQ, SQ):
2093 * 31 26 0
2094 * +--------+----------------------------------------+
2095 * | opcode | |
2096 * +--------+----------------------------------------+
2098 * opcode bits 28..26
2099 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2100 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2101 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2102 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2103 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2104 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2105 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2106 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2107 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2108 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2109 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2112 enum {
2113 TX79_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2114 TX79_LQ = 0x1E << 26, /* Same as OPC_MSA */
2115 TX79_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2119 * TX79 Multimedia Instructions with opcode field = MMI:
2121 * 31 26 5 0
2122 * +--------+-------------------------------+--------+
2123 * | MMI | |function|
2124 * +--------+-------------------------------+--------+
2126 * function bits 2..0
2127 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2128 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2129 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2130 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2131 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2132 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2133 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2134 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2135 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2136 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2137 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2140 #define MASK_TX79_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2141 enum {
2142 TX79_MMI_MADD = 0x00 | TX79_CLASS_MMI, /* Same as OPC_MADD */
2143 TX79_MMI_MADDU = 0x01 | TX79_CLASS_MMI, /* Same as OPC_MADDU */
2144 TX79_MMI_PLZCW = 0x04 | TX79_CLASS_MMI,
2145 TX79_MMI_CLASS_MMI0 = 0x08 | TX79_CLASS_MMI,
2146 TX79_MMI_CLASS_MMI2 = 0x09 | TX79_CLASS_MMI,
2147 TX79_MMI_MFHI1 = 0x10 | TX79_CLASS_MMI, /* Same minor as OPC_MFHI */
2148 TX79_MMI_MTHI1 = 0x11 | TX79_CLASS_MMI, /* Same minor as OPC_MTHI */
2149 TX79_MMI_MFLO1 = 0x12 | TX79_CLASS_MMI, /* Same minor as OPC_MFLO */
2150 TX79_MMI_MTLO1 = 0x13 | TX79_CLASS_MMI, /* Same minor as OPC_MTLO */
2151 TX79_MMI_MULT1 = 0x18 | TX79_CLASS_MMI, /* Same minor as OPC_MULT */
2152 TX79_MMI_MULTU1 = 0x19 | TX79_CLASS_MMI, /* Same minor as OPC_MULTU */
2153 TX79_MMI_DIV1 = 0x1A | TX79_CLASS_MMI, /* Same minor as OPC_DIV */
2154 TX79_MMI_DIVU1 = 0x1B | TX79_CLASS_MMI, /* Same minor as OPC_DIVU */
2155 TX79_MMI_MADD1 = 0x20 | TX79_CLASS_MMI,
2156 TX79_MMI_MADDU1 = 0x21 | TX79_CLASS_MMI,
2157 TX79_MMI_CLASS_MMI1 = 0x28 | TX79_CLASS_MMI,
2158 TX79_MMI_CLASS_MMI3 = 0x29 | TX79_CLASS_MMI,
2159 TX79_MMI_PMFHL = 0x30 | TX79_CLASS_MMI,
2160 TX79_MMI_PMTHL = 0x31 | TX79_CLASS_MMI,
2161 TX79_MMI_PSLLH = 0x34 | TX79_CLASS_MMI,
2162 TX79_MMI_PSRLH = 0x36 | TX79_CLASS_MMI,
2163 TX79_MMI_PSRAH = 0x37 | TX79_CLASS_MMI,
2164 TX79_MMI_PSLLW = 0x3C | TX79_CLASS_MMI,
2165 TX79_MMI_PSRLW = 0x3E | TX79_CLASS_MMI,
2166 TX79_MMI_PSRAW = 0x3F | TX79_CLASS_MMI,
2170 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI0:
2172 * 31 26 10 6 5 0
2173 * +--------+----------------------+--------+--------+
2174 * | MMI | |function| MMI0 |
2175 * +--------+----------------------+--------+--------+
2177 * function bits 7..6
2178 * bits | 0 | 1 | 2 | 3
2179 * 10..8 | 00 | 01 | 10 | 11
2180 * -------+-------+-------+-------+-------
2181 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2182 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2183 * 2 010 | PADDB | PSUBB | PCGTB | *
2184 * 3 011 | * | * | * | *
2185 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2186 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2187 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2188 * 7 111 | * | * | PEXT5 | PPAC5
2191 #define MASK_TX79_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2192 enum {
2193 TX79_MMI0_PADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI0,
2194 TX79_MMI0_PSUBW = (0x01 << 6) | TX79_MMI_CLASS_MMI0,
2195 TX79_MMI0_PCGTW = (0x02 << 6) | TX79_MMI_CLASS_MMI0,
2196 TX79_MMI0_PMAXW = (0x03 << 6) | TX79_MMI_CLASS_MMI0,
2197 TX79_MMI0_PADDH = (0x04 << 6) | TX79_MMI_CLASS_MMI0,
2198 TX79_MMI0_PSUBH = (0x05 << 6) | TX79_MMI_CLASS_MMI0,
2199 TX79_MMI0_PCGTH = (0x06 << 6) | TX79_MMI_CLASS_MMI0,
2200 TX79_MMI0_PMAXH = (0x07 << 6) | TX79_MMI_CLASS_MMI0,
2201 TX79_MMI0_PADDB = (0x08 << 6) | TX79_MMI_CLASS_MMI0,
2202 TX79_MMI0_PSUBB = (0x09 << 6) | TX79_MMI_CLASS_MMI0,
2203 TX79_MMI0_PCGTB = (0x0A << 6) | TX79_MMI_CLASS_MMI0,
2204 TX79_MMI0_PADDSW = (0x10 << 6) | TX79_MMI_CLASS_MMI0,
2205 TX79_MMI0_PSUBSW = (0x11 << 6) | TX79_MMI_CLASS_MMI0,
2206 TX79_MMI0_PEXTLW = (0x12 << 6) | TX79_MMI_CLASS_MMI0,
2207 TX79_MMI0_PPACW = (0x13 << 6) | TX79_MMI_CLASS_MMI0,
2208 TX79_MMI0_PADDSH = (0x14 << 6) | TX79_MMI_CLASS_MMI0,
2209 TX79_MMI0_PSUBSH = (0x15 << 6) | TX79_MMI_CLASS_MMI0,
2210 TX79_MMI0_PEXTLH = (0x16 << 6) | TX79_MMI_CLASS_MMI0,
2211 TX79_MMI0_PPACH = (0x17 << 6) | TX79_MMI_CLASS_MMI0,
2212 TX79_MMI0_PADDSB = (0x18 << 6) | TX79_MMI_CLASS_MMI0,
2213 TX79_MMI0_PSUBSB = (0x19 << 6) | TX79_MMI_CLASS_MMI0,
2214 TX79_MMI0_PEXTLB = (0x1A << 6) | TX79_MMI_CLASS_MMI0,
2215 TX79_MMI0_PPACB = (0x1B << 6) | TX79_MMI_CLASS_MMI0,
2216 TX79_MMI0_PEXT5 = (0x1E << 6) | TX79_MMI_CLASS_MMI0,
2217 TX79_MMI0_PPAC5 = (0x1F << 6) | TX79_MMI_CLASS_MMI0,
2221 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI1:
2223 * 31 26 10 6 5 0
2224 * +--------+----------------------+--------+--------+
2225 * | MMI | |function| MMI1 |
2226 * +--------+----------------------+--------+--------+
2228 * function bits 7..6
2229 * bits | 0 | 1 | 2 | 3
2230 * 10..8 | 00 | 01 | 10 | 11
2231 * -------+-------+-------+-------+-------
2232 * 0 000 | * | PABSW | PCEQW | PMINW
2233 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2234 * 2 010 | * | * | PCEQB | *
2235 * 3 011 | * | * | * | *
2236 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2237 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2238 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2239 * 7 111 | * | * | * | *
2242 #define MASK_TX79_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2243 enum {
2244 TX79_MMI1_PABSW = (0x01 << 6) | TX79_MMI_CLASS_MMI1,
2245 TX79_MMI1_PCEQW = (0x02 << 6) | TX79_MMI_CLASS_MMI1,
2246 TX79_MMI1_PMINW = (0x03 << 6) | TX79_MMI_CLASS_MMI1,
2247 TX79_MMI1_PADSBH = (0x04 << 6) | TX79_MMI_CLASS_MMI1,
2248 TX79_MMI1_PABSH = (0x05 << 6) | TX79_MMI_CLASS_MMI1,
2249 TX79_MMI1_PCEQH = (0x06 << 6) | TX79_MMI_CLASS_MMI1,
2250 TX79_MMI1_PMINH = (0x07 << 6) | TX79_MMI_CLASS_MMI1,
2251 TX79_MMI1_PCEQB = (0x0A << 6) | TX79_MMI_CLASS_MMI1,
2252 TX79_MMI1_PADDUW = (0x10 << 6) | TX79_MMI_CLASS_MMI1,
2253 TX79_MMI1_PSUBUW = (0x11 << 6) | TX79_MMI_CLASS_MMI1,
2254 TX79_MMI1_PEXTUW = (0x12 << 6) | TX79_MMI_CLASS_MMI1,
2255 TX79_MMI1_PADDUH = (0x14 << 6) | TX79_MMI_CLASS_MMI1,
2256 TX79_MMI1_PSUBUH = (0x15 << 6) | TX79_MMI_CLASS_MMI1,
2257 TX79_MMI1_PEXTUH = (0x16 << 6) | TX79_MMI_CLASS_MMI1,
2258 TX79_MMI1_PADDUB = (0x18 << 6) | TX79_MMI_CLASS_MMI1,
2259 TX79_MMI1_PSUBUB = (0x19 << 6) | TX79_MMI_CLASS_MMI1,
2260 TX79_MMI1_PEXTUB = (0x1A << 6) | TX79_MMI_CLASS_MMI1,
2261 TX79_MMI1_QFSRV = (0x1B << 6) | TX79_MMI_CLASS_MMI1,
2265 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI2:
2267 * 31 26 10 6 5 0
2268 * +--------+----------------------+--------+--------+
2269 * | MMI | |function| MMI2 |
2270 * +--------+----------------------+--------+--------+
2272 * function bits 7..6
2273 * bits | 0 | 1 | 2 | 3
2274 * 10..8 | 00 | 01 | 10 | 11
2275 * -------+-------+-------+-------+-------
2276 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2277 * 1 001 | PMSUBW| * | * | *
2278 * 2 010 | PMFHI | PMFLO | PINTH | *
2279 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2280 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2281 * 5 101 | PMSUBH| PHMSBH| * | *
2282 * 6 110 | * | * | PEXEH | PREVH
2283 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2286 #define MASK_TX79_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2287 enum {
2288 TX79_MMI2_PMADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI2,
2289 TX79_MMI2_PSLLVW = (0x02 << 6) | TX79_MMI_CLASS_MMI2,
2290 TX79_MMI2_PSRLVW = (0x03 << 6) | TX79_MMI_CLASS_MMI2,
2291 TX79_MMI2_PMSUBW = (0x04 << 6) | TX79_MMI_CLASS_MMI2,
2292 TX79_MMI2_PMFHI = (0x08 << 6) | TX79_MMI_CLASS_MMI2,
2293 TX79_MMI2_PMFLO = (0x09 << 6) | TX79_MMI_CLASS_MMI2,
2294 TX79_MMI2_PINTH = (0x0A << 6) | TX79_MMI_CLASS_MMI2,
2295 TX79_MMI2_PMULTW = (0x0C << 6) | TX79_MMI_CLASS_MMI2,
2296 TX79_MMI2_PDIVW = (0x0D << 6) | TX79_MMI_CLASS_MMI2,
2297 TX79_MMI2_PCPYLD = (0x0E << 6) | TX79_MMI_CLASS_MMI2,
2298 TX79_MMI2_PMADDH = (0x10 << 6) | TX79_MMI_CLASS_MMI2,
2299 TX79_MMI2_PHMADH = (0x11 << 6) | TX79_MMI_CLASS_MMI2,
2300 TX79_MMI2_PAND = (0x12 << 6) | TX79_MMI_CLASS_MMI2,
2301 TX79_MMI2_PXOR = (0x13 << 6) | TX79_MMI_CLASS_MMI2,
2302 TX79_MMI2_PMSUBH = (0x14 << 6) | TX79_MMI_CLASS_MMI2,
2303 TX79_MMI2_PHMSBH = (0x15 << 6) | TX79_MMI_CLASS_MMI2,
2304 TX79_MMI2_PEXEH = (0x1A << 6) | TX79_MMI_CLASS_MMI2,
2305 TX79_MMI2_PREVH = (0x1B << 6) | TX79_MMI_CLASS_MMI2,
2306 TX79_MMI2_PMULTH = (0x1C << 6) | TX79_MMI_CLASS_MMI2,
2307 TX79_MMI2_PDIVBW = (0x1D << 6) | TX79_MMI_CLASS_MMI2,
2308 TX79_MMI2_PEXEW = (0x1E << 6) | TX79_MMI_CLASS_MMI2,
2309 TX79_MMI2_PROT3W = (0x1F << 6) | TX79_MMI_CLASS_MMI2,
2313 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI3:
2315 * 31 26 10 6 5 0
2316 * +--------+----------------------+--------+--------+
2317 * | MMI | |function| MMI3 |
2318 * +--------+----------------------+--------+--------+
2320 * function bits 7..6
2321 * bits | 0 | 1 | 2 | 3
2322 * 10..8 | 00 | 01 | 10 | 11
2323 * -------+-------+-------+-------+-------
2324 * 0 000 |PMADDUW| * | * | PSRAVW
2325 * 1 001 | * | * | * | *
2326 * 2 010 | PMTHI | PMTLO | PINTEH| *
2327 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2328 * 4 100 | * | * | POR | PNOR
2329 * 5 101 | * | * | * | *
2330 * 6 110 | * | * | PEXCH | PCPYH
2331 * 7 111 | * | * | PEXCW | *
2334 #define MASK_TX79_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2335 enum {
2336 TX79_MMI3_PMADDUW = (0x00 << 6) | TX79_MMI_CLASS_MMI3,
2337 TX79_MMI3_PSRAVW = (0x03 << 6) | TX79_MMI_CLASS_MMI3,
2338 TX79_MMI3_PMTHI = (0x08 << 6) | TX79_MMI_CLASS_MMI3,
2339 TX79_MMI3_PMTLO = (0x09 << 6) | TX79_MMI_CLASS_MMI3,
2340 TX79_MMI3_PINTEH = (0x0A << 6) | TX79_MMI_CLASS_MMI3,
2341 TX79_MMI3_PMULTUW = (0x0C << 6) | TX79_MMI_CLASS_MMI3,
2342 TX79_MMI3_PDIVUW = (0x0D << 6) | TX79_MMI_CLASS_MMI3,
2343 TX79_MMI3_PCPYUD = (0x0E << 6) | TX79_MMI_CLASS_MMI3,
2344 TX79_MMI3_POR = (0x12 << 6) | TX79_MMI_CLASS_MMI3,
2345 TX79_MMI3_PNOR = (0x13 << 6) | TX79_MMI_CLASS_MMI3,
2346 TX79_MMI3_PEXCH = (0x1A << 6) | TX79_MMI_CLASS_MMI3,
2347 TX79_MMI3_PCPYH = (0x1B << 6) | TX79_MMI_CLASS_MMI3,
2348 TX79_MMI3_PEXCW = (0x1E << 6) | TX79_MMI_CLASS_MMI3,
2351 /* global register indices */
2352 static TCGv cpu_gpr[32], cpu_PC;
2353 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2354 static TCGv cpu_dspctrl, btarget, bcond;
2355 static TCGv_i32 hflags;
2356 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2357 static TCGv_i64 fpu_f64[32];
2358 static TCGv_i64 msa_wr_d[64];
2360 /* MXU registers */
2361 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2362 static TCGv mxu_CR;
2364 #include "exec/gen-icount.h"
2366 #define gen_helper_0e0i(name, arg) do { \
2367 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2368 gen_helper_##name(cpu_env, helper_tmp); \
2369 tcg_temp_free_i32(helper_tmp); \
2370 } while(0)
2372 #define gen_helper_0e1i(name, arg1, arg2) do { \
2373 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2374 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2375 tcg_temp_free_i32(helper_tmp); \
2376 } while(0)
2378 #define gen_helper_1e0i(name, ret, arg1) do { \
2379 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2380 gen_helper_##name(ret, cpu_env, helper_tmp); \
2381 tcg_temp_free_i32(helper_tmp); \
2382 } while(0)
2384 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2385 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2386 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2387 tcg_temp_free_i32(helper_tmp); \
2388 } while(0)
2390 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2391 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2392 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2393 tcg_temp_free_i32(helper_tmp); \
2394 } while(0)
2396 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2397 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2398 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2399 tcg_temp_free_i32(helper_tmp); \
2400 } while(0)
2402 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2403 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2404 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2405 tcg_temp_free_i32(helper_tmp); \
2406 } while(0)
2408 typedef struct DisasContext {
2409 DisasContextBase base;
2410 target_ulong saved_pc;
2411 target_ulong page_start;
2412 uint32_t opcode;
2413 uint64_t insn_flags;
2414 int32_t CP0_Config1;
2415 int32_t CP0_Config2;
2416 int32_t CP0_Config3;
2417 int32_t CP0_Config5;
2418 /* Routine used to access memory */
2419 int mem_idx;
2420 TCGMemOp default_tcg_memop_mask;
2421 uint32_t hflags, saved_hflags;
2422 target_ulong btarget;
2423 bool ulri;
2424 int kscrexist;
2425 bool rxi;
2426 int ie;
2427 bool bi;
2428 bool bp;
2429 uint64_t PAMask;
2430 bool mvh;
2431 bool eva;
2432 bool sc;
2433 int CP0_LLAddr_shift;
2434 bool ps;
2435 bool vp;
2436 bool cmgcr;
2437 bool mrp;
2438 bool nan2008;
2439 bool abs2008;
2440 } DisasContext;
2442 #define DISAS_STOP DISAS_TARGET_0
2443 #define DISAS_EXIT DISAS_TARGET_1
2445 static const char * const regnames[] = {
2446 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2447 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2448 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2449 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2452 static const char * const regnames_HI[] = {
2453 "HI0", "HI1", "HI2", "HI3",
2456 static const char * const regnames_LO[] = {
2457 "LO0", "LO1", "LO2", "LO3",
2460 static const char * const fregnames[] = {
2461 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2462 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2463 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2464 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2467 static const char * const msaregnames[] = {
2468 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2469 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2470 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2471 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2472 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2473 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2474 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2475 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2476 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2477 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2478 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2479 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2480 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2481 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2482 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2483 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2486 static const char * const mxuregnames[] = {
2487 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2488 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2491 #define LOG_DISAS(...) \
2492 do { \
2493 if (MIPS_DEBUG_DISAS) { \
2494 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2496 } while (0)
2498 #define MIPS_INVAL(op) \
2499 do { \
2500 if (MIPS_DEBUG_DISAS) { \
2501 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2502 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2503 ctx->base.pc_next, ctx->opcode, op, \
2504 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2505 ((ctx->opcode >> 16) & 0x1F)); \
2507 } while (0)
2509 /* General purpose registers moves. */
2510 static inline void gen_load_gpr (TCGv t, int reg)
2512 if (reg == 0)
2513 tcg_gen_movi_tl(t, 0);
2514 else
2515 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2518 static inline void gen_store_gpr (TCGv t, int reg)
2520 if (reg != 0)
2521 tcg_gen_mov_tl(cpu_gpr[reg], t);
2524 /* Moves to/from shadow registers. */
2525 static inline void gen_load_srsgpr (int from, int to)
2527 TCGv t0 = tcg_temp_new();
2529 if (from == 0)
2530 tcg_gen_movi_tl(t0, 0);
2531 else {
2532 TCGv_i32 t2 = tcg_temp_new_i32();
2533 TCGv_ptr addr = tcg_temp_new_ptr();
2535 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2536 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2537 tcg_gen_andi_i32(t2, t2, 0xf);
2538 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2539 tcg_gen_ext_i32_ptr(addr, t2);
2540 tcg_gen_add_ptr(addr, cpu_env, addr);
2542 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2543 tcg_temp_free_ptr(addr);
2544 tcg_temp_free_i32(t2);
2546 gen_store_gpr(t0, to);
2547 tcg_temp_free(t0);
2550 static inline void gen_store_srsgpr (int from, int to)
2552 if (to != 0) {
2553 TCGv t0 = tcg_temp_new();
2554 TCGv_i32 t2 = tcg_temp_new_i32();
2555 TCGv_ptr addr = tcg_temp_new_ptr();
2557 gen_load_gpr(t0, from);
2558 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2559 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2560 tcg_gen_andi_i32(t2, t2, 0xf);
2561 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2562 tcg_gen_ext_i32_ptr(addr, t2);
2563 tcg_gen_add_ptr(addr, cpu_env, addr);
2565 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2566 tcg_temp_free_ptr(addr);
2567 tcg_temp_free_i32(t2);
2568 tcg_temp_free(t0);
2572 /* Tests */
2573 static inline void gen_save_pc(target_ulong pc)
2575 tcg_gen_movi_tl(cpu_PC, pc);
2578 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2580 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2581 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2582 gen_save_pc(ctx->base.pc_next);
2583 ctx->saved_pc = ctx->base.pc_next;
2585 if (ctx->hflags != ctx->saved_hflags) {
2586 tcg_gen_movi_i32(hflags, ctx->hflags);
2587 ctx->saved_hflags = ctx->hflags;
2588 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2589 case MIPS_HFLAG_BR:
2590 break;
2591 case MIPS_HFLAG_BC:
2592 case MIPS_HFLAG_BL:
2593 case MIPS_HFLAG_B:
2594 tcg_gen_movi_tl(btarget, ctx->btarget);
2595 break;
2600 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2602 ctx->saved_hflags = ctx->hflags;
2603 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2604 case MIPS_HFLAG_BR:
2605 break;
2606 case MIPS_HFLAG_BC:
2607 case MIPS_HFLAG_BL:
2608 case MIPS_HFLAG_B:
2609 ctx->btarget = env->btarget;
2610 break;
2614 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2616 TCGv_i32 texcp = tcg_const_i32(excp);
2617 TCGv_i32 terr = tcg_const_i32(err);
2618 save_cpu_state(ctx, 1);
2619 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2620 tcg_temp_free_i32(terr);
2621 tcg_temp_free_i32(texcp);
2622 ctx->base.is_jmp = DISAS_NORETURN;
2625 static inline void generate_exception(DisasContext *ctx, int excp)
2627 gen_helper_0e0i(raise_exception, excp);
2630 static inline void generate_exception_end(DisasContext *ctx, int excp)
2632 generate_exception_err(ctx, excp, 0);
2635 /* Floating point register moves. */
2636 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2638 if (ctx->hflags & MIPS_HFLAG_FRE) {
2639 generate_exception(ctx, EXCP_RI);
2641 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2644 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2646 TCGv_i64 t64;
2647 if (ctx->hflags & MIPS_HFLAG_FRE) {
2648 generate_exception(ctx, EXCP_RI);
2650 t64 = tcg_temp_new_i64();
2651 tcg_gen_extu_i32_i64(t64, t);
2652 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2653 tcg_temp_free_i64(t64);
2656 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2658 if (ctx->hflags & MIPS_HFLAG_F64) {
2659 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2660 } else {
2661 gen_load_fpr32(ctx, t, reg | 1);
2665 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2667 if (ctx->hflags & MIPS_HFLAG_F64) {
2668 TCGv_i64 t64 = tcg_temp_new_i64();
2669 tcg_gen_extu_i32_i64(t64, t);
2670 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2671 tcg_temp_free_i64(t64);
2672 } else {
2673 gen_store_fpr32(ctx, t, reg | 1);
2677 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2679 if (ctx->hflags & MIPS_HFLAG_F64) {
2680 tcg_gen_mov_i64(t, fpu_f64[reg]);
2681 } else {
2682 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2686 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2688 if (ctx->hflags & MIPS_HFLAG_F64) {
2689 tcg_gen_mov_i64(fpu_f64[reg], t);
2690 } else {
2691 TCGv_i64 t0;
2692 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2693 t0 = tcg_temp_new_i64();
2694 tcg_gen_shri_i64(t0, t, 32);
2695 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2696 tcg_temp_free_i64(t0);
2700 static inline int get_fp_bit (int cc)
2702 if (cc)
2703 return 24 + cc;
2704 else
2705 return 23;
2708 /* Addresses computation */
2709 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2711 tcg_gen_add_tl(ret, arg0, arg1);
2713 #if defined(TARGET_MIPS64)
2714 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2715 tcg_gen_ext32s_i64(ret, ret);
2717 #endif
2720 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2721 target_long ofs)
2723 tcg_gen_addi_tl(ret, base, ofs);
2725 #if defined(TARGET_MIPS64)
2726 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2727 tcg_gen_ext32s_i64(ret, ret);
2729 #endif
2732 /* Addresses computation (translation time) */
2733 static target_long addr_add(DisasContext *ctx, target_long base,
2734 target_long offset)
2736 target_long sum = base + offset;
2738 #if defined(TARGET_MIPS64)
2739 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2740 sum = (int32_t)sum;
2742 #endif
2743 return sum;
2746 /* Sign-extract the low 32-bits to a target_long. */
2747 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2749 #if defined(TARGET_MIPS64)
2750 tcg_gen_ext32s_i64(ret, arg);
2751 #else
2752 tcg_gen_extrl_i64_i32(ret, arg);
2753 #endif
2756 /* Sign-extract the high 32-bits to a target_long. */
2757 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2759 #if defined(TARGET_MIPS64)
2760 tcg_gen_sari_i64(ret, arg, 32);
2761 #else
2762 tcg_gen_extrh_i64_i32(ret, arg);
2763 #endif
2766 static inline void check_cp0_enabled(DisasContext *ctx)
2768 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2769 generate_exception_err(ctx, EXCP_CpU, 0);
2772 static inline void check_cp1_enabled(DisasContext *ctx)
2774 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2775 generate_exception_err(ctx, EXCP_CpU, 1);
2778 /* Verify that the processor is running with COP1X instructions enabled.
2779 This is associated with the nabla symbol in the MIPS32 and MIPS64
2780 opcode tables. */
2782 static inline void check_cop1x(DisasContext *ctx)
2784 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2785 generate_exception_end(ctx, EXCP_RI);
2788 /* Verify that the processor is running with 64-bit floating-point
2789 operations enabled. */
2791 static inline void check_cp1_64bitmode(DisasContext *ctx)
2793 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2794 generate_exception_end(ctx, EXCP_RI);
2798 * Verify if floating point register is valid; an operation is not defined
2799 * if bit 0 of any register specification is set and the FR bit in the
2800 * Status register equals zero, since the register numbers specify an
2801 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2802 * in the Status register equals one, both even and odd register numbers
2803 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2805 * Multiple 64 bit wide registers can be checked by calling
2806 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2808 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2810 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2811 generate_exception_end(ctx, EXCP_RI);
2814 /* Verify that the processor is running with DSP instructions enabled.
2815 This is enabled by CP0 Status register MX(24) bit.
2818 static inline void check_dsp(DisasContext *ctx)
2820 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2821 if (ctx->insn_flags & ASE_DSP) {
2822 generate_exception_end(ctx, EXCP_DSPDIS);
2823 } else {
2824 generate_exception_end(ctx, EXCP_RI);
2829 static inline void check_dsp_r2(DisasContext *ctx)
2831 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2832 if (ctx->insn_flags & ASE_DSP) {
2833 generate_exception_end(ctx, EXCP_DSPDIS);
2834 } else {
2835 generate_exception_end(ctx, EXCP_RI);
2840 static inline void check_dsp_r3(DisasContext *ctx)
2842 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2843 if (ctx->insn_flags & ASE_DSP) {
2844 generate_exception_end(ctx, EXCP_DSPDIS);
2845 } else {
2846 generate_exception_end(ctx, EXCP_RI);
2851 /* This code generates a "reserved instruction" exception if the
2852 CPU does not support the instruction set corresponding to flags. */
2853 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2855 if (unlikely(!(ctx->insn_flags & flags))) {
2856 generate_exception_end(ctx, EXCP_RI);
2860 /* This code generates a "reserved instruction" exception if the
2861 CPU has corresponding flag set which indicates that the instruction
2862 has been removed. */
2863 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2865 if (unlikely(ctx->insn_flags & flags)) {
2866 generate_exception_end(ctx, EXCP_RI);
2871 * The Linux kernel traps certain reserved instruction exceptions to
2872 * emulate the corresponding instructions. QEMU is the kernel in user
2873 * mode, so those traps are emulated by accepting the instructions.
2875 * A reserved instruction exception is generated for flagged CPUs if
2876 * QEMU runs in system mode.
2878 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2880 #ifndef CONFIG_USER_ONLY
2881 check_insn_opc_removed(ctx, flags);
2882 #endif
2885 /* This code generates a "reserved instruction" exception if the
2886 CPU does not support 64-bit paired-single (PS) floating point data type */
2887 static inline void check_ps(DisasContext *ctx)
2889 if (unlikely(!ctx->ps)) {
2890 generate_exception(ctx, EXCP_RI);
2892 check_cp1_64bitmode(ctx);
2895 #ifdef TARGET_MIPS64
2896 /* This code generates a "reserved instruction" exception if 64-bit
2897 instructions are not enabled. */
2898 static inline void check_mips_64(DisasContext *ctx)
2900 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2901 generate_exception_end(ctx, EXCP_RI);
2903 #endif
2905 #ifndef CONFIG_USER_ONLY
2906 static inline void check_mvh(DisasContext *ctx)
2908 if (unlikely(!ctx->mvh)) {
2909 generate_exception(ctx, EXCP_RI);
2912 #endif
2915 * This code generates a "reserved instruction" exception if the
2916 * Config5 XNP bit is set.
2918 static inline void check_xnp(DisasContext *ctx)
2920 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2921 generate_exception_end(ctx, EXCP_RI);
2925 #ifndef CONFIG_USER_ONLY
2927 * This code generates a "reserved instruction" exception if the
2928 * Config3 PW bit is NOT set.
2930 static inline void check_pw(DisasContext *ctx)
2932 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2933 generate_exception_end(ctx, EXCP_RI);
2936 #endif
2939 * This code generates a "reserved instruction" exception if the
2940 * Config3 MT bit is NOT set.
2942 static inline void check_mt(DisasContext *ctx)
2944 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2945 generate_exception_end(ctx, EXCP_RI);
2949 #ifndef CONFIG_USER_ONLY
2951 * This code generates a "coprocessor unusable" exception if CP0 is not
2952 * available, and, if that is not the case, generates a "reserved instruction"
2953 * exception if the Config5 MT bit is NOT set. This is needed for availability
2954 * control of some of MT ASE instructions.
2956 static inline void check_cp0_mt(DisasContext *ctx)
2958 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2959 generate_exception_err(ctx, EXCP_CpU, 0);
2960 } else {
2961 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2962 generate_exception_err(ctx, EXCP_RI, 0);
2966 #endif
2969 * This code generates a "reserved instruction" exception if the
2970 * Config5 NMS bit is set.
2972 static inline void check_nms(DisasContext *ctx)
2974 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2975 generate_exception_end(ctx, EXCP_RI);
2980 * This code generates a "reserved instruction" exception if the
2981 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
2982 * Config2 TL, and Config5 L2C are unset.
2984 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
2986 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
2987 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
2988 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
2989 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
2990 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
2991 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
2993 generate_exception_end(ctx, EXCP_RI);
2998 * This code generates a "reserved instruction" exception if the
2999 * Config5 EVA bit is NOT set.
3001 static inline void check_eva(DisasContext *ctx)
3003 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3004 generate_exception_end(ctx, EXCP_RI);
3009 /* Define small wrappers for gen_load_fpr* so that we have a uniform
3010 calling interface for 32 and 64-bit FPRs. No sense in changing
3011 all callers for gen_load_fpr32 when we need the CTX parameter for
3012 this one use. */
3013 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3014 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3015 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3016 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3017 int ft, int fs, int cc) \
3019 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3020 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3021 switch (ifmt) { \
3022 case FMT_PS: \
3023 check_ps(ctx); \
3024 break; \
3025 case FMT_D: \
3026 if (abs) { \
3027 check_cop1x(ctx); \
3029 check_cp1_registers(ctx, fs | ft); \
3030 break; \
3031 case FMT_S: \
3032 if (abs) { \
3033 check_cop1x(ctx); \
3035 break; \
3037 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3038 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3039 switch (n) { \
3040 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3041 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3042 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3043 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3044 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3045 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3046 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3047 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3048 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3049 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3050 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3051 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3052 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3053 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3054 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3055 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3056 default: abort(); \
3058 tcg_temp_free_i##bits (fp0); \
3059 tcg_temp_free_i##bits (fp1); \
3062 FOP_CONDS(, 0, d, FMT_D, 64)
3063 FOP_CONDS(abs, 1, d, FMT_D, 64)
3064 FOP_CONDS(, 0, s, FMT_S, 32)
3065 FOP_CONDS(abs, 1, s, FMT_S, 32)
3066 FOP_CONDS(, 0, ps, FMT_PS, 64)
3067 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3068 #undef FOP_CONDS
3070 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3071 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3072 int ft, int fs, int fd) \
3074 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3075 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3076 if (ifmt == FMT_D) { \
3077 check_cp1_registers(ctx, fs | ft | fd); \
3079 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3080 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3081 switch (n) { \
3082 case 0: \
3083 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3084 break; \
3085 case 1: \
3086 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3087 break; \
3088 case 2: \
3089 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3090 break; \
3091 case 3: \
3092 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3093 break; \
3094 case 4: \
3095 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3096 break; \
3097 case 5: \
3098 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3099 break; \
3100 case 6: \
3101 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3102 break; \
3103 case 7: \
3104 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3105 break; \
3106 case 8: \
3107 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3108 break; \
3109 case 9: \
3110 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3111 break; \
3112 case 10: \
3113 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3114 break; \
3115 case 11: \
3116 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3117 break; \
3118 case 12: \
3119 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3120 break; \
3121 case 13: \
3122 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3123 break; \
3124 case 14: \
3125 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3126 break; \
3127 case 15: \
3128 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3129 break; \
3130 case 17: \
3131 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3132 break; \
3133 case 18: \
3134 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3135 break; \
3136 case 19: \
3137 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3138 break; \
3139 case 25: \
3140 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3141 break; \
3142 case 26: \
3143 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3144 break; \
3145 case 27: \
3146 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3147 break; \
3148 default: \
3149 abort(); \
3151 STORE; \
3152 tcg_temp_free_i ## bits (fp0); \
3153 tcg_temp_free_i ## bits (fp1); \
3156 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3157 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3158 #undef FOP_CONDNS
3159 #undef gen_ldcmp_fpr32
3160 #undef gen_ldcmp_fpr64
3162 /* load/store instructions. */
3163 #ifdef CONFIG_USER_ONLY
3164 #define OP_LD_ATOMIC(insn,fname) \
3165 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3166 DisasContext *ctx) \
3168 TCGv t0 = tcg_temp_new(); \
3169 tcg_gen_mov_tl(t0, arg1); \
3170 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3171 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3172 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3173 tcg_temp_free(t0); \
3175 #else
3176 #define OP_LD_ATOMIC(insn,fname) \
3177 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3178 DisasContext *ctx) \
3180 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3182 #endif
3183 OP_LD_ATOMIC(ll,ld32s);
3184 #if defined(TARGET_MIPS64)
3185 OP_LD_ATOMIC(lld,ld64);
3186 #endif
3187 #undef OP_LD_ATOMIC
3189 #ifdef CONFIG_USER_ONLY
3190 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3191 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3192 DisasContext *ctx) \
3194 TCGv t0 = tcg_temp_new(); \
3195 TCGLabel *l1 = gen_new_label(); \
3196 TCGLabel *l2 = gen_new_label(); \
3198 tcg_gen_andi_tl(t0, arg2, almask); \
3199 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
3200 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
3201 generate_exception(ctx, EXCP_AdES); \
3202 gen_set_label(l1); \
3203 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3204 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3205 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
3206 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3207 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
3208 generate_exception_end(ctx, EXCP_SC); \
3209 gen_set_label(l2); \
3210 tcg_gen_movi_tl(t0, 0); \
3211 gen_store_gpr(t0, rt); \
3212 tcg_temp_free(t0); \
3214 #else
3215 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3216 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3217 DisasContext *ctx) \
3219 TCGv t0 = tcg_temp_new(); \
3220 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
3221 gen_store_gpr(t0, rt); \
3222 tcg_temp_free(t0); \
3224 #endif
3225 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
3226 #if defined(TARGET_MIPS64)
3227 OP_ST_ATOMIC(scd,st64,ld64,0x7);
3228 #endif
3229 #undef OP_ST_ATOMIC
3231 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3232 int base, int offset)
3234 if (base == 0) {
3235 tcg_gen_movi_tl(addr, offset);
3236 } else if (offset == 0) {
3237 gen_load_gpr(addr, base);
3238 } else {
3239 tcg_gen_movi_tl(addr, offset);
3240 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3244 static target_ulong pc_relative_pc (DisasContext *ctx)
3246 target_ulong pc = ctx->base.pc_next;
3248 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3249 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3251 pc -= branch_bytes;
3254 pc &= ~(target_ulong)3;
3255 return pc;
3258 /* Load */
3259 static void gen_ld(DisasContext *ctx, uint32_t opc,
3260 int rt, int base, int offset)
3262 TCGv t0, t1, t2;
3263 int mem_idx = ctx->mem_idx;
3265 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3266 /* Loongson CPU uses a load to zero register for prefetch.
3267 We emulate it as a NOP. On other CPU we must perform the
3268 actual memory access. */
3269 return;
3272 t0 = tcg_temp_new();
3273 gen_base_offset_addr(ctx, t0, base, offset);
3275 switch (opc) {
3276 #if defined(TARGET_MIPS64)
3277 case OPC_LWU:
3278 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3279 ctx->default_tcg_memop_mask);
3280 gen_store_gpr(t0, rt);
3281 break;
3282 case OPC_LD:
3283 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3284 ctx->default_tcg_memop_mask);
3285 gen_store_gpr(t0, rt);
3286 break;
3287 case OPC_LLD:
3288 case R6_OPC_LLD:
3289 op_ld_lld(t0, t0, mem_idx, ctx);
3290 gen_store_gpr(t0, rt);
3291 break;
3292 case OPC_LDL:
3293 t1 = tcg_temp_new();
3294 /* Do a byte access to possibly trigger a page
3295 fault with the unaligned address. */
3296 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3297 tcg_gen_andi_tl(t1, t0, 7);
3298 #ifndef TARGET_WORDS_BIGENDIAN
3299 tcg_gen_xori_tl(t1, t1, 7);
3300 #endif
3301 tcg_gen_shli_tl(t1, t1, 3);
3302 tcg_gen_andi_tl(t0, t0, ~7);
3303 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3304 tcg_gen_shl_tl(t0, t0, t1);
3305 t2 = tcg_const_tl(-1);
3306 tcg_gen_shl_tl(t2, t2, t1);
3307 gen_load_gpr(t1, rt);
3308 tcg_gen_andc_tl(t1, t1, t2);
3309 tcg_temp_free(t2);
3310 tcg_gen_or_tl(t0, t0, t1);
3311 tcg_temp_free(t1);
3312 gen_store_gpr(t0, rt);
3313 break;
3314 case OPC_LDR:
3315 t1 = tcg_temp_new();
3316 /* Do a byte access to possibly trigger a page
3317 fault with the unaligned address. */
3318 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3319 tcg_gen_andi_tl(t1, t0, 7);
3320 #ifdef TARGET_WORDS_BIGENDIAN
3321 tcg_gen_xori_tl(t1, t1, 7);
3322 #endif
3323 tcg_gen_shli_tl(t1, t1, 3);
3324 tcg_gen_andi_tl(t0, t0, ~7);
3325 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3326 tcg_gen_shr_tl(t0, t0, t1);
3327 tcg_gen_xori_tl(t1, t1, 63);
3328 t2 = tcg_const_tl(0xfffffffffffffffeull);
3329 tcg_gen_shl_tl(t2, t2, t1);
3330 gen_load_gpr(t1, rt);
3331 tcg_gen_and_tl(t1, t1, t2);
3332 tcg_temp_free(t2);
3333 tcg_gen_or_tl(t0, t0, t1);
3334 tcg_temp_free(t1);
3335 gen_store_gpr(t0, rt);
3336 break;
3337 case OPC_LDPC:
3338 t1 = tcg_const_tl(pc_relative_pc(ctx));
3339 gen_op_addr_add(ctx, t0, t0, t1);
3340 tcg_temp_free(t1);
3341 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3342 gen_store_gpr(t0, rt);
3343 break;
3344 #endif
3345 case OPC_LWPC:
3346 t1 = tcg_const_tl(pc_relative_pc(ctx));
3347 gen_op_addr_add(ctx, t0, t0, t1);
3348 tcg_temp_free(t1);
3349 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3350 gen_store_gpr(t0, rt);
3351 break;
3352 case OPC_LWE:
3353 mem_idx = MIPS_HFLAG_UM;
3354 /* fall through */
3355 case OPC_LW:
3356 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3357 ctx->default_tcg_memop_mask);
3358 gen_store_gpr(t0, rt);
3359 break;
3360 case OPC_LHE:
3361 mem_idx = MIPS_HFLAG_UM;
3362 /* fall through */
3363 case OPC_LH:
3364 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3365 ctx->default_tcg_memop_mask);
3366 gen_store_gpr(t0, rt);
3367 break;
3368 case OPC_LHUE:
3369 mem_idx = MIPS_HFLAG_UM;
3370 /* fall through */
3371 case OPC_LHU:
3372 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3373 ctx->default_tcg_memop_mask);
3374 gen_store_gpr(t0, rt);
3375 break;
3376 case OPC_LBE:
3377 mem_idx = MIPS_HFLAG_UM;
3378 /* fall through */
3379 case OPC_LB:
3380 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3381 gen_store_gpr(t0, rt);
3382 break;
3383 case OPC_LBUE:
3384 mem_idx = MIPS_HFLAG_UM;
3385 /* fall through */
3386 case OPC_LBU:
3387 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3388 gen_store_gpr(t0, rt);
3389 break;
3390 case OPC_LWLE:
3391 mem_idx = MIPS_HFLAG_UM;
3392 /* fall through */
3393 case OPC_LWL:
3394 t1 = tcg_temp_new();
3395 /* Do a byte access to possibly trigger a page
3396 fault with the unaligned address. */
3397 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3398 tcg_gen_andi_tl(t1, t0, 3);
3399 #ifndef TARGET_WORDS_BIGENDIAN
3400 tcg_gen_xori_tl(t1, t1, 3);
3401 #endif
3402 tcg_gen_shli_tl(t1, t1, 3);
3403 tcg_gen_andi_tl(t0, t0, ~3);
3404 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3405 tcg_gen_shl_tl(t0, t0, t1);
3406 t2 = tcg_const_tl(-1);
3407 tcg_gen_shl_tl(t2, t2, t1);
3408 gen_load_gpr(t1, rt);
3409 tcg_gen_andc_tl(t1, t1, t2);
3410 tcg_temp_free(t2);
3411 tcg_gen_or_tl(t0, t0, t1);
3412 tcg_temp_free(t1);
3413 tcg_gen_ext32s_tl(t0, t0);
3414 gen_store_gpr(t0, rt);
3415 break;
3416 case OPC_LWRE:
3417 mem_idx = MIPS_HFLAG_UM;
3418 /* fall through */
3419 case OPC_LWR:
3420 t1 = tcg_temp_new();
3421 /* Do a byte access to possibly trigger a page
3422 fault with the unaligned address. */
3423 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3424 tcg_gen_andi_tl(t1, t0, 3);
3425 #ifdef TARGET_WORDS_BIGENDIAN
3426 tcg_gen_xori_tl(t1, t1, 3);
3427 #endif
3428 tcg_gen_shli_tl(t1, t1, 3);
3429 tcg_gen_andi_tl(t0, t0, ~3);
3430 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3431 tcg_gen_shr_tl(t0, t0, t1);
3432 tcg_gen_xori_tl(t1, t1, 31);
3433 t2 = tcg_const_tl(0xfffffffeull);
3434 tcg_gen_shl_tl(t2, t2, t1);
3435 gen_load_gpr(t1, rt);
3436 tcg_gen_and_tl(t1, t1, t2);
3437 tcg_temp_free(t2);
3438 tcg_gen_or_tl(t0, t0, t1);
3439 tcg_temp_free(t1);
3440 tcg_gen_ext32s_tl(t0, t0);
3441 gen_store_gpr(t0, rt);
3442 break;
3443 case OPC_LLE:
3444 mem_idx = MIPS_HFLAG_UM;
3445 /* fall through */
3446 case OPC_LL:
3447 case R6_OPC_LL:
3448 op_ld_ll(t0, t0, mem_idx, ctx);
3449 gen_store_gpr(t0, rt);
3450 break;
3452 tcg_temp_free(t0);
3455 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3456 uint32_t reg1, uint32_t reg2)
3458 TCGv taddr = tcg_temp_new();
3459 TCGv_i64 tval = tcg_temp_new_i64();
3460 TCGv tmp1 = tcg_temp_new();
3461 TCGv tmp2 = tcg_temp_new();
3463 gen_base_offset_addr(ctx, taddr, base, offset);
3464 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3465 #ifdef TARGET_WORDS_BIGENDIAN
3466 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3467 #else
3468 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3469 #endif
3470 gen_store_gpr(tmp1, reg1);
3471 tcg_temp_free(tmp1);
3472 gen_store_gpr(tmp2, reg2);
3473 tcg_temp_free(tmp2);
3474 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3475 tcg_temp_free_i64(tval);
3476 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3477 tcg_temp_free(taddr);
3480 /* Store */
3481 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3482 int base, int offset)
3484 TCGv t0 = tcg_temp_new();
3485 TCGv t1 = tcg_temp_new();
3486 int mem_idx = ctx->mem_idx;
3488 gen_base_offset_addr(ctx, t0, base, offset);
3489 gen_load_gpr(t1, rt);
3490 switch (opc) {
3491 #if defined(TARGET_MIPS64)
3492 case OPC_SD:
3493 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3494 ctx->default_tcg_memop_mask);
3495 break;
3496 case OPC_SDL:
3497 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3498 break;
3499 case OPC_SDR:
3500 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3501 break;
3502 #endif
3503 case OPC_SWE:
3504 mem_idx = MIPS_HFLAG_UM;
3505 /* fall through */
3506 case OPC_SW:
3507 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3508 ctx->default_tcg_memop_mask);
3509 break;
3510 case OPC_SHE:
3511 mem_idx = MIPS_HFLAG_UM;
3512 /* fall through */
3513 case OPC_SH:
3514 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3515 ctx->default_tcg_memop_mask);
3516 break;
3517 case OPC_SBE:
3518 mem_idx = MIPS_HFLAG_UM;
3519 /* fall through */
3520 case OPC_SB:
3521 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3522 break;
3523 case OPC_SWLE:
3524 mem_idx = MIPS_HFLAG_UM;
3525 /* fall through */
3526 case OPC_SWL:
3527 gen_helper_0e2i(swl, t1, t0, mem_idx);
3528 break;
3529 case OPC_SWRE:
3530 mem_idx = MIPS_HFLAG_UM;
3531 /* fall through */
3532 case OPC_SWR:
3533 gen_helper_0e2i(swr, t1, t0, mem_idx);
3534 break;
3536 tcg_temp_free(t0);
3537 tcg_temp_free(t1);
3541 /* Store conditional */
3542 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3543 int base, int16_t offset)
3545 TCGv t0, t1;
3546 int mem_idx = ctx->mem_idx;
3548 #ifdef CONFIG_USER_ONLY
3549 t0 = tcg_temp_local_new();
3550 t1 = tcg_temp_local_new();
3551 #else
3552 t0 = tcg_temp_new();
3553 t1 = tcg_temp_new();
3554 #endif
3555 gen_base_offset_addr(ctx, t0, base, offset);
3556 gen_load_gpr(t1, rt);
3557 switch (opc) {
3558 #if defined(TARGET_MIPS64)
3559 case OPC_SCD:
3560 case R6_OPC_SCD:
3561 op_st_scd(t1, t0, rt, mem_idx, ctx);
3562 break;
3563 #endif
3564 case OPC_SCE:
3565 mem_idx = MIPS_HFLAG_UM;
3566 /* fall through */
3567 case OPC_SC:
3568 case R6_OPC_SC:
3569 op_st_sc(t1, t0, rt, mem_idx, ctx);
3570 break;
3572 tcg_temp_free(t1);
3573 tcg_temp_free(t0);
3576 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3577 uint32_t reg1, uint32_t reg2)
3579 TCGv taddr = tcg_temp_local_new();
3580 TCGv lladdr = tcg_temp_local_new();
3581 TCGv_i64 tval = tcg_temp_new_i64();
3582 TCGv_i64 llval = tcg_temp_new_i64();
3583 TCGv_i64 val = tcg_temp_new_i64();
3584 TCGv tmp1 = tcg_temp_new();
3585 TCGv tmp2 = tcg_temp_new();
3586 TCGLabel *lab_fail = gen_new_label();
3587 TCGLabel *lab_done = gen_new_label();
3589 gen_base_offset_addr(ctx, taddr, base, offset);
3591 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3592 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3594 gen_load_gpr(tmp1, reg1);
3595 gen_load_gpr(tmp2, reg2);
3597 #ifdef TARGET_WORDS_BIGENDIAN
3598 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3599 #else
3600 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3601 #endif
3603 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3604 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3605 ctx->mem_idx, MO_64);
3606 if (reg1 != 0) {
3607 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3609 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3611 gen_set_label(lab_fail);
3613 if (reg1 != 0) {
3614 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3616 gen_set_label(lab_done);
3617 tcg_gen_movi_tl(lladdr, -1);
3618 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3621 /* Load and store */
3622 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3623 TCGv t0)
3625 /* Don't do NOP if destination is zero: we must perform the actual
3626 memory access. */
3627 switch (opc) {
3628 case OPC_LWC1:
3630 TCGv_i32 fp0 = tcg_temp_new_i32();
3631 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3632 ctx->default_tcg_memop_mask);
3633 gen_store_fpr32(ctx, fp0, ft);
3634 tcg_temp_free_i32(fp0);
3636 break;
3637 case OPC_SWC1:
3639 TCGv_i32 fp0 = tcg_temp_new_i32();
3640 gen_load_fpr32(ctx, fp0, ft);
3641 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3642 ctx->default_tcg_memop_mask);
3643 tcg_temp_free_i32(fp0);
3645 break;
3646 case OPC_LDC1:
3648 TCGv_i64 fp0 = tcg_temp_new_i64();
3649 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3650 ctx->default_tcg_memop_mask);
3651 gen_store_fpr64(ctx, fp0, ft);
3652 tcg_temp_free_i64(fp0);
3654 break;
3655 case OPC_SDC1:
3657 TCGv_i64 fp0 = tcg_temp_new_i64();
3658 gen_load_fpr64(ctx, fp0, ft);
3659 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3660 ctx->default_tcg_memop_mask);
3661 tcg_temp_free_i64(fp0);
3663 break;
3664 default:
3665 MIPS_INVAL("flt_ldst");
3666 generate_exception_end(ctx, EXCP_RI);
3667 break;
3671 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3672 int rs, int16_t imm)
3674 TCGv t0 = tcg_temp_new();
3676 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3677 check_cp1_enabled(ctx);
3678 switch (op) {
3679 case OPC_LDC1:
3680 case OPC_SDC1:
3681 check_insn(ctx, ISA_MIPS2);
3682 /* Fallthrough */
3683 default:
3684 gen_base_offset_addr(ctx, t0, rs, imm);
3685 gen_flt_ldst(ctx, op, rt, t0);
3687 } else {
3688 generate_exception_err(ctx, EXCP_CpU, 1);
3690 tcg_temp_free(t0);
3693 /* Arithmetic with immediate operand */
3694 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3695 int rt, int rs, int imm)
3697 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3699 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3700 /* If no destination, treat it as a NOP.
3701 For addi, we must generate the overflow exception when needed. */
3702 return;
3704 switch (opc) {
3705 case OPC_ADDI:
3707 TCGv t0 = tcg_temp_local_new();
3708 TCGv t1 = tcg_temp_new();
3709 TCGv t2 = tcg_temp_new();
3710 TCGLabel *l1 = gen_new_label();
3712 gen_load_gpr(t1, rs);
3713 tcg_gen_addi_tl(t0, t1, uimm);
3714 tcg_gen_ext32s_tl(t0, t0);
3716 tcg_gen_xori_tl(t1, t1, ~uimm);
3717 tcg_gen_xori_tl(t2, t0, uimm);
3718 tcg_gen_and_tl(t1, t1, t2);
3719 tcg_temp_free(t2);
3720 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3721 tcg_temp_free(t1);
3722 /* operands of same sign, result different sign */
3723 generate_exception(ctx, EXCP_OVERFLOW);
3724 gen_set_label(l1);
3725 tcg_gen_ext32s_tl(t0, t0);
3726 gen_store_gpr(t0, rt);
3727 tcg_temp_free(t0);
3729 break;
3730 case OPC_ADDIU:
3731 if (rs != 0) {
3732 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3733 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3734 } else {
3735 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3737 break;
3738 #if defined(TARGET_MIPS64)
3739 case OPC_DADDI:
3741 TCGv t0 = tcg_temp_local_new();
3742 TCGv t1 = tcg_temp_new();
3743 TCGv t2 = tcg_temp_new();
3744 TCGLabel *l1 = gen_new_label();
3746 gen_load_gpr(t1, rs);
3747 tcg_gen_addi_tl(t0, t1, uimm);
3749 tcg_gen_xori_tl(t1, t1, ~uimm);
3750 tcg_gen_xori_tl(t2, t0, uimm);
3751 tcg_gen_and_tl(t1, t1, t2);
3752 tcg_temp_free(t2);
3753 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3754 tcg_temp_free(t1);
3755 /* operands of same sign, result different sign */
3756 generate_exception(ctx, EXCP_OVERFLOW);
3757 gen_set_label(l1);
3758 gen_store_gpr(t0, rt);
3759 tcg_temp_free(t0);
3761 break;
3762 case OPC_DADDIU:
3763 if (rs != 0) {
3764 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3765 } else {
3766 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3768 break;
3769 #endif
3773 /* Logic with immediate operand */
3774 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3775 int rt, int rs, int16_t imm)
3777 target_ulong uimm;
3779 if (rt == 0) {
3780 /* If no destination, treat it as a NOP. */
3781 return;
3783 uimm = (uint16_t)imm;
3784 switch (opc) {
3785 case OPC_ANDI:
3786 if (likely(rs != 0))
3787 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3788 else
3789 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3790 break;
3791 case OPC_ORI:
3792 if (rs != 0)
3793 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3794 else
3795 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3796 break;
3797 case OPC_XORI:
3798 if (likely(rs != 0))
3799 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3800 else
3801 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3802 break;
3803 case OPC_LUI:
3804 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3805 /* OPC_AUI */
3806 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3807 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3808 } else {
3809 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3811 break;
3813 default:
3814 break;
3818 /* Set on less than with immediate operand */
3819 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3820 int rt, int rs, int16_t imm)
3822 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3823 TCGv t0;
3825 if (rt == 0) {
3826 /* If no destination, treat it as a NOP. */
3827 return;
3829 t0 = tcg_temp_new();
3830 gen_load_gpr(t0, rs);
3831 switch (opc) {
3832 case OPC_SLTI:
3833 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3834 break;
3835 case OPC_SLTIU:
3836 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3837 break;
3839 tcg_temp_free(t0);
3842 /* Shifts with immediate operand */
3843 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3844 int rt, int rs, int16_t imm)
3846 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3847 TCGv t0;
3849 if (rt == 0) {
3850 /* If no destination, treat it as a NOP. */
3851 return;
3854 t0 = tcg_temp_new();
3855 gen_load_gpr(t0, rs);
3856 switch (opc) {
3857 case OPC_SLL:
3858 tcg_gen_shli_tl(t0, t0, uimm);
3859 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3860 break;
3861 case OPC_SRA:
3862 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3863 break;
3864 case OPC_SRL:
3865 if (uimm != 0) {
3866 tcg_gen_ext32u_tl(t0, t0);
3867 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3868 } else {
3869 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3871 break;
3872 case OPC_ROTR:
3873 if (uimm != 0) {
3874 TCGv_i32 t1 = tcg_temp_new_i32();
3876 tcg_gen_trunc_tl_i32(t1, t0);
3877 tcg_gen_rotri_i32(t1, t1, uimm);
3878 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3879 tcg_temp_free_i32(t1);
3880 } else {
3881 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3883 break;
3884 #if defined(TARGET_MIPS64)
3885 case OPC_DSLL:
3886 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3887 break;
3888 case OPC_DSRA:
3889 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3890 break;
3891 case OPC_DSRL:
3892 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3893 break;
3894 case OPC_DROTR:
3895 if (uimm != 0) {
3896 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3897 } else {
3898 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3900 break;
3901 case OPC_DSLL32:
3902 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3903 break;
3904 case OPC_DSRA32:
3905 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3906 break;
3907 case OPC_DSRL32:
3908 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3909 break;
3910 case OPC_DROTR32:
3911 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3912 break;
3913 #endif
3915 tcg_temp_free(t0);
3918 /* Arithmetic */
3919 static void gen_arith(DisasContext *ctx, uint32_t opc,
3920 int rd, int rs, int rt)
3922 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3923 && opc != OPC_DADD && opc != OPC_DSUB) {
3924 /* If no destination, treat it as a NOP.
3925 For add & sub, we must generate the overflow exception when needed. */
3926 return;
3929 switch (opc) {
3930 case OPC_ADD:
3932 TCGv t0 = tcg_temp_local_new();
3933 TCGv t1 = tcg_temp_new();
3934 TCGv t2 = tcg_temp_new();
3935 TCGLabel *l1 = gen_new_label();
3937 gen_load_gpr(t1, rs);
3938 gen_load_gpr(t2, rt);
3939 tcg_gen_add_tl(t0, t1, t2);
3940 tcg_gen_ext32s_tl(t0, t0);
3941 tcg_gen_xor_tl(t1, t1, t2);
3942 tcg_gen_xor_tl(t2, t0, t2);
3943 tcg_gen_andc_tl(t1, t2, t1);
3944 tcg_temp_free(t2);
3945 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3946 tcg_temp_free(t1);
3947 /* operands of same sign, result different sign */
3948 generate_exception(ctx, EXCP_OVERFLOW);
3949 gen_set_label(l1);
3950 gen_store_gpr(t0, rd);
3951 tcg_temp_free(t0);
3953 break;
3954 case OPC_ADDU:
3955 if (rs != 0 && rt != 0) {
3956 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3957 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3958 } else if (rs == 0 && rt != 0) {
3959 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3960 } else if (rs != 0 && rt == 0) {
3961 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3962 } else {
3963 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3965 break;
3966 case OPC_SUB:
3968 TCGv t0 = tcg_temp_local_new();
3969 TCGv t1 = tcg_temp_new();
3970 TCGv t2 = tcg_temp_new();
3971 TCGLabel *l1 = gen_new_label();
3973 gen_load_gpr(t1, rs);
3974 gen_load_gpr(t2, rt);
3975 tcg_gen_sub_tl(t0, t1, t2);
3976 tcg_gen_ext32s_tl(t0, t0);
3977 tcg_gen_xor_tl(t2, t1, t2);
3978 tcg_gen_xor_tl(t1, t0, t1);
3979 tcg_gen_and_tl(t1, t1, t2);
3980 tcg_temp_free(t2);
3981 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3982 tcg_temp_free(t1);
3983 /* operands of different sign, first operand and result different sign */
3984 generate_exception(ctx, EXCP_OVERFLOW);
3985 gen_set_label(l1);
3986 gen_store_gpr(t0, rd);
3987 tcg_temp_free(t0);
3989 break;
3990 case OPC_SUBU:
3991 if (rs != 0 && rt != 0) {
3992 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3993 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3994 } else if (rs == 0 && rt != 0) {
3995 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3996 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3997 } else if (rs != 0 && rt == 0) {
3998 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3999 } else {
4000 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4002 break;
4003 #if defined(TARGET_MIPS64)
4004 case OPC_DADD:
4006 TCGv t0 = tcg_temp_local_new();
4007 TCGv t1 = tcg_temp_new();
4008 TCGv t2 = tcg_temp_new();
4009 TCGLabel *l1 = gen_new_label();
4011 gen_load_gpr(t1, rs);
4012 gen_load_gpr(t2, rt);
4013 tcg_gen_add_tl(t0, t1, t2);
4014 tcg_gen_xor_tl(t1, t1, t2);
4015 tcg_gen_xor_tl(t2, t0, t2);
4016 tcg_gen_andc_tl(t1, t2, t1);
4017 tcg_temp_free(t2);
4018 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4019 tcg_temp_free(t1);
4020 /* operands of same sign, result different sign */
4021 generate_exception(ctx, EXCP_OVERFLOW);
4022 gen_set_label(l1);
4023 gen_store_gpr(t0, rd);
4024 tcg_temp_free(t0);
4026 break;
4027 case OPC_DADDU:
4028 if (rs != 0 && rt != 0) {
4029 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4030 } else if (rs == 0 && rt != 0) {
4031 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4032 } else if (rs != 0 && rt == 0) {
4033 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4034 } else {
4035 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4037 break;
4038 case OPC_DSUB:
4040 TCGv t0 = tcg_temp_local_new();
4041 TCGv t1 = tcg_temp_new();
4042 TCGv t2 = tcg_temp_new();
4043 TCGLabel *l1 = gen_new_label();
4045 gen_load_gpr(t1, rs);
4046 gen_load_gpr(t2, rt);
4047 tcg_gen_sub_tl(t0, t1, t2);
4048 tcg_gen_xor_tl(t2, t1, t2);
4049 tcg_gen_xor_tl(t1, t0, t1);
4050 tcg_gen_and_tl(t1, t1, t2);
4051 tcg_temp_free(t2);
4052 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4053 tcg_temp_free(t1);
4054 /* operands of different sign, first operand and result different sign */
4055 generate_exception(ctx, EXCP_OVERFLOW);
4056 gen_set_label(l1);
4057 gen_store_gpr(t0, rd);
4058 tcg_temp_free(t0);
4060 break;
4061 case OPC_DSUBU:
4062 if (rs != 0 && rt != 0) {
4063 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4064 } else if (rs == 0 && rt != 0) {
4065 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4066 } else if (rs != 0 && rt == 0) {
4067 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4068 } else {
4069 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4071 break;
4072 #endif
4073 case OPC_MUL:
4074 if (likely(rs != 0 && rt != 0)) {
4075 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4076 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4077 } else {
4078 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4080 break;
4084 /* Conditional move */
4085 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4086 int rd, int rs, int rt)
4088 TCGv t0, t1, t2;
4090 if (rd == 0) {
4091 /* If no destination, treat it as a NOP. */
4092 return;
4095 t0 = tcg_temp_new();
4096 gen_load_gpr(t0, rt);
4097 t1 = tcg_const_tl(0);
4098 t2 = tcg_temp_new();
4099 gen_load_gpr(t2, rs);
4100 switch (opc) {
4101 case OPC_MOVN:
4102 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4103 break;
4104 case OPC_MOVZ:
4105 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4106 break;
4107 case OPC_SELNEZ:
4108 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4109 break;
4110 case OPC_SELEQZ:
4111 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4112 break;
4114 tcg_temp_free(t2);
4115 tcg_temp_free(t1);
4116 tcg_temp_free(t0);
4119 /* Logic */
4120 static void gen_logic(DisasContext *ctx, uint32_t opc,
4121 int rd, int rs, int rt)
4123 if (rd == 0) {
4124 /* If no destination, treat it as a NOP. */
4125 return;
4128 switch (opc) {
4129 case OPC_AND:
4130 if (likely(rs != 0 && rt != 0)) {
4131 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4132 } else {
4133 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4135 break;
4136 case OPC_NOR:
4137 if (rs != 0 && rt != 0) {
4138 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4139 } else if (rs == 0 && rt != 0) {
4140 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4141 } else if (rs != 0 && rt == 0) {
4142 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4143 } else {
4144 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4146 break;
4147 case OPC_OR:
4148 if (likely(rs != 0 && rt != 0)) {
4149 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4150 } else if (rs == 0 && rt != 0) {
4151 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4152 } else if (rs != 0 && rt == 0) {
4153 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4154 } else {
4155 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4157 break;
4158 case OPC_XOR:
4159 if (likely(rs != 0 && rt != 0)) {
4160 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4161 } else if (rs == 0 && rt != 0) {
4162 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4163 } else if (rs != 0 && rt == 0) {
4164 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4165 } else {
4166 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4168 break;
4172 /* Set on lower than */
4173 static void gen_slt(DisasContext *ctx, uint32_t opc,
4174 int rd, int rs, int rt)
4176 TCGv t0, t1;
4178 if (rd == 0) {
4179 /* If no destination, treat it as a NOP. */
4180 return;
4183 t0 = tcg_temp_new();
4184 t1 = tcg_temp_new();
4185 gen_load_gpr(t0, rs);
4186 gen_load_gpr(t1, rt);
4187 switch (opc) {
4188 case OPC_SLT:
4189 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4190 break;
4191 case OPC_SLTU:
4192 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4193 break;
4195 tcg_temp_free(t0);
4196 tcg_temp_free(t1);
4199 /* Shifts */
4200 static void gen_shift(DisasContext *ctx, uint32_t opc,
4201 int rd, int rs, int rt)
4203 TCGv t0, t1;
4205 if (rd == 0) {
4206 /* If no destination, treat it as a NOP.
4207 For add & sub, we must generate the overflow exception when needed. */
4208 return;
4211 t0 = tcg_temp_new();
4212 t1 = tcg_temp_new();
4213 gen_load_gpr(t0, rs);
4214 gen_load_gpr(t1, rt);
4215 switch (opc) {
4216 case OPC_SLLV:
4217 tcg_gen_andi_tl(t0, t0, 0x1f);
4218 tcg_gen_shl_tl(t0, t1, t0);
4219 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4220 break;
4221 case OPC_SRAV:
4222 tcg_gen_andi_tl(t0, t0, 0x1f);
4223 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4224 break;
4225 case OPC_SRLV:
4226 tcg_gen_ext32u_tl(t1, t1);
4227 tcg_gen_andi_tl(t0, t0, 0x1f);
4228 tcg_gen_shr_tl(t0, t1, t0);
4229 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4230 break;
4231 case OPC_ROTRV:
4233 TCGv_i32 t2 = tcg_temp_new_i32();
4234 TCGv_i32 t3 = tcg_temp_new_i32();
4236 tcg_gen_trunc_tl_i32(t2, t0);
4237 tcg_gen_trunc_tl_i32(t3, t1);
4238 tcg_gen_andi_i32(t2, t2, 0x1f);
4239 tcg_gen_rotr_i32(t2, t3, t2);
4240 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4241 tcg_temp_free_i32(t2);
4242 tcg_temp_free_i32(t3);
4244 break;
4245 #if defined(TARGET_MIPS64)
4246 case OPC_DSLLV:
4247 tcg_gen_andi_tl(t0, t0, 0x3f);
4248 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4249 break;
4250 case OPC_DSRAV:
4251 tcg_gen_andi_tl(t0, t0, 0x3f);
4252 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4253 break;
4254 case OPC_DSRLV:
4255 tcg_gen_andi_tl(t0, t0, 0x3f);
4256 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4257 break;
4258 case OPC_DROTRV:
4259 tcg_gen_andi_tl(t0, t0, 0x3f);
4260 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4261 break;
4262 #endif
4264 tcg_temp_free(t0);
4265 tcg_temp_free(t1);
4268 /* Arithmetic on HI/LO registers */
4269 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4271 if (reg == 0 && (opc == OPC_MFHI || opc == TX79_MMI_MFHI1 ||
4272 opc == OPC_MFLO || opc == TX79_MMI_MFLO1)) {
4273 /* Treat as NOP. */
4274 return;
4277 if (acc != 0) {
4278 if (!(ctx->insn_flags & INSN_R5900)) {
4279 check_dsp(ctx);
4283 switch (opc) {
4284 case OPC_MFHI:
4285 case TX79_MMI_MFHI1:
4286 #if defined(TARGET_MIPS64)
4287 if (acc != 0) {
4288 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4289 } else
4290 #endif
4292 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4294 break;
4295 case OPC_MFLO:
4296 case TX79_MMI_MFLO1:
4297 #if defined(TARGET_MIPS64)
4298 if (acc != 0) {
4299 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4300 } else
4301 #endif
4303 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4305 break;
4306 case OPC_MTHI:
4307 case TX79_MMI_MTHI1:
4308 if (reg != 0) {
4309 #if defined(TARGET_MIPS64)
4310 if (acc != 0) {
4311 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4312 } else
4313 #endif
4315 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4317 } else {
4318 tcg_gen_movi_tl(cpu_HI[acc], 0);
4320 break;
4321 case OPC_MTLO:
4322 case TX79_MMI_MTLO1:
4323 if (reg != 0) {
4324 #if defined(TARGET_MIPS64)
4325 if (acc != 0) {
4326 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4327 } else
4328 #endif
4330 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4332 } else {
4333 tcg_gen_movi_tl(cpu_LO[acc], 0);
4335 break;
4339 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4340 TCGMemOp memop)
4342 TCGv t0 = tcg_const_tl(addr);
4343 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4344 gen_store_gpr(t0, reg);
4345 tcg_temp_free(t0);
4348 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4349 int rs)
4351 target_long offset;
4352 target_long addr;
4354 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4355 case OPC_ADDIUPC:
4356 if (rs != 0) {
4357 offset = sextract32(ctx->opcode << 2, 0, 21);
4358 addr = addr_add(ctx, pc, offset);
4359 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4361 break;
4362 case R6_OPC_LWPC:
4363 offset = sextract32(ctx->opcode << 2, 0, 21);
4364 addr = addr_add(ctx, pc, offset);
4365 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4366 break;
4367 #if defined(TARGET_MIPS64)
4368 case OPC_LWUPC:
4369 check_mips_64(ctx);
4370 offset = sextract32(ctx->opcode << 2, 0, 21);
4371 addr = addr_add(ctx, pc, offset);
4372 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4373 break;
4374 #endif
4375 default:
4376 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4377 case OPC_AUIPC:
4378 if (rs != 0) {
4379 offset = sextract32(ctx->opcode, 0, 16) << 16;
4380 addr = addr_add(ctx, pc, offset);
4381 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4383 break;
4384 case OPC_ALUIPC:
4385 if (rs != 0) {
4386 offset = sextract32(ctx->opcode, 0, 16) << 16;
4387 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4388 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4390 break;
4391 #if defined(TARGET_MIPS64)
4392 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4393 case R6_OPC_LDPC + (1 << 16):
4394 case R6_OPC_LDPC + (2 << 16):
4395 case R6_OPC_LDPC + (3 << 16):
4396 check_mips_64(ctx);
4397 offset = sextract32(ctx->opcode << 3, 0, 21);
4398 addr = addr_add(ctx, (pc & ~0x7), offset);
4399 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4400 break;
4401 #endif
4402 default:
4403 MIPS_INVAL("OPC_PCREL");
4404 generate_exception_end(ctx, EXCP_RI);
4405 break;
4407 break;
4411 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4413 TCGv t0, t1;
4415 if (rd == 0) {
4416 /* Treat as NOP. */
4417 return;
4420 t0 = tcg_temp_new();
4421 t1 = tcg_temp_new();
4423 gen_load_gpr(t0, rs);
4424 gen_load_gpr(t1, rt);
4426 switch (opc) {
4427 case R6_OPC_DIV:
4429 TCGv t2 = tcg_temp_new();
4430 TCGv t3 = tcg_temp_new();
4431 tcg_gen_ext32s_tl(t0, t0);
4432 tcg_gen_ext32s_tl(t1, t1);
4433 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4434 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4435 tcg_gen_and_tl(t2, t2, t3);
4436 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4437 tcg_gen_or_tl(t2, t2, t3);
4438 tcg_gen_movi_tl(t3, 0);
4439 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4440 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4441 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4442 tcg_temp_free(t3);
4443 tcg_temp_free(t2);
4445 break;
4446 case R6_OPC_MOD:
4448 TCGv t2 = tcg_temp_new();
4449 TCGv t3 = tcg_temp_new();
4450 tcg_gen_ext32s_tl(t0, t0);
4451 tcg_gen_ext32s_tl(t1, t1);
4452 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4453 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4454 tcg_gen_and_tl(t2, t2, t3);
4455 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4456 tcg_gen_or_tl(t2, t2, t3);
4457 tcg_gen_movi_tl(t3, 0);
4458 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4459 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4460 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4461 tcg_temp_free(t3);
4462 tcg_temp_free(t2);
4464 break;
4465 case R6_OPC_DIVU:
4467 TCGv t2 = tcg_const_tl(0);
4468 TCGv t3 = tcg_const_tl(1);
4469 tcg_gen_ext32u_tl(t0, t0);
4470 tcg_gen_ext32u_tl(t1, t1);
4471 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4472 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4473 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4474 tcg_temp_free(t3);
4475 tcg_temp_free(t2);
4477 break;
4478 case R6_OPC_MODU:
4480 TCGv t2 = tcg_const_tl(0);
4481 TCGv t3 = tcg_const_tl(1);
4482 tcg_gen_ext32u_tl(t0, t0);
4483 tcg_gen_ext32u_tl(t1, t1);
4484 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4485 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4486 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4487 tcg_temp_free(t3);
4488 tcg_temp_free(t2);
4490 break;
4491 case R6_OPC_MUL:
4493 TCGv_i32 t2 = tcg_temp_new_i32();
4494 TCGv_i32 t3 = tcg_temp_new_i32();
4495 tcg_gen_trunc_tl_i32(t2, t0);
4496 tcg_gen_trunc_tl_i32(t3, t1);
4497 tcg_gen_mul_i32(t2, t2, t3);
4498 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4499 tcg_temp_free_i32(t2);
4500 tcg_temp_free_i32(t3);
4502 break;
4503 case R6_OPC_MUH:
4505 TCGv_i32 t2 = tcg_temp_new_i32();
4506 TCGv_i32 t3 = tcg_temp_new_i32();
4507 tcg_gen_trunc_tl_i32(t2, t0);
4508 tcg_gen_trunc_tl_i32(t3, t1);
4509 tcg_gen_muls2_i32(t2, t3, t2, t3);
4510 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4511 tcg_temp_free_i32(t2);
4512 tcg_temp_free_i32(t3);
4514 break;
4515 case R6_OPC_MULU:
4517 TCGv_i32 t2 = tcg_temp_new_i32();
4518 TCGv_i32 t3 = tcg_temp_new_i32();
4519 tcg_gen_trunc_tl_i32(t2, t0);
4520 tcg_gen_trunc_tl_i32(t3, t1);
4521 tcg_gen_mul_i32(t2, t2, t3);
4522 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4523 tcg_temp_free_i32(t2);
4524 tcg_temp_free_i32(t3);
4526 break;
4527 case R6_OPC_MUHU:
4529 TCGv_i32 t2 = tcg_temp_new_i32();
4530 TCGv_i32 t3 = tcg_temp_new_i32();
4531 tcg_gen_trunc_tl_i32(t2, t0);
4532 tcg_gen_trunc_tl_i32(t3, t1);
4533 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4534 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4535 tcg_temp_free_i32(t2);
4536 tcg_temp_free_i32(t3);
4538 break;
4539 #if defined(TARGET_MIPS64)
4540 case R6_OPC_DDIV:
4542 TCGv t2 = tcg_temp_new();
4543 TCGv t3 = tcg_temp_new();
4544 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4545 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4546 tcg_gen_and_tl(t2, t2, t3);
4547 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4548 tcg_gen_or_tl(t2, t2, t3);
4549 tcg_gen_movi_tl(t3, 0);
4550 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4551 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4552 tcg_temp_free(t3);
4553 tcg_temp_free(t2);
4555 break;
4556 case R6_OPC_DMOD:
4558 TCGv t2 = tcg_temp_new();
4559 TCGv t3 = tcg_temp_new();
4560 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4561 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4562 tcg_gen_and_tl(t2, t2, t3);
4563 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4564 tcg_gen_or_tl(t2, t2, t3);
4565 tcg_gen_movi_tl(t3, 0);
4566 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4567 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4568 tcg_temp_free(t3);
4569 tcg_temp_free(t2);
4571 break;
4572 case R6_OPC_DDIVU:
4574 TCGv t2 = tcg_const_tl(0);
4575 TCGv t3 = tcg_const_tl(1);
4576 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4577 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4578 tcg_temp_free(t3);
4579 tcg_temp_free(t2);
4581 break;
4582 case R6_OPC_DMODU:
4584 TCGv t2 = tcg_const_tl(0);
4585 TCGv t3 = tcg_const_tl(1);
4586 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4587 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4588 tcg_temp_free(t3);
4589 tcg_temp_free(t2);
4591 break;
4592 case R6_OPC_DMUL:
4593 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4594 break;
4595 case R6_OPC_DMUH:
4597 TCGv t2 = tcg_temp_new();
4598 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4599 tcg_temp_free(t2);
4601 break;
4602 case R6_OPC_DMULU:
4603 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4604 break;
4605 case R6_OPC_DMUHU:
4607 TCGv t2 = tcg_temp_new();
4608 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4609 tcg_temp_free(t2);
4611 break;
4612 #endif
4613 default:
4614 MIPS_INVAL("r6 mul/div");
4615 generate_exception_end(ctx, EXCP_RI);
4616 goto out;
4618 out:
4619 tcg_temp_free(t0);
4620 tcg_temp_free(t1);
4623 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4624 int acc, int rs, int rt)
4626 TCGv t0, t1;
4628 t0 = tcg_temp_new();
4629 t1 = tcg_temp_new();
4631 gen_load_gpr(t0, rs);
4632 gen_load_gpr(t1, rt);
4634 if (acc != 0) {
4635 if (!(ctx->insn_flags & INSN_R5900)) {
4636 check_dsp(ctx);
4640 switch (opc) {
4641 case OPC_DIV:
4642 case TX79_MMI_DIV1:
4644 TCGv t2 = tcg_temp_new();
4645 TCGv t3 = tcg_temp_new();
4646 tcg_gen_ext32s_tl(t0, t0);
4647 tcg_gen_ext32s_tl(t1, t1);
4648 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4649 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4650 tcg_gen_and_tl(t2, t2, t3);
4651 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4652 tcg_gen_or_tl(t2, t2, t3);
4653 tcg_gen_movi_tl(t3, 0);
4654 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4655 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4656 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4657 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4658 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4659 tcg_temp_free(t3);
4660 tcg_temp_free(t2);
4662 break;
4663 case OPC_DIVU:
4664 case TX79_MMI_DIVU1:
4666 TCGv t2 = tcg_const_tl(0);
4667 TCGv t3 = tcg_const_tl(1);
4668 tcg_gen_ext32u_tl(t0, t0);
4669 tcg_gen_ext32u_tl(t1, t1);
4670 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4671 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4672 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4673 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4674 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4675 tcg_temp_free(t3);
4676 tcg_temp_free(t2);
4678 break;
4679 case OPC_MULT:
4681 TCGv_i32 t2 = tcg_temp_new_i32();
4682 TCGv_i32 t3 = tcg_temp_new_i32();
4683 tcg_gen_trunc_tl_i32(t2, t0);
4684 tcg_gen_trunc_tl_i32(t3, t1);
4685 tcg_gen_muls2_i32(t2, t3, t2, t3);
4686 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4687 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4688 tcg_temp_free_i32(t2);
4689 tcg_temp_free_i32(t3);
4691 break;
4692 case OPC_MULTU:
4694 TCGv_i32 t2 = tcg_temp_new_i32();
4695 TCGv_i32 t3 = tcg_temp_new_i32();
4696 tcg_gen_trunc_tl_i32(t2, t0);
4697 tcg_gen_trunc_tl_i32(t3, t1);
4698 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4699 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4700 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4701 tcg_temp_free_i32(t2);
4702 tcg_temp_free_i32(t3);
4704 break;
4705 #if defined(TARGET_MIPS64)
4706 case OPC_DDIV:
4708 TCGv t2 = tcg_temp_new();
4709 TCGv t3 = tcg_temp_new();
4710 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4711 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4712 tcg_gen_and_tl(t2, t2, t3);
4713 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4714 tcg_gen_or_tl(t2, t2, t3);
4715 tcg_gen_movi_tl(t3, 0);
4716 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4717 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4718 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4719 tcg_temp_free(t3);
4720 tcg_temp_free(t2);
4722 break;
4723 case OPC_DDIVU:
4725 TCGv t2 = tcg_const_tl(0);
4726 TCGv t3 = tcg_const_tl(1);
4727 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4728 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4729 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4730 tcg_temp_free(t3);
4731 tcg_temp_free(t2);
4733 break;
4734 case OPC_DMULT:
4735 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4736 break;
4737 case OPC_DMULTU:
4738 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4739 break;
4740 #endif
4741 case OPC_MADD:
4743 TCGv_i64 t2 = tcg_temp_new_i64();
4744 TCGv_i64 t3 = tcg_temp_new_i64();
4746 tcg_gen_ext_tl_i64(t2, t0);
4747 tcg_gen_ext_tl_i64(t3, t1);
4748 tcg_gen_mul_i64(t2, t2, t3);
4749 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4750 tcg_gen_add_i64(t2, t2, t3);
4751 tcg_temp_free_i64(t3);
4752 gen_move_low32(cpu_LO[acc], t2);
4753 gen_move_high32(cpu_HI[acc], t2);
4754 tcg_temp_free_i64(t2);
4756 break;
4757 case OPC_MADDU:
4759 TCGv_i64 t2 = tcg_temp_new_i64();
4760 TCGv_i64 t3 = tcg_temp_new_i64();
4762 tcg_gen_ext32u_tl(t0, t0);
4763 tcg_gen_ext32u_tl(t1, t1);
4764 tcg_gen_extu_tl_i64(t2, t0);
4765 tcg_gen_extu_tl_i64(t3, t1);
4766 tcg_gen_mul_i64(t2, t2, t3);
4767 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4768 tcg_gen_add_i64(t2, t2, t3);
4769 tcg_temp_free_i64(t3);
4770 gen_move_low32(cpu_LO[acc], t2);
4771 gen_move_high32(cpu_HI[acc], t2);
4772 tcg_temp_free_i64(t2);
4774 break;
4775 case OPC_MSUB:
4777 TCGv_i64 t2 = tcg_temp_new_i64();
4778 TCGv_i64 t3 = tcg_temp_new_i64();
4780 tcg_gen_ext_tl_i64(t2, t0);
4781 tcg_gen_ext_tl_i64(t3, t1);
4782 tcg_gen_mul_i64(t2, t2, t3);
4783 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4784 tcg_gen_sub_i64(t2, t3, t2);
4785 tcg_temp_free_i64(t3);
4786 gen_move_low32(cpu_LO[acc], t2);
4787 gen_move_high32(cpu_HI[acc], t2);
4788 tcg_temp_free_i64(t2);
4790 break;
4791 case OPC_MSUBU:
4793 TCGv_i64 t2 = tcg_temp_new_i64();
4794 TCGv_i64 t3 = tcg_temp_new_i64();
4796 tcg_gen_ext32u_tl(t0, t0);
4797 tcg_gen_ext32u_tl(t1, t1);
4798 tcg_gen_extu_tl_i64(t2, t0);
4799 tcg_gen_extu_tl_i64(t3, t1);
4800 tcg_gen_mul_i64(t2, t2, t3);
4801 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4802 tcg_gen_sub_i64(t2, t3, t2);
4803 tcg_temp_free_i64(t3);
4804 gen_move_low32(cpu_LO[acc], t2);
4805 gen_move_high32(cpu_HI[acc], t2);
4806 tcg_temp_free_i64(t2);
4808 break;
4809 default:
4810 MIPS_INVAL("mul/div");
4811 generate_exception_end(ctx, EXCP_RI);
4812 goto out;
4814 out:
4815 tcg_temp_free(t0);
4816 tcg_temp_free(t1);
4820 * These MULT and MULTU instructions implemented in for example the
4821 * Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4822 * architectures are special three-operand variants with the syntax
4824 * MULT[U][1] rd, rs, rt
4826 * such that
4828 * (rd, LO, HI) <- rs * rt
4830 * where the low-order 32-bits of the result is placed into both the
4831 * GPR rd and the special register LO. The high-order 32-bits of the
4832 * result is placed into the special register HI.
4834 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4835 * which is the zero register that always reads as 0.
4837 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4838 int rd, int rs, int rt)
4840 TCGv t0 = tcg_temp_new();
4841 TCGv t1 = tcg_temp_new();
4842 int acc = 0;
4844 gen_load_gpr(t0, rs);
4845 gen_load_gpr(t1, rt);
4847 switch (opc) {
4848 case TX79_MMI_MULT1:
4849 acc = 1;
4850 /* Fall through */
4851 case OPC_MULT:
4853 TCGv_i32 t2 = tcg_temp_new_i32();
4854 TCGv_i32 t3 = tcg_temp_new_i32();
4855 tcg_gen_trunc_tl_i32(t2, t0);
4856 tcg_gen_trunc_tl_i32(t3, t1);
4857 tcg_gen_muls2_i32(t2, t3, t2, t3);
4858 if (rd) {
4859 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4861 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4862 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4863 tcg_temp_free_i32(t2);
4864 tcg_temp_free_i32(t3);
4866 break;
4867 case TX79_MMI_MULTU1:
4868 acc = 1;
4869 /* Fall through */
4870 case OPC_MULTU:
4872 TCGv_i32 t2 = tcg_temp_new_i32();
4873 TCGv_i32 t3 = tcg_temp_new_i32();
4874 tcg_gen_trunc_tl_i32(t2, t0);
4875 tcg_gen_trunc_tl_i32(t3, t1);
4876 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4877 if (rd) {
4878 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4880 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4881 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4882 tcg_temp_free_i32(t2);
4883 tcg_temp_free_i32(t3);
4885 break;
4886 default:
4887 MIPS_INVAL("mul TXx9");
4888 generate_exception_end(ctx, EXCP_RI);
4889 goto out;
4892 out:
4893 tcg_temp_free(t0);
4894 tcg_temp_free(t1);
4897 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4898 int rd, int rs, int rt)
4900 TCGv t0 = tcg_temp_new();
4901 TCGv t1 = tcg_temp_new();
4903 gen_load_gpr(t0, rs);
4904 gen_load_gpr(t1, rt);
4906 switch (opc) {
4907 case OPC_VR54XX_MULS:
4908 gen_helper_muls(t0, cpu_env, t0, t1);
4909 break;
4910 case OPC_VR54XX_MULSU:
4911 gen_helper_mulsu(t0, cpu_env, t0, t1);
4912 break;
4913 case OPC_VR54XX_MACC:
4914 gen_helper_macc(t0, cpu_env, t0, t1);
4915 break;
4916 case OPC_VR54XX_MACCU:
4917 gen_helper_maccu(t0, cpu_env, t0, t1);
4918 break;
4919 case OPC_VR54XX_MSAC:
4920 gen_helper_msac(t0, cpu_env, t0, t1);
4921 break;
4922 case OPC_VR54XX_MSACU:
4923 gen_helper_msacu(t0, cpu_env, t0, t1);
4924 break;
4925 case OPC_VR54XX_MULHI:
4926 gen_helper_mulhi(t0, cpu_env, t0, t1);
4927 break;
4928 case OPC_VR54XX_MULHIU:
4929 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4930 break;
4931 case OPC_VR54XX_MULSHI:
4932 gen_helper_mulshi(t0, cpu_env, t0, t1);
4933 break;
4934 case OPC_VR54XX_MULSHIU:
4935 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4936 break;
4937 case OPC_VR54XX_MACCHI:
4938 gen_helper_macchi(t0, cpu_env, t0, t1);
4939 break;
4940 case OPC_VR54XX_MACCHIU:
4941 gen_helper_macchiu(t0, cpu_env, t0, t1);
4942 break;
4943 case OPC_VR54XX_MSACHI:
4944 gen_helper_msachi(t0, cpu_env, t0, t1);
4945 break;
4946 case OPC_VR54XX_MSACHIU:
4947 gen_helper_msachiu(t0, cpu_env, t0, t1);
4948 break;
4949 default:
4950 MIPS_INVAL("mul vr54xx");
4951 generate_exception_end(ctx, EXCP_RI);
4952 goto out;
4954 gen_store_gpr(t0, rd);
4956 out:
4957 tcg_temp_free(t0);
4958 tcg_temp_free(t1);
4961 static void gen_cl (DisasContext *ctx, uint32_t opc,
4962 int rd, int rs)
4964 TCGv t0;
4966 if (rd == 0) {
4967 /* Treat as NOP. */
4968 return;
4970 t0 = cpu_gpr[rd];
4971 gen_load_gpr(t0, rs);
4973 switch (opc) {
4974 case OPC_CLO:
4975 case R6_OPC_CLO:
4976 #if defined(TARGET_MIPS64)
4977 case OPC_DCLO:
4978 case R6_OPC_DCLO:
4979 #endif
4980 tcg_gen_not_tl(t0, t0);
4981 break;
4984 switch (opc) {
4985 case OPC_CLO:
4986 case R6_OPC_CLO:
4987 case OPC_CLZ:
4988 case R6_OPC_CLZ:
4989 tcg_gen_ext32u_tl(t0, t0);
4990 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4991 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4992 break;
4993 #if defined(TARGET_MIPS64)
4994 case OPC_DCLO:
4995 case R6_OPC_DCLO:
4996 case OPC_DCLZ:
4997 case R6_OPC_DCLZ:
4998 tcg_gen_clzi_i64(t0, t0, 64);
4999 break;
5000 #endif
5004 /* Godson integer instructions */
5005 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5006 int rd, int rs, int rt)
5008 TCGv t0, t1;
5010 if (rd == 0) {
5011 /* Treat as NOP. */
5012 return;
5015 switch (opc) {
5016 case OPC_MULT_G_2E:
5017 case OPC_MULT_G_2F:
5018 case OPC_MULTU_G_2E:
5019 case OPC_MULTU_G_2F:
5020 #if defined(TARGET_MIPS64)
5021 case OPC_DMULT_G_2E:
5022 case OPC_DMULT_G_2F:
5023 case OPC_DMULTU_G_2E:
5024 case OPC_DMULTU_G_2F:
5025 #endif
5026 t0 = tcg_temp_new();
5027 t1 = tcg_temp_new();
5028 break;
5029 default:
5030 t0 = tcg_temp_local_new();
5031 t1 = tcg_temp_local_new();
5032 break;
5035 gen_load_gpr(t0, rs);
5036 gen_load_gpr(t1, rt);
5038 switch (opc) {
5039 case OPC_MULT_G_2E:
5040 case OPC_MULT_G_2F:
5041 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5042 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5043 break;
5044 case OPC_MULTU_G_2E:
5045 case OPC_MULTU_G_2F:
5046 tcg_gen_ext32u_tl(t0, t0);
5047 tcg_gen_ext32u_tl(t1, t1);
5048 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5049 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5050 break;
5051 case OPC_DIV_G_2E:
5052 case OPC_DIV_G_2F:
5054 TCGLabel *l1 = gen_new_label();
5055 TCGLabel *l2 = gen_new_label();
5056 TCGLabel *l3 = gen_new_label();
5057 tcg_gen_ext32s_tl(t0, t0);
5058 tcg_gen_ext32s_tl(t1, t1);
5059 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5060 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5061 tcg_gen_br(l3);
5062 gen_set_label(l1);
5063 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5064 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5065 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5066 tcg_gen_br(l3);
5067 gen_set_label(l2);
5068 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5069 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5070 gen_set_label(l3);
5072 break;
5073 case OPC_DIVU_G_2E:
5074 case OPC_DIVU_G_2F:
5076 TCGLabel *l1 = gen_new_label();
5077 TCGLabel *l2 = gen_new_label();
5078 tcg_gen_ext32u_tl(t0, t0);
5079 tcg_gen_ext32u_tl(t1, t1);
5080 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5081 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5082 tcg_gen_br(l2);
5083 gen_set_label(l1);
5084 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5085 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5086 gen_set_label(l2);
5088 break;
5089 case OPC_MOD_G_2E:
5090 case OPC_MOD_G_2F:
5092 TCGLabel *l1 = gen_new_label();
5093 TCGLabel *l2 = gen_new_label();
5094 TCGLabel *l3 = gen_new_label();
5095 tcg_gen_ext32u_tl(t0, t0);
5096 tcg_gen_ext32u_tl(t1, t1);
5097 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5098 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5099 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5100 gen_set_label(l1);
5101 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5102 tcg_gen_br(l3);
5103 gen_set_label(l2);
5104 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5105 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5106 gen_set_label(l3);
5108 break;
5109 case OPC_MODU_G_2E:
5110 case OPC_MODU_G_2F:
5112 TCGLabel *l1 = gen_new_label();
5113 TCGLabel *l2 = gen_new_label();
5114 tcg_gen_ext32u_tl(t0, t0);
5115 tcg_gen_ext32u_tl(t1, t1);
5116 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5117 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5118 tcg_gen_br(l2);
5119 gen_set_label(l1);
5120 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5121 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5122 gen_set_label(l2);
5124 break;
5125 #if defined(TARGET_MIPS64)
5126 case OPC_DMULT_G_2E:
5127 case OPC_DMULT_G_2F:
5128 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5129 break;
5130 case OPC_DMULTU_G_2E:
5131 case OPC_DMULTU_G_2F:
5132 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5133 break;
5134 case OPC_DDIV_G_2E:
5135 case OPC_DDIV_G_2F:
5137 TCGLabel *l1 = gen_new_label();
5138 TCGLabel *l2 = gen_new_label();
5139 TCGLabel *l3 = gen_new_label();
5140 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5141 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5142 tcg_gen_br(l3);
5143 gen_set_label(l1);
5144 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5145 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5146 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5147 tcg_gen_br(l3);
5148 gen_set_label(l2);
5149 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5150 gen_set_label(l3);
5152 break;
5153 case OPC_DDIVU_G_2E:
5154 case OPC_DDIVU_G_2F:
5156 TCGLabel *l1 = gen_new_label();
5157 TCGLabel *l2 = gen_new_label();
5158 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5159 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5160 tcg_gen_br(l2);
5161 gen_set_label(l1);
5162 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5163 gen_set_label(l2);
5165 break;
5166 case OPC_DMOD_G_2E:
5167 case OPC_DMOD_G_2F:
5169 TCGLabel *l1 = gen_new_label();
5170 TCGLabel *l2 = gen_new_label();
5171 TCGLabel *l3 = gen_new_label();
5172 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5173 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5174 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5175 gen_set_label(l1);
5176 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5177 tcg_gen_br(l3);
5178 gen_set_label(l2);
5179 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5180 gen_set_label(l3);
5182 break;
5183 case OPC_DMODU_G_2E:
5184 case OPC_DMODU_G_2F:
5186 TCGLabel *l1 = gen_new_label();
5187 TCGLabel *l2 = gen_new_label();
5188 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5189 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5190 tcg_gen_br(l2);
5191 gen_set_label(l1);
5192 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5193 gen_set_label(l2);
5195 break;
5196 #endif
5199 tcg_temp_free(t0);
5200 tcg_temp_free(t1);
5203 /* Loongson multimedia instructions */
5204 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5206 uint32_t opc, shift_max;
5207 TCGv_i64 t0, t1;
5209 opc = MASK_LMI(ctx->opcode);
5210 switch (opc) {
5211 case OPC_ADD_CP2:
5212 case OPC_SUB_CP2:
5213 case OPC_DADD_CP2:
5214 case OPC_DSUB_CP2:
5215 t0 = tcg_temp_local_new_i64();
5216 t1 = tcg_temp_local_new_i64();
5217 break;
5218 default:
5219 t0 = tcg_temp_new_i64();
5220 t1 = tcg_temp_new_i64();
5221 break;
5224 check_cp1_enabled(ctx);
5225 gen_load_fpr64(ctx, t0, rs);
5226 gen_load_fpr64(ctx, t1, rt);
5228 #define LMI_HELPER(UP, LO) \
5229 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5230 #define LMI_HELPER_1(UP, LO) \
5231 case OPC_##UP: gen_helper_##LO(t0, t0); break
5232 #define LMI_DIRECT(UP, LO, OP) \
5233 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5235 switch (opc) {
5236 LMI_HELPER(PADDSH, paddsh);
5237 LMI_HELPER(PADDUSH, paddush);
5238 LMI_HELPER(PADDH, paddh);
5239 LMI_HELPER(PADDW, paddw);
5240 LMI_HELPER(PADDSB, paddsb);
5241 LMI_HELPER(PADDUSB, paddusb);
5242 LMI_HELPER(PADDB, paddb);
5244 LMI_HELPER(PSUBSH, psubsh);
5245 LMI_HELPER(PSUBUSH, psubush);
5246 LMI_HELPER(PSUBH, psubh);
5247 LMI_HELPER(PSUBW, psubw);
5248 LMI_HELPER(PSUBSB, psubsb);
5249 LMI_HELPER(PSUBUSB, psubusb);
5250 LMI_HELPER(PSUBB, psubb);
5252 LMI_HELPER(PSHUFH, pshufh);
5253 LMI_HELPER(PACKSSWH, packsswh);
5254 LMI_HELPER(PACKSSHB, packsshb);
5255 LMI_HELPER(PACKUSHB, packushb);
5257 LMI_HELPER(PUNPCKLHW, punpcklhw);
5258 LMI_HELPER(PUNPCKHHW, punpckhhw);
5259 LMI_HELPER(PUNPCKLBH, punpcklbh);
5260 LMI_HELPER(PUNPCKHBH, punpckhbh);
5261 LMI_HELPER(PUNPCKLWD, punpcklwd);
5262 LMI_HELPER(PUNPCKHWD, punpckhwd);
5264 LMI_HELPER(PAVGH, pavgh);
5265 LMI_HELPER(PAVGB, pavgb);
5266 LMI_HELPER(PMAXSH, pmaxsh);
5267 LMI_HELPER(PMINSH, pminsh);
5268 LMI_HELPER(PMAXUB, pmaxub);
5269 LMI_HELPER(PMINUB, pminub);
5271 LMI_HELPER(PCMPEQW, pcmpeqw);
5272 LMI_HELPER(PCMPGTW, pcmpgtw);
5273 LMI_HELPER(PCMPEQH, pcmpeqh);
5274 LMI_HELPER(PCMPGTH, pcmpgth);
5275 LMI_HELPER(PCMPEQB, pcmpeqb);
5276 LMI_HELPER(PCMPGTB, pcmpgtb);
5278 LMI_HELPER(PSLLW, psllw);
5279 LMI_HELPER(PSLLH, psllh);
5280 LMI_HELPER(PSRLW, psrlw);
5281 LMI_HELPER(PSRLH, psrlh);
5282 LMI_HELPER(PSRAW, psraw);
5283 LMI_HELPER(PSRAH, psrah);
5285 LMI_HELPER(PMULLH, pmullh);
5286 LMI_HELPER(PMULHH, pmulhh);
5287 LMI_HELPER(PMULHUH, pmulhuh);
5288 LMI_HELPER(PMADDHW, pmaddhw);
5290 LMI_HELPER(PASUBUB, pasubub);
5291 LMI_HELPER_1(BIADD, biadd);
5292 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5294 LMI_DIRECT(PADDD, paddd, add);
5295 LMI_DIRECT(PSUBD, psubd, sub);
5296 LMI_DIRECT(XOR_CP2, xor, xor);
5297 LMI_DIRECT(NOR_CP2, nor, nor);
5298 LMI_DIRECT(AND_CP2, and, and);
5299 LMI_DIRECT(OR_CP2, or, or);
5301 case OPC_PANDN:
5302 tcg_gen_andc_i64(t0, t1, t0);
5303 break;
5305 case OPC_PINSRH_0:
5306 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5307 break;
5308 case OPC_PINSRH_1:
5309 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5310 break;
5311 case OPC_PINSRH_2:
5312 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5313 break;
5314 case OPC_PINSRH_3:
5315 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5316 break;
5318 case OPC_PEXTRH:
5319 tcg_gen_andi_i64(t1, t1, 3);
5320 tcg_gen_shli_i64(t1, t1, 4);
5321 tcg_gen_shr_i64(t0, t0, t1);
5322 tcg_gen_ext16u_i64(t0, t0);
5323 break;
5325 case OPC_ADDU_CP2:
5326 tcg_gen_add_i64(t0, t0, t1);
5327 tcg_gen_ext32s_i64(t0, t0);
5328 break;
5329 case OPC_SUBU_CP2:
5330 tcg_gen_sub_i64(t0, t0, t1);
5331 tcg_gen_ext32s_i64(t0, t0);
5332 break;
5334 case OPC_SLL_CP2:
5335 shift_max = 32;
5336 goto do_shift;
5337 case OPC_SRL_CP2:
5338 shift_max = 32;
5339 goto do_shift;
5340 case OPC_SRA_CP2:
5341 shift_max = 32;
5342 goto do_shift;
5343 case OPC_DSLL_CP2:
5344 shift_max = 64;
5345 goto do_shift;
5346 case OPC_DSRL_CP2:
5347 shift_max = 64;
5348 goto do_shift;
5349 case OPC_DSRA_CP2:
5350 shift_max = 64;
5351 goto do_shift;
5352 do_shift:
5353 /* Make sure shift count isn't TCG undefined behaviour. */
5354 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5356 switch (opc) {
5357 case OPC_SLL_CP2:
5358 case OPC_DSLL_CP2:
5359 tcg_gen_shl_i64(t0, t0, t1);
5360 break;
5361 case OPC_SRA_CP2:
5362 case OPC_DSRA_CP2:
5363 /* Since SRA is UndefinedResult without sign-extended inputs,
5364 we can treat SRA and DSRA the same. */
5365 tcg_gen_sar_i64(t0, t0, t1);
5366 break;
5367 case OPC_SRL_CP2:
5368 /* We want to shift in zeros for SRL; zero-extend first. */
5369 tcg_gen_ext32u_i64(t0, t0);
5370 /* FALLTHRU */
5371 case OPC_DSRL_CP2:
5372 tcg_gen_shr_i64(t0, t0, t1);
5373 break;
5376 if (shift_max == 32) {
5377 tcg_gen_ext32s_i64(t0, t0);
5380 /* Shifts larger than MAX produce zero. */
5381 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5382 tcg_gen_neg_i64(t1, t1);
5383 tcg_gen_and_i64(t0, t0, t1);
5384 break;
5386 case OPC_ADD_CP2:
5387 case OPC_DADD_CP2:
5389 TCGv_i64 t2 = tcg_temp_new_i64();
5390 TCGLabel *lab = gen_new_label();
5392 tcg_gen_mov_i64(t2, t0);
5393 tcg_gen_add_i64(t0, t1, t2);
5394 if (opc == OPC_ADD_CP2) {
5395 tcg_gen_ext32s_i64(t0, t0);
5397 tcg_gen_xor_i64(t1, t1, t2);
5398 tcg_gen_xor_i64(t2, t2, t0);
5399 tcg_gen_andc_i64(t1, t2, t1);
5400 tcg_temp_free_i64(t2);
5401 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5402 generate_exception(ctx, EXCP_OVERFLOW);
5403 gen_set_label(lab);
5404 break;
5407 case OPC_SUB_CP2:
5408 case OPC_DSUB_CP2:
5410 TCGv_i64 t2 = tcg_temp_new_i64();
5411 TCGLabel *lab = gen_new_label();
5413 tcg_gen_mov_i64(t2, t0);
5414 tcg_gen_sub_i64(t0, t1, t2);
5415 if (opc == OPC_SUB_CP2) {
5416 tcg_gen_ext32s_i64(t0, t0);
5418 tcg_gen_xor_i64(t1, t1, t2);
5419 tcg_gen_xor_i64(t2, t2, t0);
5420 tcg_gen_and_i64(t1, t1, t2);
5421 tcg_temp_free_i64(t2);
5422 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5423 generate_exception(ctx, EXCP_OVERFLOW);
5424 gen_set_label(lab);
5425 break;
5428 case OPC_PMULUW:
5429 tcg_gen_ext32u_i64(t0, t0);
5430 tcg_gen_ext32u_i64(t1, t1);
5431 tcg_gen_mul_i64(t0, t0, t1);
5432 break;
5434 case OPC_SEQU_CP2:
5435 case OPC_SEQ_CP2:
5436 case OPC_SLTU_CP2:
5437 case OPC_SLT_CP2:
5438 case OPC_SLEU_CP2:
5439 case OPC_SLE_CP2:
5440 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5441 FD field is the CC field? */
5442 default:
5443 MIPS_INVAL("loongson_cp2");
5444 generate_exception_end(ctx, EXCP_RI);
5445 return;
5448 #undef LMI_HELPER
5449 #undef LMI_DIRECT
5451 gen_store_fpr64(ctx, t0, rd);
5453 tcg_temp_free_i64(t0);
5454 tcg_temp_free_i64(t1);
5457 /* Traps */
5458 static void gen_trap (DisasContext *ctx, uint32_t opc,
5459 int rs, int rt, int16_t imm)
5461 int cond;
5462 TCGv t0 = tcg_temp_new();
5463 TCGv t1 = tcg_temp_new();
5465 cond = 0;
5466 /* Load needed operands */
5467 switch (opc) {
5468 case OPC_TEQ:
5469 case OPC_TGE:
5470 case OPC_TGEU:
5471 case OPC_TLT:
5472 case OPC_TLTU:
5473 case OPC_TNE:
5474 /* Compare two registers */
5475 if (rs != rt) {
5476 gen_load_gpr(t0, rs);
5477 gen_load_gpr(t1, rt);
5478 cond = 1;
5480 break;
5481 case OPC_TEQI:
5482 case OPC_TGEI:
5483 case OPC_TGEIU:
5484 case OPC_TLTI:
5485 case OPC_TLTIU:
5486 case OPC_TNEI:
5487 /* Compare register to immediate */
5488 if (rs != 0 || imm != 0) {
5489 gen_load_gpr(t0, rs);
5490 tcg_gen_movi_tl(t1, (int32_t)imm);
5491 cond = 1;
5493 break;
5495 if (cond == 0) {
5496 switch (opc) {
5497 case OPC_TEQ: /* rs == rs */
5498 case OPC_TEQI: /* r0 == 0 */
5499 case OPC_TGE: /* rs >= rs */
5500 case OPC_TGEI: /* r0 >= 0 */
5501 case OPC_TGEU: /* rs >= rs unsigned */
5502 case OPC_TGEIU: /* r0 >= 0 unsigned */
5503 /* Always trap */
5504 generate_exception_end(ctx, EXCP_TRAP);
5505 break;
5506 case OPC_TLT: /* rs < rs */
5507 case OPC_TLTI: /* r0 < 0 */
5508 case OPC_TLTU: /* rs < rs unsigned */
5509 case OPC_TLTIU: /* r0 < 0 unsigned */
5510 case OPC_TNE: /* rs != rs */
5511 case OPC_TNEI: /* r0 != 0 */
5512 /* Never trap: treat as NOP. */
5513 break;
5515 } else {
5516 TCGLabel *l1 = gen_new_label();
5518 switch (opc) {
5519 case OPC_TEQ:
5520 case OPC_TEQI:
5521 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5522 break;
5523 case OPC_TGE:
5524 case OPC_TGEI:
5525 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5526 break;
5527 case OPC_TGEU:
5528 case OPC_TGEIU:
5529 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5530 break;
5531 case OPC_TLT:
5532 case OPC_TLTI:
5533 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5534 break;
5535 case OPC_TLTU:
5536 case OPC_TLTIU:
5537 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5538 break;
5539 case OPC_TNE:
5540 case OPC_TNEI:
5541 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5542 break;
5544 generate_exception(ctx, EXCP_TRAP);
5545 gen_set_label(l1);
5547 tcg_temp_free(t0);
5548 tcg_temp_free(t1);
5551 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5553 if (unlikely(ctx->base.singlestep_enabled)) {
5554 return false;
5557 #ifndef CONFIG_USER_ONLY
5558 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5559 #else
5560 return true;
5561 #endif
5564 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5566 if (use_goto_tb(ctx, dest)) {
5567 tcg_gen_goto_tb(n);
5568 gen_save_pc(dest);
5569 tcg_gen_exit_tb(ctx->base.tb, n);
5570 } else {
5571 gen_save_pc(dest);
5572 if (ctx->base.singlestep_enabled) {
5573 save_cpu_state(ctx, 0);
5574 gen_helper_raise_exception_debug(cpu_env);
5576 tcg_gen_lookup_and_goto_ptr();
5580 /* Branches (before delay slot) */
5581 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5582 int insn_bytes,
5583 int rs, int rt, int32_t offset,
5584 int delayslot_size)
5586 target_ulong btgt = -1;
5587 int blink = 0;
5588 int bcond_compute = 0;
5589 TCGv t0 = tcg_temp_new();
5590 TCGv t1 = tcg_temp_new();
5592 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5593 #ifdef MIPS_DEBUG_DISAS
5594 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5595 TARGET_FMT_lx "\n", ctx->base.pc_next);
5596 #endif
5597 generate_exception_end(ctx, EXCP_RI);
5598 goto out;
5601 /* Load needed operands */
5602 switch (opc) {
5603 case OPC_BEQ:
5604 case OPC_BEQL:
5605 case OPC_BNE:
5606 case OPC_BNEL:
5607 /* Compare two registers */
5608 if (rs != rt) {
5609 gen_load_gpr(t0, rs);
5610 gen_load_gpr(t1, rt);
5611 bcond_compute = 1;
5613 btgt = ctx->base.pc_next + insn_bytes + offset;
5614 break;
5615 case OPC_BGEZ:
5616 case OPC_BGEZAL:
5617 case OPC_BGEZALL:
5618 case OPC_BGEZL:
5619 case OPC_BGTZ:
5620 case OPC_BGTZL:
5621 case OPC_BLEZ:
5622 case OPC_BLEZL:
5623 case OPC_BLTZ:
5624 case OPC_BLTZAL:
5625 case OPC_BLTZALL:
5626 case OPC_BLTZL:
5627 /* Compare to zero */
5628 if (rs != 0) {
5629 gen_load_gpr(t0, rs);
5630 bcond_compute = 1;
5632 btgt = ctx->base.pc_next + insn_bytes + offset;
5633 break;
5634 case OPC_BPOSGE32:
5635 #if defined(TARGET_MIPS64)
5636 case OPC_BPOSGE64:
5637 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5638 #else
5639 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5640 #endif
5641 bcond_compute = 1;
5642 btgt = ctx->base.pc_next + insn_bytes + offset;
5643 break;
5644 case OPC_J:
5645 case OPC_JAL:
5646 case OPC_JALX:
5647 /* Jump to immediate */
5648 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5649 (uint32_t)offset;
5650 break;
5651 case OPC_JR:
5652 case OPC_JALR:
5653 /* Jump to register */
5654 if (offset != 0 && offset != 16) {
5655 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5656 others are reserved. */
5657 MIPS_INVAL("jump hint");
5658 generate_exception_end(ctx, EXCP_RI);
5659 goto out;
5661 gen_load_gpr(btarget, rs);
5662 break;
5663 default:
5664 MIPS_INVAL("branch/jump");
5665 generate_exception_end(ctx, EXCP_RI);
5666 goto out;
5668 if (bcond_compute == 0) {
5669 /* No condition to be computed */
5670 switch (opc) {
5671 case OPC_BEQ: /* rx == rx */
5672 case OPC_BEQL: /* rx == rx likely */
5673 case OPC_BGEZ: /* 0 >= 0 */
5674 case OPC_BGEZL: /* 0 >= 0 likely */
5675 case OPC_BLEZ: /* 0 <= 0 */
5676 case OPC_BLEZL: /* 0 <= 0 likely */
5677 /* Always take */
5678 ctx->hflags |= MIPS_HFLAG_B;
5679 break;
5680 case OPC_BGEZAL: /* 0 >= 0 */
5681 case OPC_BGEZALL: /* 0 >= 0 likely */
5682 /* Always take and link */
5683 blink = 31;
5684 ctx->hflags |= MIPS_HFLAG_B;
5685 break;
5686 case OPC_BNE: /* rx != rx */
5687 case OPC_BGTZ: /* 0 > 0 */
5688 case OPC_BLTZ: /* 0 < 0 */
5689 /* Treat as NOP. */
5690 goto out;
5691 case OPC_BLTZAL: /* 0 < 0 */
5692 /* Handle as an unconditional branch to get correct delay
5693 slot checking. */
5694 blink = 31;
5695 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5696 ctx->hflags |= MIPS_HFLAG_B;
5697 break;
5698 case OPC_BLTZALL: /* 0 < 0 likely */
5699 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5700 /* Skip the instruction in the delay slot */
5701 ctx->base.pc_next += 4;
5702 goto out;
5703 case OPC_BNEL: /* rx != rx likely */
5704 case OPC_BGTZL: /* 0 > 0 likely */
5705 case OPC_BLTZL: /* 0 < 0 likely */
5706 /* Skip the instruction in the delay slot */
5707 ctx->base.pc_next += 4;
5708 goto out;
5709 case OPC_J:
5710 ctx->hflags |= MIPS_HFLAG_B;
5711 break;
5712 case OPC_JALX:
5713 ctx->hflags |= MIPS_HFLAG_BX;
5714 /* Fallthrough */
5715 case OPC_JAL:
5716 blink = 31;
5717 ctx->hflags |= MIPS_HFLAG_B;
5718 break;
5719 case OPC_JR:
5720 ctx->hflags |= MIPS_HFLAG_BR;
5721 break;
5722 case OPC_JALR:
5723 blink = rt;
5724 ctx->hflags |= MIPS_HFLAG_BR;
5725 break;
5726 default:
5727 MIPS_INVAL("branch/jump");
5728 generate_exception_end(ctx, EXCP_RI);
5729 goto out;
5731 } else {
5732 switch (opc) {
5733 case OPC_BEQ:
5734 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5735 goto not_likely;
5736 case OPC_BEQL:
5737 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5738 goto likely;
5739 case OPC_BNE:
5740 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5741 goto not_likely;
5742 case OPC_BNEL:
5743 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5744 goto likely;
5745 case OPC_BGEZ:
5746 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5747 goto not_likely;
5748 case OPC_BGEZL:
5749 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5750 goto likely;
5751 case OPC_BGEZAL:
5752 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5753 blink = 31;
5754 goto not_likely;
5755 case OPC_BGEZALL:
5756 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5757 blink = 31;
5758 goto likely;
5759 case OPC_BGTZ:
5760 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5761 goto not_likely;
5762 case OPC_BGTZL:
5763 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5764 goto likely;
5765 case OPC_BLEZ:
5766 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5767 goto not_likely;
5768 case OPC_BLEZL:
5769 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5770 goto likely;
5771 case OPC_BLTZ:
5772 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5773 goto not_likely;
5774 case OPC_BLTZL:
5775 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5776 goto likely;
5777 case OPC_BPOSGE32:
5778 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5779 goto not_likely;
5780 #if defined(TARGET_MIPS64)
5781 case OPC_BPOSGE64:
5782 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5783 goto not_likely;
5784 #endif
5785 case OPC_BLTZAL:
5786 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5787 blink = 31;
5788 not_likely:
5789 ctx->hflags |= MIPS_HFLAG_BC;
5790 break;
5791 case OPC_BLTZALL:
5792 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5793 blink = 31;
5794 likely:
5795 ctx->hflags |= MIPS_HFLAG_BL;
5796 break;
5797 default:
5798 MIPS_INVAL("conditional branch/jump");
5799 generate_exception_end(ctx, EXCP_RI);
5800 goto out;
5804 ctx->btarget = btgt;
5806 switch (delayslot_size) {
5807 case 2:
5808 ctx->hflags |= MIPS_HFLAG_BDS16;
5809 break;
5810 case 4:
5811 ctx->hflags |= MIPS_HFLAG_BDS32;
5812 break;
5815 if (blink > 0) {
5816 int post_delay = insn_bytes + delayslot_size;
5817 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5819 tcg_gen_movi_tl(cpu_gpr[blink],
5820 ctx->base.pc_next + post_delay + lowbit);
5823 out:
5824 if (insn_bytes == 2)
5825 ctx->hflags |= MIPS_HFLAG_B16;
5826 tcg_temp_free(t0);
5827 tcg_temp_free(t1);
5831 /* nanoMIPS Branches */
5832 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5833 int insn_bytes,
5834 int rs, int rt, int32_t offset)
5836 target_ulong btgt = -1;
5837 int bcond_compute = 0;
5838 TCGv t0 = tcg_temp_new();
5839 TCGv t1 = tcg_temp_new();
5841 /* Load needed operands */
5842 switch (opc) {
5843 case OPC_BEQ:
5844 case OPC_BNE:
5845 /* Compare two registers */
5846 if (rs != rt) {
5847 gen_load_gpr(t0, rs);
5848 gen_load_gpr(t1, rt);
5849 bcond_compute = 1;
5851 btgt = ctx->base.pc_next + insn_bytes + offset;
5852 break;
5853 case OPC_BGEZAL:
5854 /* Compare to zero */
5855 if (rs != 0) {
5856 gen_load_gpr(t0, rs);
5857 bcond_compute = 1;
5859 btgt = ctx->base.pc_next + insn_bytes + offset;
5860 break;
5861 case OPC_BPOSGE32:
5862 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5863 bcond_compute = 1;
5864 btgt = ctx->base.pc_next + insn_bytes + offset;
5865 break;
5866 case OPC_JR:
5867 case OPC_JALR:
5868 /* Jump to register */
5869 if (offset != 0 && offset != 16) {
5870 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5871 others are reserved. */
5872 MIPS_INVAL("jump hint");
5873 generate_exception_end(ctx, EXCP_RI);
5874 goto out;
5876 gen_load_gpr(btarget, rs);
5877 break;
5878 default:
5879 MIPS_INVAL("branch/jump");
5880 generate_exception_end(ctx, EXCP_RI);
5881 goto out;
5883 if (bcond_compute == 0) {
5884 /* No condition to be computed */
5885 switch (opc) {
5886 case OPC_BEQ: /* rx == rx */
5887 /* Always take */
5888 ctx->hflags |= MIPS_HFLAG_B;
5889 break;
5890 case OPC_BGEZAL: /* 0 >= 0 */
5891 /* Always take and link */
5892 tcg_gen_movi_tl(cpu_gpr[31],
5893 ctx->base.pc_next + insn_bytes);
5894 ctx->hflags |= MIPS_HFLAG_B;
5895 break;
5896 case OPC_BNE: /* rx != rx */
5897 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5898 /* Skip the instruction in the delay slot */
5899 ctx->base.pc_next += 4;
5900 goto out;
5901 case OPC_JR:
5902 ctx->hflags |= MIPS_HFLAG_BR;
5903 break;
5904 case OPC_JALR:
5905 if (rt > 0) {
5906 tcg_gen_movi_tl(cpu_gpr[rt],
5907 ctx->base.pc_next + insn_bytes);
5909 ctx->hflags |= MIPS_HFLAG_BR;
5910 break;
5911 default:
5912 MIPS_INVAL("branch/jump");
5913 generate_exception_end(ctx, EXCP_RI);
5914 goto out;
5916 } else {
5917 switch (opc) {
5918 case OPC_BEQ:
5919 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5920 goto not_likely;
5921 case OPC_BNE:
5922 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5923 goto not_likely;
5924 case OPC_BGEZAL:
5925 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5926 tcg_gen_movi_tl(cpu_gpr[31],
5927 ctx->base.pc_next + insn_bytes);
5928 goto not_likely;
5929 case OPC_BPOSGE32:
5930 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5931 not_likely:
5932 ctx->hflags |= MIPS_HFLAG_BC;
5933 break;
5934 default:
5935 MIPS_INVAL("conditional branch/jump");
5936 generate_exception_end(ctx, EXCP_RI);
5937 goto out;
5941 ctx->btarget = btgt;
5943 out:
5944 if (insn_bytes == 2) {
5945 ctx->hflags |= MIPS_HFLAG_B16;
5947 tcg_temp_free(t0);
5948 tcg_temp_free(t1);
5952 /* special3 bitfield operations */
5953 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5954 int rs, int lsb, int msb)
5956 TCGv t0 = tcg_temp_new();
5957 TCGv t1 = tcg_temp_new();
5959 gen_load_gpr(t1, rs);
5960 switch (opc) {
5961 case OPC_EXT:
5962 if (lsb + msb > 31) {
5963 goto fail;
5965 if (msb != 31) {
5966 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5967 } else {
5968 /* The two checks together imply that lsb == 0,
5969 so this is a simple sign-extension. */
5970 tcg_gen_ext32s_tl(t0, t1);
5972 break;
5973 #if defined(TARGET_MIPS64)
5974 case OPC_DEXTU:
5975 lsb += 32;
5976 goto do_dext;
5977 case OPC_DEXTM:
5978 msb += 32;
5979 goto do_dext;
5980 case OPC_DEXT:
5981 do_dext:
5982 if (lsb + msb > 63) {
5983 goto fail;
5985 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5986 break;
5987 #endif
5988 case OPC_INS:
5989 if (lsb > msb) {
5990 goto fail;
5992 gen_load_gpr(t0, rt);
5993 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5994 tcg_gen_ext32s_tl(t0, t0);
5995 break;
5996 #if defined(TARGET_MIPS64)
5997 case OPC_DINSU:
5998 lsb += 32;
5999 /* FALLTHRU */
6000 case OPC_DINSM:
6001 msb += 32;
6002 /* FALLTHRU */
6003 case OPC_DINS:
6004 if (lsb > msb) {
6005 goto fail;
6007 gen_load_gpr(t0, rt);
6008 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6009 break;
6010 #endif
6011 default:
6012 fail:
6013 MIPS_INVAL("bitops");
6014 generate_exception_end(ctx, EXCP_RI);
6015 tcg_temp_free(t0);
6016 tcg_temp_free(t1);
6017 return;
6019 gen_store_gpr(t0, rt);
6020 tcg_temp_free(t0);
6021 tcg_temp_free(t1);
6024 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6026 TCGv t0;
6028 if (rd == 0) {
6029 /* If no destination, treat it as a NOP. */
6030 return;
6033 t0 = tcg_temp_new();
6034 gen_load_gpr(t0, rt);
6035 switch (op2) {
6036 case OPC_WSBH:
6038 TCGv t1 = tcg_temp_new();
6039 TCGv t2 = tcg_const_tl(0x00FF00FF);
6041 tcg_gen_shri_tl(t1, t0, 8);
6042 tcg_gen_and_tl(t1, t1, t2);
6043 tcg_gen_and_tl(t0, t0, t2);
6044 tcg_gen_shli_tl(t0, t0, 8);
6045 tcg_gen_or_tl(t0, t0, t1);
6046 tcg_temp_free(t2);
6047 tcg_temp_free(t1);
6048 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6050 break;
6051 case OPC_SEB:
6052 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6053 break;
6054 case OPC_SEH:
6055 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6056 break;
6057 #if defined(TARGET_MIPS64)
6058 case OPC_DSBH:
6060 TCGv t1 = tcg_temp_new();
6061 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6063 tcg_gen_shri_tl(t1, t0, 8);
6064 tcg_gen_and_tl(t1, t1, t2);
6065 tcg_gen_and_tl(t0, t0, t2);
6066 tcg_gen_shli_tl(t0, t0, 8);
6067 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6068 tcg_temp_free(t2);
6069 tcg_temp_free(t1);
6071 break;
6072 case OPC_DSHD:
6074 TCGv t1 = tcg_temp_new();
6075 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6077 tcg_gen_shri_tl(t1, t0, 16);
6078 tcg_gen_and_tl(t1, t1, t2);
6079 tcg_gen_and_tl(t0, t0, t2);
6080 tcg_gen_shli_tl(t0, t0, 16);
6081 tcg_gen_or_tl(t0, t0, t1);
6082 tcg_gen_shri_tl(t1, t0, 32);
6083 tcg_gen_shli_tl(t0, t0, 32);
6084 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6085 tcg_temp_free(t2);
6086 tcg_temp_free(t1);
6088 break;
6089 #endif
6090 default:
6091 MIPS_INVAL("bsfhl");
6092 generate_exception_end(ctx, EXCP_RI);
6093 tcg_temp_free(t0);
6094 return;
6096 tcg_temp_free(t0);
6099 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6100 int imm2)
6102 TCGv t0;
6103 TCGv t1;
6104 if (rd == 0) {
6105 /* Treat as NOP. */
6106 return;
6108 t0 = tcg_temp_new();
6109 t1 = tcg_temp_new();
6110 gen_load_gpr(t0, rs);
6111 gen_load_gpr(t1, rt);
6112 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6113 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6114 if (opc == OPC_LSA) {
6115 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6118 tcg_temp_free(t1);
6119 tcg_temp_free(t0);
6121 return;
6124 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6125 int rt, int bits)
6127 TCGv t0;
6128 if (rd == 0) {
6129 /* Treat as NOP. */
6130 return;
6132 t0 = tcg_temp_new();
6133 if (bits == 0 || bits == wordsz) {
6134 if (bits == 0) {
6135 gen_load_gpr(t0, rt);
6136 } else {
6137 gen_load_gpr(t0, rs);
6139 switch (wordsz) {
6140 case 32:
6141 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6142 break;
6143 #if defined(TARGET_MIPS64)
6144 case 64:
6145 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6146 break;
6147 #endif
6149 } else {
6150 TCGv t1 = tcg_temp_new();
6151 gen_load_gpr(t0, rt);
6152 gen_load_gpr(t1, rs);
6153 switch (wordsz) {
6154 case 32:
6156 TCGv_i64 t2 = tcg_temp_new_i64();
6157 tcg_gen_concat_tl_i64(t2, t1, t0);
6158 tcg_gen_shri_i64(t2, t2, 32 - bits);
6159 gen_move_low32(cpu_gpr[rd], t2);
6160 tcg_temp_free_i64(t2);
6162 break;
6163 #if defined(TARGET_MIPS64)
6164 case 64:
6165 tcg_gen_shli_tl(t0, t0, bits);
6166 tcg_gen_shri_tl(t1, t1, 64 - bits);
6167 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6168 break;
6169 #endif
6171 tcg_temp_free(t1);
6174 tcg_temp_free(t0);
6177 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6178 int bp)
6180 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6183 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6184 int shift)
6186 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6189 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6191 TCGv t0;
6192 if (rd == 0) {
6193 /* Treat as NOP. */
6194 return;
6196 t0 = tcg_temp_new();
6197 gen_load_gpr(t0, rt);
6198 switch (opc) {
6199 case OPC_BITSWAP:
6200 gen_helper_bitswap(cpu_gpr[rd], t0);
6201 break;
6202 #if defined(TARGET_MIPS64)
6203 case OPC_DBITSWAP:
6204 gen_helper_dbitswap(cpu_gpr[rd], t0);
6205 break;
6206 #endif
6208 tcg_temp_free(t0);
6211 #ifndef CONFIG_USER_ONLY
6212 /* CP0 (MMU and control) */
6213 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6215 TCGv_i64 t0 = tcg_temp_new_i64();
6216 TCGv_i64 t1 = tcg_temp_new_i64();
6218 tcg_gen_ext_tl_i64(t0, arg);
6219 tcg_gen_ld_i64(t1, cpu_env, off);
6220 #if defined(TARGET_MIPS64)
6221 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6222 #else
6223 tcg_gen_concat32_i64(t1, t1, t0);
6224 #endif
6225 tcg_gen_st_i64(t1, cpu_env, off);
6226 tcg_temp_free_i64(t1);
6227 tcg_temp_free_i64(t0);
6230 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6232 TCGv_i64 t0 = tcg_temp_new_i64();
6233 TCGv_i64 t1 = tcg_temp_new_i64();
6235 tcg_gen_ext_tl_i64(t0, arg);
6236 tcg_gen_ld_i64(t1, cpu_env, off);
6237 tcg_gen_concat32_i64(t1, t1, t0);
6238 tcg_gen_st_i64(t1, cpu_env, off);
6239 tcg_temp_free_i64(t1);
6240 tcg_temp_free_i64(t0);
6243 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6245 TCGv_i64 t0 = tcg_temp_new_i64();
6247 tcg_gen_ld_i64(t0, cpu_env, off);
6248 #if defined(TARGET_MIPS64)
6249 tcg_gen_shri_i64(t0, t0, 30);
6250 #else
6251 tcg_gen_shri_i64(t0, t0, 32);
6252 #endif
6253 gen_move_low32(arg, t0);
6254 tcg_temp_free_i64(t0);
6257 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6259 TCGv_i64 t0 = tcg_temp_new_i64();
6261 tcg_gen_ld_i64(t0, cpu_env, off);
6262 tcg_gen_shri_i64(t0, t0, 32 + shift);
6263 gen_move_low32(arg, t0);
6264 tcg_temp_free_i64(t0);
6267 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6269 TCGv_i32 t0 = tcg_temp_new_i32();
6271 tcg_gen_ld_i32(t0, cpu_env, off);
6272 tcg_gen_ext_i32_tl(arg, t0);
6273 tcg_temp_free_i32(t0);
6276 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6278 tcg_gen_ld_tl(arg, cpu_env, off);
6279 tcg_gen_ext32s_tl(arg, arg);
6282 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6284 TCGv_i32 t0 = tcg_temp_new_i32();
6286 tcg_gen_trunc_tl_i32(t0, arg);
6287 tcg_gen_st_i32(t0, cpu_env, off);
6288 tcg_temp_free_i32(t0);
6291 #define CP0_CHECK(c) \
6292 do { \
6293 if (!(c)) { \
6294 goto cp0_unimplemented; \
6296 } while (0)
6298 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6300 const char *rn = "invalid";
6302 switch (reg) {
6303 case 2:
6304 switch (sel) {
6305 case 0:
6306 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6307 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6308 rn = "EntryLo0";
6309 break;
6310 default:
6311 goto cp0_unimplemented;
6313 break;
6314 case 3:
6315 switch (sel) {
6316 case 0:
6317 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6318 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6319 rn = "EntryLo1";
6320 break;
6321 default:
6322 goto cp0_unimplemented;
6324 break;
6325 case 17:
6326 switch (sel) {
6327 case 0:
6328 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6329 ctx->CP0_LLAddr_shift);
6330 rn = "LLAddr";
6331 break;
6332 case 1:
6333 CP0_CHECK(ctx->mrp);
6334 gen_helper_mfhc0_maar(arg, cpu_env);
6335 rn = "MAAR";
6336 break;
6337 default:
6338 goto cp0_unimplemented;
6340 break;
6341 case 28:
6342 switch (sel) {
6343 case 0:
6344 case 2:
6345 case 4:
6346 case 6:
6347 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6348 rn = "TagLo";
6349 break;
6350 default:
6351 goto cp0_unimplemented;
6353 break;
6354 default:
6355 goto cp0_unimplemented;
6357 trace_mips_translate_c0("mfhc0", rn, reg, sel);
6358 return;
6360 cp0_unimplemented:
6361 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6362 tcg_gen_movi_tl(arg, 0);
6365 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6367 const char *rn = "invalid";
6368 uint64_t mask = ctx->PAMask >> 36;
6370 switch (reg) {
6371 case 2:
6372 switch (sel) {
6373 case 0:
6374 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6375 tcg_gen_andi_tl(arg, arg, mask);
6376 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6377 rn = "EntryLo0";
6378 break;
6379 default:
6380 goto cp0_unimplemented;
6382 break;
6383 case 3:
6384 switch (sel) {
6385 case 0:
6386 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6387 tcg_gen_andi_tl(arg, arg, mask);
6388 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6389 rn = "EntryLo1";
6390 break;
6391 default:
6392 goto cp0_unimplemented;
6394 break;
6395 case 17:
6396 switch (sel) {
6397 case 0:
6398 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6399 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6400 relevant for modern MIPS cores supporting MTHC0, therefore
6401 treating MTHC0 to LLAddr as NOP. */
6402 rn = "LLAddr";
6403 break;
6404 case 1:
6405 CP0_CHECK(ctx->mrp);
6406 gen_helper_mthc0_maar(cpu_env, arg);
6407 rn = "MAAR";
6408 break;
6409 default:
6410 goto cp0_unimplemented;
6412 break;
6413 case 28:
6414 switch (sel) {
6415 case 0:
6416 case 2:
6417 case 4:
6418 case 6:
6419 tcg_gen_andi_tl(arg, arg, mask);
6420 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6421 rn = "TagLo";
6422 break;
6423 default:
6424 goto cp0_unimplemented;
6426 break;
6427 default:
6428 goto cp0_unimplemented;
6430 trace_mips_translate_c0("mthc0", rn, reg, sel);
6432 cp0_unimplemented:
6433 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6436 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6438 if (ctx->insn_flags & ISA_MIPS32R6) {
6439 tcg_gen_movi_tl(arg, 0);
6440 } else {
6441 tcg_gen_movi_tl(arg, ~0);
6445 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6447 const char *rn = "invalid";
6449 if (sel != 0)
6450 check_insn(ctx, ISA_MIPS32);
6452 switch (reg) {
6453 case 0:
6454 switch (sel) {
6455 case 0:
6456 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6457 rn = "Index";
6458 break;
6459 case 1:
6460 CP0_CHECK(ctx->insn_flags & ASE_MT);
6461 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6462 rn = "MVPControl";
6463 break;
6464 case 2:
6465 CP0_CHECK(ctx->insn_flags & ASE_MT);
6466 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6467 rn = "MVPConf0";
6468 break;
6469 case 3:
6470 CP0_CHECK(ctx->insn_flags & ASE_MT);
6471 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6472 rn = "MVPConf1";
6473 break;
6474 case 4:
6475 CP0_CHECK(ctx->vp);
6476 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6477 rn = "VPControl";
6478 break;
6479 default:
6480 goto cp0_unimplemented;
6482 break;
6483 case 1:
6484 switch (sel) {
6485 case 0:
6486 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6487 gen_helper_mfc0_random(arg, cpu_env);
6488 rn = "Random";
6489 break;
6490 case 1:
6491 CP0_CHECK(ctx->insn_flags & ASE_MT);
6492 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6493 rn = "VPEControl";
6494 break;
6495 case 2:
6496 CP0_CHECK(ctx->insn_flags & ASE_MT);
6497 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6498 rn = "VPEConf0";
6499 break;
6500 case 3:
6501 CP0_CHECK(ctx->insn_flags & ASE_MT);
6502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6503 rn = "VPEConf1";
6504 break;
6505 case 4:
6506 CP0_CHECK(ctx->insn_flags & ASE_MT);
6507 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6508 rn = "YQMask";
6509 break;
6510 case 5:
6511 CP0_CHECK(ctx->insn_flags & ASE_MT);
6512 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6513 rn = "VPESchedule";
6514 break;
6515 case 6:
6516 CP0_CHECK(ctx->insn_flags & ASE_MT);
6517 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6518 rn = "VPEScheFBack";
6519 break;
6520 case 7:
6521 CP0_CHECK(ctx->insn_flags & ASE_MT);
6522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6523 rn = "VPEOpt";
6524 break;
6525 default:
6526 goto cp0_unimplemented;
6528 break;
6529 case 2:
6530 switch (sel) {
6531 case 0:
6533 TCGv_i64 tmp = tcg_temp_new_i64();
6534 tcg_gen_ld_i64(tmp, cpu_env,
6535 offsetof(CPUMIPSState, CP0_EntryLo0));
6536 #if defined(TARGET_MIPS64)
6537 if (ctx->rxi) {
6538 /* Move RI/XI fields to bits 31:30 */
6539 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6540 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6542 #endif
6543 gen_move_low32(arg, tmp);
6544 tcg_temp_free_i64(tmp);
6546 rn = "EntryLo0";
6547 break;
6548 case 1:
6549 CP0_CHECK(ctx->insn_flags & ASE_MT);
6550 gen_helper_mfc0_tcstatus(arg, cpu_env);
6551 rn = "TCStatus";
6552 break;
6553 case 2:
6554 CP0_CHECK(ctx->insn_flags & ASE_MT);
6555 gen_helper_mfc0_tcbind(arg, cpu_env);
6556 rn = "TCBind";
6557 break;
6558 case 3:
6559 CP0_CHECK(ctx->insn_flags & ASE_MT);
6560 gen_helper_mfc0_tcrestart(arg, cpu_env);
6561 rn = "TCRestart";
6562 break;
6563 case 4:
6564 CP0_CHECK(ctx->insn_flags & ASE_MT);
6565 gen_helper_mfc0_tchalt(arg, cpu_env);
6566 rn = "TCHalt";
6567 break;
6568 case 5:
6569 CP0_CHECK(ctx->insn_flags & ASE_MT);
6570 gen_helper_mfc0_tccontext(arg, cpu_env);
6571 rn = "TCContext";
6572 break;
6573 case 6:
6574 CP0_CHECK(ctx->insn_flags & ASE_MT);
6575 gen_helper_mfc0_tcschedule(arg, cpu_env);
6576 rn = "TCSchedule";
6577 break;
6578 case 7:
6579 CP0_CHECK(ctx->insn_flags & ASE_MT);
6580 gen_helper_mfc0_tcschefback(arg, cpu_env);
6581 rn = "TCScheFBack";
6582 break;
6583 default:
6584 goto cp0_unimplemented;
6586 break;
6587 case 3:
6588 switch (sel) {
6589 case 0:
6591 TCGv_i64 tmp = tcg_temp_new_i64();
6592 tcg_gen_ld_i64(tmp, cpu_env,
6593 offsetof(CPUMIPSState, CP0_EntryLo1));
6594 #if defined(TARGET_MIPS64)
6595 if (ctx->rxi) {
6596 /* Move RI/XI fields to bits 31:30 */
6597 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6598 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6600 #endif
6601 gen_move_low32(arg, tmp);
6602 tcg_temp_free_i64(tmp);
6604 rn = "EntryLo1";
6605 break;
6606 case 1:
6607 CP0_CHECK(ctx->vp);
6608 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6609 rn = "GlobalNumber";
6610 break;
6611 default:
6612 goto cp0_unimplemented;
6614 break;
6615 case 4:
6616 switch (sel) {
6617 case 0:
6618 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6619 tcg_gen_ext32s_tl(arg, arg);
6620 rn = "Context";
6621 break;
6622 case 1:
6623 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6624 rn = "ContextConfig";
6625 goto cp0_unimplemented;
6626 case 2:
6627 CP0_CHECK(ctx->ulri);
6628 tcg_gen_ld_tl(arg, cpu_env,
6629 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6630 tcg_gen_ext32s_tl(arg, arg);
6631 rn = "UserLocal";
6632 break;
6633 default:
6634 goto cp0_unimplemented;
6636 break;
6637 case 5:
6638 switch (sel) {
6639 case 0:
6640 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6641 rn = "PageMask";
6642 break;
6643 case 1:
6644 check_insn(ctx, ISA_MIPS32R2);
6645 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6646 rn = "PageGrain";
6647 break;
6648 case 2:
6649 CP0_CHECK(ctx->sc);
6650 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6651 tcg_gen_ext32s_tl(arg, arg);
6652 rn = "SegCtl0";
6653 break;
6654 case 3:
6655 CP0_CHECK(ctx->sc);
6656 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6657 tcg_gen_ext32s_tl(arg, arg);
6658 rn = "SegCtl1";
6659 break;
6660 case 4:
6661 CP0_CHECK(ctx->sc);
6662 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6663 tcg_gen_ext32s_tl(arg, arg);
6664 rn = "SegCtl2";
6665 break;
6666 case 5:
6667 check_pw(ctx);
6668 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6669 rn = "PWBase";
6670 break;
6671 case 6:
6672 check_pw(ctx);
6673 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6674 rn = "PWField";
6675 break;
6676 case 7:
6677 check_pw(ctx);
6678 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6679 rn = "PWSize";
6680 break;
6681 default:
6682 goto cp0_unimplemented;
6684 break;
6685 case 6:
6686 switch (sel) {
6687 case 0:
6688 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6689 rn = "Wired";
6690 break;
6691 case 1:
6692 check_insn(ctx, ISA_MIPS32R2);
6693 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6694 rn = "SRSConf0";
6695 break;
6696 case 2:
6697 check_insn(ctx, ISA_MIPS32R2);
6698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6699 rn = "SRSConf1";
6700 break;
6701 case 3:
6702 check_insn(ctx, ISA_MIPS32R2);
6703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6704 rn = "SRSConf2";
6705 break;
6706 case 4:
6707 check_insn(ctx, ISA_MIPS32R2);
6708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6709 rn = "SRSConf3";
6710 break;
6711 case 5:
6712 check_insn(ctx, ISA_MIPS32R2);
6713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6714 rn = "SRSConf4";
6715 break;
6716 case 6:
6717 check_pw(ctx);
6718 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6719 rn = "PWCtl";
6720 break;
6721 default:
6722 goto cp0_unimplemented;
6724 break;
6725 case 7:
6726 switch (sel) {
6727 case 0:
6728 check_insn(ctx, ISA_MIPS32R2);
6729 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6730 rn = "HWREna";
6731 break;
6732 default:
6733 goto cp0_unimplemented;
6735 break;
6736 case 8:
6737 switch (sel) {
6738 case 0:
6739 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6740 tcg_gen_ext32s_tl(arg, arg);
6741 rn = "BadVAddr";
6742 break;
6743 case 1:
6744 CP0_CHECK(ctx->bi);
6745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6746 rn = "BadInstr";
6747 break;
6748 case 2:
6749 CP0_CHECK(ctx->bp);
6750 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6751 rn = "BadInstrP";
6752 break;
6753 case 3:
6754 CP0_CHECK(ctx->bi);
6755 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6756 tcg_gen_andi_tl(arg, arg, ~0xffff);
6757 rn = "BadInstrX";
6758 break;
6759 default:
6760 goto cp0_unimplemented;
6762 break;
6763 case 9:
6764 switch (sel) {
6765 case 0:
6766 /* Mark as an IO operation because we read the time. */
6767 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6768 gen_io_start();
6770 gen_helper_mfc0_count(arg, cpu_env);
6771 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6772 gen_io_end();
6774 /* Break the TB to be able to take timer interrupts immediately
6775 after reading count. DISAS_STOP isn't sufficient, we need to
6776 ensure we break completely out of translated code. */
6777 gen_save_pc(ctx->base.pc_next + 4);
6778 ctx->base.is_jmp = DISAS_EXIT;
6779 rn = "Count";
6780 break;
6781 /* 6,7 are implementation dependent */
6782 default:
6783 goto cp0_unimplemented;
6785 break;
6786 case 10:
6787 switch (sel) {
6788 case 0:
6789 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6790 tcg_gen_ext32s_tl(arg, arg);
6791 rn = "EntryHi";
6792 break;
6793 default:
6794 goto cp0_unimplemented;
6796 break;
6797 case 11:
6798 switch (sel) {
6799 case 0:
6800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6801 rn = "Compare";
6802 break;
6803 /* 6,7 are implementation dependent */
6804 default:
6805 goto cp0_unimplemented;
6807 break;
6808 case 12:
6809 switch (sel) {
6810 case 0:
6811 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6812 rn = "Status";
6813 break;
6814 case 1:
6815 check_insn(ctx, ISA_MIPS32R2);
6816 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6817 rn = "IntCtl";
6818 break;
6819 case 2:
6820 check_insn(ctx, ISA_MIPS32R2);
6821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6822 rn = "SRSCtl";
6823 break;
6824 case 3:
6825 check_insn(ctx, ISA_MIPS32R2);
6826 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6827 rn = "SRSMap";
6828 break;
6829 default:
6830 goto cp0_unimplemented;
6832 break;
6833 case 13:
6834 switch (sel) {
6835 case 0:
6836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6837 rn = "Cause";
6838 break;
6839 default:
6840 goto cp0_unimplemented;
6842 break;
6843 case 14:
6844 switch (sel) {
6845 case 0:
6846 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6847 tcg_gen_ext32s_tl(arg, arg);
6848 rn = "EPC";
6849 break;
6850 default:
6851 goto cp0_unimplemented;
6853 break;
6854 case 15:
6855 switch (sel) {
6856 case 0:
6857 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6858 rn = "PRid";
6859 break;
6860 case 1:
6861 check_insn(ctx, ISA_MIPS32R2);
6862 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6863 tcg_gen_ext32s_tl(arg, arg);
6864 rn = "EBase";
6865 break;
6866 case 3:
6867 check_insn(ctx, ISA_MIPS32R2);
6868 CP0_CHECK(ctx->cmgcr);
6869 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6870 tcg_gen_ext32s_tl(arg, arg);
6871 rn = "CMGCRBase";
6872 break;
6873 default:
6874 goto cp0_unimplemented;
6876 break;
6877 case 16:
6878 switch (sel) {
6879 case 0:
6880 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6881 rn = "Config";
6882 break;
6883 case 1:
6884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6885 rn = "Config1";
6886 break;
6887 case 2:
6888 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6889 rn = "Config2";
6890 break;
6891 case 3:
6892 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6893 rn = "Config3";
6894 break;
6895 case 4:
6896 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6897 rn = "Config4";
6898 break;
6899 case 5:
6900 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6901 rn = "Config5";
6902 break;
6903 /* 6,7 are implementation dependent */
6904 case 6:
6905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6906 rn = "Config6";
6907 break;
6908 case 7:
6909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6910 rn = "Config7";
6911 break;
6912 default:
6913 goto cp0_unimplemented;
6915 break;
6916 case 17:
6917 switch (sel) {
6918 case 0:
6919 gen_helper_mfc0_lladdr(arg, cpu_env);
6920 rn = "LLAddr";
6921 break;
6922 case 1:
6923 CP0_CHECK(ctx->mrp);
6924 gen_helper_mfc0_maar(arg, cpu_env);
6925 rn = "MAAR";
6926 break;
6927 case 2:
6928 CP0_CHECK(ctx->mrp);
6929 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6930 rn = "MAARI";
6931 break;
6932 default:
6933 goto cp0_unimplemented;
6935 break;
6936 case 18:
6937 switch (sel) {
6938 case 0:
6939 case 1:
6940 case 2:
6941 case 3:
6942 case 4:
6943 case 5:
6944 case 6:
6945 case 7:
6946 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6947 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6948 rn = "WatchLo";
6949 break;
6950 default:
6951 goto cp0_unimplemented;
6953 break;
6954 case 19:
6955 switch (sel) {
6956 case 0:
6957 case 1:
6958 case 2:
6959 case 3:
6960 case 4:
6961 case 5:
6962 case 6:
6963 case 7:
6964 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6965 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6966 rn = "WatchHi";
6967 break;
6968 default:
6969 goto cp0_unimplemented;
6971 break;
6972 case 20:
6973 switch (sel) {
6974 case 0:
6975 #if defined(TARGET_MIPS64)
6976 check_insn(ctx, ISA_MIPS3);
6977 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6978 tcg_gen_ext32s_tl(arg, arg);
6979 rn = "XContext";
6980 break;
6981 #endif
6982 default:
6983 goto cp0_unimplemented;
6985 break;
6986 case 21:
6987 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6988 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6989 switch (sel) {
6990 case 0:
6991 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6992 rn = "Framemask";
6993 break;
6994 default:
6995 goto cp0_unimplemented;
6997 break;
6998 case 22:
6999 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7000 rn = "'Diagnostic"; /* implementation dependent */
7001 break;
7002 case 23:
7003 switch (sel) {
7004 case 0:
7005 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7006 rn = "Debug";
7007 break;
7008 case 1:
7009 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7010 rn = "TraceControl";
7011 goto cp0_unimplemented;
7012 case 2:
7013 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7014 rn = "TraceControl2";
7015 goto cp0_unimplemented;
7016 case 3:
7017 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7018 rn = "UserTraceData";
7019 goto cp0_unimplemented;
7020 case 4:
7021 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7022 rn = "TraceBPC";
7023 goto cp0_unimplemented;
7024 default:
7025 goto cp0_unimplemented;
7027 break;
7028 case 24:
7029 switch (sel) {
7030 case 0:
7031 /* EJTAG support */
7032 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7033 tcg_gen_ext32s_tl(arg, arg);
7034 rn = "DEPC";
7035 break;
7036 default:
7037 goto cp0_unimplemented;
7039 break;
7040 case 25:
7041 switch (sel) {
7042 case 0:
7043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7044 rn = "Performance0";
7045 break;
7046 case 1:
7047 // gen_helper_mfc0_performance1(arg);
7048 rn = "Performance1";
7049 goto cp0_unimplemented;
7050 case 2:
7051 // gen_helper_mfc0_performance2(arg);
7052 rn = "Performance2";
7053 goto cp0_unimplemented;
7054 case 3:
7055 // gen_helper_mfc0_performance3(arg);
7056 rn = "Performance3";
7057 goto cp0_unimplemented;
7058 case 4:
7059 // gen_helper_mfc0_performance4(arg);
7060 rn = "Performance4";
7061 goto cp0_unimplemented;
7062 case 5:
7063 // gen_helper_mfc0_performance5(arg);
7064 rn = "Performance5";
7065 goto cp0_unimplemented;
7066 case 6:
7067 // gen_helper_mfc0_performance6(arg);
7068 rn = "Performance6";
7069 goto cp0_unimplemented;
7070 case 7:
7071 // gen_helper_mfc0_performance7(arg);
7072 rn = "Performance7";
7073 goto cp0_unimplemented;
7074 default:
7075 goto cp0_unimplemented;
7077 break;
7078 case 26:
7079 switch (sel) {
7080 case 0:
7081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7082 rn = "ErrCtl";
7083 break;
7084 default:
7085 goto cp0_unimplemented;
7087 break;
7088 case 27:
7089 switch (sel) {
7090 case 0:
7091 case 1:
7092 case 2:
7093 case 3:
7094 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7095 rn = "CacheErr";
7096 break;
7097 default:
7098 goto cp0_unimplemented;
7100 break;
7101 case 28:
7102 switch (sel) {
7103 case 0:
7104 case 2:
7105 case 4:
7106 case 6:
7108 TCGv_i64 tmp = tcg_temp_new_i64();
7109 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7110 gen_move_low32(arg, tmp);
7111 tcg_temp_free_i64(tmp);
7113 rn = "TagLo";
7114 break;
7115 case 1:
7116 case 3:
7117 case 5:
7118 case 7:
7119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7120 rn = "DataLo";
7121 break;
7122 default:
7123 goto cp0_unimplemented;
7125 break;
7126 case 29:
7127 switch (sel) {
7128 case 0:
7129 case 2:
7130 case 4:
7131 case 6:
7132 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7133 rn = "TagHi";
7134 break;
7135 case 1:
7136 case 3:
7137 case 5:
7138 case 7:
7139 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7140 rn = "DataHi";
7141 break;
7142 default:
7143 goto cp0_unimplemented;
7145 break;
7146 case 30:
7147 switch (sel) {
7148 case 0:
7149 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7150 tcg_gen_ext32s_tl(arg, arg);
7151 rn = "ErrorEPC";
7152 break;
7153 default:
7154 goto cp0_unimplemented;
7156 break;
7157 case 31:
7158 switch (sel) {
7159 case 0:
7160 /* EJTAG support */
7161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7162 rn = "DESAVE";
7163 break;
7164 case 2:
7165 case 3:
7166 case 4:
7167 case 5:
7168 case 6:
7169 case 7:
7170 CP0_CHECK(ctx->kscrexist & (1 << sel));
7171 tcg_gen_ld_tl(arg, cpu_env,
7172 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7173 tcg_gen_ext32s_tl(arg, arg);
7174 rn = "KScratch";
7175 break;
7176 default:
7177 goto cp0_unimplemented;
7179 break;
7180 default:
7181 goto cp0_unimplemented;
7183 trace_mips_translate_c0("mfc0", rn, reg, sel);
7184 return;
7186 cp0_unimplemented:
7187 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7188 gen_mfc0_unimplemented(ctx, arg);
7191 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7193 const char *rn = "invalid";
7195 if (sel != 0)
7196 check_insn(ctx, ISA_MIPS32);
7198 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7199 gen_io_start();
7202 switch (reg) {
7203 case 0:
7204 switch (sel) {
7205 case 0:
7206 gen_helper_mtc0_index(cpu_env, arg);
7207 rn = "Index";
7208 break;
7209 case 1:
7210 CP0_CHECK(ctx->insn_flags & ASE_MT);
7211 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7212 rn = "MVPControl";
7213 break;
7214 case 2:
7215 CP0_CHECK(ctx->insn_flags & ASE_MT);
7216 /* ignored */
7217 rn = "MVPConf0";
7218 break;
7219 case 3:
7220 CP0_CHECK(ctx->insn_flags & ASE_MT);
7221 /* ignored */
7222 rn = "MVPConf1";
7223 break;
7224 case 4:
7225 CP0_CHECK(ctx->vp);
7226 /* ignored */
7227 rn = "VPControl";
7228 break;
7229 default:
7230 goto cp0_unimplemented;
7232 break;
7233 case 1:
7234 switch (sel) {
7235 case 0:
7236 /* ignored */
7237 rn = "Random";
7238 break;
7239 case 1:
7240 CP0_CHECK(ctx->insn_flags & ASE_MT);
7241 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7242 rn = "VPEControl";
7243 break;
7244 case 2:
7245 CP0_CHECK(ctx->insn_flags & ASE_MT);
7246 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7247 rn = "VPEConf0";
7248 break;
7249 case 3:
7250 CP0_CHECK(ctx->insn_flags & ASE_MT);
7251 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7252 rn = "VPEConf1";
7253 break;
7254 case 4:
7255 CP0_CHECK(ctx->insn_flags & ASE_MT);
7256 gen_helper_mtc0_yqmask(cpu_env, arg);
7257 rn = "YQMask";
7258 break;
7259 case 5:
7260 CP0_CHECK(ctx->insn_flags & ASE_MT);
7261 tcg_gen_st_tl(arg, cpu_env,
7262 offsetof(CPUMIPSState, CP0_VPESchedule));
7263 rn = "VPESchedule";
7264 break;
7265 case 6:
7266 CP0_CHECK(ctx->insn_flags & ASE_MT);
7267 tcg_gen_st_tl(arg, cpu_env,
7268 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7269 rn = "VPEScheFBack";
7270 break;
7271 case 7:
7272 CP0_CHECK(ctx->insn_flags & ASE_MT);
7273 gen_helper_mtc0_vpeopt(cpu_env, arg);
7274 rn = "VPEOpt";
7275 break;
7276 default:
7277 goto cp0_unimplemented;
7279 break;
7280 case 2:
7281 switch (sel) {
7282 case 0:
7283 gen_helper_mtc0_entrylo0(cpu_env, arg);
7284 rn = "EntryLo0";
7285 break;
7286 case 1:
7287 CP0_CHECK(ctx->insn_flags & ASE_MT);
7288 gen_helper_mtc0_tcstatus(cpu_env, arg);
7289 rn = "TCStatus";
7290 break;
7291 case 2:
7292 CP0_CHECK(ctx->insn_flags & ASE_MT);
7293 gen_helper_mtc0_tcbind(cpu_env, arg);
7294 rn = "TCBind";
7295 break;
7296 case 3:
7297 CP0_CHECK(ctx->insn_flags & ASE_MT);
7298 gen_helper_mtc0_tcrestart(cpu_env, arg);
7299 rn = "TCRestart";
7300 break;
7301 case 4:
7302 CP0_CHECK(ctx->insn_flags & ASE_MT);
7303 gen_helper_mtc0_tchalt(cpu_env, arg);
7304 rn = "TCHalt";
7305 break;
7306 case 5:
7307 CP0_CHECK(ctx->insn_flags & ASE_MT);
7308 gen_helper_mtc0_tccontext(cpu_env, arg);
7309 rn = "TCContext";
7310 break;
7311 case 6:
7312 CP0_CHECK(ctx->insn_flags & ASE_MT);
7313 gen_helper_mtc0_tcschedule(cpu_env, arg);
7314 rn = "TCSchedule";
7315 break;
7316 case 7:
7317 CP0_CHECK(ctx->insn_flags & ASE_MT);
7318 gen_helper_mtc0_tcschefback(cpu_env, arg);
7319 rn = "TCScheFBack";
7320 break;
7321 default:
7322 goto cp0_unimplemented;
7324 break;
7325 case 3:
7326 switch (sel) {
7327 case 0:
7328 gen_helper_mtc0_entrylo1(cpu_env, arg);
7329 rn = "EntryLo1";
7330 break;
7331 case 1:
7332 CP0_CHECK(ctx->vp);
7333 /* ignored */
7334 rn = "GlobalNumber";
7335 break;
7336 default:
7337 goto cp0_unimplemented;
7339 break;
7340 case 4:
7341 switch (sel) {
7342 case 0:
7343 gen_helper_mtc0_context(cpu_env, arg);
7344 rn = "Context";
7345 break;
7346 case 1:
7347 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7348 rn = "ContextConfig";
7349 goto cp0_unimplemented;
7350 case 2:
7351 CP0_CHECK(ctx->ulri);
7352 tcg_gen_st_tl(arg, cpu_env,
7353 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7354 rn = "UserLocal";
7355 break;
7356 default:
7357 goto cp0_unimplemented;
7359 break;
7360 case 5:
7361 switch (sel) {
7362 case 0:
7363 gen_helper_mtc0_pagemask(cpu_env, arg);
7364 rn = "PageMask";
7365 break;
7366 case 1:
7367 check_insn(ctx, ISA_MIPS32R2);
7368 gen_helper_mtc0_pagegrain(cpu_env, arg);
7369 rn = "PageGrain";
7370 ctx->base.is_jmp = DISAS_STOP;
7371 break;
7372 case 2:
7373 CP0_CHECK(ctx->sc);
7374 gen_helper_mtc0_segctl0(cpu_env, arg);
7375 rn = "SegCtl0";
7376 break;
7377 case 3:
7378 CP0_CHECK(ctx->sc);
7379 gen_helper_mtc0_segctl1(cpu_env, arg);
7380 rn = "SegCtl1";
7381 break;
7382 case 4:
7383 CP0_CHECK(ctx->sc);
7384 gen_helper_mtc0_segctl2(cpu_env, arg);
7385 rn = "SegCtl2";
7386 break;
7387 case 5:
7388 check_pw(ctx);
7389 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7390 rn = "PWBase";
7391 break;
7392 case 6:
7393 check_pw(ctx);
7394 gen_helper_mtc0_pwfield(cpu_env, arg);
7395 rn = "PWField";
7396 break;
7397 case 7:
7398 check_pw(ctx);
7399 gen_helper_mtc0_pwsize(cpu_env, arg);
7400 rn = "PWSize";
7401 break;
7402 default:
7403 goto cp0_unimplemented;
7405 break;
7406 case 6:
7407 switch (sel) {
7408 case 0:
7409 gen_helper_mtc0_wired(cpu_env, arg);
7410 rn = "Wired";
7411 break;
7412 case 1:
7413 check_insn(ctx, ISA_MIPS32R2);
7414 gen_helper_mtc0_srsconf0(cpu_env, arg);
7415 rn = "SRSConf0";
7416 break;
7417 case 2:
7418 check_insn(ctx, ISA_MIPS32R2);
7419 gen_helper_mtc0_srsconf1(cpu_env, arg);
7420 rn = "SRSConf1";
7421 break;
7422 case 3:
7423 check_insn(ctx, ISA_MIPS32R2);
7424 gen_helper_mtc0_srsconf2(cpu_env, arg);
7425 rn = "SRSConf2";
7426 break;
7427 case 4:
7428 check_insn(ctx, ISA_MIPS32R2);
7429 gen_helper_mtc0_srsconf3(cpu_env, arg);
7430 rn = "SRSConf3";
7431 break;
7432 case 5:
7433 check_insn(ctx, ISA_MIPS32R2);
7434 gen_helper_mtc0_srsconf4(cpu_env, arg);
7435 rn = "SRSConf4";
7436 break;
7437 case 6:
7438 check_pw(ctx);
7439 gen_helper_mtc0_pwctl(cpu_env, arg);
7440 rn = "PWCtl";
7441 break;
7442 default:
7443 goto cp0_unimplemented;
7445 break;
7446 case 7:
7447 switch (sel) {
7448 case 0:
7449 check_insn(ctx, ISA_MIPS32R2);
7450 gen_helper_mtc0_hwrena(cpu_env, arg);
7451 ctx->base.is_jmp = DISAS_STOP;
7452 rn = "HWREna";
7453 break;
7454 default:
7455 goto cp0_unimplemented;
7457 break;
7458 case 8:
7459 switch (sel) {
7460 case 0:
7461 /* ignored */
7462 rn = "BadVAddr";
7463 break;
7464 case 1:
7465 /* ignored */
7466 rn = "BadInstr";
7467 break;
7468 case 2:
7469 /* ignored */
7470 rn = "BadInstrP";
7471 break;
7472 case 3:
7473 /* ignored */
7474 rn = "BadInstrX";
7475 break;
7476 default:
7477 goto cp0_unimplemented;
7479 break;
7480 case 9:
7481 switch (sel) {
7482 case 0:
7483 gen_helper_mtc0_count(cpu_env, arg);
7484 rn = "Count";
7485 break;
7486 /* 6,7 are implementation dependent */
7487 default:
7488 goto cp0_unimplemented;
7490 break;
7491 case 10:
7492 switch (sel) {
7493 case 0:
7494 gen_helper_mtc0_entryhi(cpu_env, arg);
7495 rn = "EntryHi";
7496 break;
7497 default:
7498 goto cp0_unimplemented;
7500 break;
7501 case 11:
7502 switch (sel) {
7503 case 0:
7504 gen_helper_mtc0_compare(cpu_env, arg);
7505 rn = "Compare";
7506 break;
7507 /* 6,7 are implementation dependent */
7508 default:
7509 goto cp0_unimplemented;
7511 break;
7512 case 12:
7513 switch (sel) {
7514 case 0:
7515 save_cpu_state(ctx, 1);
7516 gen_helper_mtc0_status(cpu_env, arg);
7517 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7518 gen_save_pc(ctx->base.pc_next + 4);
7519 ctx->base.is_jmp = DISAS_EXIT;
7520 rn = "Status";
7521 break;
7522 case 1:
7523 check_insn(ctx, ISA_MIPS32R2);
7524 gen_helper_mtc0_intctl(cpu_env, arg);
7525 /* Stop translation as we may have switched the execution mode */
7526 ctx->base.is_jmp = DISAS_STOP;
7527 rn = "IntCtl";
7528 break;
7529 case 2:
7530 check_insn(ctx, ISA_MIPS32R2);
7531 gen_helper_mtc0_srsctl(cpu_env, arg);
7532 /* Stop translation as we may have switched the execution mode */
7533 ctx->base.is_jmp = DISAS_STOP;
7534 rn = "SRSCtl";
7535 break;
7536 case 3:
7537 check_insn(ctx, ISA_MIPS32R2);
7538 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7539 /* Stop translation as we may have switched the execution mode */
7540 ctx->base.is_jmp = DISAS_STOP;
7541 rn = "SRSMap";
7542 break;
7543 default:
7544 goto cp0_unimplemented;
7546 break;
7547 case 13:
7548 switch (sel) {
7549 case 0:
7550 save_cpu_state(ctx, 1);
7551 gen_helper_mtc0_cause(cpu_env, arg);
7552 /* Stop translation as we may have triggered an interrupt.
7553 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7554 * translated code to check for pending interrupts. */
7555 gen_save_pc(ctx->base.pc_next + 4);
7556 ctx->base.is_jmp = DISAS_EXIT;
7557 rn = "Cause";
7558 break;
7559 default:
7560 goto cp0_unimplemented;
7562 break;
7563 case 14:
7564 switch (sel) {
7565 case 0:
7566 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7567 rn = "EPC";
7568 break;
7569 default:
7570 goto cp0_unimplemented;
7572 break;
7573 case 15:
7574 switch (sel) {
7575 case 0:
7576 /* ignored */
7577 rn = "PRid";
7578 break;
7579 case 1:
7580 check_insn(ctx, ISA_MIPS32R2);
7581 gen_helper_mtc0_ebase(cpu_env, arg);
7582 rn = "EBase";
7583 break;
7584 default:
7585 goto cp0_unimplemented;
7587 break;
7588 case 16:
7589 switch (sel) {
7590 case 0:
7591 gen_helper_mtc0_config0(cpu_env, arg);
7592 rn = "Config";
7593 /* Stop translation as we may have switched the execution mode */
7594 ctx->base.is_jmp = DISAS_STOP;
7595 break;
7596 case 1:
7597 /* ignored, read only */
7598 rn = "Config1";
7599 break;
7600 case 2:
7601 gen_helper_mtc0_config2(cpu_env, arg);
7602 rn = "Config2";
7603 /* Stop translation as we may have switched the execution mode */
7604 ctx->base.is_jmp = DISAS_STOP;
7605 break;
7606 case 3:
7607 gen_helper_mtc0_config3(cpu_env, arg);
7608 rn = "Config3";
7609 /* Stop translation as we may have switched the execution mode */
7610 ctx->base.is_jmp = DISAS_STOP;
7611 break;
7612 case 4:
7613 gen_helper_mtc0_config4(cpu_env, arg);
7614 rn = "Config4";
7615 ctx->base.is_jmp = DISAS_STOP;
7616 break;
7617 case 5:
7618 gen_helper_mtc0_config5(cpu_env, arg);
7619 rn = "Config5";
7620 /* Stop translation as we may have switched the execution mode */
7621 ctx->base.is_jmp = DISAS_STOP;
7622 break;
7623 /* 6,7 are implementation dependent */
7624 case 6:
7625 /* ignored */
7626 rn = "Config6";
7627 break;
7628 case 7:
7629 /* ignored */
7630 rn = "Config7";
7631 break;
7632 default:
7633 rn = "Invalid config selector";
7634 goto cp0_unimplemented;
7636 break;
7637 case 17:
7638 switch (sel) {
7639 case 0:
7640 gen_helper_mtc0_lladdr(cpu_env, arg);
7641 rn = "LLAddr";
7642 break;
7643 case 1:
7644 CP0_CHECK(ctx->mrp);
7645 gen_helper_mtc0_maar(cpu_env, arg);
7646 rn = "MAAR";
7647 break;
7648 case 2:
7649 CP0_CHECK(ctx->mrp);
7650 gen_helper_mtc0_maari(cpu_env, arg);
7651 rn = "MAARI";
7652 break;
7653 default:
7654 goto cp0_unimplemented;
7656 break;
7657 case 18:
7658 switch (sel) {
7659 case 0:
7660 case 1:
7661 case 2:
7662 case 3:
7663 case 4:
7664 case 5:
7665 case 6:
7666 case 7:
7667 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7668 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7669 rn = "WatchLo";
7670 break;
7671 default:
7672 goto cp0_unimplemented;
7674 break;
7675 case 19:
7676 switch (sel) {
7677 case 0:
7678 case 1:
7679 case 2:
7680 case 3:
7681 case 4:
7682 case 5:
7683 case 6:
7684 case 7:
7685 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7686 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7687 rn = "WatchHi";
7688 break;
7689 default:
7690 goto cp0_unimplemented;
7692 break;
7693 case 20:
7694 switch (sel) {
7695 case 0:
7696 #if defined(TARGET_MIPS64)
7697 check_insn(ctx, ISA_MIPS3);
7698 gen_helper_mtc0_xcontext(cpu_env, arg);
7699 rn = "XContext";
7700 break;
7701 #endif
7702 default:
7703 goto cp0_unimplemented;
7705 break;
7706 case 21:
7707 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7708 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7709 switch (sel) {
7710 case 0:
7711 gen_helper_mtc0_framemask(cpu_env, arg);
7712 rn = "Framemask";
7713 break;
7714 default:
7715 goto cp0_unimplemented;
7717 break;
7718 case 22:
7719 /* ignored */
7720 rn = "Diagnostic"; /* implementation dependent */
7721 break;
7722 case 23:
7723 switch (sel) {
7724 case 0:
7725 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7726 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7727 gen_save_pc(ctx->base.pc_next + 4);
7728 ctx->base.is_jmp = DISAS_EXIT;
7729 rn = "Debug";
7730 break;
7731 case 1:
7732 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7733 rn = "TraceControl";
7734 /* Stop translation as we may have switched the execution mode */
7735 ctx->base.is_jmp = DISAS_STOP;
7736 goto cp0_unimplemented;
7737 case 2:
7738 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7739 rn = "TraceControl2";
7740 /* Stop translation as we may have switched the execution mode */
7741 ctx->base.is_jmp = DISAS_STOP;
7742 goto cp0_unimplemented;
7743 case 3:
7744 /* Stop translation as we may have switched the execution mode */
7745 ctx->base.is_jmp = DISAS_STOP;
7746 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7747 rn = "UserTraceData";
7748 /* Stop translation as we may have switched the execution mode */
7749 ctx->base.is_jmp = DISAS_STOP;
7750 goto cp0_unimplemented;
7751 case 4:
7752 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7753 /* Stop translation as we may have switched the execution mode */
7754 ctx->base.is_jmp = DISAS_STOP;
7755 rn = "TraceBPC";
7756 goto cp0_unimplemented;
7757 default:
7758 goto cp0_unimplemented;
7760 break;
7761 case 24:
7762 switch (sel) {
7763 case 0:
7764 /* EJTAG support */
7765 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7766 rn = "DEPC";
7767 break;
7768 default:
7769 goto cp0_unimplemented;
7771 break;
7772 case 25:
7773 switch (sel) {
7774 case 0:
7775 gen_helper_mtc0_performance0(cpu_env, arg);
7776 rn = "Performance0";
7777 break;
7778 case 1:
7779 // gen_helper_mtc0_performance1(arg);
7780 rn = "Performance1";
7781 goto cp0_unimplemented;
7782 case 2:
7783 // gen_helper_mtc0_performance2(arg);
7784 rn = "Performance2";
7785 goto cp0_unimplemented;
7786 case 3:
7787 // gen_helper_mtc0_performance3(arg);
7788 rn = "Performance3";
7789 goto cp0_unimplemented;
7790 case 4:
7791 // gen_helper_mtc0_performance4(arg);
7792 rn = "Performance4";
7793 goto cp0_unimplemented;
7794 case 5:
7795 // gen_helper_mtc0_performance5(arg);
7796 rn = "Performance5";
7797 goto cp0_unimplemented;
7798 case 6:
7799 // gen_helper_mtc0_performance6(arg);
7800 rn = "Performance6";
7801 goto cp0_unimplemented;
7802 case 7:
7803 // gen_helper_mtc0_performance7(arg);
7804 rn = "Performance7";
7805 goto cp0_unimplemented;
7806 default:
7807 goto cp0_unimplemented;
7809 break;
7810 case 26:
7811 switch (sel) {
7812 case 0:
7813 gen_helper_mtc0_errctl(cpu_env, arg);
7814 ctx->base.is_jmp = DISAS_STOP;
7815 rn = "ErrCtl";
7816 break;
7817 default:
7818 goto cp0_unimplemented;
7820 break;
7821 case 27:
7822 switch (sel) {
7823 case 0:
7824 case 1:
7825 case 2:
7826 case 3:
7827 /* ignored */
7828 rn = "CacheErr";
7829 break;
7830 default:
7831 goto cp0_unimplemented;
7833 break;
7834 case 28:
7835 switch (sel) {
7836 case 0:
7837 case 2:
7838 case 4:
7839 case 6:
7840 gen_helper_mtc0_taglo(cpu_env, arg);
7841 rn = "TagLo";
7842 break;
7843 case 1:
7844 case 3:
7845 case 5:
7846 case 7:
7847 gen_helper_mtc0_datalo(cpu_env, arg);
7848 rn = "DataLo";
7849 break;
7850 default:
7851 goto cp0_unimplemented;
7853 break;
7854 case 29:
7855 switch (sel) {
7856 case 0:
7857 case 2:
7858 case 4:
7859 case 6:
7860 gen_helper_mtc0_taghi(cpu_env, arg);
7861 rn = "TagHi";
7862 break;
7863 case 1:
7864 case 3:
7865 case 5:
7866 case 7:
7867 gen_helper_mtc0_datahi(cpu_env, arg);
7868 rn = "DataHi";
7869 break;
7870 default:
7871 rn = "invalid sel";
7872 goto cp0_unimplemented;
7874 break;
7875 case 30:
7876 switch (sel) {
7877 case 0:
7878 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7879 rn = "ErrorEPC";
7880 break;
7881 default:
7882 goto cp0_unimplemented;
7884 break;
7885 case 31:
7886 switch (sel) {
7887 case 0:
7888 /* EJTAG support */
7889 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7890 rn = "DESAVE";
7891 break;
7892 case 2:
7893 case 3:
7894 case 4:
7895 case 5:
7896 case 6:
7897 case 7:
7898 CP0_CHECK(ctx->kscrexist & (1 << sel));
7899 tcg_gen_st_tl(arg, cpu_env,
7900 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7901 rn = "KScratch";
7902 break;
7903 default:
7904 goto cp0_unimplemented;
7906 break;
7907 default:
7908 goto cp0_unimplemented;
7910 trace_mips_translate_c0("mtc0", rn, reg, sel);
7912 /* For simplicity assume that all writes can cause interrupts. */
7913 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7914 gen_io_end();
7915 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7916 * translated code to check for pending interrupts. */
7917 gen_save_pc(ctx->base.pc_next + 4);
7918 ctx->base.is_jmp = DISAS_EXIT;
7920 return;
7922 cp0_unimplemented:
7923 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7926 #if defined(TARGET_MIPS64)
7927 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7929 const char *rn = "invalid";
7931 if (sel != 0)
7932 check_insn(ctx, ISA_MIPS64);
7934 switch (reg) {
7935 case 0:
7936 switch (sel) {
7937 case 0:
7938 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7939 rn = "Index";
7940 break;
7941 case 1:
7942 CP0_CHECK(ctx->insn_flags & ASE_MT);
7943 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7944 rn = "MVPControl";
7945 break;
7946 case 2:
7947 CP0_CHECK(ctx->insn_flags & ASE_MT);
7948 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7949 rn = "MVPConf0";
7950 break;
7951 case 3:
7952 CP0_CHECK(ctx->insn_flags & ASE_MT);
7953 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7954 rn = "MVPConf1";
7955 break;
7956 case 4:
7957 CP0_CHECK(ctx->vp);
7958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7959 rn = "VPControl";
7960 break;
7961 default:
7962 goto cp0_unimplemented;
7964 break;
7965 case 1:
7966 switch (sel) {
7967 case 0:
7968 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7969 gen_helper_mfc0_random(arg, cpu_env);
7970 rn = "Random";
7971 break;
7972 case 1:
7973 CP0_CHECK(ctx->insn_flags & ASE_MT);
7974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7975 rn = "VPEControl";
7976 break;
7977 case 2:
7978 CP0_CHECK(ctx->insn_flags & ASE_MT);
7979 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7980 rn = "VPEConf0";
7981 break;
7982 case 3:
7983 CP0_CHECK(ctx->insn_flags & ASE_MT);
7984 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7985 rn = "VPEConf1";
7986 break;
7987 case 4:
7988 CP0_CHECK(ctx->insn_flags & ASE_MT);
7989 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
7990 rn = "YQMask";
7991 break;
7992 case 5:
7993 CP0_CHECK(ctx->insn_flags & ASE_MT);
7994 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7995 rn = "VPESchedule";
7996 break;
7997 case 6:
7998 CP0_CHECK(ctx->insn_flags & ASE_MT);
7999 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8000 rn = "VPEScheFBack";
8001 break;
8002 case 7:
8003 CP0_CHECK(ctx->insn_flags & ASE_MT);
8004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8005 rn = "VPEOpt";
8006 break;
8007 default:
8008 goto cp0_unimplemented;
8010 break;
8011 case 2:
8012 switch (sel) {
8013 case 0:
8014 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8015 rn = "EntryLo0";
8016 break;
8017 case 1:
8018 CP0_CHECK(ctx->insn_flags & ASE_MT);
8019 gen_helper_mfc0_tcstatus(arg, cpu_env);
8020 rn = "TCStatus";
8021 break;
8022 case 2:
8023 CP0_CHECK(ctx->insn_flags & ASE_MT);
8024 gen_helper_mfc0_tcbind(arg, cpu_env);
8025 rn = "TCBind";
8026 break;
8027 case 3:
8028 CP0_CHECK(ctx->insn_flags & ASE_MT);
8029 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8030 rn = "TCRestart";
8031 break;
8032 case 4:
8033 CP0_CHECK(ctx->insn_flags & ASE_MT);
8034 gen_helper_dmfc0_tchalt(arg, cpu_env);
8035 rn = "TCHalt";
8036 break;
8037 case 5:
8038 CP0_CHECK(ctx->insn_flags & ASE_MT);
8039 gen_helper_dmfc0_tccontext(arg, cpu_env);
8040 rn = "TCContext";
8041 break;
8042 case 6:
8043 CP0_CHECK(ctx->insn_flags & ASE_MT);
8044 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8045 rn = "TCSchedule";
8046 break;
8047 case 7:
8048 CP0_CHECK(ctx->insn_flags & ASE_MT);
8049 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8050 rn = "TCScheFBack";
8051 break;
8052 default:
8053 goto cp0_unimplemented;
8055 break;
8056 case 3:
8057 switch (sel) {
8058 case 0:
8059 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8060 rn = "EntryLo1";
8061 break;
8062 case 1:
8063 CP0_CHECK(ctx->vp);
8064 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8065 rn = "GlobalNumber";
8066 break;
8067 default:
8068 goto cp0_unimplemented;
8070 break;
8071 case 4:
8072 switch (sel) {
8073 case 0:
8074 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8075 rn = "Context";
8076 break;
8077 case 1:
8078 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8079 rn = "ContextConfig";
8080 goto cp0_unimplemented;
8081 case 2:
8082 CP0_CHECK(ctx->ulri);
8083 tcg_gen_ld_tl(arg, cpu_env,
8084 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8085 rn = "UserLocal";
8086 break;
8087 default:
8088 goto cp0_unimplemented;
8090 break;
8091 case 5:
8092 switch (sel) {
8093 case 0:
8094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8095 rn = "PageMask";
8096 break;
8097 case 1:
8098 check_insn(ctx, ISA_MIPS32R2);
8099 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8100 rn = "PageGrain";
8101 break;
8102 case 2:
8103 CP0_CHECK(ctx->sc);
8104 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8105 rn = "SegCtl0";
8106 break;
8107 case 3:
8108 CP0_CHECK(ctx->sc);
8109 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8110 rn = "SegCtl1";
8111 break;
8112 case 4:
8113 CP0_CHECK(ctx->sc);
8114 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8115 rn = "SegCtl2";
8116 break;
8117 case 5:
8118 check_pw(ctx);
8119 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8120 rn = "PWBase";
8121 break;
8122 case 6:
8123 check_pw(ctx);
8124 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8125 rn = "PWField";
8126 break;
8127 case 7:
8128 check_pw(ctx);
8129 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8130 rn = "PWSize";
8131 break;
8132 default:
8133 goto cp0_unimplemented;
8135 break;
8136 case 6:
8137 switch (sel) {
8138 case 0:
8139 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8140 rn = "Wired";
8141 break;
8142 case 1:
8143 check_insn(ctx, ISA_MIPS32R2);
8144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8145 rn = "SRSConf0";
8146 break;
8147 case 2:
8148 check_insn(ctx, ISA_MIPS32R2);
8149 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8150 rn = "SRSConf1";
8151 break;
8152 case 3:
8153 check_insn(ctx, ISA_MIPS32R2);
8154 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8155 rn = "SRSConf2";
8156 break;
8157 case 4:
8158 check_insn(ctx, ISA_MIPS32R2);
8159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8160 rn = "SRSConf3";
8161 break;
8162 case 5:
8163 check_insn(ctx, ISA_MIPS32R2);
8164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8165 rn = "SRSConf4";
8166 break;
8167 case 6:
8168 check_pw(ctx);
8169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8170 rn = "PWCtl";
8171 break;
8172 default:
8173 goto cp0_unimplemented;
8175 break;
8176 case 7:
8177 switch (sel) {
8178 case 0:
8179 check_insn(ctx, ISA_MIPS32R2);
8180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8181 rn = "HWREna";
8182 break;
8183 default:
8184 goto cp0_unimplemented;
8186 break;
8187 case 8:
8188 switch (sel) {
8189 case 0:
8190 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8191 rn = "BadVAddr";
8192 break;
8193 case 1:
8194 CP0_CHECK(ctx->bi);
8195 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8196 rn = "BadInstr";
8197 break;
8198 case 2:
8199 CP0_CHECK(ctx->bp);
8200 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8201 rn = "BadInstrP";
8202 break;
8203 case 3:
8204 CP0_CHECK(ctx->bi);
8205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8206 tcg_gen_andi_tl(arg, arg, ~0xffff);
8207 rn = "BadInstrX";
8208 break;
8209 default:
8210 goto cp0_unimplemented;
8212 break;
8213 case 9:
8214 switch (sel) {
8215 case 0:
8216 /* Mark as an IO operation because we read the time. */
8217 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8218 gen_io_start();
8220 gen_helper_mfc0_count(arg, cpu_env);
8221 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8222 gen_io_end();
8224 /* Break the TB to be able to take timer interrupts immediately
8225 after reading count. DISAS_STOP isn't sufficient, we need to
8226 ensure we break completely out of translated code. */
8227 gen_save_pc(ctx->base.pc_next + 4);
8228 ctx->base.is_jmp = DISAS_EXIT;
8229 rn = "Count";
8230 break;
8231 /* 6,7 are implementation dependent */
8232 default:
8233 goto cp0_unimplemented;
8235 break;
8236 case 10:
8237 switch (sel) {
8238 case 0:
8239 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8240 rn = "EntryHi";
8241 break;
8242 default:
8243 goto cp0_unimplemented;
8245 break;
8246 case 11:
8247 switch (sel) {
8248 case 0:
8249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8250 rn = "Compare";
8251 break;
8252 /* 6,7 are implementation dependent */
8253 default:
8254 goto cp0_unimplemented;
8256 break;
8257 case 12:
8258 switch (sel) {
8259 case 0:
8260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8261 rn = "Status";
8262 break;
8263 case 1:
8264 check_insn(ctx, ISA_MIPS32R2);
8265 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8266 rn = "IntCtl";
8267 break;
8268 case 2:
8269 check_insn(ctx, ISA_MIPS32R2);
8270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8271 rn = "SRSCtl";
8272 break;
8273 case 3:
8274 check_insn(ctx, ISA_MIPS32R2);
8275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8276 rn = "SRSMap";
8277 break;
8278 default:
8279 goto cp0_unimplemented;
8281 break;
8282 case 13:
8283 switch (sel) {
8284 case 0:
8285 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8286 rn = "Cause";
8287 break;
8288 default:
8289 goto cp0_unimplemented;
8291 break;
8292 case 14:
8293 switch (sel) {
8294 case 0:
8295 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8296 rn = "EPC";
8297 break;
8298 default:
8299 goto cp0_unimplemented;
8301 break;
8302 case 15:
8303 switch (sel) {
8304 case 0:
8305 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8306 rn = "PRid";
8307 break;
8308 case 1:
8309 check_insn(ctx, ISA_MIPS32R2);
8310 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8311 rn = "EBase";
8312 break;
8313 case 3:
8314 check_insn(ctx, ISA_MIPS32R2);
8315 CP0_CHECK(ctx->cmgcr);
8316 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8317 rn = "CMGCRBase";
8318 break;
8319 default:
8320 goto cp0_unimplemented;
8322 break;
8323 case 16:
8324 switch (sel) {
8325 case 0:
8326 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8327 rn = "Config";
8328 break;
8329 case 1:
8330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8331 rn = "Config1";
8332 break;
8333 case 2:
8334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8335 rn = "Config2";
8336 break;
8337 case 3:
8338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8339 rn = "Config3";
8340 break;
8341 case 4:
8342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8343 rn = "Config4";
8344 break;
8345 case 5:
8346 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8347 rn = "Config5";
8348 break;
8349 /* 6,7 are implementation dependent */
8350 case 6:
8351 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8352 rn = "Config6";
8353 break;
8354 case 7:
8355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8356 rn = "Config7";
8357 break;
8358 default:
8359 goto cp0_unimplemented;
8361 break;
8362 case 17:
8363 switch (sel) {
8364 case 0:
8365 gen_helper_dmfc0_lladdr(arg, cpu_env);
8366 rn = "LLAddr";
8367 break;
8368 case 1:
8369 CP0_CHECK(ctx->mrp);
8370 gen_helper_dmfc0_maar(arg, cpu_env);
8371 rn = "MAAR";
8372 break;
8373 case 2:
8374 CP0_CHECK(ctx->mrp);
8375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8376 rn = "MAARI";
8377 break;
8378 default:
8379 goto cp0_unimplemented;
8381 break;
8382 case 18:
8383 switch (sel) {
8384 case 0:
8385 case 1:
8386 case 2:
8387 case 3:
8388 case 4:
8389 case 5:
8390 case 6:
8391 case 7:
8392 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8393 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8394 rn = "WatchLo";
8395 break;
8396 default:
8397 goto cp0_unimplemented;
8399 break;
8400 case 19:
8401 switch (sel) {
8402 case 0:
8403 case 1:
8404 case 2:
8405 case 3:
8406 case 4:
8407 case 5:
8408 case 6:
8409 case 7:
8410 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8411 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8412 rn = "WatchHi";
8413 break;
8414 default:
8415 goto cp0_unimplemented;
8417 break;
8418 case 20:
8419 switch (sel) {
8420 case 0:
8421 check_insn(ctx, ISA_MIPS3);
8422 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8423 rn = "XContext";
8424 break;
8425 default:
8426 goto cp0_unimplemented;
8428 break;
8429 case 21:
8430 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8431 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8432 switch (sel) {
8433 case 0:
8434 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8435 rn = "Framemask";
8436 break;
8437 default:
8438 goto cp0_unimplemented;
8440 break;
8441 case 22:
8442 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8443 rn = "'Diagnostic"; /* implementation dependent */
8444 break;
8445 case 23:
8446 switch (sel) {
8447 case 0:
8448 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8449 rn = "Debug";
8450 break;
8451 case 1:
8452 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8453 rn = "TraceControl";
8454 goto cp0_unimplemented;
8455 case 2:
8456 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8457 rn = "TraceControl2";
8458 goto cp0_unimplemented;
8459 case 3:
8460 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8461 rn = "UserTraceData";
8462 goto cp0_unimplemented;
8463 case 4:
8464 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8465 rn = "TraceBPC";
8466 goto cp0_unimplemented;
8467 default:
8468 goto cp0_unimplemented;
8470 break;
8471 case 24:
8472 switch (sel) {
8473 case 0:
8474 /* EJTAG support */
8475 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8476 rn = "DEPC";
8477 break;
8478 default:
8479 goto cp0_unimplemented;
8481 break;
8482 case 25:
8483 switch (sel) {
8484 case 0:
8485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8486 rn = "Performance0";
8487 break;
8488 case 1:
8489 // gen_helper_dmfc0_performance1(arg);
8490 rn = "Performance1";
8491 goto cp0_unimplemented;
8492 case 2:
8493 // gen_helper_dmfc0_performance2(arg);
8494 rn = "Performance2";
8495 goto cp0_unimplemented;
8496 case 3:
8497 // gen_helper_dmfc0_performance3(arg);
8498 rn = "Performance3";
8499 goto cp0_unimplemented;
8500 case 4:
8501 // gen_helper_dmfc0_performance4(arg);
8502 rn = "Performance4";
8503 goto cp0_unimplemented;
8504 case 5:
8505 // gen_helper_dmfc0_performance5(arg);
8506 rn = "Performance5";
8507 goto cp0_unimplemented;
8508 case 6:
8509 // gen_helper_dmfc0_performance6(arg);
8510 rn = "Performance6";
8511 goto cp0_unimplemented;
8512 case 7:
8513 // gen_helper_dmfc0_performance7(arg);
8514 rn = "Performance7";
8515 goto cp0_unimplemented;
8516 default:
8517 goto cp0_unimplemented;
8519 break;
8520 case 26:
8521 switch (sel) {
8522 case 0:
8523 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8524 rn = "ErrCtl";
8525 break;
8526 default:
8527 goto cp0_unimplemented;
8529 break;
8530 case 27:
8531 switch (sel) {
8532 /* ignored */
8533 case 0:
8534 case 1:
8535 case 2:
8536 case 3:
8537 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8538 rn = "CacheErr";
8539 break;
8540 default:
8541 goto cp0_unimplemented;
8543 break;
8544 case 28:
8545 switch (sel) {
8546 case 0:
8547 case 2:
8548 case 4:
8549 case 6:
8550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8551 rn = "TagLo";
8552 break;
8553 case 1:
8554 case 3:
8555 case 5:
8556 case 7:
8557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8558 rn = "DataLo";
8559 break;
8560 default:
8561 goto cp0_unimplemented;
8563 break;
8564 case 29:
8565 switch (sel) {
8566 case 0:
8567 case 2:
8568 case 4:
8569 case 6:
8570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8571 rn = "TagHi";
8572 break;
8573 case 1:
8574 case 3:
8575 case 5:
8576 case 7:
8577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8578 rn = "DataHi";
8579 break;
8580 default:
8581 goto cp0_unimplemented;
8583 break;
8584 case 30:
8585 switch (sel) {
8586 case 0:
8587 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8588 rn = "ErrorEPC";
8589 break;
8590 default:
8591 goto cp0_unimplemented;
8593 break;
8594 case 31:
8595 switch (sel) {
8596 case 0:
8597 /* EJTAG support */
8598 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8599 rn = "DESAVE";
8600 break;
8601 case 2:
8602 case 3:
8603 case 4:
8604 case 5:
8605 case 6:
8606 case 7:
8607 CP0_CHECK(ctx->kscrexist & (1 << sel));
8608 tcg_gen_ld_tl(arg, cpu_env,
8609 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8610 rn = "KScratch";
8611 break;
8612 default:
8613 goto cp0_unimplemented;
8615 break;
8616 default:
8617 goto cp0_unimplemented;
8619 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8620 return;
8622 cp0_unimplemented:
8623 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8624 gen_mfc0_unimplemented(ctx, arg);
8627 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8629 const char *rn = "invalid";
8631 if (sel != 0)
8632 check_insn(ctx, ISA_MIPS64);
8634 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8635 gen_io_start();
8638 switch (reg) {
8639 case 0:
8640 switch (sel) {
8641 case 0:
8642 gen_helper_mtc0_index(cpu_env, arg);
8643 rn = "Index";
8644 break;
8645 case 1:
8646 CP0_CHECK(ctx->insn_flags & ASE_MT);
8647 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8648 rn = "MVPControl";
8649 break;
8650 case 2:
8651 CP0_CHECK(ctx->insn_flags & ASE_MT);
8652 /* ignored */
8653 rn = "MVPConf0";
8654 break;
8655 case 3:
8656 CP0_CHECK(ctx->insn_flags & ASE_MT);
8657 /* ignored */
8658 rn = "MVPConf1";
8659 break;
8660 case 4:
8661 CP0_CHECK(ctx->vp);
8662 /* ignored */
8663 rn = "VPControl";
8664 break;
8665 default:
8666 goto cp0_unimplemented;
8668 break;
8669 case 1:
8670 switch (sel) {
8671 case 0:
8672 /* ignored */
8673 rn = "Random";
8674 break;
8675 case 1:
8676 CP0_CHECK(ctx->insn_flags & ASE_MT);
8677 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8678 rn = "VPEControl";
8679 break;
8680 case 2:
8681 CP0_CHECK(ctx->insn_flags & ASE_MT);
8682 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8683 rn = "VPEConf0";
8684 break;
8685 case 3:
8686 CP0_CHECK(ctx->insn_flags & ASE_MT);
8687 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8688 rn = "VPEConf1";
8689 break;
8690 case 4:
8691 CP0_CHECK(ctx->insn_flags & ASE_MT);
8692 gen_helper_mtc0_yqmask(cpu_env, arg);
8693 rn = "YQMask";
8694 break;
8695 case 5:
8696 CP0_CHECK(ctx->insn_flags & ASE_MT);
8697 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8698 rn = "VPESchedule";
8699 break;
8700 case 6:
8701 CP0_CHECK(ctx->insn_flags & ASE_MT);
8702 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8703 rn = "VPEScheFBack";
8704 break;
8705 case 7:
8706 CP0_CHECK(ctx->insn_flags & ASE_MT);
8707 gen_helper_mtc0_vpeopt(cpu_env, arg);
8708 rn = "VPEOpt";
8709 break;
8710 default:
8711 goto cp0_unimplemented;
8713 break;
8714 case 2:
8715 switch (sel) {
8716 case 0:
8717 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8718 rn = "EntryLo0";
8719 break;
8720 case 1:
8721 CP0_CHECK(ctx->insn_flags & ASE_MT);
8722 gen_helper_mtc0_tcstatus(cpu_env, arg);
8723 rn = "TCStatus";
8724 break;
8725 case 2:
8726 CP0_CHECK(ctx->insn_flags & ASE_MT);
8727 gen_helper_mtc0_tcbind(cpu_env, arg);
8728 rn = "TCBind";
8729 break;
8730 case 3:
8731 CP0_CHECK(ctx->insn_flags & ASE_MT);
8732 gen_helper_mtc0_tcrestart(cpu_env, arg);
8733 rn = "TCRestart";
8734 break;
8735 case 4:
8736 CP0_CHECK(ctx->insn_flags & ASE_MT);
8737 gen_helper_mtc0_tchalt(cpu_env, arg);
8738 rn = "TCHalt";
8739 break;
8740 case 5:
8741 CP0_CHECK(ctx->insn_flags & ASE_MT);
8742 gen_helper_mtc0_tccontext(cpu_env, arg);
8743 rn = "TCContext";
8744 break;
8745 case 6:
8746 CP0_CHECK(ctx->insn_flags & ASE_MT);
8747 gen_helper_mtc0_tcschedule(cpu_env, arg);
8748 rn = "TCSchedule";
8749 break;
8750 case 7:
8751 CP0_CHECK(ctx->insn_flags & ASE_MT);
8752 gen_helper_mtc0_tcschefback(cpu_env, arg);
8753 rn = "TCScheFBack";
8754 break;
8755 default:
8756 goto cp0_unimplemented;
8758 break;
8759 case 3:
8760 switch (sel) {
8761 case 0:
8762 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8763 rn = "EntryLo1";
8764 break;
8765 case 1:
8766 CP0_CHECK(ctx->vp);
8767 /* ignored */
8768 rn = "GlobalNumber";
8769 break;
8770 default:
8771 goto cp0_unimplemented;
8773 break;
8774 case 4:
8775 switch (sel) {
8776 case 0:
8777 gen_helper_mtc0_context(cpu_env, arg);
8778 rn = "Context";
8779 break;
8780 case 1:
8781 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8782 rn = "ContextConfig";
8783 goto cp0_unimplemented;
8784 case 2:
8785 CP0_CHECK(ctx->ulri);
8786 tcg_gen_st_tl(arg, cpu_env,
8787 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8788 rn = "UserLocal";
8789 break;
8790 default:
8791 goto cp0_unimplemented;
8793 break;
8794 case 5:
8795 switch (sel) {
8796 case 0:
8797 gen_helper_mtc0_pagemask(cpu_env, arg);
8798 rn = "PageMask";
8799 break;
8800 case 1:
8801 check_insn(ctx, ISA_MIPS32R2);
8802 gen_helper_mtc0_pagegrain(cpu_env, arg);
8803 rn = "PageGrain";
8804 break;
8805 case 2:
8806 CP0_CHECK(ctx->sc);
8807 gen_helper_mtc0_segctl0(cpu_env, arg);
8808 rn = "SegCtl0";
8809 break;
8810 case 3:
8811 CP0_CHECK(ctx->sc);
8812 gen_helper_mtc0_segctl1(cpu_env, arg);
8813 rn = "SegCtl1";
8814 break;
8815 case 4:
8816 CP0_CHECK(ctx->sc);
8817 gen_helper_mtc0_segctl2(cpu_env, arg);
8818 rn = "SegCtl2";
8819 break;
8820 case 5:
8821 check_pw(ctx);
8822 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8823 rn = "PWBase";
8824 break;
8825 case 6:
8826 check_pw(ctx);
8827 gen_helper_mtc0_pwfield(cpu_env, arg);
8828 rn = "PWField";
8829 break;
8830 case 7:
8831 check_pw(ctx);
8832 gen_helper_mtc0_pwsize(cpu_env, arg);
8833 rn = "PWSize";
8834 break;
8835 default:
8836 goto cp0_unimplemented;
8838 break;
8839 case 6:
8840 switch (sel) {
8841 case 0:
8842 gen_helper_mtc0_wired(cpu_env, arg);
8843 rn = "Wired";
8844 break;
8845 case 1:
8846 check_insn(ctx, ISA_MIPS32R2);
8847 gen_helper_mtc0_srsconf0(cpu_env, arg);
8848 rn = "SRSConf0";
8849 break;
8850 case 2:
8851 check_insn(ctx, ISA_MIPS32R2);
8852 gen_helper_mtc0_srsconf1(cpu_env, arg);
8853 rn = "SRSConf1";
8854 break;
8855 case 3:
8856 check_insn(ctx, ISA_MIPS32R2);
8857 gen_helper_mtc0_srsconf2(cpu_env, arg);
8858 rn = "SRSConf2";
8859 break;
8860 case 4:
8861 check_insn(ctx, ISA_MIPS32R2);
8862 gen_helper_mtc0_srsconf3(cpu_env, arg);
8863 rn = "SRSConf3";
8864 break;
8865 case 5:
8866 check_insn(ctx, ISA_MIPS32R2);
8867 gen_helper_mtc0_srsconf4(cpu_env, arg);
8868 rn = "SRSConf4";
8869 break;
8870 case 6:
8871 check_pw(ctx);
8872 gen_helper_mtc0_pwctl(cpu_env, arg);
8873 rn = "PWCtl";
8874 break;
8875 default:
8876 goto cp0_unimplemented;
8878 break;
8879 case 7:
8880 switch (sel) {
8881 case 0:
8882 check_insn(ctx, ISA_MIPS32R2);
8883 gen_helper_mtc0_hwrena(cpu_env, arg);
8884 ctx->base.is_jmp = DISAS_STOP;
8885 rn = "HWREna";
8886 break;
8887 default:
8888 goto cp0_unimplemented;
8890 break;
8891 case 8:
8892 switch (sel) {
8893 case 0:
8894 /* ignored */
8895 rn = "BadVAddr";
8896 break;
8897 case 1:
8898 /* ignored */
8899 rn = "BadInstr";
8900 break;
8901 case 2:
8902 /* ignored */
8903 rn = "BadInstrP";
8904 break;
8905 case 3:
8906 /* ignored */
8907 rn = "BadInstrX";
8908 break;
8909 default:
8910 goto cp0_unimplemented;
8912 break;
8913 case 9:
8914 switch (sel) {
8915 case 0:
8916 gen_helper_mtc0_count(cpu_env, arg);
8917 rn = "Count";
8918 break;
8919 /* 6,7 are implementation dependent */
8920 default:
8921 goto cp0_unimplemented;
8923 /* Stop translation as we may have switched the execution mode */
8924 ctx->base.is_jmp = DISAS_STOP;
8925 break;
8926 case 10:
8927 switch (sel) {
8928 case 0:
8929 gen_helper_mtc0_entryhi(cpu_env, arg);
8930 rn = "EntryHi";
8931 break;
8932 default:
8933 goto cp0_unimplemented;
8935 break;
8936 case 11:
8937 switch (sel) {
8938 case 0:
8939 gen_helper_mtc0_compare(cpu_env, arg);
8940 rn = "Compare";
8941 break;
8942 /* 6,7 are implementation dependent */
8943 default:
8944 goto cp0_unimplemented;
8946 /* Stop translation as we may have switched the execution mode */
8947 ctx->base.is_jmp = DISAS_STOP;
8948 break;
8949 case 12:
8950 switch (sel) {
8951 case 0:
8952 save_cpu_state(ctx, 1);
8953 gen_helper_mtc0_status(cpu_env, arg);
8954 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8955 gen_save_pc(ctx->base.pc_next + 4);
8956 ctx->base.is_jmp = DISAS_EXIT;
8957 rn = "Status";
8958 break;
8959 case 1:
8960 check_insn(ctx, ISA_MIPS32R2);
8961 gen_helper_mtc0_intctl(cpu_env, arg);
8962 /* Stop translation as we may have switched the execution mode */
8963 ctx->base.is_jmp = DISAS_STOP;
8964 rn = "IntCtl";
8965 break;
8966 case 2:
8967 check_insn(ctx, ISA_MIPS32R2);
8968 gen_helper_mtc0_srsctl(cpu_env, arg);
8969 /* Stop translation as we may have switched the execution mode */
8970 ctx->base.is_jmp = DISAS_STOP;
8971 rn = "SRSCtl";
8972 break;
8973 case 3:
8974 check_insn(ctx, ISA_MIPS32R2);
8975 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8976 /* Stop translation as we may have switched the execution mode */
8977 ctx->base.is_jmp = DISAS_STOP;
8978 rn = "SRSMap";
8979 break;
8980 default:
8981 goto cp0_unimplemented;
8983 break;
8984 case 13:
8985 switch (sel) {
8986 case 0:
8987 save_cpu_state(ctx, 1);
8988 gen_helper_mtc0_cause(cpu_env, arg);
8989 /* Stop translation as we may have triggered an interrupt.
8990 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8991 * translated code to check for pending interrupts. */
8992 gen_save_pc(ctx->base.pc_next + 4);
8993 ctx->base.is_jmp = DISAS_EXIT;
8994 rn = "Cause";
8995 break;
8996 default:
8997 goto cp0_unimplemented;
8999 break;
9000 case 14:
9001 switch (sel) {
9002 case 0:
9003 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9004 rn = "EPC";
9005 break;
9006 default:
9007 goto cp0_unimplemented;
9009 break;
9010 case 15:
9011 switch (sel) {
9012 case 0:
9013 /* ignored */
9014 rn = "PRid";
9015 break;
9016 case 1:
9017 check_insn(ctx, ISA_MIPS32R2);
9018 gen_helper_mtc0_ebase(cpu_env, arg);
9019 rn = "EBase";
9020 break;
9021 default:
9022 goto cp0_unimplemented;
9024 break;
9025 case 16:
9026 switch (sel) {
9027 case 0:
9028 gen_helper_mtc0_config0(cpu_env, arg);
9029 rn = "Config";
9030 /* Stop translation as we may have switched the execution mode */
9031 ctx->base.is_jmp = DISAS_STOP;
9032 break;
9033 case 1:
9034 /* ignored, read only */
9035 rn = "Config1";
9036 break;
9037 case 2:
9038 gen_helper_mtc0_config2(cpu_env, arg);
9039 rn = "Config2";
9040 /* Stop translation as we may have switched the execution mode */
9041 ctx->base.is_jmp = DISAS_STOP;
9042 break;
9043 case 3:
9044 gen_helper_mtc0_config3(cpu_env, arg);
9045 rn = "Config3";
9046 /* Stop translation as we may have switched the execution mode */
9047 ctx->base.is_jmp = DISAS_STOP;
9048 break;
9049 case 4:
9050 /* currently ignored */
9051 rn = "Config4";
9052 break;
9053 case 5:
9054 gen_helper_mtc0_config5(cpu_env, arg);
9055 rn = "Config5";
9056 /* Stop translation as we may have switched the execution mode */
9057 ctx->base.is_jmp = DISAS_STOP;
9058 break;
9059 /* 6,7 are implementation dependent */
9060 default:
9061 rn = "Invalid config selector";
9062 goto cp0_unimplemented;
9064 break;
9065 case 17:
9066 switch (sel) {
9067 case 0:
9068 gen_helper_mtc0_lladdr(cpu_env, arg);
9069 rn = "LLAddr";
9070 break;
9071 case 1:
9072 CP0_CHECK(ctx->mrp);
9073 gen_helper_mtc0_maar(cpu_env, arg);
9074 rn = "MAAR";
9075 break;
9076 case 2:
9077 CP0_CHECK(ctx->mrp);
9078 gen_helper_mtc0_maari(cpu_env, arg);
9079 rn = "MAARI";
9080 break;
9081 default:
9082 goto cp0_unimplemented;
9084 break;
9085 case 18:
9086 switch (sel) {
9087 case 0:
9088 case 1:
9089 case 2:
9090 case 3:
9091 case 4:
9092 case 5:
9093 case 6:
9094 case 7:
9095 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9096 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9097 rn = "WatchLo";
9098 break;
9099 default:
9100 goto cp0_unimplemented;
9102 break;
9103 case 19:
9104 switch (sel) {
9105 case 0:
9106 case 1:
9107 case 2:
9108 case 3:
9109 case 4:
9110 case 5:
9111 case 6:
9112 case 7:
9113 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9114 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9115 rn = "WatchHi";
9116 break;
9117 default:
9118 goto cp0_unimplemented;
9120 break;
9121 case 20:
9122 switch (sel) {
9123 case 0:
9124 check_insn(ctx, ISA_MIPS3);
9125 gen_helper_mtc0_xcontext(cpu_env, arg);
9126 rn = "XContext";
9127 break;
9128 default:
9129 goto cp0_unimplemented;
9131 break;
9132 case 21:
9133 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9134 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9135 switch (sel) {
9136 case 0:
9137 gen_helper_mtc0_framemask(cpu_env, arg);
9138 rn = "Framemask";
9139 break;
9140 default:
9141 goto cp0_unimplemented;
9143 break;
9144 case 22:
9145 /* ignored */
9146 rn = "Diagnostic"; /* implementation dependent */
9147 break;
9148 case 23:
9149 switch (sel) {
9150 case 0:
9151 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9152 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9153 gen_save_pc(ctx->base.pc_next + 4);
9154 ctx->base.is_jmp = DISAS_EXIT;
9155 rn = "Debug";
9156 break;
9157 case 1:
9158 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9159 /* Stop translation as we may have switched the execution mode */
9160 ctx->base.is_jmp = DISAS_STOP;
9161 rn = "TraceControl";
9162 goto cp0_unimplemented;
9163 case 2:
9164 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9165 /* Stop translation as we may have switched the execution mode */
9166 ctx->base.is_jmp = DISAS_STOP;
9167 rn = "TraceControl2";
9168 goto cp0_unimplemented;
9169 case 3:
9170 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9171 /* Stop translation as we may have switched the execution mode */
9172 ctx->base.is_jmp = DISAS_STOP;
9173 rn = "UserTraceData";
9174 goto cp0_unimplemented;
9175 case 4:
9176 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9177 /* Stop translation as we may have switched the execution mode */
9178 ctx->base.is_jmp = DISAS_STOP;
9179 rn = "TraceBPC";
9180 goto cp0_unimplemented;
9181 default:
9182 goto cp0_unimplemented;
9184 break;
9185 case 24:
9186 switch (sel) {
9187 case 0:
9188 /* EJTAG support */
9189 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9190 rn = "DEPC";
9191 break;
9192 default:
9193 goto cp0_unimplemented;
9195 break;
9196 case 25:
9197 switch (sel) {
9198 case 0:
9199 gen_helper_mtc0_performance0(cpu_env, arg);
9200 rn = "Performance0";
9201 break;
9202 case 1:
9203 // gen_helper_mtc0_performance1(cpu_env, arg);
9204 rn = "Performance1";
9205 goto cp0_unimplemented;
9206 case 2:
9207 // gen_helper_mtc0_performance2(cpu_env, arg);
9208 rn = "Performance2";
9209 goto cp0_unimplemented;
9210 case 3:
9211 // gen_helper_mtc0_performance3(cpu_env, arg);
9212 rn = "Performance3";
9213 goto cp0_unimplemented;
9214 case 4:
9215 // gen_helper_mtc0_performance4(cpu_env, arg);
9216 rn = "Performance4";
9217 goto cp0_unimplemented;
9218 case 5:
9219 // gen_helper_mtc0_performance5(cpu_env, arg);
9220 rn = "Performance5";
9221 goto cp0_unimplemented;
9222 case 6:
9223 // gen_helper_mtc0_performance6(cpu_env, arg);
9224 rn = "Performance6";
9225 goto cp0_unimplemented;
9226 case 7:
9227 // gen_helper_mtc0_performance7(cpu_env, arg);
9228 rn = "Performance7";
9229 goto cp0_unimplemented;
9230 default:
9231 goto cp0_unimplemented;
9233 break;
9234 case 26:
9235 switch (sel) {
9236 case 0:
9237 gen_helper_mtc0_errctl(cpu_env, arg);
9238 ctx->base.is_jmp = DISAS_STOP;
9239 rn = "ErrCtl";
9240 break;
9241 default:
9242 goto cp0_unimplemented;
9244 break;
9245 case 27:
9246 switch (sel) {
9247 case 0:
9248 case 1:
9249 case 2:
9250 case 3:
9251 /* ignored */
9252 rn = "CacheErr";
9253 break;
9254 default:
9255 goto cp0_unimplemented;
9257 break;
9258 case 28:
9259 switch (sel) {
9260 case 0:
9261 case 2:
9262 case 4:
9263 case 6:
9264 gen_helper_mtc0_taglo(cpu_env, arg);
9265 rn = "TagLo";
9266 break;
9267 case 1:
9268 case 3:
9269 case 5:
9270 case 7:
9271 gen_helper_mtc0_datalo(cpu_env, arg);
9272 rn = "DataLo";
9273 break;
9274 default:
9275 goto cp0_unimplemented;
9277 break;
9278 case 29:
9279 switch (sel) {
9280 case 0:
9281 case 2:
9282 case 4:
9283 case 6:
9284 gen_helper_mtc0_taghi(cpu_env, arg);
9285 rn = "TagHi";
9286 break;
9287 case 1:
9288 case 3:
9289 case 5:
9290 case 7:
9291 gen_helper_mtc0_datahi(cpu_env, arg);
9292 rn = "DataHi";
9293 break;
9294 default:
9295 rn = "invalid sel";
9296 goto cp0_unimplemented;
9298 break;
9299 case 30:
9300 switch (sel) {
9301 case 0:
9302 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9303 rn = "ErrorEPC";
9304 break;
9305 default:
9306 goto cp0_unimplemented;
9308 break;
9309 case 31:
9310 switch (sel) {
9311 case 0:
9312 /* EJTAG support */
9313 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9314 rn = "DESAVE";
9315 break;
9316 case 2:
9317 case 3:
9318 case 4:
9319 case 5:
9320 case 6:
9321 case 7:
9322 CP0_CHECK(ctx->kscrexist & (1 << sel));
9323 tcg_gen_st_tl(arg, cpu_env,
9324 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9325 rn = "KScratch";
9326 break;
9327 default:
9328 goto cp0_unimplemented;
9330 break;
9331 default:
9332 goto cp0_unimplemented;
9334 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9336 /* For simplicity assume that all writes can cause interrupts. */
9337 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9338 gen_io_end();
9339 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9340 * translated code to check for pending interrupts. */
9341 gen_save_pc(ctx->base.pc_next + 4);
9342 ctx->base.is_jmp = DISAS_EXIT;
9344 return;
9346 cp0_unimplemented:
9347 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9349 #endif /* TARGET_MIPS64 */
9351 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9352 int u, int sel, int h)
9354 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9355 TCGv t0 = tcg_temp_local_new();
9357 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9358 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9359 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9360 tcg_gen_movi_tl(t0, -1);
9361 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9362 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9363 tcg_gen_movi_tl(t0, -1);
9364 else if (u == 0) {
9365 switch (rt) {
9366 case 1:
9367 switch (sel) {
9368 case 1:
9369 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9370 break;
9371 case 2:
9372 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9373 break;
9374 default:
9375 goto die;
9376 break;
9378 break;
9379 case 2:
9380 switch (sel) {
9381 case 1:
9382 gen_helper_mftc0_tcstatus(t0, cpu_env);
9383 break;
9384 case 2:
9385 gen_helper_mftc0_tcbind(t0, cpu_env);
9386 break;
9387 case 3:
9388 gen_helper_mftc0_tcrestart(t0, cpu_env);
9389 break;
9390 case 4:
9391 gen_helper_mftc0_tchalt(t0, cpu_env);
9392 break;
9393 case 5:
9394 gen_helper_mftc0_tccontext(t0, cpu_env);
9395 break;
9396 case 6:
9397 gen_helper_mftc0_tcschedule(t0, cpu_env);
9398 break;
9399 case 7:
9400 gen_helper_mftc0_tcschefback(t0, cpu_env);
9401 break;
9402 default:
9403 gen_mfc0(ctx, t0, rt, sel);
9404 break;
9406 break;
9407 case 10:
9408 switch (sel) {
9409 case 0:
9410 gen_helper_mftc0_entryhi(t0, cpu_env);
9411 break;
9412 default:
9413 gen_mfc0(ctx, t0, rt, sel);
9414 break;
9416 case 12:
9417 switch (sel) {
9418 case 0:
9419 gen_helper_mftc0_status(t0, cpu_env);
9420 break;
9421 default:
9422 gen_mfc0(ctx, t0, rt, sel);
9423 break;
9425 case 13:
9426 switch (sel) {
9427 case 0:
9428 gen_helper_mftc0_cause(t0, cpu_env);
9429 break;
9430 default:
9431 goto die;
9432 break;
9434 break;
9435 case 14:
9436 switch (sel) {
9437 case 0:
9438 gen_helper_mftc0_epc(t0, cpu_env);
9439 break;
9440 default:
9441 goto die;
9442 break;
9444 break;
9445 case 15:
9446 switch (sel) {
9447 case 1:
9448 gen_helper_mftc0_ebase(t0, cpu_env);
9449 break;
9450 default:
9451 goto die;
9452 break;
9454 break;
9455 case 16:
9456 switch (sel) {
9457 case 0:
9458 case 1:
9459 case 2:
9460 case 3:
9461 case 4:
9462 case 5:
9463 case 6:
9464 case 7:
9465 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9466 break;
9467 default:
9468 goto die;
9469 break;
9471 break;
9472 case 23:
9473 switch (sel) {
9474 case 0:
9475 gen_helper_mftc0_debug(t0, cpu_env);
9476 break;
9477 default:
9478 gen_mfc0(ctx, t0, rt, sel);
9479 break;
9481 break;
9482 default:
9483 gen_mfc0(ctx, t0, rt, sel);
9485 } else switch (sel) {
9486 /* GPR registers. */
9487 case 0:
9488 gen_helper_1e0i(mftgpr, t0, rt);
9489 break;
9490 /* Auxiliary CPU registers */
9491 case 1:
9492 switch (rt) {
9493 case 0:
9494 gen_helper_1e0i(mftlo, t0, 0);
9495 break;
9496 case 1:
9497 gen_helper_1e0i(mfthi, t0, 0);
9498 break;
9499 case 2:
9500 gen_helper_1e0i(mftacx, t0, 0);
9501 break;
9502 case 4:
9503 gen_helper_1e0i(mftlo, t0, 1);
9504 break;
9505 case 5:
9506 gen_helper_1e0i(mfthi, t0, 1);
9507 break;
9508 case 6:
9509 gen_helper_1e0i(mftacx, t0, 1);
9510 break;
9511 case 8:
9512 gen_helper_1e0i(mftlo, t0, 2);
9513 break;
9514 case 9:
9515 gen_helper_1e0i(mfthi, t0, 2);
9516 break;
9517 case 10:
9518 gen_helper_1e0i(mftacx, t0, 2);
9519 break;
9520 case 12:
9521 gen_helper_1e0i(mftlo, t0, 3);
9522 break;
9523 case 13:
9524 gen_helper_1e0i(mfthi, t0, 3);
9525 break;
9526 case 14:
9527 gen_helper_1e0i(mftacx, t0, 3);
9528 break;
9529 case 16:
9530 gen_helper_mftdsp(t0, cpu_env);
9531 break;
9532 default:
9533 goto die;
9535 break;
9536 /* Floating point (COP1). */
9537 case 2:
9538 /* XXX: For now we support only a single FPU context. */
9539 if (h == 0) {
9540 TCGv_i32 fp0 = tcg_temp_new_i32();
9542 gen_load_fpr32(ctx, fp0, rt);
9543 tcg_gen_ext_i32_tl(t0, fp0);
9544 tcg_temp_free_i32(fp0);
9545 } else {
9546 TCGv_i32 fp0 = tcg_temp_new_i32();
9548 gen_load_fpr32h(ctx, fp0, rt);
9549 tcg_gen_ext_i32_tl(t0, fp0);
9550 tcg_temp_free_i32(fp0);
9552 break;
9553 case 3:
9554 /* XXX: For now we support only a single FPU context. */
9555 gen_helper_1e0i(cfc1, t0, rt);
9556 break;
9557 /* COP2: Not implemented. */
9558 case 4:
9559 case 5:
9560 /* fall through */
9561 default:
9562 goto die;
9564 trace_mips_translate_tr("mftr", rt, u, sel, h);
9565 gen_store_gpr(t0, rd);
9566 tcg_temp_free(t0);
9567 return;
9569 die:
9570 tcg_temp_free(t0);
9571 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9572 generate_exception_end(ctx, EXCP_RI);
9575 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9576 int u, int sel, int h)
9578 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9579 TCGv t0 = tcg_temp_local_new();
9581 gen_load_gpr(t0, rt);
9582 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9583 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9584 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9585 /* NOP */ ;
9586 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9587 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9588 /* NOP */ ;
9589 else if (u == 0) {
9590 switch (rd) {
9591 case 1:
9592 switch (sel) {
9593 case 1:
9594 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9595 break;
9596 case 2:
9597 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9598 break;
9599 default:
9600 goto die;
9601 break;
9603 break;
9604 case 2:
9605 switch (sel) {
9606 case 1:
9607 gen_helper_mttc0_tcstatus(cpu_env, t0);
9608 break;
9609 case 2:
9610 gen_helper_mttc0_tcbind(cpu_env, t0);
9611 break;
9612 case 3:
9613 gen_helper_mttc0_tcrestart(cpu_env, t0);
9614 break;
9615 case 4:
9616 gen_helper_mttc0_tchalt(cpu_env, t0);
9617 break;
9618 case 5:
9619 gen_helper_mttc0_tccontext(cpu_env, t0);
9620 break;
9621 case 6:
9622 gen_helper_mttc0_tcschedule(cpu_env, t0);
9623 break;
9624 case 7:
9625 gen_helper_mttc0_tcschefback(cpu_env, t0);
9626 break;
9627 default:
9628 gen_mtc0(ctx, t0, rd, sel);
9629 break;
9631 break;
9632 case 10:
9633 switch (sel) {
9634 case 0:
9635 gen_helper_mttc0_entryhi(cpu_env, t0);
9636 break;
9637 default:
9638 gen_mtc0(ctx, t0, rd, sel);
9639 break;
9641 case 12:
9642 switch (sel) {
9643 case 0:
9644 gen_helper_mttc0_status(cpu_env, t0);
9645 break;
9646 default:
9647 gen_mtc0(ctx, t0, rd, sel);
9648 break;
9650 case 13:
9651 switch (sel) {
9652 case 0:
9653 gen_helper_mttc0_cause(cpu_env, t0);
9654 break;
9655 default:
9656 goto die;
9657 break;
9659 break;
9660 case 15:
9661 switch (sel) {
9662 case 1:
9663 gen_helper_mttc0_ebase(cpu_env, t0);
9664 break;
9665 default:
9666 goto die;
9667 break;
9669 break;
9670 case 23:
9671 switch (sel) {
9672 case 0:
9673 gen_helper_mttc0_debug(cpu_env, t0);
9674 break;
9675 default:
9676 gen_mtc0(ctx, t0, rd, sel);
9677 break;
9679 break;
9680 default:
9681 gen_mtc0(ctx, t0, rd, sel);
9683 } else switch (sel) {
9684 /* GPR registers. */
9685 case 0:
9686 gen_helper_0e1i(mttgpr, t0, rd);
9687 break;
9688 /* Auxiliary CPU registers */
9689 case 1:
9690 switch (rd) {
9691 case 0:
9692 gen_helper_0e1i(mttlo, t0, 0);
9693 break;
9694 case 1:
9695 gen_helper_0e1i(mtthi, t0, 0);
9696 break;
9697 case 2:
9698 gen_helper_0e1i(mttacx, t0, 0);
9699 break;
9700 case 4:
9701 gen_helper_0e1i(mttlo, t0, 1);
9702 break;
9703 case 5:
9704 gen_helper_0e1i(mtthi, t0, 1);
9705 break;
9706 case 6:
9707 gen_helper_0e1i(mttacx, t0, 1);
9708 break;
9709 case 8:
9710 gen_helper_0e1i(mttlo, t0, 2);
9711 break;
9712 case 9:
9713 gen_helper_0e1i(mtthi, t0, 2);
9714 break;
9715 case 10:
9716 gen_helper_0e1i(mttacx, t0, 2);
9717 break;
9718 case 12:
9719 gen_helper_0e1i(mttlo, t0, 3);
9720 break;
9721 case 13:
9722 gen_helper_0e1i(mtthi, t0, 3);
9723 break;
9724 case 14:
9725 gen_helper_0e1i(mttacx, t0, 3);
9726 break;
9727 case 16:
9728 gen_helper_mttdsp(cpu_env, t0);
9729 break;
9730 default:
9731 goto die;
9733 break;
9734 /* Floating point (COP1). */
9735 case 2:
9736 /* XXX: For now we support only a single FPU context. */
9737 if (h == 0) {
9738 TCGv_i32 fp0 = tcg_temp_new_i32();
9740 tcg_gen_trunc_tl_i32(fp0, t0);
9741 gen_store_fpr32(ctx, fp0, rd);
9742 tcg_temp_free_i32(fp0);
9743 } else {
9744 TCGv_i32 fp0 = tcg_temp_new_i32();
9746 tcg_gen_trunc_tl_i32(fp0, t0);
9747 gen_store_fpr32h(ctx, fp0, rd);
9748 tcg_temp_free_i32(fp0);
9750 break;
9751 case 3:
9752 /* XXX: For now we support only a single FPU context. */
9754 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9756 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9757 tcg_temp_free_i32(fs_tmp);
9759 /* Stop translation as we may have changed hflags */
9760 ctx->base.is_jmp = DISAS_STOP;
9761 break;
9762 /* COP2: Not implemented. */
9763 case 4:
9764 case 5:
9765 /* fall through */
9766 default:
9767 goto die;
9769 trace_mips_translate_tr("mttr", rd, u, sel, h);
9770 tcg_temp_free(t0);
9771 return;
9773 die:
9774 tcg_temp_free(t0);
9775 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9776 generate_exception_end(ctx, EXCP_RI);
9779 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9781 const char *opn = "ldst";
9783 check_cp0_enabled(ctx);
9784 switch (opc) {
9785 case OPC_MFC0:
9786 if (rt == 0) {
9787 /* Treat as NOP. */
9788 return;
9790 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9791 opn = "mfc0";
9792 break;
9793 case OPC_MTC0:
9795 TCGv t0 = tcg_temp_new();
9797 gen_load_gpr(t0, rt);
9798 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9799 tcg_temp_free(t0);
9801 opn = "mtc0";
9802 break;
9803 #if defined(TARGET_MIPS64)
9804 case OPC_DMFC0:
9805 check_insn(ctx, ISA_MIPS3);
9806 if (rt == 0) {
9807 /* Treat as NOP. */
9808 return;
9810 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9811 opn = "dmfc0";
9812 break;
9813 case OPC_DMTC0:
9814 check_insn(ctx, ISA_MIPS3);
9816 TCGv t0 = tcg_temp_new();
9818 gen_load_gpr(t0, rt);
9819 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9820 tcg_temp_free(t0);
9822 opn = "dmtc0";
9823 break;
9824 #endif
9825 case OPC_MFHC0:
9826 check_mvh(ctx);
9827 if (rt == 0) {
9828 /* Treat as NOP. */
9829 return;
9831 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9832 opn = "mfhc0";
9833 break;
9834 case OPC_MTHC0:
9835 check_mvh(ctx);
9837 TCGv t0 = tcg_temp_new();
9838 gen_load_gpr(t0, rt);
9839 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9840 tcg_temp_free(t0);
9842 opn = "mthc0";
9843 break;
9844 case OPC_MFTR:
9845 check_cp0_enabled(ctx);
9846 if (rd == 0) {
9847 /* Treat as NOP. */
9848 return;
9850 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9851 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9852 opn = "mftr";
9853 break;
9854 case OPC_MTTR:
9855 check_cp0_enabled(ctx);
9856 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9857 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9858 opn = "mttr";
9859 break;
9860 case OPC_TLBWI:
9861 opn = "tlbwi";
9862 if (!env->tlb->helper_tlbwi)
9863 goto die;
9864 gen_helper_tlbwi(cpu_env);
9865 break;
9866 case OPC_TLBINV:
9867 opn = "tlbinv";
9868 if (ctx->ie >= 2) {
9869 if (!env->tlb->helper_tlbinv) {
9870 goto die;
9872 gen_helper_tlbinv(cpu_env);
9873 } /* treat as nop if TLBINV not supported */
9874 break;
9875 case OPC_TLBINVF:
9876 opn = "tlbinvf";
9877 if (ctx->ie >= 2) {
9878 if (!env->tlb->helper_tlbinvf) {
9879 goto die;
9881 gen_helper_tlbinvf(cpu_env);
9882 } /* treat as nop if TLBINV not supported */
9883 break;
9884 case OPC_TLBWR:
9885 opn = "tlbwr";
9886 if (!env->tlb->helper_tlbwr)
9887 goto die;
9888 gen_helper_tlbwr(cpu_env);
9889 break;
9890 case OPC_TLBP:
9891 opn = "tlbp";
9892 if (!env->tlb->helper_tlbp)
9893 goto die;
9894 gen_helper_tlbp(cpu_env);
9895 break;
9896 case OPC_TLBR:
9897 opn = "tlbr";
9898 if (!env->tlb->helper_tlbr)
9899 goto die;
9900 gen_helper_tlbr(cpu_env);
9901 break;
9902 case OPC_ERET: /* OPC_ERETNC */
9903 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9904 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9905 goto die;
9906 } else {
9907 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9908 if (ctx->opcode & (1 << bit_shift)) {
9909 /* OPC_ERETNC */
9910 opn = "eretnc";
9911 check_insn(ctx, ISA_MIPS32R5);
9912 gen_helper_eretnc(cpu_env);
9913 } else {
9914 /* OPC_ERET */
9915 opn = "eret";
9916 check_insn(ctx, ISA_MIPS2);
9917 gen_helper_eret(cpu_env);
9919 ctx->base.is_jmp = DISAS_EXIT;
9921 break;
9922 case OPC_DERET:
9923 opn = "deret";
9924 check_insn(ctx, ISA_MIPS32);
9925 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9926 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9927 goto die;
9929 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9930 MIPS_INVAL(opn);
9931 generate_exception_end(ctx, EXCP_RI);
9932 } else {
9933 gen_helper_deret(cpu_env);
9934 ctx->base.is_jmp = DISAS_EXIT;
9936 break;
9937 case OPC_WAIT:
9938 opn = "wait";
9939 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9940 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9941 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9942 goto die;
9944 /* If we get an exception, we want to restart at next instruction */
9945 ctx->base.pc_next += 4;
9946 save_cpu_state(ctx, 1);
9947 ctx->base.pc_next -= 4;
9948 gen_helper_wait(cpu_env);
9949 ctx->base.is_jmp = DISAS_NORETURN;
9950 break;
9951 default:
9952 die:
9953 MIPS_INVAL(opn);
9954 generate_exception_end(ctx, EXCP_RI);
9955 return;
9957 (void)opn; /* avoid a compiler warning */
9959 #endif /* !CONFIG_USER_ONLY */
9961 /* CP1 Branches (before delay slot) */
9962 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9963 int32_t cc, int32_t offset)
9965 target_ulong btarget;
9966 TCGv_i32 t0 = tcg_temp_new_i32();
9968 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9969 generate_exception_end(ctx, EXCP_RI);
9970 goto out;
9973 if (cc != 0)
9974 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9976 btarget = ctx->base.pc_next + 4 + offset;
9978 switch (op) {
9979 case OPC_BC1F:
9980 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9981 tcg_gen_not_i32(t0, t0);
9982 tcg_gen_andi_i32(t0, t0, 1);
9983 tcg_gen_extu_i32_tl(bcond, t0);
9984 goto not_likely;
9985 case OPC_BC1FL:
9986 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9987 tcg_gen_not_i32(t0, t0);
9988 tcg_gen_andi_i32(t0, t0, 1);
9989 tcg_gen_extu_i32_tl(bcond, t0);
9990 goto likely;
9991 case OPC_BC1T:
9992 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9993 tcg_gen_andi_i32(t0, t0, 1);
9994 tcg_gen_extu_i32_tl(bcond, t0);
9995 goto not_likely;
9996 case OPC_BC1TL:
9997 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9998 tcg_gen_andi_i32(t0, t0, 1);
9999 tcg_gen_extu_i32_tl(bcond, t0);
10000 likely:
10001 ctx->hflags |= MIPS_HFLAG_BL;
10002 break;
10003 case OPC_BC1FANY2:
10005 TCGv_i32 t1 = tcg_temp_new_i32();
10006 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10007 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10008 tcg_gen_nand_i32(t0, t0, t1);
10009 tcg_temp_free_i32(t1);
10010 tcg_gen_andi_i32(t0, t0, 1);
10011 tcg_gen_extu_i32_tl(bcond, t0);
10013 goto not_likely;
10014 case OPC_BC1TANY2:
10016 TCGv_i32 t1 = tcg_temp_new_i32();
10017 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10018 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10019 tcg_gen_or_i32(t0, t0, t1);
10020 tcg_temp_free_i32(t1);
10021 tcg_gen_andi_i32(t0, t0, 1);
10022 tcg_gen_extu_i32_tl(bcond, t0);
10024 goto not_likely;
10025 case OPC_BC1FANY4:
10027 TCGv_i32 t1 = tcg_temp_new_i32();
10028 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10029 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10030 tcg_gen_and_i32(t0, t0, t1);
10031 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10032 tcg_gen_and_i32(t0, t0, t1);
10033 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10034 tcg_gen_nand_i32(t0, t0, t1);
10035 tcg_temp_free_i32(t1);
10036 tcg_gen_andi_i32(t0, t0, 1);
10037 tcg_gen_extu_i32_tl(bcond, t0);
10039 goto not_likely;
10040 case OPC_BC1TANY4:
10042 TCGv_i32 t1 = tcg_temp_new_i32();
10043 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10044 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10045 tcg_gen_or_i32(t0, t0, t1);
10046 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10047 tcg_gen_or_i32(t0, t0, t1);
10048 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10049 tcg_gen_or_i32(t0, t0, t1);
10050 tcg_temp_free_i32(t1);
10051 tcg_gen_andi_i32(t0, t0, 1);
10052 tcg_gen_extu_i32_tl(bcond, t0);
10054 not_likely:
10055 ctx->hflags |= MIPS_HFLAG_BC;
10056 break;
10057 default:
10058 MIPS_INVAL("cp1 cond branch");
10059 generate_exception_end(ctx, EXCP_RI);
10060 goto out;
10062 ctx->btarget = btarget;
10063 ctx->hflags |= MIPS_HFLAG_BDS32;
10064 out:
10065 tcg_temp_free_i32(t0);
10068 /* R6 CP1 Branches */
10069 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10070 int32_t ft, int32_t offset,
10071 int delayslot_size)
10073 target_ulong btarget;
10074 TCGv_i64 t0 = tcg_temp_new_i64();
10076 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10077 #ifdef MIPS_DEBUG_DISAS
10078 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10079 "\n", ctx->base.pc_next);
10080 #endif
10081 generate_exception_end(ctx, EXCP_RI);
10082 goto out;
10085 gen_load_fpr64(ctx, t0, ft);
10086 tcg_gen_andi_i64(t0, t0, 1);
10088 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10090 switch (op) {
10091 case OPC_BC1EQZ:
10092 tcg_gen_xori_i64(t0, t0, 1);
10093 ctx->hflags |= MIPS_HFLAG_BC;
10094 break;
10095 case OPC_BC1NEZ:
10096 /* t0 already set */
10097 ctx->hflags |= MIPS_HFLAG_BC;
10098 break;
10099 default:
10100 MIPS_INVAL("cp1 cond branch");
10101 generate_exception_end(ctx, EXCP_RI);
10102 goto out;
10105 tcg_gen_trunc_i64_tl(bcond, t0);
10107 ctx->btarget = btarget;
10109 switch (delayslot_size) {
10110 case 2:
10111 ctx->hflags |= MIPS_HFLAG_BDS16;
10112 break;
10113 case 4:
10114 ctx->hflags |= MIPS_HFLAG_BDS32;
10115 break;
10118 out:
10119 tcg_temp_free_i64(t0);
10122 /* Coprocessor 1 (FPU) */
10124 #define FOP(func, fmt) (((fmt) << 21) | (func))
10126 enum fopcode {
10127 OPC_ADD_S = FOP(0, FMT_S),
10128 OPC_SUB_S = FOP(1, FMT_S),
10129 OPC_MUL_S = FOP(2, FMT_S),
10130 OPC_DIV_S = FOP(3, FMT_S),
10131 OPC_SQRT_S = FOP(4, FMT_S),
10132 OPC_ABS_S = FOP(5, FMT_S),
10133 OPC_MOV_S = FOP(6, FMT_S),
10134 OPC_NEG_S = FOP(7, FMT_S),
10135 OPC_ROUND_L_S = FOP(8, FMT_S),
10136 OPC_TRUNC_L_S = FOP(9, FMT_S),
10137 OPC_CEIL_L_S = FOP(10, FMT_S),
10138 OPC_FLOOR_L_S = FOP(11, FMT_S),
10139 OPC_ROUND_W_S = FOP(12, FMT_S),
10140 OPC_TRUNC_W_S = FOP(13, FMT_S),
10141 OPC_CEIL_W_S = FOP(14, FMT_S),
10142 OPC_FLOOR_W_S = FOP(15, FMT_S),
10143 OPC_SEL_S = FOP(16, FMT_S),
10144 OPC_MOVCF_S = FOP(17, FMT_S),
10145 OPC_MOVZ_S = FOP(18, FMT_S),
10146 OPC_MOVN_S = FOP(19, FMT_S),
10147 OPC_SELEQZ_S = FOP(20, FMT_S),
10148 OPC_RECIP_S = FOP(21, FMT_S),
10149 OPC_RSQRT_S = FOP(22, FMT_S),
10150 OPC_SELNEZ_S = FOP(23, FMT_S),
10151 OPC_MADDF_S = FOP(24, FMT_S),
10152 OPC_MSUBF_S = FOP(25, FMT_S),
10153 OPC_RINT_S = FOP(26, FMT_S),
10154 OPC_CLASS_S = FOP(27, FMT_S),
10155 OPC_MIN_S = FOP(28, FMT_S),
10156 OPC_RECIP2_S = FOP(28, FMT_S),
10157 OPC_MINA_S = FOP(29, FMT_S),
10158 OPC_RECIP1_S = FOP(29, FMT_S),
10159 OPC_MAX_S = FOP(30, FMT_S),
10160 OPC_RSQRT1_S = FOP(30, FMT_S),
10161 OPC_MAXA_S = FOP(31, FMT_S),
10162 OPC_RSQRT2_S = FOP(31, FMT_S),
10163 OPC_CVT_D_S = FOP(33, FMT_S),
10164 OPC_CVT_W_S = FOP(36, FMT_S),
10165 OPC_CVT_L_S = FOP(37, FMT_S),
10166 OPC_CVT_PS_S = FOP(38, FMT_S),
10167 OPC_CMP_F_S = FOP (48, FMT_S),
10168 OPC_CMP_UN_S = FOP (49, FMT_S),
10169 OPC_CMP_EQ_S = FOP (50, FMT_S),
10170 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10171 OPC_CMP_OLT_S = FOP (52, FMT_S),
10172 OPC_CMP_ULT_S = FOP (53, FMT_S),
10173 OPC_CMP_OLE_S = FOP (54, FMT_S),
10174 OPC_CMP_ULE_S = FOP (55, FMT_S),
10175 OPC_CMP_SF_S = FOP (56, FMT_S),
10176 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10177 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10178 OPC_CMP_NGL_S = FOP (59, FMT_S),
10179 OPC_CMP_LT_S = FOP (60, FMT_S),
10180 OPC_CMP_NGE_S = FOP (61, FMT_S),
10181 OPC_CMP_LE_S = FOP (62, FMT_S),
10182 OPC_CMP_NGT_S = FOP (63, FMT_S),
10184 OPC_ADD_D = FOP(0, FMT_D),
10185 OPC_SUB_D = FOP(1, FMT_D),
10186 OPC_MUL_D = FOP(2, FMT_D),
10187 OPC_DIV_D = FOP(3, FMT_D),
10188 OPC_SQRT_D = FOP(4, FMT_D),
10189 OPC_ABS_D = FOP(5, FMT_D),
10190 OPC_MOV_D = FOP(6, FMT_D),
10191 OPC_NEG_D = FOP(7, FMT_D),
10192 OPC_ROUND_L_D = FOP(8, FMT_D),
10193 OPC_TRUNC_L_D = FOP(9, FMT_D),
10194 OPC_CEIL_L_D = FOP(10, FMT_D),
10195 OPC_FLOOR_L_D = FOP(11, FMT_D),
10196 OPC_ROUND_W_D = FOP(12, FMT_D),
10197 OPC_TRUNC_W_D = FOP(13, FMT_D),
10198 OPC_CEIL_W_D = FOP(14, FMT_D),
10199 OPC_FLOOR_W_D = FOP(15, FMT_D),
10200 OPC_SEL_D = FOP(16, FMT_D),
10201 OPC_MOVCF_D = FOP(17, FMT_D),
10202 OPC_MOVZ_D = FOP(18, FMT_D),
10203 OPC_MOVN_D = FOP(19, FMT_D),
10204 OPC_SELEQZ_D = FOP(20, FMT_D),
10205 OPC_RECIP_D = FOP(21, FMT_D),
10206 OPC_RSQRT_D = FOP(22, FMT_D),
10207 OPC_SELNEZ_D = FOP(23, FMT_D),
10208 OPC_MADDF_D = FOP(24, FMT_D),
10209 OPC_MSUBF_D = FOP(25, FMT_D),
10210 OPC_RINT_D = FOP(26, FMT_D),
10211 OPC_CLASS_D = FOP(27, FMT_D),
10212 OPC_MIN_D = FOP(28, FMT_D),
10213 OPC_RECIP2_D = FOP(28, FMT_D),
10214 OPC_MINA_D = FOP(29, FMT_D),
10215 OPC_RECIP1_D = FOP(29, FMT_D),
10216 OPC_MAX_D = FOP(30, FMT_D),
10217 OPC_RSQRT1_D = FOP(30, FMT_D),
10218 OPC_MAXA_D = FOP(31, FMT_D),
10219 OPC_RSQRT2_D = FOP(31, FMT_D),
10220 OPC_CVT_S_D = FOP(32, FMT_D),
10221 OPC_CVT_W_D = FOP(36, FMT_D),
10222 OPC_CVT_L_D = FOP(37, FMT_D),
10223 OPC_CMP_F_D = FOP (48, FMT_D),
10224 OPC_CMP_UN_D = FOP (49, FMT_D),
10225 OPC_CMP_EQ_D = FOP (50, FMT_D),
10226 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10227 OPC_CMP_OLT_D = FOP (52, FMT_D),
10228 OPC_CMP_ULT_D = FOP (53, FMT_D),
10229 OPC_CMP_OLE_D = FOP (54, FMT_D),
10230 OPC_CMP_ULE_D = FOP (55, FMT_D),
10231 OPC_CMP_SF_D = FOP (56, FMT_D),
10232 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10233 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10234 OPC_CMP_NGL_D = FOP (59, FMT_D),
10235 OPC_CMP_LT_D = FOP (60, FMT_D),
10236 OPC_CMP_NGE_D = FOP (61, FMT_D),
10237 OPC_CMP_LE_D = FOP (62, FMT_D),
10238 OPC_CMP_NGT_D = FOP (63, FMT_D),
10240 OPC_CVT_S_W = FOP(32, FMT_W),
10241 OPC_CVT_D_W = FOP(33, FMT_W),
10242 OPC_CVT_S_L = FOP(32, FMT_L),
10243 OPC_CVT_D_L = FOP(33, FMT_L),
10244 OPC_CVT_PS_PW = FOP(38, FMT_W),
10246 OPC_ADD_PS = FOP(0, FMT_PS),
10247 OPC_SUB_PS = FOP(1, FMT_PS),
10248 OPC_MUL_PS = FOP(2, FMT_PS),
10249 OPC_DIV_PS = FOP(3, FMT_PS),
10250 OPC_ABS_PS = FOP(5, FMT_PS),
10251 OPC_MOV_PS = FOP(6, FMT_PS),
10252 OPC_NEG_PS = FOP(7, FMT_PS),
10253 OPC_MOVCF_PS = FOP(17, FMT_PS),
10254 OPC_MOVZ_PS = FOP(18, FMT_PS),
10255 OPC_MOVN_PS = FOP(19, FMT_PS),
10256 OPC_ADDR_PS = FOP(24, FMT_PS),
10257 OPC_MULR_PS = FOP(26, FMT_PS),
10258 OPC_RECIP2_PS = FOP(28, FMT_PS),
10259 OPC_RECIP1_PS = FOP(29, FMT_PS),
10260 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10261 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10263 OPC_CVT_S_PU = FOP(32, FMT_PS),
10264 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10265 OPC_CVT_S_PL = FOP(40, FMT_PS),
10266 OPC_PLL_PS = FOP(44, FMT_PS),
10267 OPC_PLU_PS = FOP(45, FMT_PS),
10268 OPC_PUL_PS = FOP(46, FMT_PS),
10269 OPC_PUU_PS = FOP(47, FMT_PS),
10270 OPC_CMP_F_PS = FOP (48, FMT_PS),
10271 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10272 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10273 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10274 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10275 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10276 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10277 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10278 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10279 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10280 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10281 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10282 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10283 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10284 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10285 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10288 enum r6_f_cmp_op {
10289 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10290 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10291 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10292 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10293 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10294 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10295 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10296 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10297 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10298 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10299 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10300 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10301 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10302 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10303 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10304 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10305 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10306 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10307 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10308 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10309 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10310 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10312 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10313 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10314 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10315 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10316 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10317 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10318 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10319 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10320 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10321 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10322 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10323 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10324 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10325 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10326 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10327 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10328 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10329 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10330 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10331 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10332 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10333 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10335 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10337 TCGv t0 = tcg_temp_new();
10339 switch (opc) {
10340 case OPC_MFC1:
10342 TCGv_i32 fp0 = tcg_temp_new_i32();
10344 gen_load_fpr32(ctx, fp0, fs);
10345 tcg_gen_ext_i32_tl(t0, fp0);
10346 tcg_temp_free_i32(fp0);
10348 gen_store_gpr(t0, rt);
10349 break;
10350 case OPC_MTC1:
10351 gen_load_gpr(t0, rt);
10353 TCGv_i32 fp0 = tcg_temp_new_i32();
10355 tcg_gen_trunc_tl_i32(fp0, t0);
10356 gen_store_fpr32(ctx, fp0, fs);
10357 tcg_temp_free_i32(fp0);
10359 break;
10360 case OPC_CFC1:
10361 gen_helper_1e0i(cfc1, t0, fs);
10362 gen_store_gpr(t0, rt);
10363 break;
10364 case OPC_CTC1:
10365 gen_load_gpr(t0, rt);
10366 save_cpu_state(ctx, 0);
10368 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10370 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10371 tcg_temp_free_i32(fs_tmp);
10373 /* Stop translation as we may have changed hflags */
10374 ctx->base.is_jmp = DISAS_STOP;
10375 break;
10376 #if defined(TARGET_MIPS64)
10377 case OPC_DMFC1:
10378 gen_load_fpr64(ctx, t0, fs);
10379 gen_store_gpr(t0, rt);
10380 break;
10381 case OPC_DMTC1:
10382 gen_load_gpr(t0, rt);
10383 gen_store_fpr64(ctx, t0, fs);
10384 break;
10385 #endif
10386 case OPC_MFHC1:
10388 TCGv_i32 fp0 = tcg_temp_new_i32();
10390 gen_load_fpr32h(ctx, fp0, fs);
10391 tcg_gen_ext_i32_tl(t0, fp0);
10392 tcg_temp_free_i32(fp0);
10394 gen_store_gpr(t0, rt);
10395 break;
10396 case OPC_MTHC1:
10397 gen_load_gpr(t0, rt);
10399 TCGv_i32 fp0 = tcg_temp_new_i32();
10401 tcg_gen_trunc_tl_i32(fp0, t0);
10402 gen_store_fpr32h(ctx, fp0, fs);
10403 tcg_temp_free_i32(fp0);
10405 break;
10406 default:
10407 MIPS_INVAL("cp1 move");
10408 generate_exception_end(ctx, EXCP_RI);
10409 goto out;
10412 out:
10413 tcg_temp_free(t0);
10416 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10418 TCGLabel *l1;
10419 TCGCond cond;
10420 TCGv_i32 t0;
10422 if (rd == 0) {
10423 /* Treat as NOP. */
10424 return;
10427 if (tf)
10428 cond = TCG_COND_EQ;
10429 else
10430 cond = TCG_COND_NE;
10432 l1 = gen_new_label();
10433 t0 = tcg_temp_new_i32();
10434 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10435 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10436 tcg_temp_free_i32(t0);
10437 if (rs == 0) {
10438 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10439 } else {
10440 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10442 gen_set_label(l1);
10445 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10446 int tf)
10448 int cond;
10449 TCGv_i32 t0 = tcg_temp_new_i32();
10450 TCGLabel *l1 = gen_new_label();
10452 if (tf)
10453 cond = TCG_COND_EQ;
10454 else
10455 cond = TCG_COND_NE;
10457 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10458 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10459 gen_load_fpr32(ctx, t0, fs);
10460 gen_store_fpr32(ctx, t0, fd);
10461 gen_set_label(l1);
10462 tcg_temp_free_i32(t0);
10465 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10467 int cond;
10468 TCGv_i32 t0 = tcg_temp_new_i32();
10469 TCGv_i64 fp0;
10470 TCGLabel *l1 = gen_new_label();
10472 if (tf)
10473 cond = TCG_COND_EQ;
10474 else
10475 cond = TCG_COND_NE;
10477 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10478 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10479 tcg_temp_free_i32(t0);
10480 fp0 = tcg_temp_new_i64();
10481 gen_load_fpr64(ctx, fp0, fs);
10482 gen_store_fpr64(ctx, fp0, fd);
10483 tcg_temp_free_i64(fp0);
10484 gen_set_label(l1);
10487 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10488 int cc, int tf)
10490 int cond;
10491 TCGv_i32 t0 = tcg_temp_new_i32();
10492 TCGLabel *l1 = gen_new_label();
10493 TCGLabel *l2 = gen_new_label();
10495 if (tf)
10496 cond = TCG_COND_EQ;
10497 else
10498 cond = TCG_COND_NE;
10500 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10501 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10502 gen_load_fpr32(ctx, t0, fs);
10503 gen_store_fpr32(ctx, t0, fd);
10504 gen_set_label(l1);
10506 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10507 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10508 gen_load_fpr32h(ctx, t0, fs);
10509 gen_store_fpr32h(ctx, t0, fd);
10510 tcg_temp_free_i32(t0);
10511 gen_set_label(l2);
10514 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10515 int fs)
10517 TCGv_i32 t1 = tcg_const_i32(0);
10518 TCGv_i32 fp0 = tcg_temp_new_i32();
10519 TCGv_i32 fp1 = tcg_temp_new_i32();
10520 TCGv_i32 fp2 = tcg_temp_new_i32();
10521 gen_load_fpr32(ctx, fp0, fd);
10522 gen_load_fpr32(ctx, fp1, ft);
10523 gen_load_fpr32(ctx, fp2, fs);
10525 switch (op1) {
10526 case OPC_SEL_S:
10527 tcg_gen_andi_i32(fp0, fp0, 1);
10528 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10529 break;
10530 case OPC_SELEQZ_S:
10531 tcg_gen_andi_i32(fp1, fp1, 1);
10532 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10533 break;
10534 case OPC_SELNEZ_S:
10535 tcg_gen_andi_i32(fp1, fp1, 1);
10536 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10537 break;
10538 default:
10539 MIPS_INVAL("gen_sel_s");
10540 generate_exception_end(ctx, EXCP_RI);
10541 break;
10544 gen_store_fpr32(ctx, fp0, fd);
10545 tcg_temp_free_i32(fp2);
10546 tcg_temp_free_i32(fp1);
10547 tcg_temp_free_i32(fp0);
10548 tcg_temp_free_i32(t1);
10551 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10552 int fs)
10554 TCGv_i64 t1 = tcg_const_i64(0);
10555 TCGv_i64 fp0 = tcg_temp_new_i64();
10556 TCGv_i64 fp1 = tcg_temp_new_i64();
10557 TCGv_i64 fp2 = tcg_temp_new_i64();
10558 gen_load_fpr64(ctx, fp0, fd);
10559 gen_load_fpr64(ctx, fp1, ft);
10560 gen_load_fpr64(ctx, fp2, fs);
10562 switch (op1) {
10563 case OPC_SEL_D:
10564 tcg_gen_andi_i64(fp0, fp0, 1);
10565 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10566 break;
10567 case OPC_SELEQZ_D:
10568 tcg_gen_andi_i64(fp1, fp1, 1);
10569 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10570 break;
10571 case OPC_SELNEZ_D:
10572 tcg_gen_andi_i64(fp1, fp1, 1);
10573 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10574 break;
10575 default:
10576 MIPS_INVAL("gen_sel_d");
10577 generate_exception_end(ctx, EXCP_RI);
10578 break;
10581 gen_store_fpr64(ctx, fp0, fd);
10582 tcg_temp_free_i64(fp2);
10583 tcg_temp_free_i64(fp1);
10584 tcg_temp_free_i64(fp0);
10585 tcg_temp_free_i64(t1);
10588 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10589 int ft, int fs, int fd, int cc)
10591 uint32_t func = ctx->opcode & 0x3f;
10592 switch (op1) {
10593 case OPC_ADD_S:
10595 TCGv_i32 fp0 = tcg_temp_new_i32();
10596 TCGv_i32 fp1 = tcg_temp_new_i32();
10598 gen_load_fpr32(ctx, fp0, fs);
10599 gen_load_fpr32(ctx, fp1, ft);
10600 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10601 tcg_temp_free_i32(fp1);
10602 gen_store_fpr32(ctx, fp0, fd);
10603 tcg_temp_free_i32(fp0);
10605 break;
10606 case OPC_SUB_S:
10608 TCGv_i32 fp0 = tcg_temp_new_i32();
10609 TCGv_i32 fp1 = tcg_temp_new_i32();
10611 gen_load_fpr32(ctx, fp0, fs);
10612 gen_load_fpr32(ctx, fp1, ft);
10613 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10614 tcg_temp_free_i32(fp1);
10615 gen_store_fpr32(ctx, fp0, fd);
10616 tcg_temp_free_i32(fp0);
10618 break;
10619 case OPC_MUL_S:
10621 TCGv_i32 fp0 = tcg_temp_new_i32();
10622 TCGv_i32 fp1 = tcg_temp_new_i32();
10624 gen_load_fpr32(ctx, fp0, fs);
10625 gen_load_fpr32(ctx, fp1, ft);
10626 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10627 tcg_temp_free_i32(fp1);
10628 gen_store_fpr32(ctx, fp0, fd);
10629 tcg_temp_free_i32(fp0);
10631 break;
10632 case OPC_DIV_S:
10634 TCGv_i32 fp0 = tcg_temp_new_i32();
10635 TCGv_i32 fp1 = tcg_temp_new_i32();
10637 gen_load_fpr32(ctx, fp0, fs);
10638 gen_load_fpr32(ctx, fp1, ft);
10639 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10640 tcg_temp_free_i32(fp1);
10641 gen_store_fpr32(ctx, fp0, fd);
10642 tcg_temp_free_i32(fp0);
10644 break;
10645 case OPC_SQRT_S:
10647 TCGv_i32 fp0 = tcg_temp_new_i32();
10649 gen_load_fpr32(ctx, fp0, fs);
10650 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10651 gen_store_fpr32(ctx, fp0, fd);
10652 tcg_temp_free_i32(fp0);
10654 break;
10655 case OPC_ABS_S:
10657 TCGv_i32 fp0 = tcg_temp_new_i32();
10659 gen_load_fpr32(ctx, fp0, fs);
10660 if (ctx->abs2008) {
10661 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10662 } else {
10663 gen_helper_float_abs_s(fp0, fp0);
10665 gen_store_fpr32(ctx, fp0, fd);
10666 tcg_temp_free_i32(fp0);
10668 break;
10669 case OPC_MOV_S:
10671 TCGv_i32 fp0 = tcg_temp_new_i32();
10673 gen_load_fpr32(ctx, fp0, fs);
10674 gen_store_fpr32(ctx, fp0, fd);
10675 tcg_temp_free_i32(fp0);
10677 break;
10678 case OPC_NEG_S:
10680 TCGv_i32 fp0 = tcg_temp_new_i32();
10682 gen_load_fpr32(ctx, fp0, fs);
10683 if (ctx->abs2008) {
10684 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10685 } else {
10686 gen_helper_float_chs_s(fp0, fp0);
10688 gen_store_fpr32(ctx, fp0, fd);
10689 tcg_temp_free_i32(fp0);
10691 break;
10692 case OPC_ROUND_L_S:
10693 check_cp1_64bitmode(ctx);
10695 TCGv_i32 fp32 = tcg_temp_new_i32();
10696 TCGv_i64 fp64 = tcg_temp_new_i64();
10698 gen_load_fpr32(ctx, fp32, fs);
10699 if (ctx->nan2008) {
10700 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10701 } else {
10702 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10704 tcg_temp_free_i32(fp32);
10705 gen_store_fpr64(ctx, fp64, fd);
10706 tcg_temp_free_i64(fp64);
10708 break;
10709 case OPC_TRUNC_L_S:
10710 check_cp1_64bitmode(ctx);
10712 TCGv_i32 fp32 = tcg_temp_new_i32();
10713 TCGv_i64 fp64 = tcg_temp_new_i64();
10715 gen_load_fpr32(ctx, fp32, fs);
10716 if (ctx->nan2008) {
10717 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10718 } else {
10719 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10721 tcg_temp_free_i32(fp32);
10722 gen_store_fpr64(ctx, fp64, fd);
10723 tcg_temp_free_i64(fp64);
10725 break;
10726 case OPC_CEIL_L_S:
10727 check_cp1_64bitmode(ctx);
10729 TCGv_i32 fp32 = tcg_temp_new_i32();
10730 TCGv_i64 fp64 = tcg_temp_new_i64();
10732 gen_load_fpr32(ctx, fp32, fs);
10733 if (ctx->nan2008) {
10734 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10735 } else {
10736 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10738 tcg_temp_free_i32(fp32);
10739 gen_store_fpr64(ctx, fp64, fd);
10740 tcg_temp_free_i64(fp64);
10742 break;
10743 case OPC_FLOOR_L_S:
10744 check_cp1_64bitmode(ctx);
10746 TCGv_i32 fp32 = tcg_temp_new_i32();
10747 TCGv_i64 fp64 = tcg_temp_new_i64();
10749 gen_load_fpr32(ctx, fp32, fs);
10750 if (ctx->nan2008) {
10751 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10752 } else {
10753 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10755 tcg_temp_free_i32(fp32);
10756 gen_store_fpr64(ctx, fp64, fd);
10757 tcg_temp_free_i64(fp64);
10759 break;
10760 case OPC_ROUND_W_S:
10762 TCGv_i32 fp0 = tcg_temp_new_i32();
10764 gen_load_fpr32(ctx, fp0, fs);
10765 if (ctx->nan2008) {
10766 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10767 } else {
10768 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10770 gen_store_fpr32(ctx, fp0, fd);
10771 tcg_temp_free_i32(fp0);
10773 break;
10774 case OPC_TRUNC_W_S:
10776 TCGv_i32 fp0 = tcg_temp_new_i32();
10778 gen_load_fpr32(ctx, fp0, fs);
10779 if (ctx->nan2008) {
10780 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10781 } else {
10782 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10784 gen_store_fpr32(ctx, fp0, fd);
10785 tcg_temp_free_i32(fp0);
10787 break;
10788 case OPC_CEIL_W_S:
10790 TCGv_i32 fp0 = tcg_temp_new_i32();
10792 gen_load_fpr32(ctx, fp0, fs);
10793 if (ctx->nan2008) {
10794 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10795 } else {
10796 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10798 gen_store_fpr32(ctx, fp0, fd);
10799 tcg_temp_free_i32(fp0);
10801 break;
10802 case OPC_FLOOR_W_S:
10804 TCGv_i32 fp0 = tcg_temp_new_i32();
10806 gen_load_fpr32(ctx, fp0, fs);
10807 if (ctx->nan2008) {
10808 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10809 } else {
10810 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10812 gen_store_fpr32(ctx, fp0, fd);
10813 tcg_temp_free_i32(fp0);
10815 break;
10816 case OPC_SEL_S:
10817 check_insn(ctx, ISA_MIPS32R6);
10818 gen_sel_s(ctx, op1, fd, ft, fs);
10819 break;
10820 case OPC_SELEQZ_S:
10821 check_insn(ctx, ISA_MIPS32R6);
10822 gen_sel_s(ctx, op1, fd, ft, fs);
10823 break;
10824 case OPC_SELNEZ_S:
10825 check_insn(ctx, ISA_MIPS32R6);
10826 gen_sel_s(ctx, op1, fd, ft, fs);
10827 break;
10828 case OPC_MOVCF_S:
10829 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10830 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10831 break;
10832 case OPC_MOVZ_S:
10833 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10835 TCGLabel *l1 = gen_new_label();
10836 TCGv_i32 fp0;
10838 if (ft != 0) {
10839 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10841 fp0 = tcg_temp_new_i32();
10842 gen_load_fpr32(ctx, fp0, fs);
10843 gen_store_fpr32(ctx, fp0, fd);
10844 tcg_temp_free_i32(fp0);
10845 gen_set_label(l1);
10847 break;
10848 case OPC_MOVN_S:
10849 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10851 TCGLabel *l1 = gen_new_label();
10852 TCGv_i32 fp0;
10854 if (ft != 0) {
10855 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10856 fp0 = tcg_temp_new_i32();
10857 gen_load_fpr32(ctx, fp0, fs);
10858 gen_store_fpr32(ctx, fp0, fd);
10859 tcg_temp_free_i32(fp0);
10860 gen_set_label(l1);
10863 break;
10864 case OPC_RECIP_S:
10866 TCGv_i32 fp0 = tcg_temp_new_i32();
10868 gen_load_fpr32(ctx, fp0, fs);
10869 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10870 gen_store_fpr32(ctx, fp0, fd);
10871 tcg_temp_free_i32(fp0);
10873 break;
10874 case OPC_RSQRT_S:
10876 TCGv_i32 fp0 = tcg_temp_new_i32();
10878 gen_load_fpr32(ctx, fp0, fs);
10879 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10880 gen_store_fpr32(ctx, fp0, fd);
10881 tcg_temp_free_i32(fp0);
10883 break;
10884 case OPC_MADDF_S:
10885 check_insn(ctx, ISA_MIPS32R6);
10887 TCGv_i32 fp0 = tcg_temp_new_i32();
10888 TCGv_i32 fp1 = tcg_temp_new_i32();
10889 TCGv_i32 fp2 = tcg_temp_new_i32();
10890 gen_load_fpr32(ctx, fp0, fs);
10891 gen_load_fpr32(ctx, fp1, ft);
10892 gen_load_fpr32(ctx, fp2, fd);
10893 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10894 gen_store_fpr32(ctx, fp2, fd);
10895 tcg_temp_free_i32(fp2);
10896 tcg_temp_free_i32(fp1);
10897 tcg_temp_free_i32(fp0);
10899 break;
10900 case OPC_MSUBF_S:
10901 check_insn(ctx, ISA_MIPS32R6);
10903 TCGv_i32 fp0 = tcg_temp_new_i32();
10904 TCGv_i32 fp1 = tcg_temp_new_i32();
10905 TCGv_i32 fp2 = tcg_temp_new_i32();
10906 gen_load_fpr32(ctx, fp0, fs);
10907 gen_load_fpr32(ctx, fp1, ft);
10908 gen_load_fpr32(ctx, fp2, fd);
10909 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10910 gen_store_fpr32(ctx, fp2, fd);
10911 tcg_temp_free_i32(fp2);
10912 tcg_temp_free_i32(fp1);
10913 tcg_temp_free_i32(fp0);
10915 break;
10916 case OPC_RINT_S:
10917 check_insn(ctx, ISA_MIPS32R6);
10919 TCGv_i32 fp0 = tcg_temp_new_i32();
10920 gen_load_fpr32(ctx, fp0, fs);
10921 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10922 gen_store_fpr32(ctx, fp0, fd);
10923 tcg_temp_free_i32(fp0);
10925 break;
10926 case OPC_CLASS_S:
10927 check_insn(ctx, ISA_MIPS32R6);
10929 TCGv_i32 fp0 = tcg_temp_new_i32();
10930 gen_load_fpr32(ctx, fp0, fs);
10931 gen_helper_float_class_s(fp0, cpu_env, fp0);
10932 gen_store_fpr32(ctx, fp0, fd);
10933 tcg_temp_free_i32(fp0);
10935 break;
10936 case OPC_MIN_S: /* OPC_RECIP2_S */
10937 if (ctx->insn_flags & ISA_MIPS32R6) {
10938 /* OPC_MIN_S */
10939 TCGv_i32 fp0 = tcg_temp_new_i32();
10940 TCGv_i32 fp1 = tcg_temp_new_i32();
10941 TCGv_i32 fp2 = tcg_temp_new_i32();
10942 gen_load_fpr32(ctx, fp0, fs);
10943 gen_load_fpr32(ctx, fp1, ft);
10944 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10945 gen_store_fpr32(ctx, fp2, fd);
10946 tcg_temp_free_i32(fp2);
10947 tcg_temp_free_i32(fp1);
10948 tcg_temp_free_i32(fp0);
10949 } else {
10950 /* OPC_RECIP2_S */
10951 check_cp1_64bitmode(ctx);
10953 TCGv_i32 fp0 = tcg_temp_new_i32();
10954 TCGv_i32 fp1 = tcg_temp_new_i32();
10956 gen_load_fpr32(ctx, fp0, fs);
10957 gen_load_fpr32(ctx, fp1, ft);
10958 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10959 tcg_temp_free_i32(fp1);
10960 gen_store_fpr32(ctx, fp0, fd);
10961 tcg_temp_free_i32(fp0);
10964 break;
10965 case OPC_MINA_S: /* OPC_RECIP1_S */
10966 if (ctx->insn_flags & ISA_MIPS32R6) {
10967 /* OPC_MINA_S */
10968 TCGv_i32 fp0 = tcg_temp_new_i32();
10969 TCGv_i32 fp1 = tcg_temp_new_i32();
10970 TCGv_i32 fp2 = tcg_temp_new_i32();
10971 gen_load_fpr32(ctx, fp0, fs);
10972 gen_load_fpr32(ctx, fp1, ft);
10973 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10974 gen_store_fpr32(ctx, fp2, fd);
10975 tcg_temp_free_i32(fp2);
10976 tcg_temp_free_i32(fp1);
10977 tcg_temp_free_i32(fp0);
10978 } else {
10979 /* OPC_RECIP1_S */
10980 check_cp1_64bitmode(ctx);
10982 TCGv_i32 fp0 = tcg_temp_new_i32();
10984 gen_load_fpr32(ctx, fp0, fs);
10985 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10986 gen_store_fpr32(ctx, fp0, fd);
10987 tcg_temp_free_i32(fp0);
10990 break;
10991 case OPC_MAX_S: /* OPC_RSQRT1_S */
10992 if (ctx->insn_flags & ISA_MIPS32R6) {
10993 /* OPC_MAX_S */
10994 TCGv_i32 fp0 = tcg_temp_new_i32();
10995 TCGv_i32 fp1 = tcg_temp_new_i32();
10996 gen_load_fpr32(ctx, fp0, fs);
10997 gen_load_fpr32(ctx, fp1, ft);
10998 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10999 gen_store_fpr32(ctx, fp1, fd);
11000 tcg_temp_free_i32(fp1);
11001 tcg_temp_free_i32(fp0);
11002 } else {
11003 /* OPC_RSQRT1_S */
11004 check_cp1_64bitmode(ctx);
11006 TCGv_i32 fp0 = tcg_temp_new_i32();
11008 gen_load_fpr32(ctx, fp0, fs);
11009 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11010 gen_store_fpr32(ctx, fp0, fd);
11011 tcg_temp_free_i32(fp0);
11014 break;
11015 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11016 if (ctx->insn_flags & ISA_MIPS32R6) {
11017 /* OPC_MAXA_S */
11018 TCGv_i32 fp0 = tcg_temp_new_i32();
11019 TCGv_i32 fp1 = tcg_temp_new_i32();
11020 gen_load_fpr32(ctx, fp0, fs);
11021 gen_load_fpr32(ctx, fp1, ft);
11022 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11023 gen_store_fpr32(ctx, fp1, fd);
11024 tcg_temp_free_i32(fp1);
11025 tcg_temp_free_i32(fp0);
11026 } else {
11027 /* OPC_RSQRT2_S */
11028 check_cp1_64bitmode(ctx);
11030 TCGv_i32 fp0 = tcg_temp_new_i32();
11031 TCGv_i32 fp1 = tcg_temp_new_i32();
11033 gen_load_fpr32(ctx, fp0, fs);
11034 gen_load_fpr32(ctx, fp1, ft);
11035 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11036 tcg_temp_free_i32(fp1);
11037 gen_store_fpr32(ctx, fp0, fd);
11038 tcg_temp_free_i32(fp0);
11041 break;
11042 case OPC_CVT_D_S:
11043 check_cp1_registers(ctx, fd);
11045 TCGv_i32 fp32 = tcg_temp_new_i32();
11046 TCGv_i64 fp64 = tcg_temp_new_i64();
11048 gen_load_fpr32(ctx, fp32, fs);
11049 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11050 tcg_temp_free_i32(fp32);
11051 gen_store_fpr64(ctx, fp64, fd);
11052 tcg_temp_free_i64(fp64);
11054 break;
11055 case OPC_CVT_W_S:
11057 TCGv_i32 fp0 = tcg_temp_new_i32();
11059 gen_load_fpr32(ctx, fp0, fs);
11060 if (ctx->nan2008) {
11061 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11062 } else {
11063 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11065 gen_store_fpr32(ctx, fp0, fd);
11066 tcg_temp_free_i32(fp0);
11068 break;
11069 case OPC_CVT_L_S:
11070 check_cp1_64bitmode(ctx);
11072 TCGv_i32 fp32 = tcg_temp_new_i32();
11073 TCGv_i64 fp64 = tcg_temp_new_i64();
11075 gen_load_fpr32(ctx, fp32, fs);
11076 if (ctx->nan2008) {
11077 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11078 } else {
11079 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11081 tcg_temp_free_i32(fp32);
11082 gen_store_fpr64(ctx, fp64, fd);
11083 tcg_temp_free_i64(fp64);
11085 break;
11086 case OPC_CVT_PS_S:
11087 check_ps(ctx);
11089 TCGv_i64 fp64 = tcg_temp_new_i64();
11090 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11091 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11093 gen_load_fpr32(ctx, fp32_0, fs);
11094 gen_load_fpr32(ctx, fp32_1, ft);
11095 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11096 tcg_temp_free_i32(fp32_1);
11097 tcg_temp_free_i32(fp32_0);
11098 gen_store_fpr64(ctx, fp64, fd);
11099 tcg_temp_free_i64(fp64);
11101 break;
11102 case OPC_CMP_F_S:
11103 case OPC_CMP_UN_S:
11104 case OPC_CMP_EQ_S:
11105 case OPC_CMP_UEQ_S:
11106 case OPC_CMP_OLT_S:
11107 case OPC_CMP_ULT_S:
11108 case OPC_CMP_OLE_S:
11109 case OPC_CMP_ULE_S:
11110 case OPC_CMP_SF_S:
11111 case OPC_CMP_NGLE_S:
11112 case OPC_CMP_SEQ_S:
11113 case OPC_CMP_NGL_S:
11114 case OPC_CMP_LT_S:
11115 case OPC_CMP_NGE_S:
11116 case OPC_CMP_LE_S:
11117 case OPC_CMP_NGT_S:
11118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11119 if (ctx->opcode & (1 << 6)) {
11120 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11121 } else {
11122 gen_cmp_s(ctx, func-48, ft, fs, cc);
11124 break;
11125 case OPC_ADD_D:
11126 check_cp1_registers(ctx, fs | ft | fd);
11128 TCGv_i64 fp0 = tcg_temp_new_i64();
11129 TCGv_i64 fp1 = tcg_temp_new_i64();
11131 gen_load_fpr64(ctx, fp0, fs);
11132 gen_load_fpr64(ctx, fp1, ft);
11133 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11134 tcg_temp_free_i64(fp1);
11135 gen_store_fpr64(ctx, fp0, fd);
11136 tcg_temp_free_i64(fp0);
11138 break;
11139 case OPC_SUB_D:
11140 check_cp1_registers(ctx, fs | ft | fd);
11142 TCGv_i64 fp0 = tcg_temp_new_i64();
11143 TCGv_i64 fp1 = tcg_temp_new_i64();
11145 gen_load_fpr64(ctx, fp0, fs);
11146 gen_load_fpr64(ctx, fp1, ft);
11147 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11148 tcg_temp_free_i64(fp1);
11149 gen_store_fpr64(ctx, fp0, fd);
11150 tcg_temp_free_i64(fp0);
11152 break;
11153 case OPC_MUL_D:
11154 check_cp1_registers(ctx, fs | ft | fd);
11156 TCGv_i64 fp0 = tcg_temp_new_i64();
11157 TCGv_i64 fp1 = tcg_temp_new_i64();
11159 gen_load_fpr64(ctx, fp0, fs);
11160 gen_load_fpr64(ctx, fp1, ft);
11161 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11162 tcg_temp_free_i64(fp1);
11163 gen_store_fpr64(ctx, fp0, fd);
11164 tcg_temp_free_i64(fp0);
11166 break;
11167 case OPC_DIV_D:
11168 check_cp1_registers(ctx, fs | ft | fd);
11170 TCGv_i64 fp0 = tcg_temp_new_i64();
11171 TCGv_i64 fp1 = tcg_temp_new_i64();
11173 gen_load_fpr64(ctx, fp0, fs);
11174 gen_load_fpr64(ctx, fp1, ft);
11175 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11176 tcg_temp_free_i64(fp1);
11177 gen_store_fpr64(ctx, fp0, fd);
11178 tcg_temp_free_i64(fp0);
11180 break;
11181 case OPC_SQRT_D:
11182 check_cp1_registers(ctx, fs | fd);
11184 TCGv_i64 fp0 = tcg_temp_new_i64();
11186 gen_load_fpr64(ctx, fp0, fs);
11187 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11188 gen_store_fpr64(ctx, fp0, fd);
11189 tcg_temp_free_i64(fp0);
11191 break;
11192 case OPC_ABS_D:
11193 check_cp1_registers(ctx, fs | fd);
11195 TCGv_i64 fp0 = tcg_temp_new_i64();
11197 gen_load_fpr64(ctx, fp0, fs);
11198 if (ctx->abs2008) {
11199 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11200 } else {
11201 gen_helper_float_abs_d(fp0, fp0);
11203 gen_store_fpr64(ctx, fp0, fd);
11204 tcg_temp_free_i64(fp0);
11206 break;
11207 case OPC_MOV_D:
11208 check_cp1_registers(ctx, fs | fd);
11210 TCGv_i64 fp0 = tcg_temp_new_i64();
11212 gen_load_fpr64(ctx, fp0, fs);
11213 gen_store_fpr64(ctx, fp0, fd);
11214 tcg_temp_free_i64(fp0);
11216 break;
11217 case OPC_NEG_D:
11218 check_cp1_registers(ctx, fs | fd);
11220 TCGv_i64 fp0 = tcg_temp_new_i64();
11222 gen_load_fpr64(ctx, fp0, fs);
11223 if (ctx->abs2008) {
11224 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11225 } else {
11226 gen_helper_float_chs_d(fp0, fp0);
11228 gen_store_fpr64(ctx, fp0, fd);
11229 tcg_temp_free_i64(fp0);
11231 break;
11232 case OPC_ROUND_L_D:
11233 check_cp1_64bitmode(ctx);
11235 TCGv_i64 fp0 = tcg_temp_new_i64();
11237 gen_load_fpr64(ctx, fp0, fs);
11238 if (ctx->nan2008) {
11239 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11240 } else {
11241 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11243 gen_store_fpr64(ctx, fp0, fd);
11244 tcg_temp_free_i64(fp0);
11246 break;
11247 case OPC_TRUNC_L_D:
11248 check_cp1_64bitmode(ctx);
11250 TCGv_i64 fp0 = tcg_temp_new_i64();
11252 gen_load_fpr64(ctx, fp0, fs);
11253 if (ctx->nan2008) {
11254 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11255 } else {
11256 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11258 gen_store_fpr64(ctx, fp0, fd);
11259 tcg_temp_free_i64(fp0);
11261 break;
11262 case OPC_CEIL_L_D:
11263 check_cp1_64bitmode(ctx);
11265 TCGv_i64 fp0 = tcg_temp_new_i64();
11267 gen_load_fpr64(ctx, fp0, fs);
11268 if (ctx->nan2008) {
11269 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11270 } else {
11271 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11273 gen_store_fpr64(ctx, fp0, fd);
11274 tcg_temp_free_i64(fp0);
11276 break;
11277 case OPC_FLOOR_L_D:
11278 check_cp1_64bitmode(ctx);
11280 TCGv_i64 fp0 = tcg_temp_new_i64();
11282 gen_load_fpr64(ctx, fp0, fs);
11283 if (ctx->nan2008) {
11284 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11285 } else {
11286 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11288 gen_store_fpr64(ctx, fp0, fd);
11289 tcg_temp_free_i64(fp0);
11291 break;
11292 case OPC_ROUND_W_D:
11293 check_cp1_registers(ctx, fs);
11295 TCGv_i32 fp32 = tcg_temp_new_i32();
11296 TCGv_i64 fp64 = tcg_temp_new_i64();
11298 gen_load_fpr64(ctx, fp64, fs);
11299 if (ctx->nan2008) {
11300 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11301 } else {
11302 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11304 tcg_temp_free_i64(fp64);
11305 gen_store_fpr32(ctx, fp32, fd);
11306 tcg_temp_free_i32(fp32);
11308 break;
11309 case OPC_TRUNC_W_D:
11310 check_cp1_registers(ctx, fs);
11312 TCGv_i32 fp32 = tcg_temp_new_i32();
11313 TCGv_i64 fp64 = tcg_temp_new_i64();
11315 gen_load_fpr64(ctx, fp64, fs);
11316 if (ctx->nan2008) {
11317 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11318 } else {
11319 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11321 tcg_temp_free_i64(fp64);
11322 gen_store_fpr32(ctx, fp32, fd);
11323 tcg_temp_free_i32(fp32);
11325 break;
11326 case OPC_CEIL_W_D:
11327 check_cp1_registers(ctx, fs);
11329 TCGv_i32 fp32 = tcg_temp_new_i32();
11330 TCGv_i64 fp64 = tcg_temp_new_i64();
11332 gen_load_fpr64(ctx, fp64, fs);
11333 if (ctx->nan2008) {
11334 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11335 } else {
11336 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11338 tcg_temp_free_i64(fp64);
11339 gen_store_fpr32(ctx, fp32, fd);
11340 tcg_temp_free_i32(fp32);
11342 break;
11343 case OPC_FLOOR_W_D:
11344 check_cp1_registers(ctx, fs);
11346 TCGv_i32 fp32 = tcg_temp_new_i32();
11347 TCGv_i64 fp64 = tcg_temp_new_i64();
11349 gen_load_fpr64(ctx, fp64, fs);
11350 if (ctx->nan2008) {
11351 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11352 } else {
11353 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11355 tcg_temp_free_i64(fp64);
11356 gen_store_fpr32(ctx, fp32, fd);
11357 tcg_temp_free_i32(fp32);
11359 break;
11360 case OPC_SEL_D:
11361 check_insn(ctx, ISA_MIPS32R6);
11362 gen_sel_d(ctx, op1, fd, ft, fs);
11363 break;
11364 case OPC_SELEQZ_D:
11365 check_insn(ctx, ISA_MIPS32R6);
11366 gen_sel_d(ctx, op1, fd, ft, fs);
11367 break;
11368 case OPC_SELNEZ_D:
11369 check_insn(ctx, ISA_MIPS32R6);
11370 gen_sel_d(ctx, op1, fd, ft, fs);
11371 break;
11372 case OPC_MOVCF_D:
11373 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11374 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11375 break;
11376 case OPC_MOVZ_D:
11377 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11379 TCGLabel *l1 = gen_new_label();
11380 TCGv_i64 fp0;
11382 if (ft != 0) {
11383 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11385 fp0 = tcg_temp_new_i64();
11386 gen_load_fpr64(ctx, fp0, fs);
11387 gen_store_fpr64(ctx, fp0, fd);
11388 tcg_temp_free_i64(fp0);
11389 gen_set_label(l1);
11391 break;
11392 case OPC_MOVN_D:
11393 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11395 TCGLabel *l1 = gen_new_label();
11396 TCGv_i64 fp0;
11398 if (ft != 0) {
11399 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11400 fp0 = tcg_temp_new_i64();
11401 gen_load_fpr64(ctx, fp0, fs);
11402 gen_store_fpr64(ctx, fp0, fd);
11403 tcg_temp_free_i64(fp0);
11404 gen_set_label(l1);
11407 break;
11408 case OPC_RECIP_D:
11409 check_cp1_registers(ctx, fs | fd);
11411 TCGv_i64 fp0 = tcg_temp_new_i64();
11413 gen_load_fpr64(ctx, fp0, fs);
11414 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11415 gen_store_fpr64(ctx, fp0, fd);
11416 tcg_temp_free_i64(fp0);
11418 break;
11419 case OPC_RSQRT_D:
11420 check_cp1_registers(ctx, fs | fd);
11422 TCGv_i64 fp0 = tcg_temp_new_i64();
11424 gen_load_fpr64(ctx, fp0, fs);
11425 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11426 gen_store_fpr64(ctx, fp0, fd);
11427 tcg_temp_free_i64(fp0);
11429 break;
11430 case OPC_MADDF_D:
11431 check_insn(ctx, ISA_MIPS32R6);
11433 TCGv_i64 fp0 = tcg_temp_new_i64();
11434 TCGv_i64 fp1 = tcg_temp_new_i64();
11435 TCGv_i64 fp2 = tcg_temp_new_i64();
11436 gen_load_fpr64(ctx, fp0, fs);
11437 gen_load_fpr64(ctx, fp1, ft);
11438 gen_load_fpr64(ctx, fp2, fd);
11439 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11440 gen_store_fpr64(ctx, fp2, fd);
11441 tcg_temp_free_i64(fp2);
11442 tcg_temp_free_i64(fp1);
11443 tcg_temp_free_i64(fp0);
11445 break;
11446 case OPC_MSUBF_D:
11447 check_insn(ctx, ISA_MIPS32R6);
11449 TCGv_i64 fp0 = tcg_temp_new_i64();
11450 TCGv_i64 fp1 = tcg_temp_new_i64();
11451 TCGv_i64 fp2 = tcg_temp_new_i64();
11452 gen_load_fpr64(ctx, fp0, fs);
11453 gen_load_fpr64(ctx, fp1, ft);
11454 gen_load_fpr64(ctx, fp2, fd);
11455 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11456 gen_store_fpr64(ctx, fp2, fd);
11457 tcg_temp_free_i64(fp2);
11458 tcg_temp_free_i64(fp1);
11459 tcg_temp_free_i64(fp0);
11461 break;
11462 case OPC_RINT_D:
11463 check_insn(ctx, ISA_MIPS32R6);
11465 TCGv_i64 fp0 = tcg_temp_new_i64();
11466 gen_load_fpr64(ctx, fp0, fs);
11467 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11468 gen_store_fpr64(ctx, fp0, fd);
11469 tcg_temp_free_i64(fp0);
11471 break;
11472 case OPC_CLASS_D:
11473 check_insn(ctx, ISA_MIPS32R6);
11475 TCGv_i64 fp0 = tcg_temp_new_i64();
11476 gen_load_fpr64(ctx, fp0, fs);
11477 gen_helper_float_class_d(fp0, cpu_env, fp0);
11478 gen_store_fpr64(ctx, fp0, fd);
11479 tcg_temp_free_i64(fp0);
11481 break;
11482 case OPC_MIN_D: /* OPC_RECIP2_D */
11483 if (ctx->insn_flags & ISA_MIPS32R6) {
11484 /* OPC_MIN_D */
11485 TCGv_i64 fp0 = tcg_temp_new_i64();
11486 TCGv_i64 fp1 = tcg_temp_new_i64();
11487 gen_load_fpr64(ctx, fp0, fs);
11488 gen_load_fpr64(ctx, fp1, ft);
11489 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11490 gen_store_fpr64(ctx, fp1, fd);
11491 tcg_temp_free_i64(fp1);
11492 tcg_temp_free_i64(fp0);
11493 } else {
11494 /* OPC_RECIP2_D */
11495 check_cp1_64bitmode(ctx);
11497 TCGv_i64 fp0 = tcg_temp_new_i64();
11498 TCGv_i64 fp1 = tcg_temp_new_i64();
11500 gen_load_fpr64(ctx, fp0, fs);
11501 gen_load_fpr64(ctx, fp1, ft);
11502 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11503 tcg_temp_free_i64(fp1);
11504 gen_store_fpr64(ctx, fp0, fd);
11505 tcg_temp_free_i64(fp0);
11508 break;
11509 case OPC_MINA_D: /* OPC_RECIP1_D */
11510 if (ctx->insn_flags & ISA_MIPS32R6) {
11511 /* OPC_MINA_D */
11512 TCGv_i64 fp0 = tcg_temp_new_i64();
11513 TCGv_i64 fp1 = tcg_temp_new_i64();
11514 gen_load_fpr64(ctx, fp0, fs);
11515 gen_load_fpr64(ctx, fp1, ft);
11516 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11517 gen_store_fpr64(ctx, fp1, fd);
11518 tcg_temp_free_i64(fp1);
11519 tcg_temp_free_i64(fp0);
11520 } else {
11521 /* OPC_RECIP1_D */
11522 check_cp1_64bitmode(ctx);
11524 TCGv_i64 fp0 = tcg_temp_new_i64();
11526 gen_load_fpr64(ctx, fp0, fs);
11527 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11528 gen_store_fpr64(ctx, fp0, fd);
11529 tcg_temp_free_i64(fp0);
11532 break;
11533 case OPC_MAX_D: /* OPC_RSQRT1_D */
11534 if (ctx->insn_flags & ISA_MIPS32R6) {
11535 /* OPC_MAX_D */
11536 TCGv_i64 fp0 = tcg_temp_new_i64();
11537 TCGv_i64 fp1 = tcg_temp_new_i64();
11538 gen_load_fpr64(ctx, fp0, fs);
11539 gen_load_fpr64(ctx, fp1, ft);
11540 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11541 gen_store_fpr64(ctx, fp1, fd);
11542 tcg_temp_free_i64(fp1);
11543 tcg_temp_free_i64(fp0);
11544 } else {
11545 /* OPC_RSQRT1_D */
11546 check_cp1_64bitmode(ctx);
11548 TCGv_i64 fp0 = tcg_temp_new_i64();
11550 gen_load_fpr64(ctx, fp0, fs);
11551 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11552 gen_store_fpr64(ctx, fp0, fd);
11553 tcg_temp_free_i64(fp0);
11556 break;
11557 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11558 if (ctx->insn_flags & ISA_MIPS32R6) {
11559 /* OPC_MAXA_D */
11560 TCGv_i64 fp0 = tcg_temp_new_i64();
11561 TCGv_i64 fp1 = tcg_temp_new_i64();
11562 gen_load_fpr64(ctx, fp0, fs);
11563 gen_load_fpr64(ctx, fp1, ft);
11564 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11565 gen_store_fpr64(ctx, fp1, fd);
11566 tcg_temp_free_i64(fp1);
11567 tcg_temp_free_i64(fp0);
11568 } else {
11569 /* OPC_RSQRT2_D */
11570 check_cp1_64bitmode(ctx);
11572 TCGv_i64 fp0 = tcg_temp_new_i64();
11573 TCGv_i64 fp1 = tcg_temp_new_i64();
11575 gen_load_fpr64(ctx, fp0, fs);
11576 gen_load_fpr64(ctx, fp1, ft);
11577 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11578 tcg_temp_free_i64(fp1);
11579 gen_store_fpr64(ctx, fp0, fd);
11580 tcg_temp_free_i64(fp0);
11583 break;
11584 case OPC_CMP_F_D:
11585 case OPC_CMP_UN_D:
11586 case OPC_CMP_EQ_D:
11587 case OPC_CMP_UEQ_D:
11588 case OPC_CMP_OLT_D:
11589 case OPC_CMP_ULT_D:
11590 case OPC_CMP_OLE_D:
11591 case OPC_CMP_ULE_D:
11592 case OPC_CMP_SF_D:
11593 case OPC_CMP_NGLE_D:
11594 case OPC_CMP_SEQ_D:
11595 case OPC_CMP_NGL_D:
11596 case OPC_CMP_LT_D:
11597 case OPC_CMP_NGE_D:
11598 case OPC_CMP_LE_D:
11599 case OPC_CMP_NGT_D:
11600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11601 if (ctx->opcode & (1 << 6)) {
11602 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11603 } else {
11604 gen_cmp_d(ctx, func-48, ft, fs, cc);
11606 break;
11607 case OPC_CVT_S_D:
11608 check_cp1_registers(ctx, fs);
11610 TCGv_i32 fp32 = tcg_temp_new_i32();
11611 TCGv_i64 fp64 = tcg_temp_new_i64();
11613 gen_load_fpr64(ctx, fp64, fs);
11614 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11615 tcg_temp_free_i64(fp64);
11616 gen_store_fpr32(ctx, fp32, fd);
11617 tcg_temp_free_i32(fp32);
11619 break;
11620 case OPC_CVT_W_D:
11621 check_cp1_registers(ctx, fs);
11623 TCGv_i32 fp32 = tcg_temp_new_i32();
11624 TCGv_i64 fp64 = tcg_temp_new_i64();
11626 gen_load_fpr64(ctx, fp64, fs);
11627 if (ctx->nan2008) {
11628 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11629 } else {
11630 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11632 tcg_temp_free_i64(fp64);
11633 gen_store_fpr32(ctx, fp32, fd);
11634 tcg_temp_free_i32(fp32);
11636 break;
11637 case OPC_CVT_L_D:
11638 check_cp1_64bitmode(ctx);
11640 TCGv_i64 fp0 = tcg_temp_new_i64();
11642 gen_load_fpr64(ctx, fp0, fs);
11643 if (ctx->nan2008) {
11644 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11645 } else {
11646 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11648 gen_store_fpr64(ctx, fp0, fd);
11649 tcg_temp_free_i64(fp0);
11651 break;
11652 case OPC_CVT_S_W:
11654 TCGv_i32 fp0 = tcg_temp_new_i32();
11656 gen_load_fpr32(ctx, fp0, fs);
11657 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11658 gen_store_fpr32(ctx, fp0, fd);
11659 tcg_temp_free_i32(fp0);
11661 break;
11662 case OPC_CVT_D_W:
11663 check_cp1_registers(ctx, fd);
11665 TCGv_i32 fp32 = tcg_temp_new_i32();
11666 TCGv_i64 fp64 = tcg_temp_new_i64();
11668 gen_load_fpr32(ctx, fp32, fs);
11669 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11670 tcg_temp_free_i32(fp32);
11671 gen_store_fpr64(ctx, fp64, fd);
11672 tcg_temp_free_i64(fp64);
11674 break;
11675 case OPC_CVT_S_L:
11676 check_cp1_64bitmode(ctx);
11678 TCGv_i32 fp32 = tcg_temp_new_i32();
11679 TCGv_i64 fp64 = tcg_temp_new_i64();
11681 gen_load_fpr64(ctx, fp64, fs);
11682 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11683 tcg_temp_free_i64(fp64);
11684 gen_store_fpr32(ctx, fp32, fd);
11685 tcg_temp_free_i32(fp32);
11687 break;
11688 case OPC_CVT_D_L:
11689 check_cp1_64bitmode(ctx);
11691 TCGv_i64 fp0 = tcg_temp_new_i64();
11693 gen_load_fpr64(ctx, fp0, fs);
11694 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11695 gen_store_fpr64(ctx, fp0, fd);
11696 tcg_temp_free_i64(fp0);
11698 break;
11699 case OPC_CVT_PS_PW:
11700 check_ps(ctx);
11702 TCGv_i64 fp0 = tcg_temp_new_i64();
11704 gen_load_fpr64(ctx, fp0, fs);
11705 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11706 gen_store_fpr64(ctx, fp0, fd);
11707 tcg_temp_free_i64(fp0);
11709 break;
11710 case OPC_ADD_PS:
11711 check_ps(ctx);
11713 TCGv_i64 fp0 = tcg_temp_new_i64();
11714 TCGv_i64 fp1 = tcg_temp_new_i64();
11716 gen_load_fpr64(ctx, fp0, fs);
11717 gen_load_fpr64(ctx, fp1, ft);
11718 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11719 tcg_temp_free_i64(fp1);
11720 gen_store_fpr64(ctx, fp0, fd);
11721 tcg_temp_free_i64(fp0);
11723 break;
11724 case OPC_SUB_PS:
11725 check_ps(ctx);
11727 TCGv_i64 fp0 = tcg_temp_new_i64();
11728 TCGv_i64 fp1 = tcg_temp_new_i64();
11730 gen_load_fpr64(ctx, fp0, fs);
11731 gen_load_fpr64(ctx, fp1, ft);
11732 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11733 tcg_temp_free_i64(fp1);
11734 gen_store_fpr64(ctx, fp0, fd);
11735 tcg_temp_free_i64(fp0);
11737 break;
11738 case OPC_MUL_PS:
11739 check_ps(ctx);
11741 TCGv_i64 fp0 = tcg_temp_new_i64();
11742 TCGv_i64 fp1 = tcg_temp_new_i64();
11744 gen_load_fpr64(ctx, fp0, fs);
11745 gen_load_fpr64(ctx, fp1, ft);
11746 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11747 tcg_temp_free_i64(fp1);
11748 gen_store_fpr64(ctx, fp0, fd);
11749 tcg_temp_free_i64(fp0);
11751 break;
11752 case OPC_ABS_PS:
11753 check_ps(ctx);
11755 TCGv_i64 fp0 = tcg_temp_new_i64();
11757 gen_load_fpr64(ctx, fp0, fs);
11758 gen_helper_float_abs_ps(fp0, fp0);
11759 gen_store_fpr64(ctx, fp0, fd);
11760 tcg_temp_free_i64(fp0);
11762 break;
11763 case OPC_MOV_PS:
11764 check_ps(ctx);
11766 TCGv_i64 fp0 = tcg_temp_new_i64();
11768 gen_load_fpr64(ctx, fp0, fs);
11769 gen_store_fpr64(ctx, fp0, fd);
11770 tcg_temp_free_i64(fp0);
11772 break;
11773 case OPC_NEG_PS:
11774 check_ps(ctx);
11776 TCGv_i64 fp0 = tcg_temp_new_i64();
11778 gen_load_fpr64(ctx, fp0, fs);
11779 gen_helper_float_chs_ps(fp0, fp0);
11780 gen_store_fpr64(ctx, fp0, fd);
11781 tcg_temp_free_i64(fp0);
11783 break;
11784 case OPC_MOVCF_PS:
11785 check_ps(ctx);
11786 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11787 break;
11788 case OPC_MOVZ_PS:
11789 check_ps(ctx);
11791 TCGLabel *l1 = gen_new_label();
11792 TCGv_i64 fp0;
11794 if (ft != 0)
11795 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11796 fp0 = tcg_temp_new_i64();
11797 gen_load_fpr64(ctx, fp0, fs);
11798 gen_store_fpr64(ctx, fp0, fd);
11799 tcg_temp_free_i64(fp0);
11800 gen_set_label(l1);
11802 break;
11803 case OPC_MOVN_PS:
11804 check_ps(ctx);
11806 TCGLabel *l1 = gen_new_label();
11807 TCGv_i64 fp0;
11809 if (ft != 0) {
11810 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11811 fp0 = tcg_temp_new_i64();
11812 gen_load_fpr64(ctx, fp0, fs);
11813 gen_store_fpr64(ctx, fp0, fd);
11814 tcg_temp_free_i64(fp0);
11815 gen_set_label(l1);
11818 break;
11819 case OPC_ADDR_PS:
11820 check_ps(ctx);
11822 TCGv_i64 fp0 = tcg_temp_new_i64();
11823 TCGv_i64 fp1 = tcg_temp_new_i64();
11825 gen_load_fpr64(ctx, fp0, ft);
11826 gen_load_fpr64(ctx, fp1, fs);
11827 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11828 tcg_temp_free_i64(fp1);
11829 gen_store_fpr64(ctx, fp0, fd);
11830 tcg_temp_free_i64(fp0);
11832 break;
11833 case OPC_MULR_PS:
11834 check_ps(ctx);
11836 TCGv_i64 fp0 = tcg_temp_new_i64();
11837 TCGv_i64 fp1 = tcg_temp_new_i64();
11839 gen_load_fpr64(ctx, fp0, ft);
11840 gen_load_fpr64(ctx, fp1, fs);
11841 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11842 tcg_temp_free_i64(fp1);
11843 gen_store_fpr64(ctx, fp0, fd);
11844 tcg_temp_free_i64(fp0);
11846 break;
11847 case OPC_RECIP2_PS:
11848 check_ps(ctx);
11850 TCGv_i64 fp0 = tcg_temp_new_i64();
11851 TCGv_i64 fp1 = tcg_temp_new_i64();
11853 gen_load_fpr64(ctx, fp0, fs);
11854 gen_load_fpr64(ctx, fp1, ft);
11855 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11856 tcg_temp_free_i64(fp1);
11857 gen_store_fpr64(ctx, fp0, fd);
11858 tcg_temp_free_i64(fp0);
11860 break;
11861 case OPC_RECIP1_PS:
11862 check_ps(ctx);
11864 TCGv_i64 fp0 = tcg_temp_new_i64();
11866 gen_load_fpr64(ctx, fp0, fs);
11867 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11868 gen_store_fpr64(ctx, fp0, fd);
11869 tcg_temp_free_i64(fp0);
11871 break;
11872 case OPC_RSQRT1_PS:
11873 check_ps(ctx);
11875 TCGv_i64 fp0 = tcg_temp_new_i64();
11877 gen_load_fpr64(ctx, fp0, fs);
11878 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11879 gen_store_fpr64(ctx, fp0, fd);
11880 tcg_temp_free_i64(fp0);
11882 break;
11883 case OPC_RSQRT2_PS:
11884 check_ps(ctx);
11886 TCGv_i64 fp0 = tcg_temp_new_i64();
11887 TCGv_i64 fp1 = tcg_temp_new_i64();
11889 gen_load_fpr64(ctx, fp0, fs);
11890 gen_load_fpr64(ctx, fp1, ft);
11891 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11892 tcg_temp_free_i64(fp1);
11893 gen_store_fpr64(ctx, fp0, fd);
11894 tcg_temp_free_i64(fp0);
11896 break;
11897 case OPC_CVT_S_PU:
11898 check_cp1_64bitmode(ctx);
11900 TCGv_i32 fp0 = tcg_temp_new_i32();
11902 gen_load_fpr32h(ctx, fp0, fs);
11903 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11904 gen_store_fpr32(ctx, fp0, fd);
11905 tcg_temp_free_i32(fp0);
11907 break;
11908 case OPC_CVT_PW_PS:
11909 check_ps(ctx);
11911 TCGv_i64 fp0 = tcg_temp_new_i64();
11913 gen_load_fpr64(ctx, fp0, fs);
11914 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11915 gen_store_fpr64(ctx, fp0, fd);
11916 tcg_temp_free_i64(fp0);
11918 break;
11919 case OPC_CVT_S_PL:
11920 check_cp1_64bitmode(ctx);
11922 TCGv_i32 fp0 = tcg_temp_new_i32();
11924 gen_load_fpr32(ctx, fp0, fs);
11925 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11926 gen_store_fpr32(ctx, fp0, fd);
11927 tcg_temp_free_i32(fp0);
11929 break;
11930 case OPC_PLL_PS:
11931 check_ps(ctx);
11933 TCGv_i32 fp0 = tcg_temp_new_i32();
11934 TCGv_i32 fp1 = tcg_temp_new_i32();
11936 gen_load_fpr32(ctx, fp0, fs);
11937 gen_load_fpr32(ctx, fp1, ft);
11938 gen_store_fpr32h(ctx, fp0, fd);
11939 gen_store_fpr32(ctx, fp1, fd);
11940 tcg_temp_free_i32(fp0);
11941 tcg_temp_free_i32(fp1);
11943 break;
11944 case OPC_PLU_PS:
11945 check_ps(ctx);
11947 TCGv_i32 fp0 = tcg_temp_new_i32();
11948 TCGv_i32 fp1 = tcg_temp_new_i32();
11950 gen_load_fpr32(ctx, fp0, fs);
11951 gen_load_fpr32h(ctx, fp1, ft);
11952 gen_store_fpr32(ctx, fp1, fd);
11953 gen_store_fpr32h(ctx, fp0, fd);
11954 tcg_temp_free_i32(fp0);
11955 tcg_temp_free_i32(fp1);
11957 break;
11958 case OPC_PUL_PS:
11959 check_ps(ctx);
11961 TCGv_i32 fp0 = tcg_temp_new_i32();
11962 TCGv_i32 fp1 = tcg_temp_new_i32();
11964 gen_load_fpr32h(ctx, fp0, fs);
11965 gen_load_fpr32(ctx, fp1, ft);
11966 gen_store_fpr32(ctx, fp1, fd);
11967 gen_store_fpr32h(ctx, fp0, fd);
11968 tcg_temp_free_i32(fp0);
11969 tcg_temp_free_i32(fp1);
11971 break;
11972 case OPC_PUU_PS:
11973 check_ps(ctx);
11975 TCGv_i32 fp0 = tcg_temp_new_i32();
11976 TCGv_i32 fp1 = tcg_temp_new_i32();
11978 gen_load_fpr32h(ctx, fp0, fs);
11979 gen_load_fpr32h(ctx, fp1, ft);
11980 gen_store_fpr32(ctx, fp1, fd);
11981 gen_store_fpr32h(ctx, fp0, fd);
11982 tcg_temp_free_i32(fp0);
11983 tcg_temp_free_i32(fp1);
11985 break;
11986 case OPC_CMP_F_PS:
11987 case OPC_CMP_UN_PS:
11988 case OPC_CMP_EQ_PS:
11989 case OPC_CMP_UEQ_PS:
11990 case OPC_CMP_OLT_PS:
11991 case OPC_CMP_ULT_PS:
11992 case OPC_CMP_OLE_PS:
11993 case OPC_CMP_ULE_PS:
11994 case OPC_CMP_SF_PS:
11995 case OPC_CMP_NGLE_PS:
11996 case OPC_CMP_SEQ_PS:
11997 case OPC_CMP_NGL_PS:
11998 case OPC_CMP_LT_PS:
11999 case OPC_CMP_NGE_PS:
12000 case OPC_CMP_LE_PS:
12001 case OPC_CMP_NGT_PS:
12002 if (ctx->opcode & (1 << 6)) {
12003 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
12004 } else {
12005 gen_cmp_ps(ctx, func-48, ft, fs, cc);
12007 break;
12008 default:
12009 MIPS_INVAL("farith");
12010 generate_exception_end(ctx, EXCP_RI);
12011 return;
12015 /* Coprocessor 3 (FPU) */
12016 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12017 int fd, int fs, int base, int index)
12019 TCGv t0 = tcg_temp_new();
12021 if (base == 0) {
12022 gen_load_gpr(t0, index);
12023 } else if (index == 0) {
12024 gen_load_gpr(t0, base);
12025 } else {
12026 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12028 /* Don't do NOP if destination is zero: we must perform the actual
12029 memory access. */
12030 switch (opc) {
12031 case OPC_LWXC1:
12032 check_cop1x(ctx);
12034 TCGv_i32 fp0 = tcg_temp_new_i32();
12036 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12037 tcg_gen_trunc_tl_i32(fp0, t0);
12038 gen_store_fpr32(ctx, fp0, fd);
12039 tcg_temp_free_i32(fp0);
12041 break;
12042 case OPC_LDXC1:
12043 check_cop1x(ctx);
12044 check_cp1_registers(ctx, fd);
12046 TCGv_i64 fp0 = tcg_temp_new_i64();
12047 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12048 gen_store_fpr64(ctx, fp0, fd);
12049 tcg_temp_free_i64(fp0);
12051 break;
12052 case OPC_LUXC1:
12053 check_cp1_64bitmode(ctx);
12054 tcg_gen_andi_tl(t0, t0, ~0x7);
12056 TCGv_i64 fp0 = tcg_temp_new_i64();
12058 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12059 gen_store_fpr64(ctx, fp0, fd);
12060 tcg_temp_free_i64(fp0);
12062 break;
12063 case OPC_SWXC1:
12064 check_cop1x(ctx);
12066 TCGv_i32 fp0 = tcg_temp_new_i32();
12067 gen_load_fpr32(ctx, fp0, fs);
12068 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12069 tcg_temp_free_i32(fp0);
12071 break;
12072 case OPC_SDXC1:
12073 check_cop1x(ctx);
12074 check_cp1_registers(ctx, fs);
12076 TCGv_i64 fp0 = tcg_temp_new_i64();
12077 gen_load_fpr64(ctx, fp0, fs);
12078 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12079 tcg_temp_free_i64(fp0);
12081 break;
12082 case OPC_SUXC1:
12083 check_cp1_64bitmode(ctx);
12084 tcg_gen_andi_tl(t0, t0, ~0x7);
12086 TCGv_i64 fp0 = tcg_temp_new_i64();
12087 gen_load_fpr64(ctx, fp0, fs);
12088 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12089 tcg_temp_free_i64(fp0);
12091 break;
12093 tcg_temp_free(t0);
12096 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12097 int fd, int fr, int fs, int ft)
12099 switch (opc) {
12100 case OPC_ALNV_PS:
12101 check_ps(ctx);
12103 TCGv t0 = tcg_temp_local_new();
12104 TCGv_i32 fp = tcg_temp_new_i32();
12105 TCGv_i32 fph = tcg_temp_new_i32();
12106 TCGLabel *l1 = gen_new_label();
12107 TCGLabel *l2 = gen_new_label();
12109 gen_load_gpr(t0, fr);
12110 tcg_gen_andi_tl(t0, t0, 0x7);
12112 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12113 gen_load_fpr32(ctx, fp, fs);
12114 gen_load_fpr32h(ctx, fph, fs);
12115 gen_store_fpr32(ctx, fp, fd);
12116 gen_store_fpr32h(ctx, fph, fd);
12117 tcg_gen_br(l2);
12118 gen_set_label(l1);
12119 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12120 tcg_temp_free(t0);
12121 #ifdef TARGET_WORDS_BIGENDIAN
12122 gen_load_fpr32(ctx, fp, fs);
12123 gen_load_fpr32h(ctx, fph, ft);
12124 gen_store_fpr32h(ctx, fp, fd);
12125 gen_store_fpr32(ctx, fph, fd);
12126 #else
12127 gen_load_fpr32h(ctx, fph, fs);
12128 gen_load_fpr32(ctx, fp, ft);
12129 gen_store_fpr32(ctx, fph, fd);
12130 gen_store_fpr32h(ctx, fp, fd);
12131 #endif
12132 gen_set_label(l2);
12133 tcg_temp_free_i32(fp);
12134 tcg_temp_free_i32(fph);
12136 break;
12137 case OPC_MADD_S:
12138 check_cop1x(ctx);
12140 TCGv_i32 fp0 = tcg_temp_new_i32();
12141 TCGv_i32 fp1 = tcg_temp_new_i32();
12142 TCGv_i32 fp2 = tcg_temp_new_i32();
12144 gen_load_fpr32(ctx, fp0, fs);
12145 gen_load_fpr32(ctx, fp1, ft);
12146 gen_load_fpr32(ctx, fp2, fr);
12147 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12148 tcg_temp_free_i32(fp0);
12149 tcg_temp_free_i32(fp1);
12150 gen_store_fpr32(ctx, fp2, fd);
12151 tcg_temp_free_i32(fp2);
12153 break;
12154 case OPC_MADD_D:
12155 check_cop1x(ctx);
12156 check_cp1_registers(ctx, fd | fs | ft | fr);
12158 TCGv_i64 fp0 = tcg_temp_new_i64();
12159 TCGv_i64 fp1 = tcg_temp_new_i64();
12160 TCGv_i64 fp2 = tcg_temp_new_i64();
12162 gen_load_fpr64(ctx, fp0, fs);
12163 gen_load_fpr64(ctx, fp1, ft);
12164 gen_load_fpr64(ctx, fp2, fr);
12165 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12166 tcg_temp_free_i64(fp0);
12167 tcg_temp_free_i64(fp1);
12168 gen_store_fpr64(ctx, fp2, fd);
12169 tcg_temp_free_i64(fp2);
12171 break;
12172 case OPC_MADD_PS:
12173 check_ps(ctx);
12175 TCGv_i64 fp0 = tcg_temp_new_i64();
12176 TCGv_i64 fp1 = tcg_temp_new_i64();
12177 TCGv_i64 fp2 = tcg_temp_new_i64();
12179 gen_load_fpr64(ctx, fp0, fs);
12180 gen_load_fpr64(ctx, fp1, ft);
12181 gen_load_fpr64(ctx, fp2, fr);
12182 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12183 tcg_temp_free_i64(fp0);
12184 tcg_temp_free_i64(fp1);
12185 gen_store_fpr64(ctx, fp2, fd);
12186 tcg_temp_free_i64(fp2);
12188 break;
12189 case OPC_MSUB_S:
12190 check_cop1x(ctx);
12192 TCGv_i32 fp0 = tcg_temp_new_i32();
12193 TCGv_i32 fp1 = tcg_temp_new_i32();
12194 TCGv_i32 fp2 = tcg_temp_new_i32();
12196 gen_load_fpr32(ctx, fp0, fs);
12197 gen_load_fpr32(ctx, fp1, ft);
12198 gen_load_fpr32(ctx, fp2, fr);
12199 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12200 tcg_temp_free_i32(fp0);
12201 tcg_temp_free_i32(fp1);
12202 gen_store_fpr32(ctx, fp2, fd);
12203 tcg_temp_free_i32(fp2);
12205 break;
12206 case OPC_MSUB_D:
12207 check_cop1x(ctx);
12208 check_cp1_registers(ctx, fd | fs | ft | fr);
12210 TCGv_i64 fp0 = tcg_temp_new_i64();
12211 TCGv_i64 fp1 = tcg_temp_new_i64();
12212 TCGv_i64 fp2 = tcg_temp_new_i64();
12214 gen_load_fpr64(ctx, fp0, fs);
12215 gen_load_fpr64(ctx, fp1, ft);
12216 gen_load_fpr64(ctx, fp2, fr);
12217 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12218 tcg_temp_free_i64(fp0);
12219 tcg_temp_free_i64(fp1);
12220 gen_store_fpr64(ctx, fp2, fd);
12221 tcg_temp_free_i64(fp2);
12223 break;
12224 case OPC_MSUB_PS:
12225 check_ps(ctx);
12227 TCGv_i64 fp0 = tcg_temp_new_i64();
12228 TCGv_i64 fp1 = tcg_temp_new_i64();
12229 TCGv_i64 fp2 = tcg_temp_new_i64();
12231 gen_load_fpr64(ctx, fp0, fs);
12232 gen_load_fpr64(ctx, fp1, ft);
12233 gen_load_fpr64(ctx, fp2, fr);
12234 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12235 tcg_temp_free_i64(fp0);
12236 tcg_temp_free_i64(fp1);
12237 gen_store_fpr64(ctx, fp2, fd);
12238 tcg_temp_free_i64(fp2);
12240 break;
12241 case OPC_NMADD_S:
12242 check_cop1x(ctx);
12244 TCGv_i32 fp0 = tcg_temp_new_i32();
12245 TCGv_i32 fp1 = tcg_temp_new_i32();
12246 TCGv_i32 fp2 = tcg_temp_new_i32();
12248 gen_load_fpr32(ctx, fp0, fs);
12249 gen_load_fpr32(ctx, fp1, ft);
12250 gen_load_fpr32(ctx, fp2, fr);
12251 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12252 tcg_temp_free_i32(fp0);
12253 tcg_temp_free_i32(fp1);
12254 gen_store_fpr32(ctx, fp2, fd);
12255 tcg_temp_free_i32(fp2);
12257 break;
12258 case OPC_NMADD_D:
12259 check_cop1x(ctx);
12260 check_cp1_registers(ctx, fd | fs | ft | fr);
12262 TCGv_i64 fp0 = tcg_temp_new_i64();
12263 TCGv_i64 fp1 = tcg_temp_new_i64();
12264 TCGv_i64 fp2 = tcg_temp_new_i64();
12266 gen_load_fpr64(ctx, fp0, fs);
12267 gen_load_fpr64(ctx, fp1, ft);
12268 gen_load_fpr64(ctx, fp2, fr);
12269 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12270 tcg_temp_free_i64(fp0);
12271 tcg_temp_free_i64(fp1);
12272 gen_store_fpr64(ctx, fp2, fd);
12273 tcg_temp_free_i64(fp2);
12275 break;
12276 case OPC_NMADD_PS:
12277 check_ps(ctx);
12279 TCGv_i64 fp0 = tcg_temp_new_i64();
12280 TCGv_i64 fp1 = tcg_temp_new_i64();
12281 TCGv_i64 fp2 = tcg_temp_new_i64();
12283 gen_load_fpr64(ctx, fp0, fs);
12284 gen_load_fpr64(ctx, fp1, ft);
12285 gen_load_fpr64(ctx, fp2, fr);
12286 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12287 tcg_temp_free_i64(fp0);
12288 tcg_temp_free_i64(fp1);
12289 gen_store_fpr64(ctx, fp2, fd);
12290 tcg_temp_free_i64(fp2);
12292 break;
12293 case OPC_NMSUB_S:
12294 check_cop1x(ctx);
12296 TCGv_i32 fp0 = tcg_temp_new_i32();
12297 TCGv_i32 fp1 = tcg_temp_new_i32();
12298 TCGv_i32 fp2 = tcg_temp_new_i32();
12300 gen_load_fpr32(ctx, fp0, fs);
12301 gen_load_fpr32(ctx, fp1, ft);
12302 gen_load_fpr32(ctx, fp2, fr);
12303 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12304 tcg_temp_free_i32(fp0);
12305 tcg_temp_free_i32(fp1);
12306 gen_store_fpr32(ctx, fp2, fd);
12307 tcg_temp_free_i32(fp2);
12309 break;
12310 case OPC_NMSUB_D:
12311 check_cop1x(ctx);
12312 check_cp1_registers(ctx, fd | fs | ft | fr);
12314 TCGv_i64 fp0 = tcg_temp_new_i64();
12315 TCGv_i64 fp1 = tcg_temp_new_i64();
12316 TCGv_i64 fp2 = tcg_temp_new_i64();
12318 gen_load_fpr64(ctx, fp0, fs);
12319 gen_load_fpr64(ctx, fp1, ft);
12320 gen_load_fpr64(ctx, fp2, fr);
12321 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12322 tcg_temp_free_i64(fp0);
12323 tcg_temp_free_i64(fp1);
12324 gen_store_fpr64(ctx, fp2, fd);
12325 tcg_temp_free_i64(fp2);
12327 break;
12328 case OPC_NMSUB_PS:
12329 check_ps(ctx);
12331 TCGv_i64 fp0 = tcg_temp_new_i64();
12332 TCGv_i64 fp1 = tcg_temp_new_i64();
12333 TCGv_i64 fp2 = tcg_temp_new_i64();
12335 gen_load_fpr64(ctx, fp0, fs);
12336 gen_load_fpr64(ctx, fp1, ft);
12337 gen_load_fpr64(ctx, fp2, fr);
12338 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12339 tcg_temp_free_i64(fp0);
12340 tcg_temp_free_i64(fp1);
12341 gen_store_fpr64(ctx, fp2, fd);
12342 tcg_temp_free_i64(fp2);
12344 break;
12345 default:
12346 MIPS_INVAL("flt3_arith");
12347 generate_exception_end(ctx, EXCP_RI);
12348 return;
12352 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12354 TCGv t0;
12356 #if !defined(CONFIG_USER_ONLY)
12357 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12358 Therefore only check the ISA in system mode. */
12359 check_insn(ctx, ISA_MIPS32R2);
12360 #endif
12361 t0 = tcg_temp_new();
12363 switch (rd) {
12364 case 0:
12365 gen_helper_rdhwr_cpunum(t0, cpu_env);
12366 gen_store_gpr(t0, rt);
12367 break;
12368 case 1:
12369 gen_helper_rdhwr_synci_step(t0, cpu_env);
12370 gen_store_gpr(t0, rt);
12371 break;
12372 case 2:
12373 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12374 gen_io_start();
12376 gen_helper_rdhwr_cc(t0, cpu_env);
12377 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12378 gen_io_end();
12380 gen_store_gpr(t0, rt);
12381 /* Break the TB to be able to take timer interrupts immediately
12382 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12383 we break completely out of translated code. */
12384 gen_save_pc(ctx->base.pc_next + 4);
12385 ctx->base.is_jmp = DISAS_EXIT;
12386 break;
12387 case 3:
12388 gen_helper_rdhwr_ccres(t0, cpu_env);
12389 gen_store_gpr(t0, rt);
12390 break;
12391 case 4:
12392 check_insn(ctx, ISA_MIPS32R6);
12393 if (sel != 0) {
12394 /* Performance counter registers are not implemented other than
12395 * control register 0.
12397 generate_exception(ctx, EXCP_RI);
12399 gen_helper_rdhwr_performance(t0, cpu_env);
12400 gen_store_gpr(t0, rt);
12401 break;
12402 case 5:
12403 check_insn(ctx, ISA_MIPS32R6);
12404 gen_helper_rdhwr_xnp(t0, cpu_env);
12405 gen_store_gpr(t0, rt);
12406 break;
12407 case 29:
12408 #if defined(CONFIG_USER_ONLY)
12409 tcg_gen_ld_tl(t0, cpu_env,
12410 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12411 gen_store_gpr(t0, rt);
12412 break;
12413 #else
12414 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12415 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12416 tcg_gen_ld_tl(t0, cpu_env,
12417 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12418 gen_store_gpr(t0, rt);
12419 } else {
12420 generate_exception_end(ctx, EXCP_RI);
12422 break;
12423 #endif
12424 default: /* Invalid */
12425 MIPS_INVAL("rdhwr");
12426 generate_exception_end(ctx, EXCP_RI);
12427 break;
12429 tcg_temp_free(t0);
12432 static inline void clear_branch_hflags(DisasContext *ctx)
12434 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12435 if (ctx->base.is_jmp == DISAS_NEXT) {
12436 save_cpu_state(ctx, 0);
12437 } else {
12438 /* it is not safe to save ctx->hflags as hflags may be changed
12439 in execution time by the instruction in delay / forbidden slot. */
12440 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12444 static void gen_branch(DisasContext *ctx, int insn_bytes)
12446 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12447 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12448 /* Branches completion */
12449 clear_branch_hflags(ctx);
12450 ctx->base.is_jmp = DISAS_NORETURN;
12451 /* FIXME: Need to clear can_do_io. */
12452 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12453 case MIPS_HFLAG_FBNSLOT:
12454 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12455 break;
12456 case MIPS_HFLAG_B:
12457 /* unconditional branch */
12458 if (proc_hflags & MIPS_HFLAG_BX) {
12459 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12461 gen_goto_tb(ctx, 0, ctx->btarget);
12462 break;
12463 case MIPS_HFLAG_BL:
12464 /* blikely taken case */
12465 gen_goto_tb(ctx, 0, ctx->btarget);
12466 break;
12467 case MIPS_HFLAG_BC:
12468 /* Conditional branch */
12470 TCGLabel *l1 = gen_new_label();
12472 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12473 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12474 gen_set_label(l1);
12475 gen_goto_tb(ctx, 0, ctx->btarget);
12477 break;
12478 case MIPS_HFLAG_BR:
12479 /* unconditional branch to register */
12480 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12481 TCGv t0 = tcg_temp_new();
12482 TCGv_i32 t1 = tcg_temp_new_i32();
12484 tcg_gen_andi_tl(t0, btarget, 0x1);
12485 tcg_gen_trunc_tl_i32(t1, t0);
12486 tcg_temp_free(t0);
12487 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12488 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12489 tcg_gen_or_i32(hflags, hflags, t1);
12490 tcg_temp_free_i32(t1);
12492 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12493 } else {
12494 tcg_gen_mov_tl(cpu_PC, btarget);
12496 if (ctx->base.singlestep_enabled) {
12497 save_cpu_state(ctx, 0);
12498 gen_helper_raise_exception_debug(cpu_env);
12500 tcg_gen_lookup_and_goto_ptr();
12501 break;
12502 default:
12503 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12504 abort();
12509 /* Compact Branches */
12510 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12511 int rs, int rt, int32_t offset)
12513 int bcond_compute = 0;
12514 TCGv t0 = tcg_temp_new();
12515 TCGv t1 = tcg_temp_new();
12516 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12518 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12519 #ifdef MIPS_DEBUG_DISAS
12520 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12521 "\n", ctx->base.pc_next);
12522 #endif
12523 generate_exception_end(ctx, EXCP_RI);
12524 goto out;
12527 /* Load needed operands and calculate btarget */
12528 switch (opc) {
12529 /* compact branch */
12530 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12531 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12532 gen_load_gpr(t0, rs);
12533 gen_load_gpr(t1, rt);
12534 bcond_compute = 1;
12535 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12536 if (rs <= rt && rs == 0) {
12537 /* OPC_BEQZALC, OPC_BNEZALC */
12538 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12540 break;
12541 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12542 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12543 gen_load_gpr(t0, rs);
12544 gen_load_gpr(t1, rt);
12545 bcond_compute = 1;
12546 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12547 break;
12548 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12549 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12550 if (rs == 0 || rs == rt) {
12551 /* OPC_BLEZALC, OPC_BGEZALC */
12552 /* OPC_BGTZALC, OPC_BLTZALC */
12553 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12555 gen_load_gpr(t0, rs);
12556 gen_load_gpr(t1, rt);
12557 bcond_compute = 1;
12558 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12559 break;
12560 case OPC_BC:
12561 case OPC_BALC:
12562 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12563 break;
12564 case OPC_BEQZC:
12565 case OPC_BNEZC:
12566 if (rs != 0) {
12567 /* OPC_BEQZC, OPC_BNEZC */
12568 gen_load_gpr(t0, rs);
12569 bcond_compute = 1;
12570 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12571 } else {
12572 /* OPC_JIC, OPC_JIALC */
12573 TCGv tbase = tcg_temp_new();
12574 TCGv toffset = tcg_temp_new();
12576 gen_load_gpr(tbase, rt);
12577 tcg_gen_movi_tl(toffset, offset);
12578 gen_op_addr_add(ctx, btarget, tbase, toffset);
12579 tcg_temp_free(tbase);
12580 tcg_temp_free(toffset);
12582 break;
12583 default:
12584 MIPS_INVAL("Compact branch/jump");
12585 generate_exception_end(ctx, EXCP_RI);
12586 goto out;
12589 if (bcond_compute == 0) {
12590 /* Uncoditional compact branch */
12591 switch (opc) {
12592 case OPC_JIALC:
12593 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12594 /* Fallthrough */
12595 case OPC_JIC:
12596 ctx->hflags |= MIPS_HFLAG_BR;
12597 break;
12598 case OPC_BALC:
12599 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12600 /* Fallthrough */
12601 case OPC_BC:
12602 ctx->hflags |= MIPS_HFLAG_B;
12603 break;
12604 default:
12605 MIPS_INVAL("Compact branch/jump");
12606 generate_exception_end(ctx, EXCP_RI);
12607 goto out;
12610 /* Generating branch here as compact branches don't have delay slot */
12611 gen_branch(ctx, 4);
12612 } else {
12613 /* Conditional compact branch */
12614 TCGLabel *fs = gen_new_label();
12615 save_cpu_state(ctx, 0);
12617 switch (opc) {
12618 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12619 if (rs == 0 && rt != 0) {
12620 /* OPC_BLEZALC */
12621 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12622 } else if (rs != 0 && rt != 0 && rs == rt) {
12623 /* OPC_BGEZALC */
12624 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12625 } else {
12626 /* OPC_BGEUC */
12627 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12629 break;
12630 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12631 if (rs == 0 && rt != 0) {
12632 /* OPC_BGTZALC */
12633 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12634 } else if (rs != 0 && rt != 0 && rs == rt) {
12635 /* OPC_BLTZALC */
12636 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12637 } else {
12638 /* OPC_BLTUC */
12639 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12641 break;
12642 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12643 if (rs == 0 && rt != 0) {
12644 /* OPC_BLEZC */
12645 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12646 } else if (rs != 0 && rt != 0 && rs == rt) {
12647 /* OPC_BGEZC */
12648 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12649 } else {
12650 /* OPC_BGEC */
12651 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12653 break;
12654 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12655 if (rs == 0 && rt != 0) {
12656 /* OPC_BGTZC */
12657 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12658 } else if (rs != 0 && rt != 0 && rs == rt) {
12659 /* OPC_BLTZC */
12660 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12661 } else {
12662 /* OPC_BLTC */
12663 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12665 break;
12666 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12667 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12668 if (rs >= rt) {
12669 /* OPC_BOVC, OPC_BNVC */
12670 TCGv t2 = tcg_temp_new();
12671 TCGv t3 = tcg_temp_new();
12672 TCGv t4 = tcg_temp_new();
12673 TCGv input_overflow = tcg_temp_new();
12675 gen_load_gpr(t0, rs);
12676 gen_load_gpr(t1, rt);
12677 tcg_gen_ext32s_tl(t2, t0);
12678 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12679 tcg_gen_ext32s_tl(t3, t1);
12680 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12681 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12683 tcg_gen_add_tl(t4, t2, t3);
12684 tcg_gen_ext32s_tl(t4, t4);
12685 tcg_gen_xor_tl(t2, t2, t3);
12686 tcg_gen_xor_tl(t3, t4, t3);
12687 tcg_gen_andc_tl(t2, t3, t2);
12688 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12689 tcg_gen_or_tl(t4, t4, input_overflow);
12690 if (opc == OPC_BOVC) {
12691 /* OPC_BOVC */
12692 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12693 } else {
12694 /* OPC_BNVC */
12695 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12697 tcg_temp_free(input_overflow);
12698 tcg_temp_free(t4);
12699 tcg_temp_free(t3);
12700 tcg_temp_free(t2);
12701 } else if (rs < rt && rs == 0) {
12702 /* OPC_BEQZALC, OPC_BNEZALC */
12703 if (opc == OPC_BEQZALC) {
12704 /* OPC_BEQZALC */
12705 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12706 } else {
12707 /* OPC_BNEZALC */
12708 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12710 } else {
12711 /* OPC_BEQC, OPC_BNEC */
12712 if (opc == OPC_BEQC) {
12713 /* OPC_BEQC */
12714 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12715 } else {
12716 /* OPC_BNEC */
12717 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12720 break;
12721 case OPC_BEQZC:
12722 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12723 break;
12724 case OPC_BNEZC:
12725 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12726 break;
12727 default:
12728 MIPS_INVAL("Compact conditional branch/jump");
12729 generate_exception_end(ctx, EXCP_RI);
12730 goto out;
12733 /* Generating branch here as compact branches don't have delay slot */
12734 gen_goto_tb(ctx, 1, ctx->btarget);
12735 gen_set_label(fs);
12737 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12740 out:
12741 tcg_temp_free(t0);
12742 tcg_temp_free(t1);
12745 /* ISA extensions (ASEs) */
12746 /* MIPS16 extension to MIPS32 */
12748 /* MIPS16 major opcodes */
12749 enum {
12750 M16_OPC_ADDIUSP = 0x00,
12751 M16_OPC_ADDIUPC = 0x01,
12752 M16_OPC_B = 0x02,
12753 M16_OPC_JAL = 0x03,
12754 M16_OPC_BEQZ = 0x04,
12755 M16_OPC_BNEQZ = 0x05,
12756 M16_OPC_SHIFT = 0x06,
12757 M16_OPC_LD = 0x07,
12758 M16_OPC_RRIA = 0x08,
12759 M16_OPC_ADDIU8 = 0x09,
12760 M16_OPC_SLTI = 0x0a,
12761 M16_OPC_SLTIU = 0x0b,
12762 M16_OPC_I8 = 0x0c,
12763 M16_OPC_LI = 0x0d,
12764 M16_OPC_CMPI = 0x0e,
12765 M16_OPC_SD = 0x0f,
12766 M16_OPC_LB = 0x10,
12767 M16_OPC_LH = 0x11,
12768 M16_OPC_LWSP = 0x12,
12769 M16_OPC_LW = 0x13,
12770 M16_OPC_LBU = 0x14,
12771 M16_OPC_LHU = 0x15,
12772 M16_OPC_LWPC = 0x16,
12773 M16_OPC_LWU = 0x17,
12774 M16_OPC_SB = 0x18,
12775 M16_OPC_SH = 0x19,
12776 M16_OPC_SWSP = 0x1a,
12777 M16_OPC_SW = 0x1b,
12778 M16_OPC_RRR = 0x1c,
12779 M16_OPC_RR = 0x1d,
12780 M16_OPC_EXTEND = 0x1e,
12781 M16_OPC_I64 = 0x1f
12784 /* I8 funct field */
12785 enum {
12786 I8_BTEQZ = 0x0,
12787 I8_BTNEZ = 0x1,
12788 I8_SWRASP = 0x2,
12789 I8_ADJSP = 0x3,
12790 I8_SVRS = 0x4,
12791 I8_MOV32R = 0x5,
12792 I8_MOVR32 = 0x7
12795 /* RRR f field */
12796 enum {
12797 RRR_DADDU = 0x0,
12798 RRR_ADDU = 0x1,
12799 RRR_DSUBU = 0x2,
12800 RRR_SUBU = 0x3
12803 /* RR funct field */
12804 enum {
12805 RR_JR = 0x00,
12806 RR_SDBBP = 0x01,
12807 RR_SLT = 0x02,
12808 RR_SLTU = 0x03,
12809 RR_SLLV = 0x04,
12810 RR_BREAK = 0x05,
12811 RR_SRLV = 0x06,
12812 RR_SRAV = 0x07,
12813 RR_DSRL = 0x08,
12814 RR_CMP = 0x0a,
12815 RR_NEG = 0x0b,
12816 RR_AND = 0x0c,
12817 RR_OR = 0x0d,
12818 RR_XOR = 0x0e,
12819 RR_NOT = 0x0f,
12820 RR_MFHI = 0x10,
12821 RR_CNVT = 0x11,
12822 RR_MFLO = 0x12,
12823 RR_DSRA = 0x13,
12824 RR_DSLLV = 0x14,
12825 RR_DSRLV = 0x16,
12826 RR_DSRAV = 0x17,
12827 RR_MULT = 0x18,
12828 RR_MULTU = 0x19,
12829 RR_DIV = 0x1a,
12830 RR_DIVU = 0x1b,
12831 RR_DMULT = 0x1c,
12832 RR_DMULTU = 0x1d,
12833 RR_DDIV = 0x1e,
12834 RR_DDIVU = 0x1f
12837 /* I64 funct field */
12838 enum {
12839 I64_LDSP = 0x0,
12840 I64_SDSP = 0x1,
12841 I64_SDRASP = 0x2,
12842 I64_DADJSP = 0x3,
12843 I64_LDPC = 0x4,
12844 I64_DADDIU5 = 0x5,
12845 I64_DADDIUPC = 0x6,
12846 I64_DADDIUSP = 0x7
12849 /* RR ry field for CNVT */
12850 enum {
12851 RR_RY_CNVT_ZEB = 0x0,
12852 RR_RY_CNVT_ZEH = 0x1,
12853 RR_RY_CNVT_ZEW = 0x2,
12854 RR_RY_CNVT_SEB = 0x4,
12855 RR_RY_CNVT_SEH = 0x5,
12856 RR_RY_CNVT_SEW = 0x6,
12859 static int xlat (int r)
12861 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12863 return map[r];
12866 static void gen_mips16_save (DisasContext *ctx,
12867 int xsregs, int aregs,
12868 int do_ra, int do_s0, int do_s1,
12869 int framesize)
12871 TCGv t0 = tcg_temp_new();
12872 TCGv t1 = tcg_temp_new();
12873 TCGv t2 = tcg_temp_new();
12874 int args, astatic;
12876 switch (aregs) {
12877 case 0:
12878 case 1:
12879 case 2:
12880 case 3:
12881 case 11:
12882 args = 0;
12883 break;
12884 case 4:
12885 case 5:
12886 case 6:
12887 case 7:
12888 args = 1;
12889 break;
12890 case 8:
12891 case 9:
12892 case 10:
12893 args = 2;
12894 break;
12895 case 12:
12896 case 13:
12897 args = 3;
12898 break;
12899 case 14:
12900 args = 4;
12901 break;
12902 default:
12903 generate_exception_end(ctx, EXCP_RI);
12904 return;
12907 switch (args) {
12908 case 4:
12909 gen_base_offset_addr(ctx, t0, 29, 12);
12910 gen_load_gpr(t1, 7);
12911 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12912 /* Fall through */
12913 case 3:
12914 gen_base_offset_addr(ctx, t0, 29, 8);
12915 gen_load_gpr(t1, 6);
12916 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12917 /* Fall through */
12918 case 2:
12919 gen_base_offset_addr(ctx, t0, 29, 4);
12920 gen_load_gpr(t1, 5);
12921 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12922 /* Fall through */
12923 case 1:
12924 gen_base_offset_addr(ctx, t0, 29, 0);
12925 gen_load_gpr(t1, 4);
12926 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12929 gen_load_gpr(t0, 29);
12931 #define DECR_AND_STORE(reg) do { \
12932 tcg_gen_movi_tl(t2, -4); \
12933 gen_op_addr_add(ctx, t0, t0, t2); \
12934 gen_load_gpr(t1, reg); \
12935 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12936 } while (0)
12938 if (do_ra) {
12939 DECR_AND_STORE(31);
12942 switch (xsregs) {
12943 case 7:
12944 DECR_AND_STORE(30);
12945 /* Fall through */
12946 case 6:
12947 DECR_AND_STORE(23);
12948 /* Fall through */
12949 case 5:
12950 DECR_AND_STORE(22);
12951 /* Fall through */
12952 case 4:
12953 DECR_AND_STORE(21);
12954 /* Fall through */
12955 case 3:
12956 DECR_AND_STORE(20);
12957 /* Fall through */
12958 case 2:
12959 DECR_AND_STORE(19);
12960 /* Fall through */
12961 case 1:
12962 DECR_AND_STORE(18);
12965 if (do_s1) {
12966 DECR_AND_STORE(17);
12968 if (do_s0) {
12969 DECR_AND_STORE(16);
12972 switch (aregs) {
12973 case 0:
12974 case 4:
12975 case 8:
12976 case 12:
12977 case 14:
12978 astatic = 0;
12979 break;
12980 case 1:
12981 case 5:
12982 case 9:
12983 case 13:
12984 astatic = 1;
12985 break;
12986 case 2:
12987 case 6:
12988 case 10:
12989 astatic = 2;
12990 break;
12991 case 3:
12992 case 7:
12993 astatic = 3;
12994 break;
12995 case 11:
12996 astatic = 4;
12997 break;
12998 default:
12999 generate_exception_end(ctx, EXCP_RI);
13000 return;
13003 if (astatic > 0) {
13004 DECR_AND_STORE(7);
13005 if (astatic > 1) {
13006 DECR_AND_STORE(6);
13007 if (astatic > 2) {
13008 DECR_AND_STORE(5);
13009 if (astatic > 3) {
13010 DECR_AND_STORE(4);
13015 #undef DECR_AND_STORE
13017 tcg_gen_movi_tl(t2, -framesize);
13018 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13019 tcg_temp_free(t0);
13020 tcg_temp_free(t1);
13021 tcg_temp_free(t2);
13024 static void gen_mips16_restore (DisasContext *ctx,
13025 int xsregs, int aregs,
13026 int do_ra, int do_s0, int do_s1,
13027 int framesize)
13029 int astatic;
13030 TCGv t0 = tcg_temp_new();
13031 TCGv t1 = tcg_temp_new();
13032 TCGv t2 = tcg_temp_new();
13034 tcg_gen_movi_tl(t2, framesize);
13035 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13037 #define DECR_AND_LOAD(reg) do { \
13038 tcg_gen_movi_tl(t2, -4); \
13039 gen_op_addr_add(ctx, t0, t0, t2); \
13040 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13041 gen_store_gpr(t1, reg); \
13042 } while (0)
13044 if (do_ra) {
13045 DECR_AND_LOAD(31);
13048 switch (xsregs) {
13049 case 7:
13050 DECR_AND_LOAD(30);
13051 /* Fall through */
13052 case 6:
13053 DECR_AND_LOAD(23);
13054 /* Fall through */
13055 case 5:
13056 DECR_AND_LOAD(22);
13057 /* Fall through */
13058 case 4:
13059 DECR_AND_LOAD(21);
13060 /* Fall through */
13061 case 3:
13062 DECR_AND_LOAD(20);
13063 /* Fall through */
13064 case 2:
13065 DECR_AND_LOAD(19);
13066 /* Fall through */
13067 case 1:
13068 DECR_AND_LOAD(18);
13071 if (do_s1) {
13072 DECR_AND_LOAD(17);
13074 if (do_s0) {
13075 DECR_AND_LOAD(16);
13078 switch (aregs) {
13079 case 0:
13080 case 4:
13081 case 8:
13082 case 12:
13083 case 14:
13084 astatic = 0;
13085 break;
13086 case 1:
13087 case 5:
13088 case 9:
13089 case 13:
13090 astatic = 1;
13091 break;
13092 case 2:
13093 case 6:
13094 case 10:
13095 astatic = 2;
13096 break;
13097 case 3:
13098 case 7:
13099 astatic = 3;
13100 break;
13101 case 11:
13102 astatic = 4;
13103 break;
13104 default:
13105 generate_exception_end(ctx, EXCP_RI);
13106 return;
13109 if (astatic > 0) {
13110 DECR_AND_LOAD(7);
13111 if (astatic > 1) {
13112 DECR_AND_LOAD(6);
13113 if (astatic > 2) {
13114 DECR_AND_LOAD(5);
13115 if (astatic > 3) {
13116 DECR_AND_LOAD(4);
13121 #undef DECR_AND_LOAD
13123 tcg_gen_movi_tl(t2, framesize);
13124 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13125 tcg_temp_free(t0);
13126 tcg_temp_free(t1);
13127 tcg_temp_free(t2);
13130 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13131 int is_64_bit, int extended)
13133 TCGv t0;
13135 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13136 generate_exception_end(ctx, EXCP_RI);
13137 return;
13140 t0 = tcg_temp_new();
13142 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13143 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13144 if (!is_64_bit) {
13145 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13148 tcg_temp_free(t0);
13151 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13152 int16_t offset)
13154 TCGv_i32 t0 = tcg_const_i32(op);
13155 TCGv t1 = tcg_temp_new();
13156 gen_base_offset_addr(ctx, t1, base, offset);
13157 gen_helper_cache(cpu_env, t1, t0);
13160 #if defined(TARGET_MIPS64)
13161 static void decode_i64_mips16 (DisasContext *ctx,
13162 int ry, int funct, int16_t offset,
13163 int extended)
13165 switch (funct) {
13166 case I64_LDSP:
13167 check_insn(ctx, ISA_MIPS3);
13168 check_mips_64(ctx);
13169 offset = extended ? offset : offset << 3;
13170 gen_ld(ctx, OPC_LD, ry, 29, offset);
13171 break;
13172 case I64_SDSP:
13173 check_insn(ctx, ISA_MIPS3);
13174 check_mips_64(ctx);
13175 offset = extended ? offset : offset << 3;
13176 gen_st(ctx, OPC_SD, ry, 29, offset);
13177 break;
13178 case I64_SDRASP:
13179 check_insn(ctx, ISA_MIPS3);
13180 check_mips_64(ctx);
13181 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13182 gen_st(ctx, OPC_SD, 31, 29, offset);
13183 break;
13184 case I64_DADJSP:
13185 check_insn(ctx, ISA_MIPS3);
13186 check_mips_64(ctx);
13187 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13188 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13189 break;
13190 case I64_LDPC:
13191 check_insn(ctx, ISA_MIPS3);
13192 check_mips_64(ctx);
13193 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13194 generate_exception_end(ctx, EXCP_RI);
13195 } else {
13196 offset = extended ? offset : offset << 3;
13197 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13199 break;
13200 case I64_DADDIU5:
13201 check_insn(ctx, ISA_MIPS3);
13202 check_mips_64(ctx);
13203 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13204 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13205 break;
13206 case I64_DADDIUPC:
13207 check_insn(ctx, ISA_MIPS3);
13208 check_mips_64(ctx);
13209 offset = extended ? offset : offset << 2;
13210 gen_addiupc(ctx, ry, offset, 1, extended);
13211 break;
13212 case I64_DADDIUSP:
13213 check_insn(ctx, ISA_MIPS3);
13214 check_mips_64(ctx);
13215 offset = extended ? offset : offset << 2;
13216 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13217 break;
13220 #endif
13222 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13224 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13225 int op, rx, ry, funct, sa;
13226 int16_t imm, offset;
13228 ctx->opcode = (ctx->opcode << 16) | extend;
13229 op = (ctx->opcode >> 11) & 0x1f;
13230 sa = (ctx->opcode >> 22) & 0x1f;
13231 funct = (ctx->opcode >> 8) & 0x7;
13232 rx = xlat((ctx->opcode >> 8) & 0x7);
13233 ry = xlat((ctx->opcode >> 5) & 0x7);
13234 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13235 | ((ctx->opcode >> 21) & 0x3f) << 5
13236 | (ctx->opcode & 0x1f));
13238 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13239 counterparts. */
13240 switch (op) {
13241 case M16_OPC_ADDIUSP:
13242 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13243 break;
13244 case M16_OPC_ADDIUPC:
13245 gen_addiupc(ctx, rx, imm, 0, 1);
13246 break;
13247 case M16_OPC_B:
13248 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13249 /* No delay slot, so just process as a normal instruction */
13250 break;
13251 case M16_OPC_BEQZ:
13252 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13253 /* No delay slot, so just process as a normal instruction */
13254 break;
13255 case M16_OPC_BNEQZ:
13256 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13257 /* No delay slot, so just process as a normal instruction */
13258 break;
13259 case M16_OPC_SHIFT:
13260 switch (ctx->opcode & 0x3) {
13261 case 0x0:
13262 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13263 break;
13264 case 0x1:
13265 #if defined(TARGET_MIPS64)
13266 check_mips_64(ctx);
13267 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13268 #else
13269 generate_exception_end(ctx, EXCP_RI);
13270 #endif
13271 break;
13272 case 0x2:
13273 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13274 break;
13275 case 0x3:
13276 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13277 break;
13279 break;
13280 #if defined(TARGET_MIPS64)
13281 case M16_OPC_LD:
13282 check_insn(ctx, ISA_MIPS3);
13283 check_mips_64(ctx);
13284 gen_ld(ctx, OPC_LD, ry, rx, offset);
13285 break;
13286 #endif
13287 case M16_OPC_RRIA:
13288 imm = ctx->opcode & 0xf;
13289 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13290 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13291 imm = (int16_t) (imm << 1) >> 1;
13292 if ((ctx->opcode >> 4) & 0x1) {
13293 #if defined(TARGET_MIPS64)
13294 check_mips_64(ctx);
13295 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13296 #else
13297 generate_exception_end(ctx, EXCP_RI);
13298 #endif
13299 } else {
13300 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13302 break;
13303 case M16_OPC_ADDIU8:
13304 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13305 break;
13306 case M16_OPC_SLTI:
13307 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13308 break;
13309 case M16_OPC_SLTIU:
13310 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13311 break;
13312 case M16_OPC_I8:
13313 switch (funct) {
13314 case I8_BTEQZ:
13315 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13316 break;
13317 case I8_BTNEZ:
13318 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13319 break;
13320 case I8_SWRASP:
13321 gen_st(ctx, OPC_SW, 31, 29, imm);
13322 break;
13323 case I8_ADJSP:
13324 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13325 break;
13326 case I8_SVRS:
13327 check_insn(ctx, ISA_MIPS32);
13329 int xsregs = (ctx->opcode >> 24) & 0x7;
13330 int aregs = (ctx->opcode >> 16) & 0xf;
13331 int do_ra = (ctx->opcode >> 6) & 0x1;
13332 int do_s0 = (ctx->opcode >> 5) & 0x1;
13333 int do_s1 = (ctx->opcode >> 4) & 0x1;
13334 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13335 | (ctx->opcode & 0xf)) << 3;
13337 if (ctx->opcode & (1 << 7)) {
13338 gen_mips16_save(ctx, xsregs, aregs,
13339 do_ra, do_s0, do_s1,
13340 framesize);
13341 } else {
13342 gen_mips16_restore(ctx, xsregs, aregs,
13343 do_ra, do_s0, do_s1,
13344 framesize);
13347 break;
13348 default:
13349 generate_exception_end(ctx, EXCP_RI);
13350 break;
13352 break;
13353 case M16_OPC_LI:
13354 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13355 break;
13356 case M16_OPC_CMPI:
13357 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13358 break;
13359 #if defined(TARGET_MIPS64)
13360 case M16_OPC_SD:
13361 check_insn(ctx, ISA_MIPS3);
13362 check_mips_64(ctx);
13363 gen_st(ctx, OPC_SD, ry, rx, offset);
13364 break;
13365 #endif
13366 case M16_OPC_LB:
13367 gen_ld(ctx, OPC_LB, ry, rx, offset);
13368 break;
13369 case M16_OPC_LH:
13370 gen_ld(ctx, OPC_LH, ry, rx, offset);
13371 break;
13372 case M16_OPC_LWSP:
13373 gen_ld(ctx, OPC_LW, rx, 29, offset);
13374 break;
13375 case M16_OPC_LW:
13376 gen_ld(ctx, OPC_LW, ry, rx, offset);
13377 break;
13378 case M16_OPC_LBU:
13379 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13380 break;
13381 case M16_OPC_LHU:
13382 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13383 break;
13384 case M16_OPC_LWPC:
13385 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13386 break;
13387 #if defined(TARGET_MIPS64)
13388 case M16_OPC_LWU:
13389 check_insn(ctx, ISA_MIPS3);
13390 check_mips_64(ctx);
13391 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13392 break;
13393 #endif
13394 case M16_OPC_SB:
13395 gen_st(ctx, OPC_SB, ry, rx, offset);
13396 break;
13397 case M16_OPC_SH:
13398 gen_st(ctx, OPC_SH, ry, rx, offset);
13399 break;
13400 case M16_OPC_SWSP:
13401 gen_st(ctx, OPC_SW, rx, 29, offset);
13402 break;
13403 case M16_OPC_SW:
13404 gen_st(ctx, OPC_SW, ry, rx, offset);
13405 break;
13406 #if defined(TARGET_MIPS64)
13407 case M16_OPC_I64:
13408 decode_i64_mips16(ctx, ry, funct, offset, 1);
13409 break;
13410 #endif
13411 default:
13412 generate_exception_end(ctx, EXCP_RI);
13413 break;
13416 return 4;
13419 static inline bool is_uhi(int sdbbp_code)
13421 #ifdef CONFIG_USER_ONLY
13422 return false;
13423 #else
13424 return semihosting_enabled() && sdbbp_code == 1;
13425 #endif
13428 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13430 int rx, ry;
13431 int sa;
13432 int op, cnvt_op, op1, offset;
13433 int funct;
13434 int n_bytes;
13436 op = (ctx->opcode >> 11) & 0x1f;
13437 sa = (ctx->opcode >> 2) & 0x7;
13438 sa = sa == 0 ? 8 : sa;
13439 rx = xlat((ctx->opcode >> 8) & 0x7);
13440 cnvt_op = (ctx->opcode >> 5) & 0x7;
13441 ry = xlat((ctx->opcode >> 5) & 0x7);
13442 op1 = offset = ctx->opcode & 0x1f;
13444 n_bytes = 2;
13446 switch (op) {
13447 case M16_OPC_ADDIUSP:
13449 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13451 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13453 break;
13454 case M16_OPC_ADDIUPC:
13455 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13456 break;
13457 case M16_OPC_B:
13458 offset = (ctx->opcode & 0x7ff) << 1;
13459 offset = (int16_t)(offset << 4) >> 4;
13460 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13461 /* No delay slot, so just process as a normal instruction */
13462 break;
13463 case M16_OPC_JAL:
13464 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13465 offset = (((ctx->opcode & 0x1f) << 21)
13466 | ((ctx->opcode >> 5) & 0x1f) << 16
13467 | offset) << 2;
13468 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13469 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13470 n_bytes = 4;
13471 break;
13472 case M16_OPC_BEQZ:
13473 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13474 ((int8_t)ctx->opcode) << 1, 0);
13475 /* No delay slot, so just process as a normal instruction */
13476 break;
13477 case M16_OPC_BNEQZ:
13478 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13479 ((int8_t)ctx->opcode) << 1, 0);
13480 /* No delay slot, so just process as a normal instruction */
13481 break;
13482 case M16_OPC_SHIFT:
13483 switch (ctx->opcode & 0x3) {
13484 case 0x0:
13485 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13486 break;
13487 case 0x1:
13488 #if defined(TARGET_MIPS64)
13489 check_insn(ctx, ISA_MIPS3);
13490 check_mips_64(ctx);
13491 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13492 #else
13493 generate_exception_end(ctx, EXCP_RI);
13494 #endif
13495 break;
13496 case 0x2:
13497 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13498 break;
13499 case 0x3:
13500 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13501 break;
13503 break;
13504 #if defined(TARGET_MIPS64)
13505 case M16_OPC_LD:
13506 check_insn(ctx, ISA_MIPS3);
13507 check_mips_64(ctx);
13508 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13509 break;
13510 #endif
13511 case M16_OPC_RRIA:
13513 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13515 if ((ctx->opcode >> 4) & 1) {
13516 #if defined(TARGET_MIPS64)
13517 check_insn(ctx, ISA_MIPS3);
13518 check_mips_64(ctx);
13519 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13520 #else
13521 generate_exception_end(ctx, EXCP_RI);
13522 #endif
13523 } else {
13524 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13527 break;
13528 case M16_OPC_ADDIU8:
13530 int16_t imm = (int8_t) ctx->opcode;
13532 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13534 break;
13535 case M16_OPC_SLTI:
13537 int16_t imm = (uint8_t) ctx->opcode;
13538 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13540 break;
13541 case M16_OPC_SLTIU:
13543 int16_t imm = (uint8_t) ctx->opcode;
13544 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13546 break;
13547 case M16_OPC_I8:
13549 int reg32;
13551 funct = (ctx->opcode >> 8) & 0x7;
13552 switch (funct) {
13553 case I8_BTEQZ:
13554 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13555 ((int8_t)ctx->opcode) << 1, 0);
13556 break;
13557 case I8_BTNEZ:
13558 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13559 ((int8_t)ctx->opcode) << 1, 0);
13560 break;
13561 case I8_SWRASP:
13562 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13563 break;
13564 case I8_ADJSP:
13565 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13566 ((int8_t)ctx->opcode) << 3);
13567 break;
13568 case I8_SVRS:
13569 check_insn(ctx, ISA_MIPS32);
13571 int do_ra = ctx->opcode & (1 << 6);
13572 int do_s0 = ctx->opcode & (1 << 5);
13573 int do_s1 = ctx->opcode & (1 << 4);
13574 int framesize = ctx->opcode & 0xf;
13576 if (framesize == 0) {
13577 framesize = 128;
13578 } else {
13579 framesize = framesize << 3;
13582 if (ctx->opcode & (1 << 7)) {
13583 gen_mips16_save(ctx, 0, 0,
13584 do_ra, do_s0, do_s1, framesize);
13585 } else {
13586 gen_mips16_restore(ctx, 0, 0,
13587 do_ra, do_s0, do_s1, framesize);
13590 break;
13591 case I8_MOV32R:
13593 int rz = xlat(ctx->opcode & 0x7);
13595 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13596 ((ctx->opcode >> 5) & 0x7);
13597 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13599 break;
13600 case I8_MOVR32:
13601 reg32 = ctx->opcode & 0x1f;
13602 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13603 break;
13604 default:
13605 generate_exception_end(ctx, EXCP_RI);
13606 break;
13609 break;
13610 case M16_OPC_LI:
13612 int16_t imm = (uint8_t) ctx->opcode;
13614 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13616 break;
13617 case M16_OPC_CMPI:
13619 int16_t imm = (uint8_t) ctx->opcode;
13620 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13622 break;
13623 #if defined(TARGET_MIPS64)
13624 case M16_OPC_SD:
13625 check_insn(ctx, ISA_MIPS3);
13626 check_mips_64(ctx);
13627 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13628 break;
13629 #endif
13630 case M16_OPC_LB:
13631 gen_ld(ctx, OPC_LB, ry, rx, offset);
13632 break;
13633 case M16_OPC_LH:
13634 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13635 break;
13636 case M16_OPC_LWSP:
13637 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13638 break;
13639 case M16_OPC_LW:
13640 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13641 break;
13642 case M16_OPC_LBU:
13643 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13644 break;
13645 case M16_OPC_LHU:
13646 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13647 break;
13648 case M16_OPC_LWPC:
13649 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13650 break;
13651 #if defined (TARGET_MIPS64)
13652 case M16_OPC_LWU:
13653 check_insn(ctx, ISA_MIPS3);
13654 check_mips_64(ctx);
13655 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13656 break;
13657 #endif
13658 case M16_OPC_SB:
13659 gen_st(ctx, OPC_SB, ry, rx, offset);
13660 break;
13661 case M16_OPC_SH:
13662 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13663 break;
13664 case M16_OPC_SWSP:
13665 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13666 break;
13667 case M16_OPC_SW:
13668 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13669 break;
13670 case M16_OPC_RRR:
13672 int rz = xlat((ctx->opcode >> 2) & 0x7);
13673 int mips32_op;
13675 switch (ctx->opcode & 0x3) {
13676 case RRR_ADDU:
13677 mips32_op = OPC_ADDU;
13678 break;
13679 case RRR_SUBU:
13680 mips32_op = OPC_SUBU;
13681 break;
13682 #if defined(TARGET_MIPS64)
13683 case RRR_DADDU:
13684 mips32_op = OPC_DADDU;
13685 check_insn(ctx, ISA_MIPS3);
13686 check_mips_64(ctx);
13687 break;
13688 case RRR_DSUBU:
13689 mips32_op = OPC_DSUBU;
13690 check_insn(ctx, ISA_MIPS3);
13691 check_mips_64(ctx);
13692 break;
13693 #endif
13694 default:
13695 generate_exception_end(ctx, EXCP_RI);
13696 goto done;
13699 gen_arith(ctx, mips32_op, rz, rx, ry);
13700 done:
13703 break;
13704 case M16_OPC_RR:
13705 switch (op1) {
13706 case RR_JR:
13708 int nd = (ctx->opcode >> 7) & 0x1;
13709 int link = (ctx->opcode >> 6) & 0x1;
13710 int ra = (ctx->opcode >> 5) & 0x1;
13712 if (nd) {
13713 check_insn(ctx, ISA_MIPS32);
13716 if (link) {
13717 op = OPC_JALR;
13718 } else {
13719 op = OPC_JR;
13722 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13723 (nd ? 0 : 2));
13725 break;
13726 case RR_SDBBP:
13727 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13728 gen_helper_do_semihosting(cpu_env);
13729 } else {
13730 /* XXX: not clear which exception should be raised
13731 * when in debug mode...
13733 check_insn(ctx, ISA_MIPS32);
13734 generate_exception_end(ctx, EXCP_DBp);
13736 break;
13737 case RR_SLT:
13738 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13739 break;
13740 case RR_SLTU:
13741 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13742 break;
13743 case RR_BREAK:
13744 generate_exception_end(ctx, EXCP_BREAK);
13745 break;
13746 case RR_SLLV:
13747 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13748 break;
13749 case RR_SRLV:
13750 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13751 break;
13752 case RR_SRAV:
13753 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13754 break;
13755 #if defined (TARGET_MIPS64)
13756 case RR_DSRL:
13757 check_insn(ctx, ISA_MIPS3);
13758 check_mips_64(ctx);
13759 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13760 break;
13761 #endif
13762 case RR_CMP:
13763 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13764 break;
13765 case RR_NEG:
13766 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13767 break;
13768 case RR_AND:
13769 gen_logic(ctx, OPC_AND, rx, rx, ry);
13770 break;
13771 case RR_OR:
13772 gen_logic(ctx, OPC_OR, rx, rx, ry);
13773 break;
13774 case RR_XOR:
13775 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13776 break;
13777 case RR_NOT:
13778 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13779 break;
13780 case RR_MFHI:
13781 gen_HILO(ctx, OPC_MFHI, 0, rx);
13782 break;
13783 case RR_CNVT:
13784 check_insn(ctx, ISA_MIPS32);
13785 switch (cnvt_op) {
13786 case RR_RY_CNVT_ZEB:
13787 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13788 break;
13789 case RR_RY_CNVT_ZEH:
13790 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13791 break;
13792 case RR_RY_CNVT_SEB:
13793 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13794 break;
13795 case RR_RY_CNVT_SEH:
13796 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13797 break;
13798 #if defined (TARGET_MIPS64)
13799 case RR_RY_CNVT_ZEW:
13800 check_insn(ctx, ISA_MIPS64);
13801 check_mips_64(ctx);
13802 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13803 break;
13804 case RR_RY_CNVT_SEW:
13805 check_insn(ctx, ISA_MIPS64);
13806 check_mips_64(ctx);
13807 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13808 break;
13809 #endif
13810 default:
13811 generate_exception_end(ctx, EXCP_RI);
13812 break;
13814 break;
13815 case RR_MFLO:
13816 gen_HILO(ctx, OPC_MFLO, 0, rx);
13817 break;
13818 #if defined (TARGET_MIPS64)
13819 case RR_DSRA:
13820 check_insn(ctx, ISA_MIPS3);
13821 check_mips_64(ctx);
13822 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13823 break;
13824 case RR_DSLLV:
13825 check_insn(ctx, ISA_MIPS3);
13826 check_mips_64(ctx);
13827 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13828 break;
13829 case RR_DSRLV:
13830 check_insn(ctx, ISA_MIPS3);
13831 check_mips_64(ctx);
13832 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13833 break;
13834 case RR_DSRAV:
13835 check_insn(ctx, ISA_MIPS3);
13836 check_mips_64(ctx);
13837 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13838 break;
13839 #endif
13840 case RR_MULT:
13841 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13842 break;
13843 case RR_MULTU:
13844 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13845 break;
13846 case RR_DIV:
13847 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13848 break;
13849 case RR_DIVU:
13850 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13851 break;
13852 #if defined (TARGET_MIPS64)
13853 case RR_DMULT:
13854 check_insn(ctx, ISA_MIPS3);
13855 check_mips_64(ctx);
13856 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13857 break;
13858 case RR_DMULTU:
13859 check_insn(ctx, ISA_MIPS3);
13860 check_mips_64(ctx);
13861 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13862 break;
13863 case RR_DDIV:
13864 check_insn(ctx, ISA_MIPS3);
13865 check_mips_64(ctx);
13866 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13867 break;
13868 case RR_DDIVU:
13869 check_insn(ctx, ISA_MIPS3);
13870 check_mips_64(ctx);
13871 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13872 break;
13873 #endif
13874 default:
13875 generate_exception_end(ctx, EXCP_RI);
13876 break;
13878 break;
13879 case M16_OPC_EXTEND:
13880 decode_extended_mips16_opc(env, ctx);
13881 n_bytes = 4;
13882 break;
13883 #if defined(TARGET_MIPS64)
13884 case M16_OPC_I64:
13885 funct = (ctx->opcode >> 8) & 0x7;
13886 decode_i64_mips16(ctx, ry, funct, offset, 0);
13887 break;
13888 #endif
13889 default:
13890 generate_exception_end(ctx, EXCP_RI);
13891 break;
13894 return n_bytes;
13897 /* microMIPS extension to MIPS32/MIPS64 */
13900 * microMIPS32/microMIPS64 major opcodes
13902 * 1. MIPS Architecture for Programmers Volume II-B:
13903 * The microMIPS32 Instruction Set (Revision 3.05)
13905 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13907 * 2. MIPS Architecture For Programmers Volume II-A:
13908 * The MIPS64 Instruction Set (Revision 3.51)
13911 enum {
13912 POOL32A = 0x00,
13913 POOL16A = 0x01,
13914 LBU16 = 0x02,
13915 MOVE16 = 0x03,
13916 ADDI32 = 0x04,
13917 R6_LUI = 0x04,
13918 AUI = 0x04,
13919 LBU32 = 0x05,
13920 SB32 = 0x06,
13921 LB32 = 0x07,
13923 POOL32B = 0x08,
13924 POOL16B = 0x09,
13925 LHU16 = 0x0a,
13926 ANDI16 = 0x0b,
13927 ADDIU32 = 0x0c,
13928 LHU32 = 0x0d,
13929 SH32 = 0x0e,
13930 LH32 = 0x0f,
13932 POOL32I = 0x10,
13933 POOL16C = 0x11,
13934 LWSP16 = 0x12,
13935 POOL16D = 0x13,
13936 ORI32 = 0x14,
13937 POOL32F = 0x15,
13938 POOL32S = 0x16, /* MIPS64 */
13939 DADDIU32 = 0x17, /* MIPS64 */
13941 POOL32C = 0x18,
13942 LWGP16 = 0x19,
13943 LW16 = 0x1a,
13944 POOL16E = 0x1b,
13945 XORI32 = 0x1c,
13946 JALS32 = 0x1d,
13947 BOVC = 0x1d,
13948 BEQC = 0x1d,
13949 BEQZALC = 0x1d,
13950 ADDIUPC = 0x1e,
13951 PCREL = 0x1e,
13952 BNVC = 0x1f,
13953 BNEC = 0x1f,
13954 BNEZALC = 0x1f,
13956 R6_BEQZC = 0x20,
13957 JIC = 0x20,
13958 POOL16F = 0x21,
13959 SB16 = 0x22,
13960 BEQZ16 = 0x23,
13961 BEQZC16 = 0x23,
13962 SLTI32 = 0x24,
13963 BEQ32 = 0x25,
13964 BC = 0x25,
13965 SWC132 = 0x26,
13966 LWC132 = 0x27,
13968 /* 0x29 is reserved */
13969 RES_29 = 0x29,
13970 R6_BNEZC = 0x28,
13971 JIALC = 0x28,
13972 SH16 = 0x2a,
13973 BNEZ16 = 0x2b,
13974 BNEZC16 = 0x2b,
13975 SLTIU32 = 0x2c,
13976 BNE32 = 0x2d,
13977 BALC = 0x2d,
13978 SDC132 = 0x2e,
13979 LDC132 = 0x2f,
13981 /* 0x31 is reserved */
13982 RES_31 = 0x31,
13983 BLEZALC = 0x30,
13984 BGEZALC = 0x30,
13985 BGEUC = 0x30,
13986 SWSP16 = 0x32,
13987 B16 = 0x33,
13988 BC16 = 0x33,
13989 ANDI32 = 0x34,
13990 J32 = 0x35,
13991 BGTZC = 0x35,
13992 BLTZC = 0x35,
13993 BLTC = 0x35,
13994 SD32 = 0x36, /* MIPS64 */
13995 LD32 = 0x37, /* MIPS64 */
13997 /* 0x39 is reserved */
13998 RES_39 = 0x39,
13999 BGTZALC = 0x38,
14000 BLTZALC = 0x38,
14001 BLTUC = 0x38,
14002 SW16 = 0x3a,
14003 LI16 = 0x3b,
14004 JALX32 = 0x3c,
14005 JAL32 = 0x3d,
14006 BLEZC = 0x3d,
14007 BGEZC = 0x3d,
14008 BGEC = 0x3d,
14009 SW32 = 0x3e,
14010 LW32 = 0x3f
14013 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14014 enum {
14015 ADDIUPC_00 = 0x00,
14016 ADDIUPC_01 = 0x01,
14017 ADDIUPC_02 = 0x02,
14018 ADDIUPC_03 = 0x03,
14019 ADDIUPC_04 = 0x04,
14020 ADDIUPC_05 = 0x05,
14021 ADDIUPC_06 = 0x06,
14022 ADDIUPC_07 = 0x07,
14023 AUIPC = 0x1e,
14024 ALUIPC = 0x1f,
14025 LWPC_08 = 0x08,
14026 LWPC_09 = 0x09,
14027 LWPC_0A = 0x0A,
14028 LWPC_0B = 0x0B,
14029 LWPC_0C = 0x0C,
14030 LWPC_0D = 0x0D,
14031 LWPC_0E = 0x0E,
14032 LWPC_0F = 0x0F,
14035 /* POOL32A encoding of minor opcode field */
14037 enum {
14038 /* These opcodes are distinguished only by bits 9..6; those bits are
14039 * what are recorded below. */
14040 SLL32 = 0x0,
14041 SRL32 = 0x1,
14042 SRA = 0x2,
14043 ROTR = 0x3,
14044 SELEQZ = 0x5,
14045 SELNEZ = 0x6,
14046 R6_RDHWR = 0x7,
14048 SLLV = 0x0,
14049 SRLV = 0x1,
14050 SRAV = 0x2,
14051 ROTRV = 0x3,
14052 ADD = 0x4,
14053 ADDU32 = 0x5,
14054 SUB = 0x6,
14055 SUBU32 = 0x7,
14056 MUL = 0x8,
14057 AND = 0x9,
14058 OR32 = 0xa,
14059 NOR = 0xb,
14060 XOR32 = 0xc,
14061 SLT = 0xd,
14062 SLTU = 0xe,
14064 MOVN = 0x0,
14065 R6_MUL = 0x0,
14066 MOVZ = 0x1,
14067 MUH = 0x1,
14068 MULU = 0x2,
14069 MUHU = 0x3,
14070 LWXS = 0x4,
14071 R6_DIV = 0x4,
14072 MOD = 0x5,
14073 R6_DIVU = 0x6,
14074 MODU = 0x7,
14076 /* The following can be distinguished by their lower 6 bits. */
14077 BREAK32 = 0x07,
14078 INS = 0x0c,
14079 LSA = 0x0f,
14080 ALIGN = 0x1f,
14081 EXT = 0x2c,
14082 POOL32AXF = 0x3c,
14083 SIGRIE = 0x3f
14086 /* POOL32AXF encoding of minor opcode field extension */
14089 * 1. MIPS Architecture for Programmers Volume II-B:
14090 * The microMIPS32 Instruction Set (Revision 3.05)
14092 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14094 * 2. MIPS Architecture for Programmers VolumeIV-e:
14095 * The MIPS DSP Application-Specific Extension
14096 * to the microMIPS32 Architecture (Revision 2.34)
14098 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14101 enum {
14102 /* bits 11..6 */
14103 TEQ = 0x00,
14104 TGE = 0x08,
14105 TGEU = 0x10,
14106 TLT = 0x20,
14107 TLTU = 0x28,
14108 TNE = 0x30,
14110 MFC0 = 0x03,
14111 MTC0 = 0x0b,
14113 /* begin of microMIPS32 DSP */
14115 /* bits 13..12 for 0x01 */
14116 MFHI_ACC = 0x0,
14117 MFLO_ACC = 0x1,
14118 MTHI_ACC = 0x2,
14119 MTLO_ACC = 0x3,
14121 /* bits 13..12 for 0x2a */
14122 MADD_ACC = 0x0,
14123 MADDU_ACC = 0x1,
14124 MSUB_ACC = 0x2,
14125 MSUBU_ACC = 0x3,
14127 /* bits 13..12 for 0x32 */
14128 MULT_ACC = 0x0,
14129 MULTU_ACC = 0x1,
14131 /* end of microMIPS32 DSP */
14133 /* bits 15..12 for 0x2c */
14134 BITSWAP = 0x0,
14135 SEB = 0x2,
14136 SEH = 0x3,
14137 CLO = 0x4,
14138 CLZ = 0x5,
14139 RDHWR = 0x6,
14140 WSBH = 0x7,
14141 MULT = 0x8,
14142 MULTU = 0x9,
14143 DIV = 0xa,
14144 DIVU = 0xb,
14145 MADD = 0xc,
14146 MADDU = 0xd,
14147 MSUB = 0xe,
14148 MSUBU = 0xf,
14150 /* bits 15..12 for 0x34 */
14151 MFC2 = 0x4,
14152 MTC2 = 0x5,
14153 MFHC2 = 0x8,
14154 MTHC2 = 0x9,
14155 CFC2 = 0xc,
14156 CTC2 = 0xd,
14158 /* bits 15..12 for 0x3c */
14159 JALR = 0x0,
14160 JR = 0x0, /* alias */
14161 JALRC = 0x0,
14162 JRC = 0x0,
14163 JALR_HB = 0x1,
14164 JALRC_HB = 0x1,
14165 JALRS = 0x4,
14166 JALRS_HB = 0x5,
14168 /* bits 15..12 for 0x05 */
14169 RDPGPR = 0xe,
14170 WRPGPR = 0xf,
14172 /* bits 15..12 for 0x0d */
14173 TLBP = 0x0,
14174 TLBR = 0x1,
14175 TLBWI = 0x2,
14176 TLBWR = 0x3,
14177 TLBINV = 0x4,
14178 TLBINVF = 0x5,
14179 WAIT = 0x9,
14180 IRET = 0xd,
14181 DERET = 0xe,
14182 ERET = 0xf,
14184 /* bits 15..12 for 0x15 */
14185 DMT = 0x0,
14186 DVPE = 0x1,
14187 EMT = 0x2,
14188 EVPE = 0x3,
14190 /* bits 15..12 for 0x1d */
14191 DI = 0x4,
14192 EI = 0x5,
14194 /* bits 15..12 for 0x2d */
14195 SYNC = 0x6,
14196 SYSCALL = 0x8,
14197 SDBBP = 0xd,
14199 /* bits 15..12 for 0x35 */
14200 MFHI32 = 0x0,
14201 MFLO32 = 0x1,
14202 MTHI32 = 0x2,
14203 MTLO32 = 0x3,
14206 /* POOL32B encoding of minor opcode field (bits 15..12) */
14208 enum {
14209 LWC2 = 0x0,
14210 LWP = 0x1,
14211 LDP = 0x4,
14212 LWM32 = 0x5,
14213 CACHE = 0x6,
14214 LDM = 0x7,
14215 SWC2 = 0x8,
14216 SWP = 0x9,
14217 SDP = 0xc,
14218 SWM32 = 0xd,
14219 SDM = 0xf
14222 /* POOL32C encoding of minor opcode field (bits 15..12) */
14224 enum {
14225 LWL = 0x0,
14226 SWL = 0x8,
14227 LWR = 0x1,
14228 SWR = 0x9,
14229 PREF = 0x2,
14230 ST_EVA = 0xa,
14231 LL = 0x3,
14232 SC = 0xb,
14233 LDL = 0x4,
14234 SDL = 0xc,
14235 LDR = 0x5,
14236 SDR = 0xd,
14237 LD_EVA = 0x6,
14238 LWU = 0xe,
14239 LLD = 0x7,
14240 SCD = 0xf
14243 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14245 enum {
14246 LBUE = 0x0,
14247 LHUE = 0x1,
14248 LWLE = 0x2,
14249 LWRE = 0x3,
14250 LBE = 0x4,
14251 LHE = 0x5,
14252 LLE = 0x6,
14253 LWE = 0x7,
14256 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14258 enum {
14259 SWLE = 0x0,
14260 SWRE = 0x1,
14261 PREFE = 0x2,
14262 CACHEE = 0x3,
14263 SBE = 0x4,
14264 SHE = 0x5,
14265 SCE = 0x6,
14266 SWE = 0x7,
14269 /* POOL32F encoding of minor opcode field (bits 5..0) */
14271 enum {
14272 /* These are the bit 7..6 values */
14273 ADD_FMT = 0x0,
14275 SUB_FMT = 0x1,
14277 MUL_FMT = 0x2,
14279 DIV_FMT = 0x3,
14281 /* These are the bit 8..6 values */
14282 MOVN_FMT = 0x0,
14283 RSQRT2_FMT = 0x0,
14284 MOVF_FMT = 0x0,
14285 RINT_FMT = 0x0,
14286 SELNEZ_FMT = 0x0,
14288 MOVZ_FMT = 0x1,
14289 LWXC1 = 0x1,
14290 MOVT_FMT = 0x1,
14291 CLASS_FMT = 0x1,
14292 SELEQZ_FMT = 0x1,
14294 PLL_PS = 0x2,
14295 SWXC1 = 0x2,
14296 SEL_FMT = 0x2,
14298 PLU_PS = 0x3,
14299 LDXC1 = 0x3,
14301 MOVN_FMT_04 = 0x4,
14302 PUL_PS = 0x4,
14303 SDXC1 = 0x4,
14304 RECIP2_FMT = 0x4,
14306 MOVZ_FMT_05 = 0x05,
14307 PUU_PS = 0x5,
14308 LUXC1 = 0x5,
14310 CVT_PS_S = 0x6,
14311 SUXC1 = 0x6,
14312 ADDR_PS = 0x6,
14313 PREFX = 0x6,
14314 MADDF_FMT = 0x6,
14316 MULR_PS = 0x7,
14317 MSUBF_FMT = 0x7,
14319 MADD_S = 0x01,
14320 MADD_D = 0x09,
14321 MADD_PS = 0x11,
14322 ALNV_PS = 0x19,
14323 MSUB_S = 0x21,
14324 MSUB_D = 0x29,
14325 MSUB_PS = 0x31,
14327 NMADD_S = 0x02,
14328 NMADD_D = 0x0a,
14329 NMADD_PS = 0x12,
14330 NMSUB_S = 0x22,
14331 NMSUB_D = 0x2a,
14332 NMSUB_PS = 0x32,
14334 MIN_FMT = 0x3,
14335 MAX_FMT = 0xb,
14336 MINA_FMT = 0x23,
14337 MAXA_FMT = 0x2b,
14338 POOL32FXF = 0x3b,
14340 CABS_COND_FMT = 0x1c, /* MIPS3D */
14341 C_COND_FMT = 0x3c,
14343 CMP_CONDN_S = 0x5,
14344 CMP_CONDN_D = 0x15
14347 /* POOL32Fxf encoding of minor opcode extension field */
14349 enum {
14350 CVT_L = 0x04,
14351 RSQRT_FMT = 0x08,
14352 FLOOR_L = 0x0c,
14353 CVT_PW_PS = 0x1c,
14354 CVT_W = 0x24,
14355 SQRT_FMT = 0x28,
14356 FLOOR_W = 0x2c,
14357 CVT_PS_PW = 0x3c,
14358 CFC1 = 0x40,
14359 RECIP_FMT = 0x48,
14360 CEIL_L = 0x4c,
14361 CTC1 = 0x60,
14362 CEIL_W = 0x6c,
14363 MFC1 = 0x80,
14364 CVT_S_PL = 0x84,
14365 TRUNC_L = 0x8c,
14366 MTC1 = 0xa0,
14367 CVT_S_PU = 0xa4,
14368 TRUNC_W = 0xac,
14369 MFHC1 = 0xc0,
14370 ROUND_L = 0xcc,
14371 MTHC1 = 0xe0,
14372 ROUND_W = 0xec,
14374 MOV_FMT = 0x01,
14375 MOVF = 0x05,
14376 ABS_FMT = 0x0d,
14377 RSQRT1_FMT = 0x1d,
14378 MOVT = 0x25,
14379 NEG_FMT = 0x2d,
14380 CVT_D = 0x4d,
14381 RECIP1_FMT = 0x5d,
14382 CVT_S = 0x6d
14385 /* POOL32I encoding of minor opcode field (bits 25..21) */
14387 enum {
14388 BLTZ = 0x00,
14389 BLTZAL = 0x01,
14390 BGEZ = 0x02,
14391 BGEZAL = 0x03,
14392 BLEZ = 0x04,
14393 BNEZC = 0x05,
14394 BGTZ = 0x06,
14395 BEQZC = 0x07,
14396 TLTI = 0x08,
14397 BC1EQZC = 0x08,
14398 TGEI = 0x09,
14399 BC1NEZC = 0x09,
14400 TLTIU = 0x0a,
14401 BC2EQZC = 0x0a,
14402 TGEIU = 0x0b,
14403 BC2NEZC = 0x0a,
14404 TNEI = 0x0c,
14405 R6_SYNCI = 0x0c,
14406 LUI = 0x0d,
14407 TEQI = 0x0e,
14408 SYNCI = 0x10,
14409 BLTZALS = 0x11,
14410 BGEZALS = 0x13,
14411 BC2F = 0x14,
14412 BC2T = 0x15,
14413 BPOSGE64 = 0x1a,
14414 BPOSGE32 = 0x1b,
14415 /* These overlap and are distinguished by bit16 of the instruction */
14416 BC1F = 0x1c,
14417 BC1T = 0x1d,
14418 BC1ANY2F = 0x1c,
14419 BC1ANY2T = 0x1d,
14420 BC1ANY4F = 0x1e,
14421 BC1ANY4T = 0x1f
14424 /* POOL16A encoding of minor opcode field */
14426 enum {
14427 ADDU16 = 0x0,
14428 SUBU16 = 0x1
14431 /* POOL16B encoding of minor opcode field */
14433 enum {
14434 SLL16 = 0x0,
14435 SRL16 = 0x1
14438 /* POOL16C encoding of minor opcode field */
14440 enum {
14441 NOT16 = 0x00,
14442 XOR16 = 0x04,
14443 AND16 = 0x08,
14444 OR16 = 0x0c,
14445 LWM16 = 0x10,
14446 SWM16 = 0x14,
14447 JR16 = 0x18,
14448 JRC16 = 0x1a,
14449 JALR16 = 0x1c,
14450 JALR16S = 0x1e,
14451 MFHI16 = 0x20,
14452 MFLO16 = 0x24,
14453 BREAK16 = 0x28,
14454 SDBBP16 = 0x2c,
14455 JRADDIUSP = 0x30
14458 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14460 enum {
14461 R6_NOT16 = 0x00,
14462 R6_AND16 = 0x01,
14463 R6_LWM16 = 0x02,
14464 R6_JRC16 = 0x03,
14465 MOVEP = 0x04,
14466 MOVEP_05 = 0x05,
14467 MOVEP_06 = 0x06,
14468 MOVEP_07 = 0x07,
14469 R6_XOR16 = 0x08,
14470 R6_OR16 = 0x09,
14471 R6_SWM16 = 0x0a,
14472 JALRC16 = 0x0b,
14473 MOVEP_0C = 0x0c,
14474 MOVEP_0D = 0x0d,
14475 MOVEP_0E = 0x0e,
14476 MOVEP_0F = 0x0f,
14477 JRCADDIUSP = 0x13,
14478 R6_BREAK16 = 0x1b,
14479 R6_SDBBP16 = 0x3b
14482 /* POOL16D encoding of minor opcode field */
14484 enum {
14485 ADDIUS5 = 0x0,
14486 ADDIUSP = 0x1
14489 /* POOL16E encoding of minor opcode field */
14491 enum {
14492 ADDIUR2 = 0x0,
14493 ADDIUR1SP = 0x1
14496 static int mmreg (int r)
14498 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14500 return map[r];
14503 /* Used for 16-bit store instructions. */
14504 static int mmreg2 (int r)
14506 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14508 return map[r];
14511 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14512 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14513 #define uMIPS_RS2(op) uMIPS_RS(op)
14514 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14515 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14516 #define uMIPS_RS5(op) (op & 0x1f)
14518 /* Signed immediate */
14519 #define SIMM(op, start, width) \
14520 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14521 << (32-width)) \
14522 >> (32-width))
14523 /* Zero-extended immediate */
14524 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14526 static void gen_addiur1sp(DisasContext *ctx)
14528 int rd = mmreg(uMIPS_RD(ctx->opcode));
14530 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14533 static void gen_addiur2(DisasContext *ctx)
14535 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14536 int rd = mmreg(uMIPS_RD(ctx->opcode));
14537 int rs = mmreg(uMIPS_RS(ctx->opcode));
14539 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14542 static void gen_addiusp(DisasContext *ctx)
14544 int encoded = ZIMM(ctx->opcode, 1, 9);
14545 int decoded;
14547 if (encoded <= 1) {
14548 decoded = 256 + encoded;
14549 } else if (encoded <= 255) {
14550 decoded = encoded;
14551 } else if (encoded <= 509) {
14552 decoded = encoded - 512;
14553 } else {
14554 decoded = encoded - 768;
14557 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14560 static void gen_addius5(DisasContext *ctx)
14562 int imm = SIMM(ctx->opcode, 1, 4);
14563 int rd = (ctx->opcode >> 5) & 0x1f;
14565 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14568 static void gen_andi16(DisasContext *ctx)
14570 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14571 31, 32, 63, 64, 255, 32768, 65535 };
14572 int rd = mmreg(uMIPS_RD(ctx->opcode));
14573 int rs = mmreg(uMIPS_RS(ctx->opcode));
14574 int encoded = ZIMM(ctx->opcode, 0, 4);
14576 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14579 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14580 int base, int16_t offset)
14582 TCGv t0, t1;
14583 TCGv_i32 t2;
14585 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14586 generate_exception_end(ctx, EXCP_RI);
14587 return;
14590 t0 = tcg_temp_new();
14592 gen_base_offset_addr(ctx, t0, base, offset);
14594 t1 = tcg_const_tl(reglist);
14595 t2 = tcg_const_i32(ctx->mem_idx);
14597 save_cpu_state(ctx, 1);
14598 switch (opc) {
14599 case LWM32:
14600 gen_helper_lwm(cpu_env, t0, t1, t2);
14601 break;
14602 case SWM32:
14603 gen_helper_swm(cpu_env, t0, t1, t2);
14604 break;
14605 #ifdef TARGET_MIPS64
14606 case LDM:
14607 gen_helper_ldm(cpu_env, t0, t1, t2);
14608 break;
14609 case SDM:
14610 gen_helper_sdm(cpu_env, t0, t1, t2);
14611 break;
14612 #endif
14614 tcg_temp_free(t0);
14615 tcg_temp_free(t1);
14616 tcg_temp_free_i32(t2);
14620 static void gen_pool16c_insn(DisasContext *ctx)
14622 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14623 int rs = mmreg(ctx->opcode & 0x7);
14625 switch (((ctx->opcode) >> 4) & 0x3f) {
14626 case NOT16 + 0:
14627 case NOT16 + 1:
14628 case NOT16 + 2:
14629 case NOT16 + 3:
14630 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14631 break;
14632 case XOR16 + 0:
14633 case XOR16 + 1:
14634 case XOR16 + 2:
14635 case XOR16 + 3:
14636 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14637 break;
14638 case AND16 + 0:
14639 case AND16 + 1:
14640 case AND16 + 2:
14641 case AND16 + 3:
14642 gen_logic(ctx, OPC_AND, rd, rd, rs);
14643 break;
14644 case OR16 + 0:
14645 case OR16 + 1:
14646 case OR16 + 2:
14647 case OR16 + 3:
14648 gen_logic(ctx, OPC_OR, rd, rd, rs);
14649 break;
14650 case LWM16 + 0:
14651 case LWM16 + 1:
14652 case LWM16 + 2:
14653 case LWM16 + 3:
14655 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14656 int offset = ZIMM(ctx->opcode, 0, 4);
14658 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14659 29, offset << 2);
14661 break;
14662 case SWM16 + 0:
14663 case SWM16 + 1:
14664 case SWM16 + 2:
14665 case SWM16 + 3:
14667 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14668 int offset = ZIMM(ctx->opcode, 0, 4);
14670 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14671 29, offset << 2);
14673 break;
14674 case JR16 + 0:
14675 case JR16 + 1:
14677 int reg = ctx->opcode & 0x1f;
14679 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14681 break;
14682 case JRC16 + 0:
14683 case JRC16 + 1:
14685 int reg = ctx->opcode & 0x1f;
14686 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14687 /* Let normal delay slot handling in our caller take us
14688 to the branch target. */
14690 break;
14691 case JALR16 + 0:
14692 case JALR16 + 1:
14693 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14694 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14695 break;
14696 case JALR16S + 0:
14697 case JALR16S + 1:
14698 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14699 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14700 break;
14701 case MFHI16 + 0:
14702 case MFHI16 + 1:
14703 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14704 break;
14705 case MFLO16 + 0:
14706 case MFLO16 + 1:
14707 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14708 break;
14709 case BREAK16:
14710 generate_exception_end(ctx, EXCP_BREAK);
14711 break;
14712 case SDBBP16:
14713 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14714 gen_helper_do_semihosting(cpu_env);
14715 } else {
14716 /* XXX: not clear which exception should be raised
14717 * when in debug mode...
14719 check_insn(ctx, ISA_MIPS32);
14720 generate_exception_end(ctx, EXCP_DBp);
14722 break;
14723 case JRADDIUSP + 0:
14724 case JRADDIUSP + 1:
14726 int imm = ZIMM(ctx->opcode, 0, 5);
14727 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14728 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14729 /* Let normal delay slot handling in our caller take us
14730 to the branch target. */
14732 break;
14733 default:
14734 generate_exception_end(ctx, EXCP_RI);
14735 break;
14739 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14740 int enc_rs)
14742 int rd, rs, re, rt;
14743 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14744 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14745 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14746 rd = rd_enc[enc_dest];
14747 re = re_enc[enc_dest];
14748 rs = rs_rt_enc[enc_rs];
14749 rt = rs_rt_enc[enc_rt];
14750 if (rs) {
14751 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14752 } else {
14753 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14755 if (rt) {
14756 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14757 } else {
14758 tcg_gen_movi_tl(cpu_gpr[re], 0);
14762 static void gen_pool16c_r6_insn(DisasContext *ctx)
14764 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14765 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14767 switch (ctx->opcode & 0xf) {
14768 case R6_NOT16:
14769 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14770 break;
14771 case R6_AND16:
14772 gen_logic(ctx, OPC_AND, rt, rt, rs);
14773 break;
14774 case R6_LWM16:
14776 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14777 int offset = extract32(ctx->opcode, 4, 4);
14778 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14780 break;
14781 case R6_JRC16: /* JRCADDIUSP */
14782 if ((ctx->opcode >> 4) & 1) {
14783 /* JRCADDIUSP */
14784 int imm = extract32(ctx->opcode, 5, 5);
14785 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14786 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14787 } else {
14788 /* JRC16 */
14789 rs = extract32(ctx->opcode, 5, 5);
14790 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14792 break;
14793 case MOVEP:
14794 case MOVEP_05:
14795 case MOVEP_06:
14796 case MOVEP_07:
14797 case MOVEP_0C:
14798 case MOVEP_0D:
14799 case MOVEP_0E:
14800 case MOVEP_0F:
14802 int enc_dest = uMIPS_RD(ctx->opcode);
14803 int enc_rt = uMIPS_RS2(ctx->opcode);
14804 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14805 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14807 break;
14808 case R6_XOR16:
14809 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14810 break;
14811 case R6_OR16:
14812 gen_logic(ctx, OPC_OR, rt, rt, rs);
14813 break;
14814 case R6_SWM16:
14816 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14817 int offset = extract32(ctx->opcode, 4, 4);
14818 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14820 break;
14821 case JALRC16: /* BREAK16, SDBBP16 */
14822 switch (ctx->opcode & 0x3f) {
14823 case JALRC16:
14824 case JALRC16 + 0x20:
14825 /* JALRC16 */
14826 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14827 31, 0, 0);
14828 break;
14829 case R6_BREAK16:
14830 /* BREAK16 */
14831 generate_exception(ctx, EXCP_BREAK);
14832 break;
14833 case R6_SDBBP16:
14834 /* SDBBP16 */
14835 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14836 gen_helper_do_semihosting(cpu_env);
14837 } else {
14838 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14839 generate_exception(ctx, EXCP_RI);
14840 } else {
14841 generate_exception(ctx, EXCP_DBp);
14844 break;
14846 break;
14847 default:
14848 generate_exception(ctx, EXCP_RI);
14849 break;
14853 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14855 TCGv t0 = tcg_temp_new();
14856 TCGv t1 = tcg_temp_new();
14858 gen_load_gpr(t0, base);
14860 if (index != 0) {
14861 gen_load_gpr(t1, index);
14862 tcg_gen_shli_tl(t1, t1, 2);
14863 gen_op_addr_add(ctx, t0, t1, t0);
14866 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14867 gen_store_gpr(t1, rd);
14869 tcg_temp_free(t0);
14870 tcg_temp_free(t1);
14873 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14874 int base, int16_t offset)
14876 TCGv t0, t1;
14878 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14879 generate_exception_end(ctx, EXCP_RI);
14880 return;
14883 t0 = tcg_temp_new();
14884 t1 = tcg_temp_new();
14886 gen_base_offset_addr(ctx, t0, base, offset);
14888 switch (opc) {
14889 case LWP:
14890 if (rd == base) {
14891 generate_exception_end(ctx, EXCP_RI);
14892 return;
14894 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14895 gen_store_gpr(t1, rd);
14896 tcg_gen_movi_tl(t1, 4);
14897 gen_op_addr_add(ctx, t0, t0, t1);
14898 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14899 gen_store_gpr(t1, rd+1);
14900 break;
14901 case SWP:
14902 gen_load_gpr(t1, rd);
14903 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14904 tcg_gen_movi_tl(t1, 4);
14905 gen_op_addr_add(ctx, t0, t0, t1);
14906 gen_load_gpr(t1, rd+1);
14907 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14908 break;
14909 #ifdef TARGET_MIPS64
14910 case LDP:
14911 if (rd == base) {
14912 generate_exception_end(ctx, EXCP_RI);
14913 return;
14915 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14916 gen_store_gpr(t1, rd);
14917 tcg_gen_movi_tl(t1, 8);
14918 gen_op_addr_add(ctx, t0, t0, t1);
14919 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14920 gen_store_gpr(t1, rd+1);
14921 break;
14922 case SDP:
14923 gen_load_gpr(t1, rd);
14924 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14925 tcg_gen_movi_tl(t1, 8);
14926 gen_op_addr_add(ctx, t0, t0, t1);
14927 gen_load_gpr(t1, rd+1);
14928 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14929 break;
14930 #endif
14932 tcg_temp_free(t0);
14933 tcg_temp_free(t1);
14936 static void gen_sync(int stype)
14938 TCGBar tcg_mo = TCG_BAR_SC;
14940 switch (stype) {
14941 case 0x4: /* SYNC_WMB */
14942 tcg_mo |= TCG_MO_ST_ST;
14943 break;
14944 case 0x10: /* SYNC_MB */
14945 tcg_mo |= TCG_MO_ALL;
14946 break;
14947 case 0x11: /* SYNC_ACQUIRE */
14948 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14949 break;
14950 case 0x12: /* SYNC_RELEASE */
14951 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14952 break;
14953 case 0x13: /* SYNC_RMB */
14954 tcg_mo |= TCG_MO_LD_LD;
14955 break;
14956 default:
14957 tcg_mo |= TCG_MO_ALL;
14958 break;
14961 tcg_gen_mb(tcg_mo);
14964 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14966 int extension = (ctx->opcode >> 6) & 0x3f;
14967 int minor = (ctx->opcode >> 12) & 0xf;
14968 uint32_t mips32_op;
14970 switch (extension) {
14971 case TEQ:
14972 mips32_op = OPC_TEQ;
14973 goto do_trap;
14974 case TGE:
14975 mips32_op = OPC_TGE;
14976 goto do_trap;
14977 case TGEU:
14978 mips32_op = OPC_TGEU;
14979 goto do_trap;
14980 case TLT:
14981 mips32_op = OPC_TLT;
14982 goto do_trap;
14983 case TLTU:
14984 mips32_op = OPC_TLTU;
14985 goto do_trap;
14986 case TNE:
14987 mips32_op = OPC_TNE;
14988 do_trap:
14989 gen_trap(ctx, mips32_op, rs, rt, -1);
14990 break;
14991 #ifndef CONFIG_USER_ONLY
14992 case MFC0:
14993 case MFC0 + 32:
14994 check_cp0_enabled(ctx);
14995 if (rt == 0) {
14996 /* Treat as NOP. */
14997 break;
14999 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15000 break;
15001 case MTC0:
15002 case MTC0 + 32:
15003 check_cp0_enabled(ctx);
15005 TCGv t0 = tcg_temp_new();
15007 gen_load_gpr(t0, rt);
15008 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15009 tcg_temp_free(t0);
15011 break;
15012 #endif
15013 case 0x2a:
15014 switch (minor & 3) {
15015 case MADD_ACC:
15016 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15017 break;
15018 case MADDU_ACC:
15019 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15020 break;
15021 case MSUB_ACC:
15022 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15023 break;
15024 case MSUBU_ACC:
15025 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15026 break;
15027 default:
15028 goto pool32axf_invalid;
15030 break;
15031 case 0x32:
15032 switch (minor & 3) {
15033 case MULT_ACC:
15034 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15035 break;
15036 case MULTU_ACC:
15037 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15038 break;
15039 default:
15040 goto pool32axf_invalid;
15042 break;
15043 case 0x2c:
15044 switch (minor) {
15045 case BITSWAP:
15046 check_insn(ctx, ISA_MIPS32R6);
15047 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15048 break;
15049 case SEB:
15050 gen_bshfl(ctx, OPC_SEB, rs, rt);
15051 break;
15052 case SEH:
15053 gen_bshfl(ctx, OPC_SEH, rs, rt);
15054 break;
15055 case CLO:
15056 mips32_op = OPC_CLO;
15057 goto do_cl;
15058 case CLZ:
15059 mips32_op = OPC_CLZ;
15060 do_cl:
15061 check_insn(ctx, ISA_MIPS32);
15062 gen_cl(ctx, mips32_op, rt, rs);
15063 break;
15064 case RDHWR:
15065 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15066 gen_rdhwr(ctx, rt, rs, 0);
15067 break;
15068 case WSBH:
15069 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15070 break;
15071 case MULT:
15072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15073 mips32_op = OPC_MULT;
15074 goto do_mul;
15075 case MULTU:
15076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15077 mips32_op = OPC_MULTU;
15078 goto do_mul;
15079 case DIV:
15080 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15081 mips32_op = OPC_DIV;
15082 goto do_div;
15083 case DIVU:
15084 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15085 mips32_op = OPC_DIVU;
15086 goto do_div;
15087 do_div:
15088 check_insn(ctx, ISA_MIPS32);
15089 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15090 break;
15091 case MADD:
15092 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15093 mips32_op = OPC_MADD;
15094 goto do_mul;
15095 case MADDU:
15096 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15097 mips32_op = OPC_MADDU;
15098 goto do_mul;
15099 case MSUB:
15100 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15101 mips32_op = OPC_MSUB;
15102 goto do_mul;
15103 case MSUBU:
15104 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15105 mips32_op = OPC_MSUBU;
15106 do_mul:
15107 check_insn(ctx, ISA_MIPS32);
15108 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15109 break;
15110 default:
15111 goto pool32axf_invalid;
15113 break;
15114 case 0x34:
15115 switch (minor) {
15116 case MFC2:
15117 case MTC2:
15118 case MFHC2:
15119 case MTHC2:
15120 case CFC2:
15121 case CTC2:
15122 generate_exception_err(ctx, EXCP_CpU, 2);
15123 break;
15124 default:
15125 goto pool32axf_invalid;
15127 break;
15128 case 0x3c:
15129 switch (minor) {
15130 case JALR: /* JALRC */
15131 case JALR_HB: /* JALRC_HB */
15132 if (ctx->insn_flags & ISA_MIPS32R6) {
15133 /* JALRC, JALRC_HB */
15134 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15135 } else {
15136 /* JALR, JALR_HB */
15137 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15138 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15140 break;
15141 case JALRS:
15142 case JALRS_HB:
15143 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15144 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15145 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15146 break;
15147 default:
15148 goto pool32axf_invalid;
15150 break;
15151 case 0x05:
15152 switch (minor) {
15153 case RDPGPR:
15154 check_cp0_enabled(ctx);
15155 check_insn(ctx, ISA_MIPS32R2);
15156 gen_load_srsgpr(rs, rt);
15157 break;
15158 case WRPGPR:
15159 check_cp0_enabled(ctx);
15160 check_insn(ctx, ISA_MIPS32R2);
15161 gen_store_srsgpr(rs, rt);
15162 break;
15163 default:
15164 goto pool32axf_invalid;
15166 break;
15167 #ifndef CONFIG_USER_ONLY
15168 case 0x0d:
15169 switch (minor) {
15170 case TLBP:
15171 mips32_op = OPC_TLBP;
15172 goto do_cp0;
15173 case TLBR:
15174 mips32_op = OPC_TLBR;
15175 goto do_cp0;
15176 case TLBWI:
15177 mips32_op = OPC_TLBWI;
15178 goto do_cp0;
15179 case TLBWR:
15180 mips32_op = OPC_TLBWR;
15181 goto do_cp0;
15182 case TLBINV:
15183 mips32_op = OPC_TLBINV;
15184 goto do_cp0;
15185 case TLBINVF:
15186 mips32_op = OPC_TLBINVF;
15187 goto do_cp0;
15188 case WAIT:
15189 mips32_op = OPC_WAIT;
15190 goto do_cp0;
15191 case DERET:
15192 mips32_op = OPC_DERET;
15193 goto do_cp0;
15194 case ERET:
15195 mips32_op = OPC_ERET;
15196 do_cp0:
15197 gen_cp0(env, ctx, mips32_op, rt, rs);
15198 break;
15199 default:
15200 goto pool32axf_invalid;
15202 break;
15203 case 0x1d:
15204 switch (minor) {
15205 case DI:
15206 check_cp0_enabled(ctx);
15208 TCGv t0 = tcg_temp_new();
15210 save_cpu_state(ctx, 1);
15211 gen_helper_di(t0, cpu_env);
15212 gen_store_gpr(t0, rs);
15213 /* Stop translation as we may have switched the execution mode */
15214 ctx->base.is_jmp = DISAS_STOP;
15215 tcg_temp_free(t0);
15217 break;
15218 case EI:
15219 check_cp0_enabled(ctx);
15221 TCGv t0 = tcg_temp_new();
15223 save_cpu_state(ctx, 1);
15224 gen_helper_ei(t0, cpu_env);
15225 gen_store_gpr(t0, rs);
15226 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15227 of translated code to check for pending interrupts. */
15228 gen_save_pc(ctx->base.pc_next + 4);
15229 ctx->base.is_jmp = DISAS_EXIT;
15230 tcg_temp_free(t0);
15232 break;
15233 default:
15234 goto pool32axf_invalid;
15236 break;
15237 #endif
15238 case 0x2d:
15239 switch (minor) {
15240 case SYNC:
15241 gen_sync(extract32(ctx->opcode, 16, 5));
15242 break;
15243 case SYSCALL:
15244 generate_exception_end(ctx, EXCP_SYSCALL);
15245 break;
15246 case SDBBP:
15247 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15248 gen_helper_do_semihosting(cpu_env);
15249 } else {
15250 check_insn(ctx, ISA_MIPS32);
15251 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15252 generate_exception_end(ctx, EXCP_RI);
15253 } else {
15254 generate_exception_end(ctx, EXCP_DBp);
15257 break;
15258 default:
15259 goto pool32axf_invalid;
15261 break;
15262 case 0x01:
15263 switch (minor & 3) {
15264 case MFHI_ACC:
15265 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15266 break;
15267 case MFLO_ACC:
15268 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15269 break;
15270 case MTHI_ACC:
15271 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15272 break;
15273 case MTLO_ACC:
15274 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15275 break;
15276 default:
15277 goto pool32axf_invalid;
15279 break;
15280 case 0x35:
15281 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15282 switch (minor) {
15283 case MFHI32:
15284 gen_HILO(ctx, OPC_MFHI, 0, rs);
15285 break;
15286 case MFLO32:
15287 gen_HILO(ctx, OPC_MFLO, 0, rs);
15288 break;
15289 case MTHI32:
15290 gen_HILO(ctx, OPC_MTHI, 0, rs);
15291 break;
15292 case MTLO32:
15293 gen_HILO(ctx, OPC_MTLO, 0, rs);
15294 break;
15295 default:
15296 goto pool32axf_invalid;
15298 break;
15299 default:
15300 pool32axf_invalid:
15301 MIPS_INVAL("pool32axf");
15302 generate_exception_end(ctx, EXCP_RI);
15303 break;
15307 /* Values for microMIPS fmt field. Variable-width, depending on which
15308 formats the instruction supports. */
15310 enum {
15311 FMT_SD_S = 0,
15312 FMT_SD_D = 1,
15314 FMT_SDPS_S = 0,
15315 FMT_SDPS_D = 1,
15316 FMT_SDPS_PS = 2,
15318 FMT_SWL_S = 0,
15319 FMT_SWL_W = 1,
15320 FMT_SWL_L = 2,
15322 FMT_DWL_D = 0,
15323 FMT_DWL_W = 1,
15324 FMT_DWL_L = 2
15327 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15329 int extension = (ctx->opcode >> 6) & 0x3ff;
15330 uint32_t mips32_op;
15332 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15333 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15334 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15336 switch (extension) {
15337 case FLOAT_1BIT_FMT(CFC1, 0):
15338 mips32_op = OPC_CFC1;
15339 goto do_cp1;
15340 case FLOAT_1BIT_FMT(CTC1, 0):
15341 mips32_op = OPC_CTC1;
15342 goto do_cp1;
15343 case FLOAT_1BIT_FMT(MFC1, 0):
15344 mips32_op = OPC_MFC1;
15345 goto do_cp1;
15346 case FLOAT_1BIT_FMT(MTC1, 0):
15347 mips32_op = OPC_MTC1;
15348 goto do_cp1;
15349 case FLOAT_1BIT_FMT(MFHC1, 0):
15350 mips32_op = OPC_MFHC1;
15351 goto do_cp1;
15352 case FLOAT_1BIT_FMT(MTHC1, 0):
15353 mips32_op = OPC_MTHC1;
15354 do_cp1:
15355 gen_cp1(ctx, mips32_op, rt, rs);
15356 break;
15358 /* Reciprocal square root */
15359 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15360 mips32_op = OPC_RSQRT_S;
15361 goto do_unaryfp;
15362 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15363 mips32_op = OPC_RSQRT_D;
15364 goto do_unaryfp;
15366 /* Square root */
15367 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15368 mips32_op = OPC_SQRT_S;
15369 goto do_unaryfp;
15370 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15371 mips32_op = OPC_SQRT_D;
15372 goto do_unaryfp;
15374 /* Reciprocal */
15375 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15376 mips32_op = OPC_RECIP_S;
15377 goto do_unaryfp;
15378 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15379 mips32_op = OPC_RECIP_D;
15380 goto do_unaryfp;
15382 /* Floor */
15383 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15384 mips32_op = OPC_FLOOR_L_S;
15385 goto do_unaryfp;
15386 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15387 mips32_op = OPC_FLOOR_L_D;
15388 goto do_unaryfp;
15389 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15390 mips32_op = OPC_FLOOR_W_S;
15391 goto do_unaryfp;
15392 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15393 mips32_op = OPC_FLOOR_W_D;
15394 goto do_unaryfp;
15396 /* Ceiling */
15397 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15398 mips32_op = OPC_CEIL_L_S;
15399 goto do_unaryfp;
15400 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15401 mips32_op = OPC_CEIL_L_D;
15402 goto do_unaryfp;
15403 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15404 mips32_op = OPC_CEIL_W_S;
15405 goto do_unaryfp;
15406 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15407 mips32_op = OPC_CEIL_W_D;
15408 goto do_unaryfp;
15410 /* Truncation */
15411 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15412 mips32_op = OPC_TRUNC_L_S;
15413 goto do_unaryfp;
15414 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15415 mips32_op = OPC_TRUNC_L_D;
15416 goto do_unaryfp;
15417 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15418 mips32_op = OPC_TRUNC_W_S;
15419 goto do_unaryfp;
15420 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15421 mips32_op = OPC_TRUNC_W_D;
15422 goto do_unaryfp;
15424 /* Round */
15425 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15426 mips32_op = OPC_ROUND_L_S;
15427 goto do_unaryfp;
15428 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15429 mips32_op = OPC_ROUND_L_D;
15430 goto do_unaryfp;
15431 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15432 mips32_op = OPC_ROUND_W_S;
15433 goto do_unaryfp;
15434 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15435 mips32_op = OPC_ROUND_W_D;
15436 goto do_unaryfp;
15438 /* Integer to floating-point conversion */
15439 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15440 mips32_op = OPC_CVT_L_S;
15441 goto do_unaryfp;
15442 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15443 mips32_op = OPC_CVT_L_D;
15444 goto do_unaryfp;
15445 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15446 mips32_op = OPC_CVT_W_S;
15447 goto do_unaryfp;
15448 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15449 mips32_op = OPC_CVT_W_D;
15450 goto do_unaryfp;
15452 /* Paired-foo conversions */
15453 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15454 mips32_op = OPC_CVT_S_PL;
15455 goto do_unaryfp;
15456 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15457 mips32_op = OPC_CVT_S_PU;
15458 goto do_unaryfp;
15459 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15460 mips32_op = OPC_CVT_PW_PS;
15461 goto do_unaryfp;
15462 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15463 mips32_op = OPC_CVT_PS_PW;
15464 goto do_unaryfp;
15466 /* Floating-point moves */
15467 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15468 mips32_op = OPC_MOV_S;
15469 goto do_unaryfp;
15470 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15471 mips32_op = OPC_MOV_D;
15472 goto do_unaryfp;
15473 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15474 mips32_op = OPC_MOV_PS;
15475 goto do_unaryfp;
15477 /* Absolute value */
15478 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15479 mips32_op = OPC_ABS_S;
15480 goto do_unaryfp;
15481 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15482 mips32_op = OPC_ABS_D;
15483 goto do_unaryfp;
15484 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15485 mips32_op = OPC_ABS_PS;
15486 goto do_unaryfp;
15488 /* Negation */
15489 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15490 mips32_op = OPC_NEG_S;
15491 goto do_unaryfp;
15492 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15493 mips32_op = OPC_NEG_D;
15494 goto do_unaryfp;
15495 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15496 mips32_op = OPC_NEG_PS;
15497 goto do_unaryfp;
15499 /* Reciprocal square root step */
15500 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15501 mips32_op = OPC_RSQRT1_S;
15502 goto do_unaryfp;
15503 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15504 mips32_op = OPC_RSQRT1_D;
15505 goto do_unaryfp;
15506 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15507 mips32_op = OPC_RSQRT1_PS;
15508 goto do_unaryfp;
15510 /* Reciprocal step */
15511 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15512 mips32_op = OPC_RECIP1_S;
15513 goto do_unaryfp;
15514 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15515 mips32_op = OPC_RECIP1_S;
15516 goto do_unaryfp;
15517 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15518 mips32_op = OPC_RECIP1_PS;
15519 goto do_unaryfp;
15521 /* Conversions from double */
15522 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15523 mips32_op = OPC_CVT_D_S;
15524 goto do_unaryfp;
15525 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15526 mips32_op = OPC_CVT_D_W;
15527 goto do_unaryfp;
15528 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15529 mips32_op = OPC_CVT_D_L;
15530 goto do_unaryfp;
15532 /* Conversions from single */
15533 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15534 mips32_op = OPC_CVT_S_D;
15535 goto do_unaryfp;
15536 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15537 mips32_op = OPC_CVT_S_W;
15538 goto do_unaryfp;
15539 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15540 mips32_op = OPC_CVT_S_L;
15541 do_unaryfp:
15542 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15543 break;
15545 /* Conditional moves on floating-point codes */
15546 case COND_FLOAT_MOV(MOVT, 0):
15547 case COND_FLOAT_MOV(MOVT, 1):
15548 case COND_FLOAT_MOV(MOVT, 2):
15549 case COND_FLOAT_MOV(MOVT, 3):
15550 case COND_FLOAT_MOV(MOVT, 4):
15551 case COND_FLOAT_MOV(MOVT, 5):
15552 case COND_FLOAT_MOV(MOVT, 6):
15553 case COND_FLOAT_MOV(MOVT, 7):
15554 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15555 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15556 break;
15557 case COND_FLOAT_MOV(MOVF, 0):
15558 case COND_FLOAT_MOV(MOVF, 1):
15559 case COND_FLOAT_MOV(MOVF, 2):
15560 case COND_FLOAT_MOV(MOVF, 3):
15561 case COND_FLOAT_MOV(MOVF, 4):
15562 case COND_FLOAT_MOV(MOVF, 5):
15563 case COND_FLOAT_MOV(MOVF, 6):
15564 case COND_FLOAT_MOV(MOVF, 7):
15565 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15566 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15567 break;
15568 default:
15569 MIPS_INVAL("pool32fxf");
15570 generate_exception_end(ctx, EXCP_RI);
15571 break;
15575 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15577 int32_t offset;
15578 uint16_t insn;
15579 int rt, rs, rd, rr;
15580 int16_t imm;
15581 uint32_t op, minor, minor2, mips32_op;
15582 uint32_t cond, fmt, cc;
15584 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15585 ctx->opcode = (ctx->opcode << 16) | insn;
15587 rt = (ctx->opcode >> 21) & 0x1f;
15588 rs = (ctx->opcode >> 16) & 0x1f;
15589 rd = (ctx->opcode >> 11) & 0x1f;
15590 rr = (ctx->opcode >> 6) & 0x1f;
15591 imm = (int16_t) ctx->opcode;
15593 op = (ctx->opcode >> 26) & 0x3f;
15594 switch (op) {
15595 case POOL32A:
15596 minor = ctx->opcode & 0x3f;
15597 switch (minor) {
15598 case 0x00:
15599 minor = (ctx->opcode >> 6) & 0xf;
15600 switch (minor) {
15601 case SLL32:
15602 mips32_op = OPC_SLL;
15603 goto do_shifti;
15604 case SRA:
15605 mips32_op = OPC_SRA;
15606 goto do_shifti;
15607 case SRL32:
15608 mips32_op = OPC_SRL;
15609 goto do_shifti;
15610 case ROTR:
15611 mips32_op = OPC_ROTR;
15612 do_shifti:
15613 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15614 break;
15615 case SELEQZ:
15616 check_insn(ctx, ISA_MIPS32R6);
15617 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15618 break;
15619 case SELNEZ:
15620 check_insn(ctx, ISA_MIPS32R6);
15621 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15622 break;
15623 case R6_RDHWR:
15624 check_insn(ctx, ISA_MIPS32R6);
15625 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15626 break;
15627 default:
15628 goto pool32a_invalid;
15630 break;
15631 case 0x10:
15632 minor = (ctx->opcode >> 6) & 0xf;
15633 switch (minor) {
15634 /* Arithmetic */
15635 case ADD:
15636 mips32_op = OPC_ADD;
15637 goto do_arith;
15638 case ADDU32:
15639 mips32_op = OPC_ADDU;
15640 goto do_arith;
15641 case SUB:
15642 mips32_op = OPC_SUB;
15643 goto do_arith;
15644 case SUBU32:
15645 mips32_op = OPC_SUBU;
15646 goto do_arith;
15647 case MUL:
15648 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15649 mips32_op = OPC_MUL;
15650 do_arith:
15651 gen_arith(ctx, mips32_op, rd, rs, rt);
15652 break;
15653 /* Shifts */
15654 case SLLV:
15655 mips32_op = OPC_SLLV;
15656 goto do_shift;
15657 case SRLV:
15658 mips32_op = OPC_SRLV;
15659 goto do_shift;
15660 case SRAV:
15661 mips32_op = OPC_SRAV;
15662 goto do_shift;
15663 case ROTRV:
15664 mips32_op = OPC_ROTRV;
15665 do_shift:
15666 gen_shift(ctx, mips32_op, rd, rs, rt);
15667 break;
15668 /* Logical operations */
15669 case AND:
15670 mips32_op = OPC_AND;
15671 goto do_logic;
15672 case OR32:
15673 mips32_op = OPC_OR;
15674 goto do_logic;
15675 case NOR:
15676 mips32_op = OPC_NOR;
15677 goto do_logic;
15678 case XOR32:
15679 mips32_op = OPC_XOR;
15680 do_logic:
15681 gen_logic(ctx, mips32_op, rd, rs, rt);
15682 break;
15683 /* Set less than */
15684 case SLT:
15685 mips32_op = OPC_SLT;
15686 goto do_slt;
15687 case SLTU:
15688 mips32_op = OPC_SLTU;
15689 do_slt:
15690 gen_slt(ctx, mips32_op, rd, rs, rt);
15691 break;
15692 default:
15693 goto pool32a_invalid;
15695 break;
15696 case 0x18:
15697 minor = (ctx->opcode >> 6) & 0xf;
15698 switch (minor) {
15699 /* Conditional moves */
15700 case MOVN: /* MUL */
15701 if (ctx->insn_flags & ISA_MIPS32R6) {
15702 /* MUL */
15703 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15704 } else {
15705 /* MOVN */
15706 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15708 break;
15709 case MOVZ: /* MUH */
15710 if (ctx->insn_flags & ISA_MIPS32R6) {
15711 /* MUH */
15712 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15713 } else {
15714 /* MOVZ */
15715 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15717 break;
15718 case MULU:
15719 check_insn(ctx, ISA_MIPS32R6);
15720 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15721 break;
15722 case MUHU:
15723 check_insn(ctx, ISA_MIPS32R6);
15724 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15725 break;
15726 case LWXS: /* DIV */
15727 if (ctx->insn_flags & ISA_MIPS32R6) {
15728 /* DIV */
15729 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15730 } else {
15731 /* LWXS */
15732 gen_ldxs(ctx, rs, rt, rd);
15734 break;
15735 case MOD:
15736 check_insn(ctx, ISA_MIPS32R6);
15737 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15738 break;
15739 case R6_DIVU:
15740 check_insn(ctx, ISA_MIPS32R6);
15741 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15742 break;
15743 case MODU:
15744 check_insn(ctx, ISA_MIPS32R6);
15745 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15746 break;
15747 default:
15748 goto pool32a_invalid;
15750 break;
15751 case INS:
15752 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15753 return;
15754 case LSA:
15755 check_insn(ctx, ISA_MIPS32R6);
15756 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15757 extract32(ctx->opcode, 9, 2));
15758 break;
15759 case ALIGN:
15760 check_insn(ctx, ISA_MIPS32R6);
15761 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15762 break;
15763 case EXT:
15764 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15765 return;
15766 case POOL32AXF:
15767 gen_pool32axf(env, ctx, rt, rs);
15768 break;
15769 case BREAK32:
15770 generate_exception_end(ctx, EXCP_BREAK);
15771 break;
15772 case SIGRIE:
15773 check_insn(ctx, ISA_MIPS32R6);
15774 generate_exception_end(ctx, EXCP_RI);
15775 break;
15776 default:
15777 pool32a_invalid:
15778 MIPS_INVAL("pool32a");
15779 generate_exception_end(ctx, EXCP_RI);
15780 break;
15782 break;
15783 case POOL32B:
15784 minor = (ctx->opcode >> 12) & 0xf;
15785 switch (minor) {
15786 case CACHE:
15787 check_cp0_enabled(ctx);
15788 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15789 gen_cache_operation(ctx, rt, rs, imm);
15791 break;
15792 case LWC2:
15793 case SWC2:
15794 /* COP2: Not implemented. */
15795 generate_exception_err(ctx, EXCP_CpU, 2);
15796 break;
15797 #ifdef TARGET_MIPS64
15798 case LDP:
15799 case SDP:
15800 check_insn(ctx, ISA_MIPS3);
15801 check_mips_64(ctx);
15802 #endif
15803 /* fall through */
15804 case LWP:
15805 case SWP:
15806 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15807 break;
15808 #ifdef TARGET_MIPS64
15809 case LDM:
15810 case SDM:
15811 check_insn(ctx, ISA_MIPS3);
15812 check_mips_64(ctx);
15813 #endif
15814 /* fall through */
15815 case LWM32:
15816 case SWM32:
15817 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15818 break;
15819 default:
15820 MIPS_INVAL("pool32b");
15821 generate_exception_end(ctx, EXCP_RI);
15822 break;
15824 break;
15825 case POOL32F:
15826 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15827 minor = ctx->opcode & 0x3f;
15828 check_cp1_enabled(ctx);
15829 switch (minor) {
15830 case ALNV_PS:
15831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15832 mips32_op = OPC_ALNV_PS;
15833 goto do_madd;
15834 case MADD_S:
15835 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15836 mips32_op = OPC_MADD_S;
15837 goto do_madd;
15838 case MADD_D:
15839 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15840 mips32_op = OPC_MADD_D;
15841 goto do_madd;
15842 case MADD_PS:
15843 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15844 mips32_op = OPC_MADD_PS;
15845 goto do_madd;
15846 case MSUB_S:
15847 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15848 mips32_op = OPC_MSUB_S;
15849 goto do_madd;
15850 case MSUB_D:
15851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15852 mips32_op = OPC_MSUB_D;
15853 goto do_madd;
15854 case MSUB_PS:
15855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15856 mips32_op = OPC_MSUB_PS;
15857 goto do_madd;
15858 case NMADD_S:
15859 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15860 mips32_op = OPC_NMADD_S;
15861 goto do_madd;
15862 case NMADD_D:
15863 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15864 mips32_op = OPC_NMADD_D;
15865 goto do_madd;
15866 case NMADD_PS:
15867 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15868 mips32_op = OPC_NMADD_PS;
15869 goto do_madd;
15870 case NMSUB_S:
15871 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15872 mips32_op = OPC_NMSUB_S;
15873 goto do_madd;
15874 case NMSUB_D:
15875 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15876 mips32_op = OPC_NMSUB_D;
15877 goto do_madd;
15878 case NMSUB_PS:
15879 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15880 mips32_op = OPC_NMSUB_PS;
15881 do_madd:
15882 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15883 break;
15884 case CABS_COND_FMT:
15885 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15886 cond = (ctx->opcode >> 6) & 0xf;
15887 cc = (ctx->opcode >> 13) & 0x7;
15888 fmt = (ctx->opcode >> 10) & 0x3;
15889 switch (fmt) {
15890 case 0x0:
15891 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15892 break;
15893 case 0x1:
15894 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15895 break;
15896 case 0x2:
15897 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15898 break;
15899 default:
15900 goto pool32f_invalid;
15902 break;
15903 case C_COND_FMT:
15904 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15905 cond = (ctx->opcode >> 6) & 0xf;
15906 cc = (ctx->opcode >> 13) & 0x7;
15907 fmt = (ctx->opcode >> 10) & 0x3;
15908 switch (fmt) {
15909 case 0x0:
15910 gen_cmp_s(ctx, cond, rt, rs, cc);
15911 break;
15912 case 0x1:
15913 gen_cmp_d(ctx, cond, rt, rs, cc);
15914 break;
15915 case 0x2:
15916 gen_cmp_ps(ctx, cond, rt, rs, cc);
15917 break;
15918 default:
15919 goto pool32f_invalid;
15921 break;
15922 case CMP_CONDN_S:
15923 check_insn(ctx, ISA_MIPS32R6);
15924 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15925 break;
15926 case CMP_CONDN_D:
15927 check_insn(ctx, ISA_MIPS32R6);
15928 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15929 break;
15930 case POOL32FXF:
15931 gen_pool32fxf(ctx, rt, rs);
15932 break;
15933 case 0x00:
15934 /* PLL foo */
15935 switch ((ctx->opcode >> 6) & 0x7) {
15936 case PLL_PS:
15937 mips32_op = OPC_PLL_PS;
15938 goto do_ps;
15939 case PLU_PS:
15940 mips32_op = OPC_PLU_PS;
15941 goto do_ps;
15942 case PUL_PS:
15943 mips32_op = OPC_PUL_PS;
15944 goto do_ps;
15945 case PUU_PS:
15946 mips32_op = OPC_PUU_PS;
15947 goto do_ps;
15948 case CVT_PS_S:
15949 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15950 mips32_op = OPC_CVT_PS_S;
15951 do_ps:
15952 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15953 break;
15954 default:
15955 goto pool32f_invalid;
15957 break;
15958 case MIN_FMT:
15959 check_insn(ctx, ISA_MIPS32R6);
15960 switch ((ctx->opcode >> 9) & 0x3) {
15961 case FMT_SDPS_S:
15962 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15963 break;
15964 case FMT_SDPS_D:
15965 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15966 break;
15967 default:
15968 goto pool32f_invalid;
15970 break;
15971 case 0x08:
15972 /* [LS][WDU]XC1 */
15973 switch ((ctx->opcode >> 6) & 0x7) {
15974 case LWXC1:
15975 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15976 mips32_op = OPC_LWXC1;
15977 goto do_ldst_cp1;
15978 case SWXC1:
15979 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15980 mips32_op = OPC_SWXC1;
15981 goto do_ldst_cp1;
15982 case LDXC1:
15983 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15984 mips32_op = OPC_LDXC1;
15985 goto do_ldst_cp1;
15986 case SDXC1:
15987 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15988 mips32_op = OPC_SDXC1;
15989 goto do_ldst_cp1;
15990 case LUXC1:
15991 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15992 mips32_op = OPC_LUXC1;
15993 goto do_ldst_cp1;
15994 case SUXC1:
15995 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15996 mips32_op = OPC_SUXC1;
15997 do_ldst_cp1:
15998 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15999 break;
16000 default:
16001 goto pool32f_invalid;
16003 break;
16004 case MAX_FMT:
16005 check_insn(ctx, ISA_MIPS32R6);
16006 switch ((ctx->opcode >> 9) & 0x3) {
16007 case FMT_SDPS_S:
16008 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16009 break;
16010 case FMT_SDPS_D:
16011 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16012 break;
16013 default:
16014 goto pool32f_invalid;
16016 break;
16017 case 0x18:
16018 /* 3D insns */
16019 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16020 fmt = (ctx->opcode >> 9) & 0x3;
16021 switch ((ctx->opcode >> 6) & 0x7) {
16022 case RSQRT2_FMT:
16023 switch (fmt) {
16024 case FMT_SDPS_S:
16025 mips32_op = OPC_RSQRT2_S;
16026 goto do_3d;
16027 case FMT_SDPS_D:
16028 mips32_op = OPC_RSQRT2_D;
16029 goto do_3d;
16030 case FMT_SDPS_PS:
16031 mips32_op = OPC_RSQRT2_PS;
16032 goto do_3d;
16033 default:
16034 goto pool32f_invalid;
16036 break;
16037 case RECIP2_FMT:
16038 switch (fmt) {
16039 case FMT_SDPS_S:
16040 mips32_op = OPC_RECIP2_S;
16041 goto do_3d;
16042 case FMT_SDPS_D:
16043 mips32_op = OPC_RECIP2_D;
16044 goto do_3d;
16045 case FMT_SDPS_PS:
16046 mips32_op = OPC_RECIP2_PS;
16047 goto do_3d;
16048 default:
16049 goto pool32f_invalid;
16051 break;
16052 case ADDR_PS:
16053 mips32_op = OPC_ADDR_PS;
16054 goto do_3d;
16055 case MULR_PS:
16056 mips32_op = OPC_MULR_PS;
16057 do_3d:
16058 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16059 break;
16060 default:
16061 goto pool32f_invalid;
16063 break;
16064 case 0x20:
16065 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16066 cc = (ctx->opcode >> 13) & 0x7;
16067 fmt = (ctx->opcode >> 9) & 0x3;
16068 switch ((ctx->opcode >> 6) & 0x7) {
16069 case MOVF_FMT: /* RINT_FMT */
16070 if (ctx->insn_flags & ISA_MIPS32R6) {
16071 /* RINT_FMT */
16072 switch (fmt) {
16073 case FMT_SDPS_S:
16074 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16075 break;
16076 case FMT_SDPS_D:
16077 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16078 break;
16079 default:
16080 goto pool32f_invalid;
16082 } else {
16083 /* MOVF_FMT */
16084 switch (fmt) {
16085 case FMT_SDPS_S:
16086 gen_movcf_s(ctx, rs, rt, cc, 0);
16087 break;
16088 case FMT_SDPS_D:
16089 gen_movcf_d(ctx, rs, rt, cc, 0);
16090 break;
16091 case FMT_SDPS_PS:
16092 check_ps(ctx);
16093 gen_movcf_ps(ctx, rs, rt, cc, 0);
16094 break;
16095 default:
16096 goto pool32f_invalid;
16099 break;
16100 case MOVT_FMT: /* CLASS_FMT */
16101 if (ctx->insn_flags & ISA_MIPS32R6) {
16102 /* CLASS_FMT */
16103 switch (fmt) {
16104 case FMT_SDPS_S:
16105 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16106 break;
16107 case FMT_SDPS_D:
16108 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16109 break;
16110 default:
16111 goto pool32f_invalid;
16113 } else {
16114 /* MOVT_FMT */
16115 switch (fmt) {
16116 case FMT_SDPS_S:
16117 gen_movcf_s(ctx, rs, rt, cc, 1);
16118 break;
16119 case FMT_SDPS_D:
16120 gen_movcf_d(ctx, rs, rt, cc, 1);
16121 break;
16122 case FMT_SDPS_PS:
16123 check_ps(ctx);
16124 gen_movcf_ps(ctx, rs, rt, cc, 1);
16125 break;
16126 default:
16127 goto pool32f_invalid;
16130 break;
16131 case PREFX:
16132 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16133 break;
16134 default:
16135 goto pool32f_invalid;
16137 break;
16138 #define FINSN_3ARG_SDPS(prfx) \
16139 switch ((ctx->opcode >> 8) & 0x3) { \
16140 case FMT_SDPS_S: \
16141 mips32_op = OPC_##prfx##_S; \
16142 goto do_fpop; \
16143 case FMT_SDPS_D: \
16144 mips32_op = OPC_##prfx##_D; \
16145 goto do_fpop; \
16146 case FMT_SDPS_PS: \
16147 check_ps(ctx); \
16148 mips32_op = OPC_##prfx##_PS; \
16149 goto do_fpop; \
16150 default: \
16151 goto pool32f_invalid; \
16153 case MINA_FMT:
16154 check_insn(ctx, ISA_MIPS32R6);
16155 switch ((ctx->opcode >> 9) & 0x3) {
16156 case FMT_SDPS_S:
16157 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16158 break;
16159 case FMT_SDPS_D:
16160 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16161 break;
16162 default:
16163 goto pool32f_invalid;
16165 break;
16166 case MAXA_FMT:
16167 check_insn(ctx, ISA_MIPS32R6);
16168 switch ((ctx->opcode >> 9) & 0x3) {
16169 case FMT_SDPS_S:
16170 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16171 break;
16172 case FMT_SDPS_D:
16173 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16174 break;
16175 default:
16176 goto pool32f_invalid;
16178 break;
16179 case 0x30:
16180 /* regular FP ops */
16181 switch ((ctx->opcode >> 6) & 0x3) {
16182 case ADD_FMT:
16183 FINSN_3ARG_SDPS(ADD);
16184 break;
16185 case SUB_FMT:
16186 FINSN_3ARG_SDPS(SUB);
16187 break;
16188 case MUL_FMT:
16189 FINSN_3ARG_SDPS(MUL);
16190 break;
16191 case DIV_FMT:
16192 fmt = (ctx->opcode >> 8) & 0x3;
16193 if (fmt == 1) {
16194 mips32_op = OPC_DIV_D;
16195 } else if (fmt == 0) {
16196 mips32_op = OPC_DIV_S;
16197 } else {
16198 goto pool32f_invalid;
16200 goto do_fpop;
16201 default:
16202 goto pool32f_invalid;
16204 break;
16205 case 0x38:
16206 /* cmovs */
16207 switch ((ctx->opcode >> 6) & 0x7) {
16208 case MOVN_FMT: /* SELEQZ_FMT */
16209 if (ctx->insn_flags & ISA_MIPS32R6) {
16210 /* SELEQZ_FMT */
16211 switch ((ctx->opcode >> 9) & 0x3) {
16212 case FMT_SDPS_S:
16213 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16214 break;
16215 case FMT_SDPS_D:
16216 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16217 break;
16218 default:
16219 goto pool32f_invalid;
16221 } else {
16222 /* MOVN_FMT */
16223 FINSN_3ARG_SDPS(MOVN);
16225 break;
16226 case MOVN_FMT_04:
16227 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16228 FINSN_3ARG_SDPS(MOVN);
16229 break;
16230 case MOVZ_FMT: /* SELNEZ_FMT */
16231 if (ctx->insn_flags & ISA_MIPS32R6) {
16232 /* SELNEZ_FMT */
16233 switch ((ctx->opcode >> 9) & 0x3) {
16234 case FMT_SDPS_S:
16235 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16236 break;
16237 case FMT_SDPS_D:
16238 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16239 break;
16240 default:
16241 goto pool32f_invalid;
16243 } else {
16244 /* MOVZ_FMT */
16245 FINSN_3ARG_SDPS(MOVZ);
16247 break;
16248 case MOVZ_FMT_05:
16249 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16250 FINSN_3ARG_SDPS(MOVZ);
16251 break;
16252 case SEL_FMT:
16253 check_insn(ctx, ISA_MIPS32R6);
16254 switch ((ctx->opcode >> 9) & 0x3) {
16255 case FMT_SDPS_S:
16256 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16257 break;
16258 case FMT_SDPS_D:
16259 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16260 break;
16261 default:
16262 goto pool32f_invalid;
16264 break;
16265 case MADDF_FMT:
16266 check_insn(ctx, ISA_MIPS32R6);
16267 switch ((ctx->opcode >> 9) & 0x3) {
16268 case FMT_SDPS_S:
16269 mips32_op = OPC_MADDF_S;
16270 goto do_fpop;
16271 case FMT_SDPS_D:
16272 mips32_op = OPC_MADDF_D;
16273 goto do_fpop;
16274 default:
16275 goto pool32f_invalid;
16277 break;
16278 case MSUBF_FMT:
16279 check_insn(ctx, ISA_MIPS32R6);
16280 switch ((ctx->opcode >> 9) & 0x3) {
16281 case FMT_SDPS_S:
16282 mips32_op = OPC_MSUBF_S;
16283 goto do_fpop;
16284 case FMT_SDPS_D:
16285 mips32_op = OPC_MSUBF_D;
16286 goto do_fpop;
16287 default:
16288 goto pool32f_invalid;
16290 break;
16291 default:
16292 goto pool32f_invalid;
16294 break;
16295 do_fpop:
16296 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16297 break;
16298 default:
16299 pool32f_invalid:
16300 MIPS_INVAL("pool32f");
16301 generate_exception_end(ctx, EXCP_RI);
16302 break;
16304 } else {
16305 generate_exception_err(ctx, EXCP_CpU, 1);
16307 break;
16308 case POOL32I:
16309 minor = (ctx->opcode >> 21) & 0x1f;
16310 switch (minor) {
16311 case BLTZ:
16312 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16313 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16314 break;
16315 case BLTZAL:
16316 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16317 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16318 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16319 break;
16320 case BLTZALS:
16321 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16322 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16323 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16324 break;
16325 case BGEZ:
16326 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16327 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16328 break;
16329 case BGEZAL:
16330 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16331 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16332 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16333 break;
16334 case BGEZALS:
16335 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16336 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16337 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16338 break;
16339 case BLEZ:
16340 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16341 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16342 break;
16343 case BGTZ:
16344 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16345 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16346 break;
16348 /* Traps */
16349 case TLTI: /* BC1EQZC */
16350 if (ctx->insn_flags & ISA_MIPS32R6) {
16351 /* BC1EQZC */
16352 check_cp1_enabled(ctx);
16353 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16354 } else {
16355 /* TLTI */
16356 mips32_op = OPC_TLTI;
16357 goto do_trapi;
16359 break;
16360 case TGEI: /* BC1NEZC */
16361 if (ctx->insn_flags & ISA_MIPS32R6) {
16362 /* BC1NEZC */
16363 check_cp1_enabled(ctx);
16364 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16365 } else {
16366 /* TGEI */
16367 mips32_op = OPC_TGEI;
16368 goto do_trapi;
16370 break;
16371 case TLTIU:
16372 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16373 mips32_op = OPC_TLTIU;
16374 goto do_trapi;
16375 case TGEIU:
16376 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16377 mips32_op = OPC_TGEIU;
16378 goto do_trapi;
16379 case TNEI: /* SYNCI */
16380 if (ctx->insn_flags & ISA_MIPS32R6) {
16381 /* SYNCI */
16382 /* Break the TB to be able to sync copied instructions
16383 immediately */
16384 ctx->base.is_jmp = DISAS_STOP;
16385 } else {
16386 /* TNEI */
16387 mips32_op = OPC_TNEI;
16388 goto do_trapi;
16390 break;
16391 case TEQI:
16392 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16393 mips32_op = OPC_TEQI;
16394 do_trapi:
16395 gen_trap(ctx, mips32_op, rs, -1, imm);
16396 break;
16398 case BNEZC:
16399 case BEQZC:
16400 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16401 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16402 4, rs, 0, imm << 1, 0);
16403 /* Compact branches don't have a delay slot, so just let
16404 the normal delay slot handling take us to the branch
16405 target. */
16406 break;
16407 case LUI:
16408 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16409 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16410 break;
16411 case SYNCI:
16412 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16413 /* Break the TB to be able to sync copied instructions
16414 immediately */
16415 ctx->base.is_jmp = DISAS_STOP;
16416 break;
16417 case BC2F:
16418 case BC2T:
16419 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16420 /* COP2: Not implemented. */
16421 generate_exception_err(ctx, EXCP_CpU, 2);
16422 break;
16423 case BC1F:
16424 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16425 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16426 goto do_cp1branch;
16427 case BC1T:
16428 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16429 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16430 goto do_cp1branch;
16431 case BC1ANY4F:
16432 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16433 mips32_op = OPC_BC1FANY4;
16434 goto do_cp1mips3d;
16435 case BC1ANY4T:
16436 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16437 mips32_op = OPC_BC1TANY4;
16438 do_cp1mips3d:
16439 check_cop1x(ctx);
16440 check_insn(ctx, ASE_MIPS3D);
16441 /* Fall through */
16442 do_cp1branch:
16443 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16444 check_cp1_enabled(ctx);
16445 gen_compute_branch1(ctx, mips32_op,
16446 (ctx->opcode >> 18) & 0x7, imm << 1);
16447 } else {
16448 generate_exception_err(ctx, EXCP_CpU, 1);
16450 break;
16451 case BPOSGE64:
16452 case BPOSGE32:
16453 /* MIPS DSP: not implemented */
16454 /* Fall through */
16455 default:
16456 MIPS_INVAL("pool32i");
16457 generate_exception_end(ctx, EXCP_RI);
16458 break;
16460 break;
16461 case POOL32C:
16462 minor = (ctx->opcode >> 12) & 0xf;
16463 offset = sextract32(ctx->opcode, 0,
16464 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16465 switch (minor) {
16466 case LWL:
16467 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16468 mips32_op = OPC_LWL;
16469 goto do_ld_lr;
16470 case SWL:
16471 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16472 mips32_op = OPC_SWL;
16473 goto do_st_lr;
16474 case LWR:
16475 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16476 mips32_op = OPC_LWR;
16477 goto do_ld_lr;
16478 case SWR:
16479 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16480 mips32_op = OPC_SWR;
16481 goto do_st_lr;
16482 #if defined(TARGET_MIPS64)
16483 case LDL:
16484 check_insn(ctx, ISA_MIPS3);
16485 check_mips_64(ctx);
16486 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16487 mips32_op = OPC_LDL;
16488 goto do_ld_lr;
16489 case SDL:
16490 check_insn(ctx, ISA_MIPS3);
16491 check_mips_64(ctx);
16492 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16493 mips32_op = OPC_SDL;
16494 goto do_st_lr;
16495 case LDR:
16496 check_insn(ctx, ISA_MIPS3);
16497 check_mips_64(ctx);
16498 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16499 mips32_op = OPC_LDR;
16500 goto do_ld_lr;
16501 case SDR:
16502 check_insn(ctx, ISA_MIPS3);
16503 check_mips_64(ctx);
16504 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16505 mips32_op = OPC_SDR;
16506 goto do_st_lr;
16507 case LWU:
16508 check_insn(ctx, ISA_MIPS3);
16509 check_mips_64(ctx);
16510 mips32_op = OPC_LWU;
16511 goto do_ld_lr;
16512 case LLD:
16513 check_insn(ctx, ISA_MIPS3);
16514 check_mips_64(ctx);
16515 mips32_op = OPC_LLD;
16516 goto do_ld_lr;
16517 #endif
16518 case LL:
16519 mips32_op = OPC_LL;
16520 goto do_ld_lr;
16521 do_ld_lr:
16522 gen_ld(ctx, mips32_op, rt, rs, offset);
16523 break;
16524 do_st_lr:
16525 gen_st(ctx, mips32_op, rt, rs, offset);
16526 break;
16527 case SC:
16528 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16529 break;
16530 #if defined(TARGET_MIPS64)
16531 case SCD:
16532 check_insn(ctx, ISA_MIPS3);
16533 check_mips_64(ctx);
16534 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16535 break;
16536 #endif
16537 case LD_EVA:
16538 if (!ctx->eva) {
16539 MIPS_INVAL("pool32c ld-eva");
16540 generate_exception_end(ctx, EXCP_RI);
16541 break;
16543 check_cp0_enabled(ctx);
16545 minor2 = (ctx->opcode >> 9) & 0x7;
16546 offset = sextract32(ctx->opcode, 0, 9);
16547 switch (minor2) {
16548 case LBUE:
16549 mips32_op = OPC_LBUE;
16550 goto do_ld_lr;
16551 case LHUE:
16552 mips32_op = OPC_LHUE;
16553 goto do_ld_lr;
16554 case LWLE:
16555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16556 mips32_op = OPC_LWLE;
16557 goto do_ld_lr;
16558 case LWRE:
16559 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16560 mips32_op = OPC_LWRE;
16561 goto do_ld_lr;
16562 case LBE:
16563 mips32_op = OPC_LBE;
16564 goto do_ld_lr;
16565 case LHE:
16566 mips32_op = OPC_LHE;
16567 goto do_ld_lr;
16568 case LLE:
16569 mips32_op = OPC_LLE;
16570 goto do_ld_lr;
16571 case LWE:
16572 mips32_op = OPC_LWE;
16573 goto do_ld_lr;
16575 break;
16576 case ST_EVA:
16577 if (!ctx->eva) {
16578 MIPS_INVAL("pool32c st-eva");
16579 generate_exception_end(ctx, EXCP_RI);
16580 break;
16582 check_cp0_enabled(ctx);
16584 minor2 = (ctx->opcode >> 9) & 0x7;
16585 offset = sextract32(ctx->opcode, 0, 9);
16586 switch (minor2) {
16587 case SWLE:
16588 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16589 mips32_op = OPC_SWLE;
16590 goto do_st_lr;
16591 case SWRE:
16592 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16593 mips32_op = OPC_SWRE;
16594 goto do_st_lr;
16595 case PREFE:
16596 /* Treat as no-op */
16597 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16598 /* hint codes 24-31 are reserved and signal RI */
16599 generate_exception(ctx, EXCP_RI);
16601 break;
16602 case CACHEE:
16603 /* Treat as no-op */
16604 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16605 gen_cache_operation(ctx, rt, rs, offset);
16607 break;
16608 case SBE:
16609 mips32_op = OPC_SBE;
16610 goto do_st_lr;
16611 case SHE:
16612 mips32_op = OPC_SHE;
16613 goto do_st_lr;
16614 case SCE:
16615 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16616 break;
16617 case SWE:
16618 mips32_op = OPC_SWE;
16619 goto do_st_lr;
16621 break;
16622 case PREF:
16623 /* Treat as no-op */
16624 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16625 /* hint codes 24-31 are reserved and signal RI */
16626 generate_exception(ctx, EXCP_RI);
16628 break;
16629 default:
16630 MIPS_INVAL("pool32c");
16631 generate_exception_end(ctx, EXCP_RI);
16632 break;
16634 break;
16635 case ADDI32: /* AUI, LUI */
16636 if (ctx->insn_flags & ISA_MIPS32R6) {
16637 /* AUI, LUI */
16638 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16639 } else {
16640 /* ADDI32 */
16641 mips32_op = OPC_ADDI;
16642 goto do_addi;
16644 break;
16645 case ADDIU32:
16646 mips32_op = OPC_ADDIU;
16647 do_addi:
16648 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16649 break;
16651 /* Logical operations */
16652 case ORI32:
16653 mips32_op = OPC_ORI;
16654 goto do_logici;
16655 case XORI32:
16656 mips32_op = OPC_XORI;
16657 goto do_logici;
16658 case ANDI32:
16659 mips32_op = OPC_ANDI;
16660 do_logici:
16661 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16662 break;
16664 /* Set less than immediate */
16665 case SLTI32:
16666 mips32_op = OPC_SLTI;
16667 goto do_slti;
16668 case SLTIU32:
16669 mips32_op = OPC_SLTIU;
16670 do_slti:
16671 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16672 break;
16673 case JALX32:
16674 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16675 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16676 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16677 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16678 break;
16679 case JALS32: /* BOVC, BEQC, BEQZALC */
16680 if (ctx->insn_flags & ISA_MIPS32R6) {
16681 if (rs >= rt) {
16682 /* BOVC */
16683 mips32_op = OPC_BOVC;
16684 } else if (rs < rt && rs == 0) {
16685 /* BEQZALC */
16686 mips32_op = OPC_BEQZALC;
16687 } else {
16688 /* BEQC */
16689 mips32_op = OPC_BEQC;
16691 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16692 } else {
16693 /* JALS32 */
16694 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16695 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16696 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16698 break;
16699 case BEQ32: /* BC */
16700 if (ctx->insn_flags & ISA_MIPS32R6) {
16701 /* BC */
16702 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16703 sextract32(ctx->opcode << 1, 0, 27));
16704 } else {
16705 /* BEQ32 */
16706 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16708 break;
16709 case BNE32: /* BALC */
16710 if (ctx->insn_flags & ISA_MIPS32R6) {
16711 /* BALC */
16712 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16713 sextract32(ctx->opcode << 1, 0, 27));
16714 } else {
16715 /* BNE32 */
16716 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16718 break;
16719 case J32: /* BGTZC, BLTZC, BLTC */
16720 if (ctx->insn_flags & ISA_MIPS32R6) {
16721 if (rs == 0 && rt != 0) {
16722 /* BGTZC */
16723 mips32_op = OPC_BGTZC;
16724 } else if (rs != 0 && rt != 0 && rs == rt) {
16725 /* BLTZC */
16726 mips32_op = OPC_BLTZC;
16727 } else {
16728 /* BLTC */
16729 mips32_op = OPC_BLTC;
16731 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16732 } else {
16733 /* J32 */
16734 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16735 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16737 break;
16738 case JAL32: /* BLEZC, BGEZC, BGEC */
16739 if (ctx->insn_flags & ISA_MIPS32R6) {
16740 if (rs == 0 && rt != 0) {
16741 /* BLEZC */
16742 mips32_op = OPC_BLEZC;
16743 } else if (rs != 0 && rt != 0 && rs == rt) {
16744 /* BGEZC */
16745 mips32_op = OPC_BGEZC;
16746 } else {
16747 /* BGEC */
16748 mips32_op = OPC_BGEC;
16750 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16751 } else {
16752 /* JAL32 */
16753 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16754 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16755 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16757 break;
16758 /* Floating point (COP1) */
16759 case LWC132:
16760 mips32_op = OPC_LWC1;
16761 goto do_cop1;
16762 case LDC132:
16763 mips32_op = OPC_LDC1;
16764 goto do_cop1;
16765 case SWC132:
16766 mips32_op = OPC_SWC1;
16767 goto do_cop1;
16768 case SDC132:
16769 mips32_op = OPC_SDC1;
16770 do_cop1:
16771 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16772 break;
16773 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16774 if (ctx->insn_flags & ISA_MIPS32R6) {
16775 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16776 switch ((ctx->opcode >> 16) & 0x1f) {
16777 case ADDIUPC_00:
16778 case ADDIUPC_01:
16779 case ADDIUPC_02:
16780 case ADDIUPC_03:
16781 case ADDIUPC_04:
16782 case ADDIUPC_05:
16783 case ADDIUPC_06:
16784 case ADDIUPC_07:
16785 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16786 break;
16787 case AUIPC:
16788 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16789 break;
16790 case ALUIPC:
16791 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16792 break;
16793 case LWPC_08:
16794 case LWPC_09:
16795 case LWPC_0A:
16796 case LWPC_0B:
16797 case LWPC_0C:
16798 case LWPC_0D:
16799 case LWPC_0E:
16800 case LWPC_0F:
16801 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16802 break;
16803 default:
16804 generate_exception(ctx, EXCP_RI);
16805 break;
16807 } else {
16808 /* ADDIUPC */
16809 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16810 offset = SIMM(ctx->opcode, 0, 23) << 2;
16812 gen_addiupc(ctx, reg, offset, 0, 0);
16814 break;
16815 case BNVC: /* BNEC, BNEZALC */
16816 check_insn(ctx, ISA_MIPS32R6);
16817 if (rs >= rt) {
16818 /* BNVC */
16819 mips32_op = OPC_BNVC;
16820 } else if (rs < rt && rs == 0) {
16821 /* BNEZALC */
16822 mips32_op = OPC_BNEZALC;
16823 } else {
16824 /* BNEC */
16825 mips32_op = OPC_BNEC;
16827 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16828 break;
16829 case R6_BNEZC: /* JIALC */
16830 check_insn(ctx, ISA_MIPS32R6);
16831 if (rt != 0) {
16832 /* BNEZC */
16833 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16834 sextract32(ctx->opcode << 1, 0, 22));
16835 } else {
16836 /* JIALC */
16837 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16839 break;
16840 case R6_BEQZC: /* JIC */
16841 check_insn(ctx, ISA_MIPS32R6);
16842 if (rt != 0) {
16843 /* BEQZC */
16844 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16845 sextract32(ctx->opcode << 1, 0, 22));
16846 } else {
16847 /* JIC */
16848 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16850 break;
16851 case BLEZALC: /* BGEZALC, BGEUC */
16852 check_insn(ctx, ISA_MIPS32R6);
16853 if (rs == 0 && rt != 0) {
16854 /* BLEZALC */
16855 mips32_op = OPC_BLEZALC;
16856 } else if (rs != 0 && rt != 0 && rs == rt) {
16857 /* BGEZALC */
16858 mips32_op = OPC_BGEZALC;
16859 } else {
16860 /* BGEUC */
16861 mips32_op = OPC_BGEUC;
16863 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16864 break;
16865 case BGTZALC: /* BLTZALC, BLTUC */
16866 check_insn(ctx, ISA_MIPS32R6);
16867 if (rs == 0 && rt != 0) {
16868 /* BGTZALC */
16869 mips32_op = OPC_BGTZALC;
16870 } else if (rs != 0 && rt != 0 && rs == rt) {
16871 /* BLTZALC */
16872 mips32_op = OPC_BLTZALC;
16873 } else {
16874 /* BLTUC */
16875 mips32_op = OPC_BLTUC;
16877 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16878 break;
16879 /* Loads and stores */
16880 case LB32:
16881 mips32_op = OPC_LB;
16882 goto do_ld;
16883 case LBU32:
16884 mips32_op = OPC_LBU;
16885 goto do_ld;
16886 case LH32:
16887 mips32_op = OPC_LH;
16888 goto do_ld;
16889 case LHU32:
16890 mips32_op = OPC_LHU;
16891 goto do_ld;
16892 case LW32:
16893 mips32_op = OPC_LW;
16894 goto do_ld;
16895 #ifdef TARGET_MIPS64
16896 case LD32:
16897 check_insn(ctx, ISA_MIPS3);
16898 check_mips_64(ctx);
16899 mips32_op = OPC_LD;
16900 goto do_ld;
16901 case SD32:
16902 check_insn(ctx, ISA_MIPS3);
16903 check_mips_64(ctx);
16904 mips32_op = OPC_SD;
16905 goto do_st;
16906 #endif
16907 case SB32:
16908 mips32_op = OPC_SB;
16909 goto do_st;
16910 case SH32:
16911 mips32_op = OPC_SH;
16912 goto do_st;
16913 case SW32:
16914 mips32_op = OPC_SW;
16915 goto do_st;
16916 do_ld:
16917 gen_ld(ctx, mips32_op, rt, rs, imm);
16918 break;
16919 do_st:
16920 gen_st(ctx, mips32_op, rt, rs, imm);
16921 break;
16922 default:
16923 generate_exception_end(ctx, EXCP_RI);
16924 break;
16928 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16930 uint32_t op;
16932 /* make sure instructions are on a halfword boundary */
16933 if (ctx->base.pc_next & 0x1) {
16934 env->CP0_BadVAddr = ctx->base.pc_next;
16935 generate_exception_end(ctx, EXCP_AdEL);
16936 return 2;
16939 op = (ctx->opcode >> 10) & 0x3f;
16940 /* Enforce properly-sized instructions in a delay slot */
16941 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16942 switch (op & 0x7) { /* MSB-3..MSB-5 */
16943 case 0:
16944 /* POOL32A, POOL32B, POOL32I, POOL32C */
16945 case 4:
16946 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16947 case 5:
16948 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16949 case 6:
16950 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16951 case 7:
16952 /* LB32, LH32, LWC132, LDC132, LW32 */
16953 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16954 generate_exception_end(ctx, EXCP_RI);
16955 return 2;
16957 break;
16958 case 1:
16959 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16960 case 2:
16961 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16962 case 3:
16963 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16964 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16965 generate_exception_end(ctx, EXCP_RI);
16966 return 2;
16968 break;
16972 switch (op) {
16973 case POOL16A:
16975 int rd = mmreg(uMIPS_RD(ctx->opcode));
16976 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16977 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16978 uint32_t opc = 0;
16980 switch (ctx->opcode & 0x1) {
16981 case ADDU16:
16982 opc = OPC_ADDU;
16983 break;
16984 case SUBU16:
16985 opc = OPC_SUBU;
16986 break;
16988 if (ctx->insn_flags & ISA_MIPS32R6) {
16989 /* In the Release 6 the register number location in
16990 * the instruction encoding has changed.
16992 gen_arith(ctx, opc, rs1, rd, rs2);
16993 } else {
16994 gen_arith(ctx, opc, rd, rs1, rs2);
16997 break;
16998 case POOL16B:
17000 int rd = mmreg(uMIPS_RD(ctx->opcode));
17001 int rs = mmreg(uMIPS_RS(ctx->opcode));
17002 int amount = (ctx->opcode >> 1) & 0x7;
17003 uint32_t opc = 0;
17004 amount = amount == 0 ? 8 : amount;
17006 switch (ctx->opcode & 0x1) {
17007 case SLL16:
17008 opc = OPC_SLL;
17009 break;
17010 case SRL16:
17011 opc = OPC_SRL;
17012 break;
17015 gen_shift_imm(ctx, opc, rd, rs, amount);
17017 break;
17018 case POOL16C:
17019 if (ctx->insn_flags & ISA_MIPS32R6) {
17020 gen_pool16c_r6_insn(ctx);
17021 } else {
17022 gen_pool16c_insn(ctx);
17024 break;
17025 case LWGP16:
17027 int rd = mmreg(uMIPS_RD(ctx->opcode));
17028 int rb = 28; /* GP */
17029 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17031 gen_ld(ctx, OPC_LW, rd, rb, offset);
17033 break;
17034 case POOL16F:
17035 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17036 if (ctx->opcode & 1) {
17037 generate_exception_end(ctx, EXCP_RI);
17038 } else {
17039 /* MOVEP */
17040 int enc_dest = uMIPS_RD(ctx->opcode);
17041 int enc_rt = uMIPS_RS2(ctx->opcode);
17042 int enc_rs = uMIPS_RS1(ctx->opcode);
17043 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17045 break;
17046 case LBU16:
17048 int rd = mmreg(uMIPS_RD(ctx->opcode));
17049 int rb = mmreg(uMIPS_RS(ctx->opcode));
17050 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17051 offset = (offset == 0xf ? -1 : offset);
17053 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17055 break;
17056 case LHU16:
17058 int rd = mmreg(uMIPS_RD(ctx->opcode));
17059 int rb = mmreg(uMIPS_RS(ctx->opcode));
17060 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17062 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17064 break;
17065 case LWSP16:
17067 int rd = (ctx->opcode >> 5) & 0x1f;
17068 int rb = 29; /* SP */
17069 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17071 gen_ld(ctx, OPC_LW, rd, rb, offset);
17073 break;
17074 case LW16:
17076 int rd = mmreg(uMIPS_RD(ctx->opcode));
17077 int rb = mmreg(uMIPS_RS(ctx->opcode));
17078 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17080 gen_ld(ctx, OPC_LW, rd, rb, offset);
17082 break;
17083 case SB16:
17085 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17086 int rb = mmreg(uMIPS_RS(ctx->opcode));
17087 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17089 gen_st(ctx, OPC_SB, rd, rb, offset);
17091 break;
17092 case SH16:
17094 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17095 int rb = mmreg(uMIPS_RS(ctx->opcode));
17096 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17098 gen_st(ctx, OPC_SH, rd, rb, offset);
17100 break;
17101 case SWSP16:
17103 int rd = (ctx->opcode >> 5) & 0x1f;
17104 int rb = 29; /* SP */
17105 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17107 gen_st(ctx, OPC_SW, rd, rb, offset);
17109 break;
17110 case SW16:
17112 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17113 int rb = mmreg(uMIPS_RS(ctx->opcode));
17114 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17116 gen_st(ctx, OPC_SW, rd, rb, offset);
17118 break;
17119 case MOVE16:
17121 int rd = uMIPS_RD5(ctx->opcode);
17122 int rs = uMIPS_RS5(ctx->opcode);
17124 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17126 break;
17127 case ANDI16:
17128 gen_andi16(ctx);
17129 break;
17130 case POOL16D:
17131 switch (ctx->opcode & 0x1) {
17132 case ADDIUS5:
17133 gen_addius5(ctx);
17134 break;
17135 case ADDIUSP:
17136 gen_addiusp(ctx);
17137 break;
17139 break;
17140 case POOL16E:
17141 switch (ctx->opcode & 0x1) {
17142 case ADDIUR2:
17143 gen_addiur2(ctx);
17144 break;
17145 case ADDIUR1SP:
17146 gen_addiur1sp(ctx);
17147 break;
17149 break;
17150 case B16: /* BC16 */
17151 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17152 sextract32(ctx->opcode, 0, 10) << 1,
17153 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17154 break;
17155 case BNEZ16: /* BNEZC16 */
17156 case BEQZ16: /* BEQZC16 */
17157 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17158 mmreg(uMIPS_RD(ctx->opcode)),
17159 0, sextract32(ctx->opcode, 0, 7) << 1,
17160 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17162 break;
17163 case LI16:
17165 int reg = mmreg(uMIPS_RD(ctx->opcode));
17166 int imm = ZIMM(ctx->opcode, 0, 7);
17168 imm = (imm == 0x7f ? -1 : imm);
17169 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17171 break;
17172 case RES_29:
17173 case RES_31:
17174 case RES_39:
17175 generate_exception_end(ctx, EXCP_RI);
17176 break;
17177 default:
17178 decode_micromips32_opc(env, ctx);
17179 return 4;
17182 return 2;
17187 * nanoMIPS opcodes
17191 /* MAJOR, P16, and P32 pools opcodes */
17192 enum {
17193 NM_P_ADDIU = 0x00,
17194 NM_ADDIUPC = 0x01,
17195 NM_MOVE_BALC = 0x02,
17196 NM_P16_MV = 0x04,
17197 NM_LW16 = 0x05,
17198 NM_BC16 = 0x06,
17199 NM_P16_SR = 0x07,
17201 NM_POOL32A = 0x08,
17202 NM_P_BAL = 0x0a,
17203 NM_P16_SHIFT = 0x0c,
17204 NM_LWSP16 = 0x0d,
17205 NM_BALC16 = 0x0e,
17206 NM_P16_4X4 = 0x0f,
17208 NM_P_GP_W = 0x10,
17209 NM_P_GP_BH = 0x11,
17210 NM_P_J = 0x12,
17211 NM_P16C = 0x14,
17212 NM_LWGP16 = 0x15,
17213 NM_P16_LB = 0x17,
17215 NM_P48I = 0x18,
17216 NM_P16_A1 = 0x1c,
17217 NM_LW4X4 = 0x1d,
17218 NM_P16_LH = 0x1f,
17220 NM_P_U12 = 0x20,
17221 NM_P_LS_U12 = 0x21,
17222 NM_P_BR1 = 0x22,
17223 NM_P16_A2 = 0x24,
17224 NM_SW16 = 0x25,
17225 NM_BEQZC16 = 0x26,
17227 NM_POOL32F = 0x28,
17228 NM_P_LS_S9 = 0x29,
17229 NM_P_BR2 = 0x2a,
17231 NM_P16_ADDU = 0x2c,
17232 NM_SWSP16 = 0x2d,
17233 NM_BNEZC16 = 0x2e,
17234 NM_MOVEP = 0x2f,
17236 NM_POOL32S = 0x30,
17237 NM_P_BRI = 0x32,
17238 NM_LI16 = 0x34,
17239 NM_SWGP16 = 0x35,
17240 NM_P16_BR = 0x36,
17242 NM_P_LUI = 0x38,
17243 NM_ANDI16 = 0x3c,
17244 NM_SW4X4 = 0x3d,
17245 NM_MOVEPREV = 0x3f,
17248 /* POOL32A instruction pool */
17249 enum {
17250 NM_POOL32A0 = 0x00,
17251 NM_SPECIAL2 = 0x01,
17252 NM_COP2_1 = 0x02,
17253 NM_UDI = 0x03,
17254 NM_POOL32A5 = 0x05,
17255 NM_POOL32A7 = 0x07,
17258 /* P.GP.W instruction pool */
17259 enum {
17260 NM_ADDIUGP_W = 0x00,
17261 NM_LWGP = 0x02,
17262 NM_SWGP = 0x03,
17265 /* P48I instruction pool */
17266 enum {
17267 NM_LI48 = 0x00,
17268 NM_ADDIU48 = 0x01,
17269 NM_ADDIUGP48 = 0x02,
17270 NM_ADDIUPC48 = 0x03,
17271 NM_LWPC48 = 0x0b,
17272 NM_SWPC48 = 0x0f,
17275 /* P.U12 instruction pool */
17276 enum {
17277 NM_ORI = 0x00,
17278 NM_XORI = 0x01,
17279 NM_ANDI = 0x02,
17280 NM_P_SR = 0x03,
17281 NM_SLTI = 0x04,
17282 NM_SLTIU = 0x05,
17283 NM_SEQI = 0x06,
17284 NM_ADDIUNEG = 0x08,
17285 NM_P_SHIFT = 0x0c,
17286 NM_P_ROTX = 0x0d,
17287 NM_P_INS = 0x0e,
17288 NM_P_EXT = 0x0f,
17291 /* POOL32F instruction pool */
17292 enum {
17293 NM_POOL32F_0 = 0x00,
17294 NM_POOL32F_3 = 0x03,
17295 NM_POOL32F_5 = 0x05,
17298 /* POOL32S instruction pool */
17299 enum {
17300 NM_POOL32S_0 = 0x00,
17301 NM_POOL32S_4 = 0x04,
17304 /* P.LUI instruction pool */
17305 enum {
17306 NM_LUI = 0x00,
17307 NM_ALUIPC = 0x01,
17310 /* P.GP.BH instruction pool */
17311 enum {
17312 NM_LBGP = 0x00,
17313 NM_SBGP = 0x01,
17314 NM_LBUGP = 0x02,
17315 NM_ADDIUGP_B = 0x03,
17316 NM_P_GP_LH = 0x04,
17317 NM_P_GP_SH = 0x05,
17318 NM_P_GP_CP1 = 0x06,
17321 /* P.LS.U12 instruction pool */
17322 enum {
17323 NM_LB = 0x00,
17324 NM_SB = 0x01,
17325 NM_LBU = 0x02,
17326 NM_P_PREFU12 = 0x03,
17327 NM_LH = 0x04,
17328 NM_SH = 0x05,
17329 NM_LHU = 0x06,
17330 NM_LWU = 0x07,
17331 NM_LW = 0x08,
17332 NM_SW = 0x09,
17333 NM_LWC1 = 0x0a,
17334 NM_SWC1 = 0x0b,
17335 NM_LDC1 = 0x0e,
17336 NM_SDC1 = 0x0f,
17339 /* P.LS.S9 instruction pool */
17340 enum {
17341 NM_P_LS_S0 = 0x00,
17342 NM_P_LS_S1 = 0x01,
17343 NM_P_LS_E0 = 0x02,
17344 NM_P_LS_WM = 0x04,
17345 NM_P_LS_UAWM = 0x05,
17348 /* P.BAL instruction pool */
17349 enum {
17350 NM_BC = 0x00,
17351 NM_BALC = 0x01,
17354 /* P.J instruction pool */
17355 enum {
17356 NM_JALRC = 0x00,
17357 NM_JALRC_HB = 0x01,
17358 NM_P_BALRSC = 0x08,
17361 /* P.BR1 instruction pool */
17362 enum {
17363 NM_BEQC = 0x00,
17364 NM_P_BR3A = 0x01,
17365 NM_BGEC = 0x02,
17366 NM_BGEUC = 0x03,
17369 /* P.BR2 instruction pool */
17370 enum {
17371 NM_BNEC = 0x00,
17372 NM_BLTC = 0x02,
17373 NM_BLTUC = 0x03,
17376 /* P.BRI instruction pool */
17377 enum {
17378 NM_BEQIC = 0x00,
17379 NM_BBEQZC = 0x01,
17380 NM_BGEIC = 0x02,
17381 NM_BGEIUC = 0x03,
17382 NM_BNEIC = 0x04,
17383 NM_BBNEZC = 0x05,
17384 NM_BLTIC = 0x06,
17385 NM_BLTIUC = 0x07,
17388 /* P16.SHIFT instruction pool */
17389 enum {
17390 NM_SLL16 = 0x00,
17391 NM_SRL16 = 0x01,
17394 /* POOL16C instruction pool */
17395 enum {
17396 NM_POOL16C_0 = 0x00,
17397 NM_LWXS16 = 0x01,
17400 /* P16.A1 instruction pool */
17401 enum {
17402 NM_ADDIUR1SP = 0x01,
17405 /* P16.A2 instruction pool */
17406 enum {
17407 NM_ADDIUR2 = 0x00,
17408 NM_P_ADDIURS5 = 0x01,
17411 /* P16.ADDU instruction pool */
17412 enum {
17413 NM_ADDU16 = 0x00,
17414 NM_SUBU16 = 0x01,
17417 /* P16.SR instruction pool */
17418 enum {
17419 NM_SAVE16 = 0x00,
17420 NM_RESTORE_JRC16 = 0x01,
17423 /* P16.4X4 instruction pool */
17424 enum {
17425 NM_ADDU4X4 = 0x00,
17426 NM_MUL4X4 = 0x01,
17429 /* P16.LB instruction pool */
17430 enum {
17431 NM_LB16 = 0x00,
17432 NM_SB16 = 0x01,
17433 NM_LBU16 = 0x02,
17436 /* P16.LH instruction pool */
17437 enum {
17438 NM_LH16 = 0x00,
17439 NM_SH16 = 0x01,
17440 NM_LHU16 = 0x02,
17443 /* P.RI instruction pool */
17444 enum {
17445 NM_SIGRIE = 0x00,
17446 NM_P_SYSCALL = 0x01,
17447 NM_BREAK = 0x02,
17448 NM_SDBBP = 0x03,
17451 /* POOL32A0 instruction pool */
17452 enum {
17453 NM_P_TRAP = 0x00,
17454 NM_SEB = 0x01,
17455 NM_SLLV = 0x02,
17456 NM_MUL = 0x03,
17457 NM_MFC0 = 0x06,
17458 NM_MFHC0 = 0x07,
17459 NM_SEH = 0x09,
17460 NM_SRLV = 0x0a,
17461 NM_MUH = 0x0b,
17462 NM_MTC0 = 0x0e,
17463 NM_MTHC0 = 0x0f,
17464 NM_SRAV = 0x12,
17465 NM_MULU = 0x13,
17466 NM_ROTRV = 0x1a,
17467 NM_MUHU = 0x1b,
17468 NM_ADD = 0x22,
17469 NM_DIV = 0x23,
17470 NM_ADDU = 0x2a,
17471 NM_MOD = 0x2b,
17472 NM_SUB = 0x32,
17473 NM_DIVU = 0x33,
17474 NM_RDHWR = 0x38,
17475 NM_SUBU = 0x3a,
17476 NM_MODU = 0x3b,
17477 NM_P_CMOVE = 0x42,
17478 NM_FORK = 0x45,
17479 NM_MFTR = 0x46,
17480 NM_MFHTR = 0x47,
17481 NM_AND = 0x4a,
17482 NM_YIELD = 0x4d,
17483 NM_MTTR = 0x4e,
17484 NM_MTHTR = 0x4f,
17485 NM_OR = 0x52,
17486 NM_D_E_MT_VPE = 0x56,
17487 NM_NOR = 0x5a,
17488 NM_XOR = 0x62,
17489 NM_SLT = 0x6a,
17490 NM_P_SLTU = 0x72,
17491 NM_SOV = 0x7a,
17494 /* CRC32 instruction pool */
17495 enum {
17496 NM_CRC32B = 0x00,
17497 NM_CRC32H = 0x01,
17498 NM_CRC32W = 0x02,
17499 NM_CRC32CB = 0x04,
17500 NM_CRC32CH = 0x05,
17501 NM_CRC32CW = 0x06,
17504 /* POOL32A5 instruction pool */
17505 enum {
17506 NM_CMP_EQ_PH = 0x00,
17507 NM_CMP_LT_PH = 0x08,
17508 NM_CMP_LE_PH = 0x10,
17509 NM_CMPGU_EQ_QB = 0x18,
17510 NM_CMPGU_LT_QB = 0x20,
17511 NM_CMPGU_LE_QB = 0x28,
17512 NM_CMPGDU_EQ_QB = 0x30,
17513 NM_CMPGDU_LT_QB = 0x38,
17514 NM_CMPGDU_LE_QB = 0x40,
17515 NM_CMPU_EQ_QB = 0x48,
17516 NM_CMPU_LT_QB = 0x50,
17517 NM_CMPU_LE_QB = 0x58,
17518 NM_ADDQ_S_W = 0x60,
17519 NM_SUBQ_S_W = 0x68,
17520 NM_ADDSC = 0x70,
17521 NM_ADDWC = 0x78,
17523 NM_ADDQ_S_PH = 0x01,
17524 NM_ADDQH_R_PH = 0x09,
17525 NM_ADDQH_R_W = 0x11,
17526 NM_ADDU_S_QB = 0x19,
17527 NM_ADDU_S_PH = 0x21,
17528 NM_ADDUH_R_QB = 0x29,
17529 NM_SHRAV_R_PH = 0x31,
17530 NM_SHRAV_R_QB = 0x39,
17531 NM_SUBQ_S_PH = 0x41,
17532 NM_SUBQH_R_PH = 0x49,
17533 NM_SUBQH_R_W = 0x51,
17534 NM_SUBU_S_QB = 0x59,
17535 NM_SUBU_S_PH = 0x61,
17536 NM_SUBUH_R_QB = 0x69,
17537 NM_SHLLV_S_PH = 0x71,
17538 NM_PRECR_SRA_R_PH_W = 0x79,
17540 NM_MULEU_S_PH_QBL = 0x12,
17541 NM_MULEU_S_PH_QBR = 0x1a,
17542 NM_MULQ_RS_PH = 0x22,
17543 NM_MULQ_S_PH = 0x2a,
17544 NM_MULQ_RS_W = 0x32,
17545 NM_MULQ_S_W = 0x3a,
17546 NM_APPEND = 0x42,
17547 NM_MODSUB = 0x52,
17548 NM_SHRAV_R_W = 0x5a,
17549 NM_SHRLV_PH = 0x62,
17550 NM_SHRLV_QB = 0x6a,
17551 NM_SHLLV_QB = 0x72,
17552 NM_SHLLV_S_W = 0x7a,
17554 NM_SHILO = 0x03,
17556 NM_MULEQ_S_W_PHL = 0x04,
17557 NM_MULEQ_S_W_PHR = 0x0c,
17559 NM_MUL_S_PH = 0x05,
17560 NM_PRECR_QB_PH = 0x0d,
17561 NM_PRECRQ_QB_PH = 0x15,
17562 NM_PRECRQ_PH_W = 0x1d,
17563 NM_PRECRQ_RS_PH_W = 0x25,
17564 NM_PRECRQU_S_QB_PH = 0x2d,
17565 NM_PACKRL_PH = 0x35,
17566 NM_PICK_QB = 0x3d,
17567 NM_PICK_PH = 0x45,
17569 NM_SHRA_R_W = 0x5e,
17570 NM_SHRA_R_PH = 0x66,
17571 NM_SHLL_S_PH = 0x76,
17572 NM_SHLL_S_W = 0x7e,
17574 NM_REPL_PH = 0x07
17577 /* POOL32A7 instruction pool */
17578 enum {
17579 NM_P_LSX = 0x00,
17580 NM_LSA = 0x01,
17581 NM_EXTW = 0x03,
17582 NM_POOL32AXF = 0x07,
17585 /* P.SR instruction pool */
17586 enum {
17587 NM_PP_SR = 0x00,
17588 NM_P_SR_F = 0x01,
17591 /* P.SHIFT instruction pool */
17592 enum {
17593 NM_P_SLL = 0x00,
17594 NM_SRL = 0x02,
17595 NM_SRA = 0x04,
17596 NM_ROTR = 0x06,
17599 /* P.ROTX instruction pool */
17600 enum {
17601 NM_ROTX = 0x00,
17604 /* P.INS instruction pool */
17605 enum {
17606 NM_INS = 0x00,
17609 /* P.EXT instruction pool */
17610 enum {
17611 NM_EXT = 0x00,
17614 /* POOL32F_0 (fmt) instruction pool */
17615 enum {
17616 NM_RINT_S = 0x04,
17617 NM_RINT_D = 0x44,
17618 NM_ADD_S = 0x06,
17619 NM_SELEQZ_S = 0x07,
17620 NM_SELEQZ_D = 0x47,
17621 NM_CLASS_S = 0x0c,
17622 NM_CLASS_D = 0x4c,
17623 NM_SUB_S = 0x0e,
17624 NM_SELNEZ_S = 0x0f,
17625 NM_SELNEZ_D = 0x4f,
17626 NM_MUL_S = 0x16,
17627 NM_SEL_S = 0x17,
17628 NM_SEL_D = 0x57,
17629 NM_DIV_S = 0x1e,
17630 NM_ADD_D = 0x26,
17631 NM_SUB_D = 0x2e,
17632 NM_MUL_D = 0x36,
17633 NM_MADDF_S = 0x37,
17634 NM_MADDF_D = 0x77,
17635 NM_DIV_D = 0x3e,
17636 NM_MSUBF_S = 0x3f,
17637 NM_MSUBF_D = 0x7f,
17640 /* POOL32F_3 instruction pool */
17641 enum {
17642 NM_MIN_FMT = 0x00,
17643 NM_MAX_FMT = 0x01,
17644 NM_MINA_FMT = 0x04,
17645 NM_MAXA_FMT = 0x05,
17646 NM_POOL32FXF = 0x07,
17649 /* POOL32F_5 instruction pool */
17650 enum {
17651 NM_CMP_CONDN_S = 0x00,
17652 NM_CMP_CONDN_D = 0x02,
17655 /* P.GP.LH instruction pool */
17656 enum {
17657 NM_LHGP = 0x00,
17658 NM_LHUGP = 0x01,
17661 /* P.GP.SH instruction pool */
17662 enum {
17663 NM_SHGP = 0x00,
17666 /* P.GP.CP1 instruction pool */
17667 enum {
17668 NM_LWC1GP = 0x00,
17669 NM_SWC1GP = 0x01,
17670 NM_LDC1GP = 0x02,
17671 NM_SDC1GP = 0x03,
17674 /* P.LS.S0 instruction pool */
17675 enum {
17676 NM_LBS9 = 0x00,
17677 NM_LHS9 = 0x04,
17678 NM_LWS9 = 0x08,
17679 NM_LDS9 = 0x0c,
17681 NM_SBS9 = 0x01,
17682 NM_SHS9 = 0x05,
17683 NM_SWS9 = 0x09,
17684 NM_SDS9 = 0x0d,
17686 NM_LBUS9 = 0x02,
17687 NM_LHUS9 = 0x06,
17688 NM_LWC1S9 = 0x0a,
17689 NM_LDC1S9 = 0x0e,
17691 NM_P_PREFS9 = 0x03,
17692 NM_LWUS9 = 0x07,
17693 NM_SWC1S9 = 0x0b,
17694 NM_SDC1S9 = 0x0f,
17697 /* P.LS.S1 instruction pool */
17698 enum {
17699 NM_ASET_ACLR = 0x02,
17700 NM_UALH = 0x04,
17701 NM_UASH = 0x05,
17702 NM_CACHE = 0x07,
17703 NM_P_LL = 0x0a,
17704 NM_P_SC = 0x0b,
17707 /* P.LS.E0 instruction pool */
17708 enum {
17709 NM_LBE = 0x00,
17710 NM_SBE = 0x01,
17711 NM_LBUE = 0x02,
17712 NM_P_PREFE = 0x03,
17713 NM_LHE = 0x04,
17714 NM_SHE = 0x05,
17715 NM_LHUE = 0x06,
17716 NM_CACHEE = 0x07,
17717 NM_LWE = 0x08,
17718 NM_SWE = 0x09,
17719 NM_P_LLE = 0x0a,
17720 NM_P_SCE = 0x0b,
17723 /* P.PREFE instruction pool */
17724 enum {
17725 NM_SYNCIE = 0x00,
17726 NM_PREFE = 0x01,
17729 /* P.LLE instruction pool */
17730 enum {
17731 NM_LLE = 0x00,
17732 NM_LLWPE = 0x01,
17735 /* P.SCE instruction pool */
17736 enum {
17737 NM_SCE = 0x00,
17738 NM_SCWPE = 0x01,
17741 /* P.LS.WM instruction pool */
17742 enum {
17743 NM_LWM = 0x00,
17744 NM_SWM = 0x01,
17747 /* P.LS.UAWM instruction pool */
17748 enum {
17749 NM_UALWM = 0x00,
17750 NM_UASWM = 0x01,
17753 /* P.BR3A instruction pool */
17754 enum {
17755 NM_BC1EQZC = 0x00,
17756 NM_BC1NEZC = 0x01,
17757 NM_BC2EQZC = 0x02,
17758 NM_BC2NEZC = 0x03,
17759 NM_BPOSGE32C = 0x04,
17762 /* P16.RI instruction pool */
17763 enum {
17764 NM_P16_SYSCALL = 0x01,
17765 NM_BREAK16 = 0x02,
17766 NM_SDBBP16 = 0x03,
17769 /* POOL16C_0 instruction pool */
17770 enum {
17771 NM_POOL16C_00 = 0x00,
17774 /* P16.JRC instruction pool */
17775 enum {
17776 NM_JRC = 0x00,
17777 NM_JALRC16 = 0x01,
17780 /* P.SYSCALL instruction pool */
17781 enum {
17782 NM_SYSCALL = 0x00,
17783 NM_HYPCALL = 0x01,
17786 /* P.TRAP instruction pool */
17787 enum {
17788 NM_TEQ = 0x00,
17789 NM_TNE = 0x01,
17792 /* P.CMOVE instruction pool */
17793 enum {
17794 NM_MOVZ = 0x00,
17795 NM_MOVN = 0x01,
17798 /* POOL32Axf instruction pool */
17799 enum {
17800 NM_POOL32AXF_1 = 0x01,
17801 NM_POOL32AXF_2 = 0x02,
17802 NM_POOL32AXF_4 = 0x04,
17803 NM_POOL32AXF_5 = 0x05,
17804 NM_POOL32AXF_7 = 0x07,
17807 /* POOL32Axf_1 instruction pool */
17808 enum {
17809 NM_POOL32AXF_1_0 = 0x00,
17810 NM_POOL32AXF_1_1 = 0x01,
17811 NM_POOL32AXF_1_3 = 0x03,
17812 NM_POOL32AXF_1_4 = 0x04,
17813 NM_POOL32AXF_1_5 = 0x05,
17814 NM_POOL32AXF_1_7 = 0x07,
17817 /* POOL32Axf_2 instruction pool */
17818 enum {
17819 NM_POOL32AXF_2_0_7 = 0x00,
17820 NM_POOL32AXF_2_8_15 = 0x01,
17821 NM_POOL32AXF_2_16_23 = 0x02,
17822 NM_POOL32AXF_2_24_31 = 0x03,
17825 /* POOL32Axf_7 instruction pool */
17826 enum {
17827 NM_SHRA_R_QB = 0x0,
17828 NM_SHRL_PH = 0x1,
17829 NM_REPL_QB = 0x2,
17832 /* POOL32Axf_1_0 instruction pool */
17833 enum {
17834 NM_MFHI = 0x0,
17835 NM_MFLO = 0x1,
17836 NM_MTHI = 0x2,
17837 NM_MTLO = 0x3,
17840 /* POOL32Axf_1_1 instruction pool */
17841 enum {
17842 NM_MTHLIP = 0x0,
17843 NM_SHILOV = 0x1,
17846 /* POOL32Axf_1_3 instruction pool */
17847 enum {
17848 NM_RDDSP = 0x0,
17849 NM_WRDSP = 0x1,
17850 NM_EXTP = 0x2,
17851 NM_EXTPDP = 0x3,
17854 /* POOL32Axf_1_4 instruction pool */
17855 enum {
17856 NM_SHLL_QB = 0x0,
17857 NM_SHRL_QB = 0x1,
17860 /* POOL32Axf_1_5 instruction pool */
17861 enum {
17862 NM_MAQ_S_W_PHR = 0x0,
17863 NM_MAQ_S_W_PHL = 0x1,
17864 NM_MAQ_SA_W_PHR = 0x2,
17865 NM_MAQ_SA_W_PHL = 0x3,
17868 /* POOL32Axf_1_7 instruction pool */
17869 enum {
17870 NM_EXTR_W = 0x0,
17871 NM_EXTR_R_W = 0x1,
17872 NM_EXTR_RS_W = 0x2,
17873 NM_EXTR_S_H = 0x3,
17876 /* POOL32Axf_2_0_7 instruction pool */
17877 enum {
17878 NM_DPA_W_PH = 0x0,
17879 NM_DPAQ_S_W_PH = 0x1,
17880 NM_DPS_W_PH = 0x2,
17881 NM_DPSQ_S_W_PH = 0x3,
17882 NM_BALIGN = 0x4,
17883 NM_MADD = 0x5,
17884 NM_MULT = 0x6,
17885 NM_EXTRV_W = 0x7,
17888 /* POOL32Axf_2_8_15 instruction pool */
17889 enum {
17890 NM_DPAX_W_PH = 0x0,
17891 NM_DPAQ_SA_L_W = 0x1,
17892 NM_DPSX_W_PH = 0x2,
17893 NM_DPSQ_SA_L_W = 0x3,
17894 NM_MADDU = 0x5,
17895 NM_MULTU = 0x6,
17896 NM_EXTRV_R_W = 0x7,
17899 /* POOL32Axf_2_16_23 instruction pool */
17900 enum {
17901 NM_DPAU_H_QBL = 0x0,
17902 NM_DPAQX_S_W_PH = 0x1,
17903 NM_DPSU_H_QBL = 0x2,
17904 NM_DPSQX_S_W_PH = 0x3,
17905 NM_EXTPV = 0x4,
17906 NM_MSUB = 0x5,
17907 NM_MULSA_W_PH = 0x6,
17908 NM_EXTRV_RS_W = 0x7,
17911 /* POOL32Axf_2_24_31 instruction pool */
17912 enum {
17913 NM_DPAU_H_QBR = 0x0,
17914 NM_DPAQX_SA_W_PH = 0x1,
17915 NM_DPSU_H_QBR = 0x2,
17916 NM_DPSQX_SA_W_PH = 0x3,
17917 NM_EXTPDPV = 0x4,
17918 NM_MSUBU = 0x5,
17919 NM_MULSAQ_S_W_PH = 0x6,
17920 NM_EXTRV_S_H = 0x7,
17923 /* POOL32Axf_{4, 5} instruction pool */
17924 enum {
17925 NM_CLO = 0x25,
17926 NM_CLZ = 0x2d,
17928 NM_TLBP = 0x01,
17929 NM_TLBR = 0x09,
17930 NM_TLBWI = 0x11,
17931 NM_TLBWR = 0x19,
17932 NM_TLBINV = 0x03,
17933 NM_TLBINVF = 0x0b,
17934 NM_DI = 0x23,
17935 NM_EI = 0x2b,
17936 NM_RDPGPR = 0x70,
17937 NM_WRPGPR = 0x78,
17938 NM_WAIT = 0x61,
17939 NM_DERET = 0x71,
17940 NM_ERETX = 0x79,
17942 /* nanoMIPS DSP instructions */
17943 NM_ABSQ_S_QB = 0x00,
17944 NM_ABSQ_S_PH = 0x08,
17945 NM_ABSQ_S_W = 0x10,
17946 NM_PRECEQ_W_PHL = 0x28,
17947 NM_PRECEQ_W_PHR = 0x30,
17948 NM_PRECEQU_PH_QBL = 0x38,
17949 NM_PRECEQU_PH_QBR = 0x48,
17950 NM_PRECEU_PH_QBL = 0x58,
17951 NM_PRECEU_PH_QBR = 0x68,
17952 NM_PRECEQU_PH_QBLA = 0x39,
17953 NM_PRECEQU_PH_QBRA = 0x49,
17954 NM_PRECEU_PH_QBLA = 0x59,
17955 NM_PRECEU_PH_QBRA = 0x69,
17956 NM_REPLV_PH = 0x01,
17957 NM_REPLV_QB = 0x09,
17958 NM_BITREV = 0x18,
17959 NM_INSV = 0x20,
17960 NM_RADDU_W_QB = 0x78,
17962 NM_BITSWAP = 0x05,
17963 NM_WSBH = 0x3d,
17966 /* PP.SR instruction pool */
17967 enum {
17968 NM_SAVE = 0x00,
17969 NM_RESTORE = 0x02,
17970 NM_RESTORE_JRC = 0x03,
17973 /* P.SR.F instruction pool */
17974 enum {
17975 NM_SAVEF = 0x00,
17976 NM_RESTOREF = 0x01,
17979 /* P16.SYSCALL instruction pool */
17980 enum {
17981 NM_SYSCALL16 = 0x00,
17982 NM_HYPCALL16 = 0x01,
17985 /* POOL16C_00 instruction pool */
17986 enum {
17987 NM_NOT16 = 0x00,
17988 NM_XOR16 = 0x01,
17989 NM_AND16 = 0x02,
17990 NM_OR16 = 0x03,
17993 /* PP.LSX and PP.LSXS instruction pool */
17994 enum {
17995 NM_LBX = 0x00,
17996 NM_LHX = 0x04,
17997 NM_LWX = 0x08,
17998 NM_LDX = 0x0c,
18000 NM_SBX = 0x01,
18001 NM_SHX = 0x05,
18002 NM_SWX = 0x09,
18003 NM_SDX = 0x0d,
18005 NM_LBUX = 0x02,
18006 NM_LHUX = 0x06,
18007 NM_LWC1X = 0x0a,
18008 NM_LDC1X = 0x0e,
18010 NM_LWUX = 0x07,
18011 NM_SWC1X = 0x0b,
18012 NM_SDC1X = 0x0f,
18014 NM_LHXS = 0x04,
18015 NM_LWXS = 0x08,
18016 NM_LDXS = 0x0c,
18018 NM_SHXS = 0x05,
18019 NM_SWXS = 0x09,
18020 NM_SDXS = 0x0d,
18022 NM_LHUXS = 0x06,
18023 NM_LWC1XS = 0x0a,
18024 NM_LDC1XS = 0x0e,
18026 NM_LWUXS = 0x07,
18027 NM_SWC1XS = 0x0b,
18028 NM_SDC1XS = 0x0f,
18031 /* ERETx instruction pool */
18032 enum {
18033 NM_ERET = 0x00,
18034 NM_ERETNC = 0x01,
18037 /* POOL32FxF_{0, 1} insturction pool */
18038 enum {
18039 NM_CFC1 = 0x40,
18040 NM_CTC1 = 0x60,
18041 NM_MFC1 = 0x80,
18042 NM_MTC1 = 0xa0,
18043 NM_MFHC1 = 0xc0,
18044 NM_MTHC1 = 0xe0,
18046 NM_CVT_S_PL = 0x84,
18047 NM_CVT_S_PU = 0xa4,
18049 NM_CVT_L_S = 0x004,
18050 NM_CVT_L_D = 0x104,
18051 NM_CVT_W_S = 0x024,
18052 NM_CVT_W_D = 0x124,
18054 NM_RSQRT_S = 0x008,
18055 NM_RSQRT_D = 0x108,
18057 NM_SQRT_S = 0x028,
18058 NM_SQRT_D = 0x128,
18060 NM_RECIP_S = 0x048,
18061 NM_RECIP_D = 0x148,
18063 NM_FLOOR_L_S = 0x00c,
18064 NM_FLOOR_L_D = 0x10c,
18066 NM_FLOOR_W_S = 0x02c,
18067 NM_FLOOR_W_D = 0x12c,
18069 NM_CEIL_L_S = 0x04c,
18070 NM_CEIL_L_D = 0x14c,
18071 NM_CEIL_W_S = 0x06c,
18072 NM_CEIL_W_D = 0x16c,
18073 NM_TRUNC_L_S = 0x08c,
18074 NM_TRUNC_L_D = 0x18c,
18075 NM_TRUNC_W_S = 0x0ac,
18076 NM_TRUNC_W_D = 0x1ac,
18077 NM_ROUND_L_S = 0x0cc,
18078 NM_ROUND_L_D = 0x1cc,
18079 NM_ROUND_W_S = 0x0ec,
18080 NM_ROUND_W_D = 0x1ec,
18082 NM_MOV_S = 0x01,
18083 NM_MOV_D = 0x81,
18084 NM_ABS_S = 0x0d,
18085 NM_ABS_D = 0x8d,
18086 NM_NEG_S = 0x2d,
18087 NM_NEG_D = 0xad,
18088 NM_CVT_D_S = 0x04d,
18089 NM_CVT_D_W = 0x0cd,
18090 NM_CVT_D_L = 0x14d,
18091 NM_CVT_S_D = 0x06d,
18092 NM_CVT_S_W = 0x0ed,
18093 NM_CVT_S_L = 0x16d,
18096 /* P.LL instruction pool */
18097 enum {
18098 NM_LL = 0x00,
18099 NM_LLWP = 0x01,
18102 /* P.SC instruction pool */
18103 enum {
18104 NM_SC = 0x00,
18105 NM_SCWP = 0x01,
18108 /* P.DVP instruction pool */
18109 enum {
18110 NM_DVP = 0x00,
18111 NM_EVP = 0x01,
18117 * nanoMIPS decoding engine
18122 /* extraction utilities */
18124 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18125 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18126 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18127 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18128 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18129 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18131 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18132 static inline int decode_gpr_gpr3(int r)
18134 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18136 return map[r & 0x7];
18139 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18140 static inline int decode_gpr_gpr3_src_store(int r)
18142 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18144 return map[r & 0x7];
18147 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18148 static inline int decode_gpr_gpr4(int r)
18150 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18151 16, 17, 18, 19, 20, 21, 22, 23 };
18153 return map[r & 0xf];
18156 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18157 static inline int decode_gpr_gpr4_zero(int r)
18159 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18160 16, 17, 18, 19, 20, 21, 22, 23 };
18162 return map[r & 0xf];
18166 /* extraction utilities */
18168 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18169 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18170 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18171 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18172 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18173 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18176 static void gen_adjust_sp(DisasContext *ctx, int u)
18178 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18181 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18182 uint8_t gp, uint16_t u)
18184 int counter = 0;
18185 TCGv va = tcg_temp_new();
18186 TCGv t0 = tcg_temp_new();
18188 while (counter != count) {
18189 bool use_gp = gp && (counter == count - 1);
18190 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18191 int this_offset = -((counter + 1) << 2);
18192 gen_base_offset_addr(ctx, va, 29, this_offset);
18193 gen_load_gpr(t0, this_rt);
18194 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18195 (MO_TEUL | ctx->default_tcg_memop_mask));
18196 counter++;
18199 /* adjust stack pointer */
18200 gen_adjust_sp(ctx, -u);
18202 tcg_temp_free(t0);
18203 tcg_temp_free(va);
18206 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18207 uint8_t gp, uint16_t u)
18209 int counter = 0;
18210 TCGv va = tcg_temp_new();
18211 TCGv t0 = tcg_temp_new();
18213 while (counter != count) {
18214 bool use_gp = gp && (counter == count - 1);
18215 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18216 int this_offset = u - ((counter + 1) << 2);
18217 gen_base_offset_addr(ctx, va, 29, this_offset);
18218 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18219 ctx->default_tcg_memop_mask);
18220 tcg_gen_ext32s_tl(t0, t0);
18221 gen_store_gpr(t0, this_rt);
18222 counter++;
18225 /* adjust stack pointer */
18226 gen_adjust_sp(ctx, u);
18228 tcg_temp_free(t0);
18229 tcg_temp_free(va);
18232 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18234 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18235 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18237 switch (extract32(ctx->opcode, 2, 2)) {
18238 case NM_NOT16:
18239 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18240 break;
18241 case NM_AND16:
18242 gen_logic(ctx, OPC_AND, rt, rt, rs);
18243 break;
18244 case NM_XOR16:
18245 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18246 break;
18247 case NM_OR16:
18248 gen_logic(ctx, OPC_OR, rt, rt, rs);
18249 break;
18253 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18255 int rt = extract32(ctx->opcode, 21, 5);
18256 int rs = extract32(ctx->opcode, 16, 5);
18257 int rd = extract32(ctx->opcode, 11, 5);
18259 switch (extract32(ctx->opcode, 3, 7)) {
18260 case NM_P_TRAP:
18261 switch (extract32(ctx->opcode, 10, 1)) {
18262 case NM_TEQ:
18263 check_nms(ctx);
18264 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18265 break;
18266 case NM_TNE:
18267 check_nms(ctx);
18268 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18269 break;
18271 break;
18272 case NM_RDHWR:
18273 check_nms(ctx);
18274 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18275 break;
18276 case NM_SEB:
18277 check_nms(ctx);
18278 gen_bshfl(ctx, OPC_SEB, rs, rt);
18279 break;
18280 case NM_SEH:
18281 gen_bshfl(ctx, OPC_SEH, rs, rt);
18282 break;
18283 case NM_SLLV:
18284 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18285 break;
18286 case NM_SRLV:
18287 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18288 break;
18289 case NM_SRAV:
18290 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18291 break;
18292 case NM_ROTRV:
18293 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18294 break;
18295 case NM_ADD:
18296 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18297 break;
18298 case NM_ADDU:
18299 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18300 break;
18301 case NM_SUB:
18302 check_nms(ctx);
18303 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18304 break;
18305 case NM_SUBU:
18306 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18307 break;
18308 case NM_P_CMOVE:
18309 switch (extract32(ctx->opcode, 10, 1)) {
18310 case NM_MOVZ:
18311 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18312 break;
18313 case NM_MOVN:
18314 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18315 break;
18317 break;
18318 case NM_AND:
18319 gen_logic(ctx, OPC_AND, rd, rs, rt);
18320 break;
18321 case NM_OR:
18322 gen_logic(ctx, OPC_OR, rd, rs, rt);
18323 break;
18324 case NM_NOR:
18325 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18326 break;
18327 case NM_XOR:
18328 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18329 break;
18330 case NM_SLT:
18331 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18332 break;
18333 case NM_P_SLTU:
18334 if (rd == 0) {
18335 /* P_DVP */
18336 #ifndef CONFIG_USER_ONLY
18337 TCGv t0 = tcg_temp_new();
18338 switch (extract32(ctx->opcode, 10, 1)) {
18339 case NM_DVP:
18340 if (ctx->vp) {
18341 check_cp0_enabled(ctx);
18342 gen_helper_dvp(t0, cpu_env);
18343 gen_store_gpr(t0, rt);
18345 break;
18346 case NM_EVP:
18347 if (ctx->vp) {
18348 check_cp0_enabled(ctx);
18349 gen_helper_evp(t0, cpu_env);
18350 gen_store_gpr(t0, rt);
18352 break;
18354 tcg_temp_free(t0);
18355 #endif
18356 } else {
18357 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18359 break;
18360 case NM_SOV:
18362 TCGv t0 = tcg_temp_new();
18363 TCGv t1 = tcg_temp_new();
18364 TCGv t2 = tcg_temp_new();
18366 gen_load_gpr(t1, rs);
18367 gen_load_gpr(t2, rt);
18368 tcg_gen_add_tl(t0, t1, t2);
18369 tcg_gen_ext32s_tl(t0, t0);
18370 tcg_gen_xor_tl(t1, t1, t2);
18371 tcg_gen_xor_tl(t2, t0, t2);
18372 tcg_gen_andc_tl(t1, t2, t1);
18374 /* operands of same sign, result different sign */
18375 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18376 gen_store_gpr(t0, rd);
18378 tcg_temp_free(t0);
18379 tcg_temp_free(t1);
18380 tcg_temp_free(t2);
18382 break;
18383 case NM_MUL:
18384 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18385 break;
18386 case NM_MUH:
18387 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18388 break;
18389 case NM_MULU:
18390 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18391 break;
18392 case NM_MUHU:
18393 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18394 break;
18395 case NM_DIV:
18396 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18397 break;
18398 case NM_MOD:
18399 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18400 break;
18401 case NM_DIVU:
18402 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18403 break;
18404 case NM_MODU:
18405 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18406 break;
18407 #ifndef CONFIG_USER_ONLY
18408 case NM_MFC0:
18409 check_cp0_enabled(ctx);
18410 if (rt == 0) {
18411 /* Treat as NOP. */
18412 break;
18414 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18415 break;
18416 case NM_MTC0:
18417 check_cp0_enabled(ctx);
18419 TCGv t0 = tcg_temp_new();
18421 gen_load_gpr(t0, rt);
18422 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18423 tcg_temp_free(t0);
18425 break;
18426 case NM_D_E_MT_VPE:
18428 uint8_t sc = extract32(ctx->opcode, 10, 1);
18429 TCGv t0 = tcg_temp_new();
18431 switch (sc) {
18432 case 0:
18433 if (rs == 1) {
18434 /* DMT */
18435 check_cp0_mt(ctx);
18436 gen_helper_dmt(t0);
18437 gen_store_gpr(t0, rt);
18438 } else if (rs == 0) {
18439 /* DVPE */
18440 check_cp0_mt(ctx);
18441 gen_helper_dvpe(t0, cpu_env);
18442 gen_store_gpr(t0, rt);
18443 } else {
18444 generate_exception_end(ctx, EXCP_RI);
18446 break;
18447 case 1:
18448 if (rs == 1) {
18449 /* EMT */
18450 check_cp0_mt(ctx);
18451 gen_helper_emt(t0);
18452 gen_store_gpr(t0, rt);
18453 } else if (rs == 0) {
18454 /* EVPE */
18455 check_cp0_mt(ctx);
18456 gen_helper_evpe(t0, cpu_env);
18457 gen_store_gpr(t0, rt);
18458 } else {
18459 generate_exception_end(ctx, EXCP_RI);
18461 break;
18464 tcg_temp_free(t0);
18466 break;
18467 case NM_FORK:
18468 check_mt(ctx);
18470 TCGv t0 = tcg_temp_new();
18471 TCGv t1 = tcg_temp_new();
18473 gen_load_gpr(t0, rt);
18474 gen_load_gpr(t1, rs);
18475 gen_helper_fork(t0, t1);
18476 tcg_temp_free(t0);
18477 tcg_temp_free(t1);
18479 break;
18480 case NM_MFTR:
18481 case NM_MFHTR:
18482 check_cp0_enabled(ctx);
18483 if (rd == 0) {
18484 /* Treat as NOP. */
18485 return;
18487 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18488 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18489 break;
18490 case NM_MTTR:
18491 case NM_MTHTR:
18492 check_cp0_enabled(ctx);
18493 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18494 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18495 break;
18496 case NM_YIELD:
18497 check_mt(ctx);
18499 TCGv t0 = tcg_temp_new();
18501 gen_load_gpr(t0, rs);
18502 gen_helper_yield(t0, cpu_env, t0);
18503 gen_store_gpr(t0, rt);
18504 tcg_temp_free(t0);
18506 break;
18507 #endif
18508 default:
18509 generate_exception_end(ctx, EXCP_RI);
18510 break;
18514 /* dsp */
18515 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18516 int ret, int v1, int v2)
18518 TCGv_i32 t0;
18519 TCGv v0_t;
18520 TCGv v1_t;
18522 t0 = tcg_temp_new_i32();
18524 v0_t = tcg_temp_new();
18525 v1_t = tcg_temp_new();
18527 tcg_gen_movi_i32(t0, v2 >> 3);
18529 gen_load_gpr(v0_t, ret);
18530 gen_load_gpr(v1_t, v1);
18532 switch (opc) {
18533 case NM_MAQ_S_W_PHR:
18534 check_dsp(ctx);
18535 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18536 break;
18537 case NM_MAQ_S_W_PHL:
18538 check_dsp(ctx);
18539 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18540 break;
18541 case NM_MAQ_SA_W_PHR:
18542 check_dsp(ctx);
18543 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18544 break;
18545 case NM_MAQ_SA_W_PHL:
18546 check_dsp(ctx);
18547 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18548 break;
18549 default:
18550 generate_exception_end(ctx, EXCP_RI);
18551 break;
18554 tcg_temp_free_i32(t0);
18556 tcg_temp_free(v0_t);
18557 tcg_temp_free(v1_t);
18561 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18562 int ret, int v1, int v2)
18564 int16_t imm;
18565 TCGv t0 = tcg_temp_new();
18566 TCGv t1 = tcg_temp_new();
18567 TCGv v0_t = tcg_temp_new();
18569 gen_load_gpr(v0_t, v1);
18571 switch (opc) {
18572 case NM_POOL32AXF_1_0:
18573 check_dsp(ctx);
18574 switch (extract32(ctx->opcode, 12, 2)) {
18575 case NM_MFHI:
18576 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18577 break;
18578 case NM_MFLO:
18579 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18580 break;
18581 case NM_MTHI:
18582 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18583 break;
18584 case NM_MTLO:
18585 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18586 break;
18588 break;
18589 case NM_POOL32AXF_1_1:
18590 check_dsp(ctx);
18591 switch (extract32(ctx->opcode, 12, 2)) {
18592 case NM_MTHLIP:
18593 tcg_gen_movi_tl(t0, v2);
18594 gen_helper_mthlip(t0, v0_t, cpu_env);
18595 break;
18596 case NM_SHILOV:
18597 tcg_gen_movi_tl(t0, v2 >> 3);
18598 gen_helper_shilo(t0, v0_t, cpu_env);
18599 break;
18600 default:
18601 generate_exception_end(ctx, EXCP_RI);
18602 break;
18604 break;
18605 case NM_POOL32AXF_1_3:
18606 check_dsp(ctx);
18607 imm = extract32(ctx->opcode, 14, 7);
18608 switch (extract32(ctx->opcode, 12, 2)) {
18609 case NM_RDDSP:
18610 tcg_gen_movi_tl(t0, imm);
18611 gen_helper_rddsp(t0, t0, cpu_env);
18612 gen_store_gpr(t0, ret);
18613 break;
18614 case NM_WRDSP:
18615 gen_load_gpr(t0, ret);
18616 tcg_gen_movi_tl(t1, imm);
18617 gen_helper_wrdsp(t0, t1, cpu_env);
18618 break;
18619 case NM_EXTP:
18620 tcg_gen_movi_tl(t0, v2 >> 3);
18621 tcg_gen_movi_tl(t1, v1);
18622 gen_helper_extp(t0, t0, t1, cpu_env);
18623 gen_store_gpr(t0, ret);
18624 break;
18625 case NM_EXTPDP:
18626 tcg_gen_movi_tl(t0, v2 >> 3);
18627 tcg_gen_movi_tl(t1, v1);
18628 gen_helper_extpdp(t0, t0, t1, cpu_env);
18629 gen_store_gpr(t0, ret);
18630 break;
18632 break;
18633 case NM_POOL32AXF_1_4:
18634 check_dsp(ctx);
18635 tcg_gen_movi_tl(t0, v2 >> 2);
18636 switch (extract32(ctx->opcode, 12, 1)) {
18637 case NM_SHLL_QB:
18638 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18639 gen_store_gpr(t0, ret);
18640 break;
18641 case NM_SHRL_QB:
18642 gen_helper_shrl_qb(t0, t0, v0_t);
18643 gen_store_gpr(t0, ret);
18644 break;
18646 break;
18647 case NM_POOL32AXF_1_5:
18648 opc = extract32(ctx->opcode, 12, 2);
18649 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18650 break;
18651 case NM_POOL32AXF_1_7:
18652 check_dsp(ctx);
18653 tcg_gen_movi_tl(t0, v2 >> 3);
18654 tcg_gen_movi_tl(t1, v1);
18655 switch (extract32(ctx->opcode, 12, 2)) {
18656 case NM_EXTR_W:
18657 gen_helper_extr_w(t0, t0, t1, cpu_env);
18658 gen_store_gpr(t0, ret);
18659 break;
18660 case NM_EXTR_R_W:
18661 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18662 gen_store_gpr(t0, ret);
18663 break;
18664 case NM_EXTR_RS_W:
18665 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18666 gen_store_gpr(t0, ret);
18667 break;
18668 case NM_EXTR_S_H:
18669 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18670 gen_store_gpr(t0, ret);
18671 break;
18673 break;
18674 default:
18675 generate_exception_end(ctx, EXCP_RI);
18676 break;
18679 tcg_temp_free(t0);
18680 tcg_temp_free(t1);
18681 tcg_temp_free(v0_t);
18684 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18685 TCGv v0, TCGv v1, int rd)
18687 TCGv_i32 t0;
18689 t0 = tcg_temp_new_i32();
18691 tcg_gen_movi_i32(t0, rd >> 3);
18693 switch (opc) {
18694 case NM_POOL32AXF_2_0_7:
18695 switch (extract32(ctx->opcode, 9, 3)) {
18696 case NM_DPA_W_PH:
18697 check_dsp_r2(ctx);
18698 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18699 break;
18700 case NM_DPAQ_S_W_PH:
18701 check_dsp(ctx);
18702 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18703 break;
18704 case NM_DPS_W_PH:
18705 check_dsp_r2(ctx);
18706 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18707 break;
18708 case NM_DPSQ_S_W_PH:
18709 check_dsp(ctx);
18710 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18711 break;
18712 default:
18713 generate_exception_end(ctx, EXCP_RI);
18714 break;
18716 break;
18717 case NM_POOL32AXF_2_8_15:
18718 switch (extract32(ctx->opcode, 9, 3)) {
18719 case NM_DPAX_W_PH:
18720 check_dsp_r2(ctx);
18721 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18722 break;
18723 case NM_DPAQ_SA_L_W:
18724 check_dsp(ctx);
18725 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18726 break;
18727 case NM_DPSX_W_PH:
18728 check_dsp_r2(ctx);
18729 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18730 break;
18731 case NM_DPSQ_SA_L_W:
18732 check_dsp(ctx);
18733 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18734 break;
18735 default:
18736 generate_exception_end(ctx, EXCP_RI);
18737 break;
18739 break;
18740 case NM_POOL32AXF_2_16_23:
18741 switch (extract32(ctx->opcode, 9, 3)) {
18742 case NM_DPAU_H_QBL:
18743 check_dsp(ctx);
18744 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18745 break;
18746 case NM_DPAQX_S_W_PH:
18747 check_dsp_r2(ctx);
18748 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18749 break;
18750 case NM_DPSU_H_QBL:
18751 check_dsp(ctx);
18752 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18753 break;
18754 case NM_DPSQX_S_W_PH:
18755 check_dsp_r2(ctx);
18756 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18757 break;
18758 case NM_MULSA_W_PH:
18759 check_dsp_r2(ctx);
18760 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18761 break;
18762 default:
18763 generate_exception_end(ctx, EXCP_RI);
18764 break;
18766 break;
18767 case NM_POOL32AXF_2_24_31:
18768 switch (extract32(ctx->opcode, 9, 3)) {
18769 case NM_DPAU_H_QBR:
18770 check_dsp(ctx);
18771 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18772 break;
18773 case NM_DPAQX_SA_W_PH:
18774 check_dsp_r2(ctx);
18775 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18776 break;
18777 case NM_DPSU_H_QBR:
18778 check_dsp(ctx);
18779 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18780 break;
18781 case NM_DPSQX_SA_W_PH:
18782 check_dsp_r2(ctx);
18783 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18784 break;
18785 case NM_MULSAQ_S_W_PH:
18786 check_dsp(ctx);
18787 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18788 break;
18789 default:
18790 generate_exception_end(ctx, EXCP_RI);
18791 break;
18793 break;
18794 default:
18795 generate_exception_end(ctx, EXCP_RI);
18796 break;
18799 tcg_temp_free_i32(t0);
18802 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18803 int rt, int rs, int rd)
18805 int ret = rt;
18806 TCGv t0 = tcg_temp_new();
18807 TCGv t1 = tcg_temp_new();
18808 TCGv v0_t = tcg_temp_new();
18809 TCGv v1_t = tcg_temp_new();
18811 gen_load_gpr(v0_t, rt);
18812 gen_load_gpr(v1_t, rs);
18814 switch (opc) {
18815 case NM_POOL32AXF_2_0_7:
18816 switch (extract32(ctx->opcode, 9, 3)) {
18817 case NM_DPA_W_PH:
18818 case NM_DPAQ_S_W_PH:
18819 case NM_DPS_W_PH:
18820 case NM_DPSQ_S_W_PH:
18821 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18822 break;
18823 case NM_BALIGN:
18824 check_dsp_r2(ctx);
18825 if (rt != 0) {
18826 gen_load_gpr(t0, rs);
18827 rd &= 3;
18828 if (rd != 0 && rd != 2) {
18829 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18830 tcg_gen_ext32u_tl(t0, t0);
18831 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18832 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18834 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18836 break;
18837 case NM_MADD:
18838 check_dsp(ctx);
18840 int acc = extract32(ctx->opcode, 14, 2);
18841 TCGv_i64 t2 = tcg_temp_new_i64();
18842 TCGv_i64 t3 = tcg_temp_new_i64();
18844 gen_load_gpr(t0, rt);
18845 gen_load_gpr(t1, rs);
18846 tcg_gen_ext_tl_i64(t2, t0);
18847 tcg_gen_ext_tl_i64(t3, t1);
18848 tcg_gen_mul_i64(t2, t2, t3);
18849 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18850 tcg_gen_add_i64(t2, t2, t3);
18851 tcg_temp_free_i64(t3);
18852 gen_move_low32(cpu_LO[acc], t2);
18853 gen_move_high32(cpu_HI[acc], t2);
18854 tcg_temp_free_i64(t2);
18856 break;
18857 case NM_MULT:
18858 check_dsp(ctx);
18860 int acc = extract32(ctx->opcode, 14, 2);
18861 TCGv_i32 t2 = tcg_temp_new_i32();
18862 TCGv_i32 t3 = tcg_temp_new_i32();
18864 gen_load_gpr(t0, rs);
18865 gen_load_gpr(t1, rt);
18866 tcg_gen_trunc_tl_i32(t2, t0);
18867 tcg_gen_trunc_tl_i32(t3, t1);
18868 tcg_gen_muls2_i32(t2, t3, t2, t3);
18869 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18870 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18871 tcg_temp_free_i32(t2);
18872 tcg_temp_free_i32(t3);
18874 break;
18875 case NM_EXTRV_W:
18876 check_dsp(ctx);
18877 gen_load_gpr(v1_t, rs);
18878 tcg_gen_movi_tl(t0, rd >> 3);
18879 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18880 gen_store_gpr(t0, ret);
18881 break;
18883 break;
18884 case NM_POOL32AXF_2_8_15:
18885 switch (extract32(ctx->opcode, 9, 3)) {
18886 case NM_DPAX_W_PH:
18887 case NM_DPAQ_SA_L_W:
18888 case NM_DPSX_W_PH:
18889 case NM_DPSQ_SA_L_W:
18890 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18891 break;
18892 case NM_MADDU:
18893 check_dsp(ctx);
18895 int acc = extract32(ctx->opcode, 14, 2);
18896 TCGv_i64 t2 = tcg_temp_new_i64();
18897 TCGv_i64 t3 = tcg_temp_new_i64();
18899 gen_load_gpr(t0, rs);
18900 gen_load_gpr(t1, rt);
18901 tcg_gen_ext32u_tl(t0, t0);
18902 tcg_gen_ext32u_tl(t1, t1);
18903 tcg_gen_extu_tl_i64(t2, t0);
18904 tcg_gen_extu_tl_i64(t3, t1);
18905 tcg_gen_mul_i64(t2, t2, t3);
18906 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18907 tcg_gen_add_i64(t2, t2, t3);
18908 tcg_temp_free_i64(t3);
18909 gen_move_low32(cpu_LO[acc], t2);
18910 gen_move_high32(cpu_HI[acc], t2);
18911 tcg_temp_free_i64(t2);
18913 break;
18914 case NM_MULTU:
18915 check_dsp(ctx);
18917 int acc = extract32(ctx->opcode, 14, 2);
18918 TCGv_i32 t2 = tcg_temp_new_i32();
18919 TCGv_i32 t3 = tcg_temp_new_i32();
18921 gen_load_gpr(t0, rs);
18922 gen_load_gpr(t1, rt);
18923 tcg_gen_trunc_tl_i32(t2, t0);
18924 tcg_gen_trunc_tl_i32(t3, t1);
18925 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18926 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18927 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18928 tcg_temp_free_i32(t2);
18929 tcg_temp_free_i32(t3);
18931 break;
18932 case NM_EXTRV_R_W:
18933 check_dsp(ctx);
18934 tcg_gen_movi_tl(t0, rd >> 3);
18935 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18936 gen_store_gpr(t0, ret);
18937 break;
18938 default:
18939 generate_exception_end(ctx, EXCP_RI);
18940 break;
18942 break;
18943 case NM_POOL32AXF_2_16_23:
18944 switch (extract32(ctx->opcode, 9, 3)) {
18945 case NM_DPAU_H_QBL:
18946 case NM_DPAQX_S_W_PH:
18947 case NM_DPSU_H_QBL:
18948 case NM_DPSQX_S_W_PH:
18949 case NM_MULSA_W_PH:
18950 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18951 break;
18952 case NM_EXTPV:
18953 check_dsp(ctx);
18954 tcg_gen_movi_tl(t0, rd >> 3);
18955 gen_helper_extp(t0, t0, v1_t, cpu_env);
18956 gen_store_gpr(t0, ret);
18957 break;
18958 case NM_MSUB:
18959 check_dsp(ctx);
18961 int acc = extract32(ctx->opcode, 14, 2);
18962 TCGv_i64 t2 = tcg_temp_new_i64();
18963 TCGv_i64 t3 = tcg_temp_new_i64();
18965 gen_load_gpr(t0, rs);
18966 gen_load_gpr(t1, rt);
18967 tcg_gen_ext_tl_i64(t2, t0);
18968 tcg_gen_ext_tl_i64(t3, t1);
18969 tcg_gen_mul_i64(t2, t2, t3);
18970 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18971 tcg_gen_sub_i64(t2, t3, t2);
18972 tcg_temp_free_i64(t3);
18973 gen_move_low32(cpu_LO[acc], t2);
18974 gen_move_high32(cpu_HI[acc], t2);
18975 tcg_temp_free_i64(t2);
18977 break;
18978 case NM_EXTRV_RS_W:
18979 check_dsp(ctx);
18980 tcg_gen_movi_tl(t0, rd >> 3);
18981 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18982 gen_store_gpr(t0, ret);
18983 break;
18985 break;
18986 case NM_POOL32AXF_2_24_31:
18987 switch (extract32(ctx->opcode, 9, 3)) {
18988 case NM_DPAU_H_QBR:
18989 case NM_DPAQX_SA_W_PH:
18990 case NM_DPSU_H_QBR:
18991 case NM_DPSQX_SA_W_PH:
18992 case NM_MULSAQ_S_W_PH:
18993 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18994 break;
18995 case NM_EXTPDPV:
18996 check_dsp(ctx);
18997 tcg_gen_movi_tl(t0, rd >> 3);
18998 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18999 gen_store_gpr(t0, ret);
19000 break;
19001 case NM_MSUBU:
19002 check_dsp(ctx);
19004 int acc = extract32(ctx->opcode, 14, 2);
19005 TCGv_i64 t2 = tcg_temp_new_i64();
19006 TCGv_i64 t3 = tcg_temp_new_i64();
19008 gen_load_gpr(t0, rs);
19009 gen_load_gpr(t1, rt);
19010 tcg_gen_ext32u_tl(t0, t0);
19011 tcg_gen_ext32u_tl(t1, t1);
19012 tcg_gen_extu_tl_i64(t2, t0);
19013 tcg_gen_extu_tl_i64(t3, t1);
19014 tcg_gen_mul_i64(t2, t2, t3);
19015 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19016 tcg_gen_sub_i64(t2, t3, t2);
19017 tcg_temp_free_i64(t3);
19018 gen_move_low32(cpu_LO[acc], t2);
19019 gen_move_high32(cpu_HI[acc], t2);
19020 tcg_temp_free_i64(t2);
19022 break;
19023 case NM_EXTRV_S_H:
19024 check_dsp(ctx);
19025 tcg_gen_movi_tl(t0, rd >> 3);
19026 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19027 gen_store_gpr(t0, ret);
19028 break;
19030 break;
19031 default:
19032 generate_exception_end(ctx, EXCP_RI);
19033 break;
19036 tcg_temp_free(t0);
19037 tcg_temp_free(t1);
19039 tcg_temp_free(v0_t);
19040 tcg_temp_free(v1_t);
19043 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19044 int rt, int rs)
19046 int ret = rt;
19047 TCGv t0 = tcg_temp_new();
19048 TCGv v0_t = tcg_temp_new();
19050 gen_load_gpr(v0_t, rs);
19052 switch (opc) {
19053 case NM_ABSQ_S_QB:
19054 check_dsp_r2(ctx);
19055 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19056 gen_store_gpr(v0_t, ret);
19057 break;
19058 case NM_ABSQ_S_PH:
19059 check_dsp(ctx);
19060 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19061 gen_store_gpr(v0_t, ret);
19062 break;
19063 case NM_ABSQ_S_W:
19064 check_dsp(ctx);
19065 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19066 gen_store_gpr(v0_t, ret);
19067 break;
19068 case NM_PRECEQ_W_PHL:
19069 check_dsp(ctx);
19070 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19071 tcg_gen_ext32s_tl(v0_t, v0_t);
19072 gen_store_gpr(v0_t, ret);
19073 break;
19074 case NM_PRECEQ_W_PHR:
19075 check_dsp(ctx);
19076 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19077 tcg_gen_shli_tl(v0_t, v0_t, 16);
19078 tcg_gen_ext32s_tl(v0_t, v0_t);
19079 gen_store_gpr(v0_t, ret);
19080 break;
19081 case NM_PRECEQU_PH_QBL:
19082 check_dsp(ctx);
19083 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19084 gen_store_gpr(v0_t, ret);
19085 break;
19086 case NM_PRECEQU_PH_QBR:
19087 check_dsp(ctx);
19088 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19089 gen_store_gpr(v0_t, ret);
19090 break;
19091 case NM_PRECEQU_PH_QBLA:
19092 check_dsp(ctx);
19093 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19094 gen_store_gpr(v0_t, ret);
19095 break;
19096 case NM_PRECEQU_PH_QBRA:
19097 check_dsp(ctx);
19098 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19099 gen_store_gpr(v0_t, ret);
19100 break;
19101 case NM_PRECEU_PH_QBL:
19102 check_dsp(ctx);
19103 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19104 gen_store_gpr(v0_t, ret);
19105 break;
19106 case NM_PRECEU_PH_QBR:
19107 check_dsp(ctx);
19108 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19109 gen_store_gpr(v0_t, ret);
19110 break;
19111 case NM_PRECEU_PH_QBLA:
19112 check_dsp(ctx);
19113 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19114 gen_store_gpr(v0_t, ret);
19115 break;
19116 case NM_PRECEU_PH_QBRA:
19117 check_dsp(ctx);
19118 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19119 gen_store_gpr(v0_t, ret);
19120 break;
19121 case NM_REPLV_PH:
19122 check_dsp(ctx);
19123 tcg_gen_ext16u_tl(v0_t, v0_t);
19124 tcg_gen_shli_tl(t0, v0_t, 16);
19125 tcg_gen_or_tl(v0_t, v0_t, t0);
19126 tcg_gen_ext32s_tl(v0_t, v0_t);
19127 gen_store_gpr(v0_t, ret);
19128 break;
19129 case NM_REPLV_QB:
19130 check_dsp(ctx);
19131 tcg_gen_ext8u_tl(v0_t, v0_t);
19132 tcg_gen_shli_tl(t0, v0_t, 8);
19133 tcg_gen_or_tl(v0_t, v0_t, t0);
19134 tcg_gen_shli_tl(t0, v0_t, 16);
19135 tcg_gen_or_tl(v0_t, v0_t, t0);
19136 tcg_gen_ext32s_tl(v0_t, v0_t);
19137 gen_store_gpr(v0_t, ret);
19138 break;
19139 case NM_BITREV:
19140 check_dsp(ctx);
19141 gen_helper_bitrev(v0_t, v0_t);
19142 gen_store_gpr(v0_t, ret);
19143 break;
19144 case NM_INSV:
19145 check_dsp(ctx);
19147 TCGv tv0 = tcg_temp_new();
19149 gen_load_gpr(tv0, rt);
19150 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19151 gen_store_gpr(v0_t, ret);
19152 tcg_temp_free(tv0);
19154 break;
19155 case NM_RADDU_W_QB:
19156 check_dsp(ctx);
19157 gen_helper_raddu_w_qb(v0_t, v0_t);
19158 gen_store_gpr(v0_t, ret);
19159 break;
19160 case NM_BITSWAP:
19161 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19162 break;
19163 case NM_CLO:
19164 check_nms(ctx);
19165 gen_cl(ctx, OPC_CLO, ret, rs);
19166 break;
19167 case NM_CLZ:
19168 check_nms(ctx);
19169 gen_cl(ctx, OPC_CLZ, ret, rs);
19170 break;
19171 case NM_WSBH:
19172 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19173 break;
19174 default:
19175 generate_exception_end(ctx, EXCP_RI);
19176 break;
19179 tcg_temp_free(v0_t);
19180 tcg_temp_free(t0);
19183 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19184 int rt, int rs, int rd)
19186 TCGv t0 = tcg_temp_new();
19187 TCGv rs_t = tcg_temp_new();
19189 gen_load_gpr(rs_t, rs);
19191 switch (opc) {
19192 case NM_SHRA_R_QB:
19193 check_dsp_r2(ctx);
19194 tcg_gen_movi_tl(t0, rd >> 2);
19195 switch (extract32(ctx->opcode, 12, 1)) {
19196 case 0:
19197 /* NM_SHRA_QB */
19198 gen_helper_shra_qb(t0, t0, rs_t);
19199 gen_store_gpr(t0, rt);
19200 break;
19201 case 1:
19202 /* NM_SHRA_R_QB */
19203 gen_helper_shra_r_qb(t0, t0, rs_t);
19204 gen_store_gpr(t0, rt);
19205 break;
19207 break;
19208 case NM_SHRL_PH:
19209 check_dsp_r2(ctx);
19210 tcg_gen_movi_tl(t0, rd >> 1);
19211 gen_helper_shrl_ph(t0, t0, rs_t);
19212 gen_store_gpr(t0, rt);
19213 break;
19214 case NM_REPL_QB:
19215 check_dsp(ctx);
19217 int16_t imm;
19218 target_long result;
19219 imm = extract32(ctx->opcode, 13, 8);
19220 result = (uint32_t)imm << 24 |
19221 (uint32_t)imm << 16 |
19222 (uint32_t)imm << 8 |
19223 (uint32_t)imm;
19224 result = (int32_t)result;
19225 tcg_gen_movi_tl(t0, result);
19226 gen_store_gpr(t0, rt);
19228 break;
19229 default:
19230 generate_exception_end(ctx, EXCP_RI);
19231 break;
19233 tcg_temp_free(t0);
19234 tcg_temp_free(rs_t);
19238 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19240 int rt = extract32(ctx->opcode, 21, 5);
19241 int rs = extract32(ctx->opcode, 16, 5);
19242 int rd = extract32(ctx->opcode, 11, 5);
19244 switch (extract32(ctx->opcode, 6, 3)) {
19245 case NM_POOL32AXF_1:
19247 int32_t op1 = extract32(ctx->opcode, 9, 3);
19248 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19250 break;
19251 case NM_POOL32AXF_2:
19253 int32_t op1 = extract32(ctx->opcode, 12, 2);
19254 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19256 break;
19257 case NM_POOL32AXF_4:
19259 int32_t op1 = extract32(ctx->opcode, 9, 7);
19260 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19262 break;
19263 case NM_POOL32AXF_5:
19264 switch (extract32(ctx->opcode, 9, 7)) {
19265 #ifndef CONFIG_USER_ONLY
19266 case NM_TLBP:
19267 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19268 break;
19269 case NM_TLBR:
19270 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19271 break;
19272 case NM_TLBWI:
19273 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19274 break;
19275 case NM_TLBWR:
19276 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19277 break;
19278 case NM_TLBINV:
19279 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19280 break;
19281 case NM_TLBINVF:
19282 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19283 break;
19284 case NM_DI:
19285 check_cp0_enabled(ctx);
19287 TCGv t0 = tcg_temp_new();
19289 save_cpu_state(ctx, 1);
19290 gen_helper_di(t0, cpu_env);
19291 gen_store_gpr(t0, rt);
19292 /* Stop translation as we may have switched the execution mode */
19293 ctx->base.is_jmp = DISAS_STOP;
19294 tcg_temp_free(t0);
19296 break;
19297 case NM_EI:
19298 check_cp0_enabled(ctx);
19300 TCGv t0 = tcg_temp_new();
19302 save_cpu_state(ctx, 1);
19303 gen_helper_ei(t0, cpu_env);
19304 gen_store_gpr(t0, rt);
19305 /* Stop translation as we may have switched the execution mode */
19306 ctx->base.is_jmp = DISAS_STOP;
19307 tcg_temp_free(t0);
19309 break;
19310 case NM_RDPGPR:
19311 gen_load_srsgpr(rs, rt);
19312 break;
19313 case NM_WRPGPR:
19314 gen_store_srsgpr(rs, rt);
19315 break;
19316 case NM_WAIT:
19317 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19318 break;
19319 case NM_DERET:
19320 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19321 break;
19322 case NM_ERETX:
19323 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19324 break;
19325 #endif
19326 default:
19327 generate_exception_end(ctx, EXCP_RI);
19328 break;
19330 break;
19331 case NM_POOL32AXF_7:
19333 int32_t op1 = extract32(ctx->opcode, 9, 3);
19334 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19336 break;
19337 default:
19338 generate_exception_end(ctx, EXCP_RI);
19339 break;
19343 /* Immediate Value Compact Branches */
19344 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19345 int rt, int32_t imm, int32_t offset)
19347 TCGCond cond;
19348 int bcond_compute = 0;
19349 TCGv t0 = tcg_temp_new();
19350 TCGv t1 = tcg_temp_new();
19352 gen_load_gpr(t0, rt);
19353 tcg_gen_movi_tl(t1, imm);
19354 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19356 /* Load needed operands and calculate btarget */
19357 switch (opc) {
19358 case NM_BEQIC:
19359 if (rt == 0 && imm == 0) {
19360 /* Unconditional branch */
19361 } else if (rt == 0 && imm != 0) {
19362 /* Treat as NOP */
19363 goto out;
19364 } else {
19365 bcond_compute = 1;
19366 cond = TCG_COND_EQ;
19368 break;
19369 case NM_BBEQZC:
19370 case NM_BBNEZC:
19371 check_nms(ctx);
19372 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19373 generate_exception_end(ctx, EXCP_RI);
19374 goto out;
19375 } else if (rt == 0 && opc == NM_BBEQZC) {
19376 /* Unconditional branch */
19377 } else if (rt == 0 && opc == NM_BBNEZC) {
19378 /* Treat as NOP */
19379 goto out;
19380 } else {
19381 tcg_gen_shri_tl(t0, t0, imm);
19382 tcg_gen_andi_tl(t0, t0, 1);
19383 tcg_gen_movi_tl(t1, 0);
19384 bcond_compute = 1;
19385 if (opc == NM_BBEQZC) {
19386 cond = TCG_COND_EQ;
19387 } else {
19388 cond = TCG_COND_NE;
19391 break;
19392 case NM_BNEIC:
19393 if (rt == 0 && imm == 0) {
19394 /* Treat as NOP */
19395 goto out;
19396 } else if (rt == 0 && imm != 0) {
19397 /* Unconditional branch */
19398 } else {
19399 bcond_compute = 1;
19400 cond = TCG_COND_NE;
19402 break;
19403 case NM_BGEIC:
19404 if (rt == 0 && imm == 0) {
19405 /* Unconditional branch */
19406 } else {
19407 bcond_compute = 1;
19408 cond = TCG_COND_GE;
19410 break;
19411 case NM_BLTIC:
19412 bcond_compute = 1;
19413 cond = TCG_COND_LT;
19414 break;
19415 case NM_BGEIUC:
19416 if (rt == 0 && imm == 0) {
19417 /* Unconditional branch */
19418 } else {
19419 bcond_compute = 1;
19420 cond = TCG_COND_GEU;
19422 break;
19423 case NM_BLTIUC:
19424 bcond_compute = 1;
19425 cond = TCG_COND_LTU;
19426 break;
19427 default:
19428 MIPS_INVAL("Immediate Value Compact branch");
19429 generate_exception_end(ctx, EXCP_RI);
19430 goto out;
19433 if (bcond_compute == 0) {
19434 /* Uncoditional compact branch */
19435 gen_goto_tb(ctx, 0, ctx->btarget);
19436 } else {
19437 /* Conditional compact branch */
19438 TCGLabel *fs = gen_new_label();
19440 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19442 gen_goto_tb(ctx, 1, ctx->btarget);
19443 gen_set_label(fs);
19445 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19448 out:
19449 tcg_temp_free(t0);
19450 tcg_temp_free(t1);
19453 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19454 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19455 int rt)
19457 TCGv t0 = tcg_temp_new();
19458 TCGv t1 = tcg_temp_new();
19460 /* load rs */
19461 gen_load_gpr(t0, rs);
19463 /* link */
19464 if (rt != 0) {
19465 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19468 /* calculate btarget */
19469 tcg_gen_shli_tl(t0, t0, 1);
19470 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19471 gen_op_addr_add(ctx, btarget, t1, t0);
19473 /* unconditional branch to register */
19474 tcg_gen_mov_tl(cpu_PC, btarget);
19475 tcg_gen_lookup_and_goto_ptr();
19477 tcg_temp_free(t0);
19478 tcg_temp_free(t1);
19481 /* nanoMIPS Branches */
19482 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19483 int rs, int rt, int32_t offset)
19485 int bcond_compute = 0;
19486 TCGv t0 = tcg_temp_new();
19487 TCGv t1 = tcg_temp_new();
19489 /* Load needed operands and calculate btarget */
19490 switch (opc) {
19491 /* compact branch */
19492 case OPC_BGEC:
19493 case OPC_BLTC:
19494 gen_load_gpr(t0, rs);
19495 gen_load_gpr(t1, rt);
19496 bcond_compute = 1;
19497 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19498 break;
19499 case OPC_BGEUC:
19500 case OPC_BLTUC:
19501 if (rs == 0 || rs == rt) {
19502 /* OPC_BLEZALC, OPC_BGEZALC */
19503 /* OPC_BGTZALC, OPC_BLTZALC */
19504 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19506 gen_load_gpr(t0, rs);
19507 gen_load_gpr(t1, rt);
19508 bcond_compute = 1;
19509 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19510 break;
19511 case OPC_BC:
19512 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19513 break;
19514 case OPC_BEQZC:
19515 if (rs != 0) {
19516 /* OPC_BEQZC, OPC_BNEZC */
19517 gen_load_gpr(t0, rs);
19518 bcond_compute = 1;
19519 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19520 } else {
19521 /* OPC_JIC, OPC_JIALC */
19522 TCGv tbase = tcg_temp_new();
19523 TCGv toffset = tcg_temp_new();
19525 gen_load_gpr(tbase, rt);
19526 tcg_gen_movi_tl(toffset, offset);
19527 gen_op_addr_add(ctx, btarget, tbase, toffset);
19528 tcg_temp_free(tbase);
19529 tcg_temp_free(toffset);
19531 break;
19532 default:
19533 MIPS_INVAL("Compact branch/jump");
19534 generate_exception_end(ctx, EXCP_RI);
19535 goto out;
19538 if (bcond_compute == 0) {
19539 /* Uncoditional compact branch */
19540 switch (opc) {
19541 case OPC_BC:
19542 gen_goto_tb(ctx, 0, ctx->btarget);
19543 break;
19544 default:
19545 MIPS_INVAL("Compact branch/jump");
19546 generate_exception_end(ctx, EXCP_RI);
19547 goto out;
19549 } else {
19550 /* Conditional compact branch */
19551 TCGLabel *fs = gen_new_label();
19553 switch (opc) {
19554 case OPC_BGEUC:
19555 if (rs == 0 && rt != 0) {
19556 /* OPC_BLEZALC */
19557 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19558 } else if (rs != 0 && rt != 0 && rs == rt) {
19559 /* OPC_BGEZALC */
19560 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19561 } else {
19562 /* OPC_BGEUC */
19563 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19565 break;
19566 case OPC_BLTUC:
19567 if (rs == 0 && rt != 0) {
19568 /* OPC_BGTZALC */
19569 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19570 } else if (rs != 0 && rt != 0 && rs == rt) {
19571 /* OPC_BLTZALC */
19572 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19573 } else {
19574 /* OPC_BLTUC */
19575 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19577 break;
19578 case OPC_BGEC:
19579 if (rs == 0 && rt != 0) {
19580 /* OPC_BLEZC */
19581 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19582 } else if (rs != 0 && rt != 0 && rs == rt) {
19583 /* OPC_BGEZC */
19584 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19585 } else {
19586 /* OPC_BGEC */
19587 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19589 break;
19590 case OPC_BLTC:
19591 if (rs == 0 && rt != 0) {
19592 /* OPC_BGTZC */
19593 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19594 } else if (rs != 0 && rt != 0 && rs == rt) {
19595 /* OPC_BLTZC */
19596 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19597 } else {
19598 /* OPC_BLTC */
19599 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19601 break;
19602 case OPC_BEQZC:
19603 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19604 break;
19605 default:
19606 MIPS_INVAL("Compact conditional branch/jump");
19607 generate_exception_end(ctx, EXCP_RI);
19608 goto out;
19611 /* Generating branch here as compact branches don't have delay slot */
19612 gen_goto_tb(ctx, 1, ctx->btarget);
19613 gen_set_label(fs);
19615 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19618 out:
19619 tcg_temp_free(t0);
19620 tcg_temp_free(t1);
19624 /* nanoMIPS CP1 Branches */
19625 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19626 int32_t ft, int32_t offset)
19628 target_ulong btarget;
19629 TCGv_i64 t0 = tcg_temp_new_i64();
19631 gen_load_fpr64(ctx, t0, ft);
19632 tcg_gen_andi_i64(t0, t0, 1);
19634 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19636 switch (op) {
19637 case NM_BC1EQZC:
19638 tcg_gen_xori_i64(t0, t0, 1);
19639 ctx->hflags |= MIPS_HFLAG_BC;
19640 break;
19641 case NM_BC1NEZC:
19642 /* t0 already set */
19643 ctx->hflags |= MIPS_HFLAG_BC;
19644 break;
19645 default:
19646 MIPS_INVAL("cp1 cond branch");
19647 generate_exception_end(ctx, EXCP_RI);
19648 goto out;
19651 tcg_gen_trunc_i64_tl(bcond, t0);
19653 ctx->btarget = btarget;
19655 out:
19656 tcg_temp_free_i64(t0);
19660 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19662 TCGv t0, t1;
19663 t0 = tcg_temp_new();
19664 t1 = tcg_temp_new();
19666 gen_load_gpr(t0, rs);
19667 gen_load_gpr(t1, rt);
19669 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19670 /* PP.LSXS instructions require shifting */
19671 switch (extract32(ctx->opcode, 7, 4)) {
19672 case NM_SHXS:
19673 check_nms(ctx);
19674 case NM_LHXS:
19675 case NM_LHUXS:
19676 tcg_gen_shli_tl(t0, t0, 1);
19677 break;
19678 case NM_SWXS:
19679 check_nms(ctx);
19680 case NM_LWXS:
19681 case NM_LWC1XS:
19682 case NM_SWC1XS:
19683 tcg_gen_shli_tl(t0, t0, 2);
19684 break;
19685 case NM_LDC1XS:
19686 case NM_SDC1XS:
19687 tcg_gen_shli_tl(t0, t0, 3);
19688 break;
19691 gen_op_addr_add(ctx, t0, t0, t1);
19693 switch (extract32(ctx->opcode, 7, 4)) {
19694 case NM_LBX:
19695 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19696 MO_SB);
19697 gen_store_gpr(t0, rd);
19698 break;
19699 case NM_LHX:
19700 /*case NM_LHXS:*/
19701 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19702 MO_TESW);
19703 gen_store_gpr(t0, rd);
19704 break;
19705 case NM_LWX:
19706 /*case NM_LWXS:*/
19707 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19708 MO_TESL);
19709 gen_store_gpr(t0, rd);
19710 break;
19711 case NM_LBUX:
19712 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19713 MO_UB);
19714 gen_store_gpr(t0, rd);
19715 break;
19716 case NM_LHUX:
19717 /*case NM_LHUXS:*/
19718 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19719 MO_TEUW);
19720 gen_store_gpr(t0, rd);
19721 break;
19722 case NM_SBX:
19723 check_nms(ctx);
19724 gen_load_gpr(t1, rd);
19725 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19726 MO_8);
19727 break;
19728 case NM_SHX:
19729 /*case NM_SHXS:*/
19730 check_nms(ctx);
19731 gen_load_gpr(t1, rd);
19732 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19733 MO_TEUW);
19734 break;
19735 case NM_SWX:
19736 /*case NM_SWXS:*/
19737 check_nms(ctx);
19738 gen_load_gpr(t1, rd);
19739 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19740 MO_TEUL);
19741 break;
19742 case NM_LWC1X:
19743 /*case NM_LWC1XS:*/
19744 case NM_LDC1X:
19745 /*case NM_LDC1XS:*/
19746 case NM_SWC1X:
19747 /*case NM_SWC1XS:*/
19748 case NM_SDC1X:
19749 /*case NM_SDC1XS:*/
19750 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19751 check_cp1_enabled(ctx);
19752 switch (extract32(ctx->opcode, 7, 4)) {
19753 case NM_LWC1X:
19754 /*case NM_LWC1XS:*/
19755 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19756 break;
19757 case NM_LDC1X:
19758 /*case NM_LDC1XS:*/
19759 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19760 break;
19761 case NM_SWC1X:
19762 /*case NM_SWC1XS:*/
19763 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19764 break;
19765 case NM_SDC1X:
19766 /*case NM_SDC1XS:*/
19767 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19768 break;
19770 } else {
19771 generate_exception_err(ctx, EXCP_CpU, 1);
19773 break;
19774 default:
19775 generate_exception_end(ctx, EXCP_RI);
19776 break;
19779 tcg_temp_free(t0);
19780 tcg_temp_free(t1);
19783 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19785 int rt, rs, rd;
19787 rt = extract32(ctx->opcode, 21, 5);
19788 rs = extract32(ctx->opcode, 16, 5);
19789 rd = extract32(ctx->opcode, 11, 5);
19791 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19792 generate_exception_end(ctx, EXCP_RI);
19793 return;
19795 check_cp1_enabled(ctx);
19796 switch (extract32(ctx->opcode, 0, 3)) {
19797 case NM_POOL32F_0:
19798 switch (extract32(ctx->opcode, 3, 7)) {
19799 case NM_RINT_S:
19800 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19801 break;
19802 case NM_RINT_D:
19803 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19804 break;
19805 case NM_CLASS_S:
19806 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19807 break;
19808 case NM_CLASS_D:
19809 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19810 break;
19811 case NM_ADD_S:
19812 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19813 break;
19814 case NM_ADD_D:
19815 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19816 break;
19817 case NM_SUB_S:
19818 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19819 break;
19820 case NM_SUB_D:
19821 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19822 break;
19823 case NM_MUL_S:
19824 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19825 break;
19826 case NM_MUL_D:
19827 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19828 break;
19829 case NM_DIV_S:
19830 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19831 break;
19832 case NM_DIV_D:
19833 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19834 break;
19835 case NM_SELEQZ_S:
19836 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19837 break;
19838 case NM_SELEQZ_D:
19839 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19840 break;
19841 case NM_SELNEZ_S:
19842 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19843 break;
19844 case NM_SELNEZ_D:
19845 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19846 break;
19847 case NM_SEL_S:
19848 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19849 break;
19850 case NM_SEL_D:
19851 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19852 break;
19853 case NM_MADDF_S:
19854 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19855 break;
19856 case NM_MADDF_D:
19857 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19858 break;
19859 case NM_MSUBF_S:
19860 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19861 break;
19862 case NM_MSUBF_D:
19863 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19864 break;
19865 default:
19866 generate_exception_end(ctx, EXCP_RI);
19867 break;
19869 break;
19870 case NM_POOL32F_3:
19871 switch (extract32(ctx->opcode, 3, 3)) {
19872 case NM_MIN_FMT:
19873 switch (extract32(ctx->opcode, 9, 1)) {
19874 case FMT_SDPS_S:
19875 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19876 break;
19877 case FMT_SDPS_D:
19878 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19879 break;
19881 break;
19882 case NM_MAX_FMT:
19883 switch (extract32(ctx->opcode, 9, 1)) {
19884 case FMT_SDPS_S:
19885 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19886 break;
19887 case FMT_SDPS_D:
19888 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19889 break;
19891 break;
19892 case NM_MINA_FMT:
19893 switch (extract32(ctx->opcode, 9, 1)) {
19894 case FMT_SDPS_S:
19895 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19896 break;
19897 case FMT_SDPS_D:
19898 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19899 break;
19901 break;
19902 case NM_MAXA_FMT:
19903 switch (extract32(ctx->opcode, 9, 1)) {
19904 case FMT_SDPS_S:
19905 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19906 break;
19907 case FMT_SDPS_D:
19908 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19909 break;
19911 break;
19912 case NM_POOL32FXF:
19913 switch (extract32(ctx->opcode, 6, 8)) {
19914 case NM_CFC1:
19915 gen_cp1(ctx, OPC_CFC1, rt, rs);
19916 break;
19917 case NM_CTC1:
19918 gen_cp1(ctx, OPC_CTC1, rt, rs);
19919 break;
19920 case NM_MFC1:
19921 gen_cp1(ctx, OPC_MFC1, rt, rs);
19922 break;
19923 case NM_MTC1:
19924 gen_cp1(ctx, OPC_MTC1, rt, rs);
19925 break;
19926 case NM_MFHC1:
19927 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19928 break;
19929 case NM_MTHC1:
19930 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19931 break;
19932 case NM_CVT_S_PL:
19933 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19934 break;
19935 case NM_CVT_S_PU:
19936 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19937 break;
19938 default:
19939 switch (extract32(ctx->opcode, 6, 9)) {
19940 case NM_CVT_L_S:
19941 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19942 break;
19943 case NM_CVT_L_D:
19944 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19945 break;
19946 case NM_CVT_W_S:
19947 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19948 break;
19949 case NM_CVT_W_D:
19950 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19951 break;
19952 case NM_RSQRT_S:
19953 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19954 break;
19955 case NM_RSQRT_D:
19956 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19957 break;
19958 case NM_SQRT_S:
19959 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19960 break;
19961 case NM_SQRT_D:
19962 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19963 break;
19964 case NM_RECIP_S:
19965 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19966 break;
19967 case NM_RECIP_D:
19968 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19969 break;
19970 case NM_FLOOR_L_S:
19971 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19972 break;
19973 case NM_FLOOR_L_D:
19974 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19975 break;
19976 case NM_FLOOR_W_S:
19977 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19978 break;
19979 case NM_FLOOR_W_D:
19980 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19981 break;
19982 case NM_CEIL_L_S:
19983 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19984 break;
19985 case NM_CEIL_L_D:
19986 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19987 break;
19988 case NM_CEIL_W_S:
19989 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19990 break;
19991 case NM_CEIL_W_D:
19992 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19993 break;
19994 case NM_TRUNC_L_S:
19995 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19996 break;
19997 case NM_TRUNC_L_D:
19998 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19999 break;
20000 case NM_TRUNC_W_S:
20001 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20002 break;
20003 case NM_TRUNC_W_D:
20004 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20005 break;
20006 case NM_ROUND_L_S:
20007 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20008 break;
20009 case NM_ROUND_L_D:
20010 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20011 break;
20012 case NM_ROUND_W_S:
20013 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20014 break;
20015 case NM_ROUND_W_D:
20016 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20017 break;
20018 case NM_MOV_S:
20019 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20020 break;
20021 case NM_MOV_D:
20022 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20023 break;
20024 case NM_ABS_S:
20025 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20026 break;
20027 case NM_ABS_D:
20028 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20029 break;
20030 case NM_NEG_S:
20031 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20032 break;
20033 case NM_NEG_D:
20034 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20035 break;
20036 case NM_CVT_D_S:
20037 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20038 break;
20039 case NM_CVT_D_W:
20040 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20041 break;
20042 case NM_CVT_D_L:
20043 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20044 break;
20045 case NM_CVT_S_D:
20046 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20047 break;
20048 case NM_CVT_S_W:
20049 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20050 break;
20051 case NM_CVT_S_L:
20052 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20053 break;
20054 default:
20055 generate_exception_end(ctx, EXCP_RI);
20056 break;
20058 break;
20060 break;
20062 break;
20063 case NM_POOL32F_5:
20064 switch (extract32(ctx->opcode, 3, 3)) {
20065 case NM_CMP_CONDN_S:
20066 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20067 break;
20068 case NM_CMP_CONDN_D:
20069 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20070 break;
20071 default:
20072 generate_exception_end(ctx, EXCP_RI);
20073 break;
20075 break;
20076 default:
20077 generate_exception_end(ctx, EXCP_RI);
20078 break;
20082 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20083 int rd, int rs, int rt)
20085 int ret = rd;
20086 TCGv t0 = tcg_temp_new();
20087 TCGv v1_t = tcg_temp_new();
20088 TCGv v2_t = tcg_temp_new();
20090 gen_load_gpr(v1_t, rs);
20091 gen_load_gpr(v2_t, rt);
20093 switch (opc) {
20094 case NM_CMP_EQ_PH:
20095 check_dsp(ctx);
20096 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20097 break;
20098 case NM_CMP_LT_PH:
20099 check_dsp(ctx);
20100 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20101 break;
20102 case NM_CMP_LE_PH:
20103 check_dsp(ctx);
20104 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20105 break;
20106 case NM_CMPU_EQ_QB:
20107 check_dsp(ctx);
20108 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20109 break;
20110 case NM_CMPU_LT_QB:
20111 check_dsp(ctx);
20112 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20113 break;
20114 case NM_CMPU_LE_QB:
20115 check_dsp(ctx);
20116 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20117 break;
20118 case NM_CMPGU_EQ_QB:
20119 check_dsp(ctx);
20120 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20121 gen_store_gpr(v1_t, ret);
20122 break;
20123 case NM_CMPGU_LT_QB:
20124 check_dsp(ctx);
20125 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20126 gen_store_gpr(v1_t, ret);
20127 break;
20128 case NM_CMPGU_LE_QB:
20129 check_dsp(ctx);
20130 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20131 gen_store_gpr(v1_t, ret);
20132 break;
20133 case NM_CMPGDU_EQ_QB:
20134 check_dsp_r2(ctx);
20135 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20136 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20137 gen_store_gpr(v1_t, ret);
20138 break;
20139 case NM_CMPGDU_LT_QB:
20140 check_dsp_r2(ctx);
20141 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20142 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20143 gen_store_gpr(v1_t, ret);
20144 break;
20145 case NM_CMPGDU_LE_QB:
20146 check_dsp_r2(ctx);
20147 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20148 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20149 gen_store_gpr(v1_t, ret);
20150 break;
20151 case NM_PACKRL_PH:
20152 check_dsp(ctx);
20153 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20154 gen_store_gpr(v1_t, ret);
20155 break;
20156 case NM_PICK_QB:
20157 check_dsp(ctx);
20158 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20159 gen_store_gpr(v1_t, ret);
20160 break;
20161 case NM_PICK_PH:
20162 check_dsp(ctx);
20163 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20164 gen_store_gpr(v1_t, ret);
20165 break;
20166 case NM_ADDQ_S_W:
20167 check_dsp(ctx);
20168 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20169 gen_store_gpr(v1_t, ret);
20170 break;
20171 case NM_SUBQ_S_W:
20172 check_dsp(ctx);
20173 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20174 gen_store_gpr(v1_t, ret);
20175 break;
20176 case NM_ADDSC:
20177 check_dsp(ctx);
20178 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20179 gen_store_gpr(v1_t, ret);
20180 break;
20181 case NM_ADDWC:
20182 check_dsp(ctx);
20183 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20184 gen_store_gpr(v1_t, ret);
20185 break;
20186 case NM_ADDQ_S_PH:
20187 check_dsp(ctx);
20188 switch (extract32(ctx->opcode, 10, 1)) {
20189 case 0:
20190 /* ADDQ_PH */
20191 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20192 gen_store_gpr(v1_t, ret);
20193 break;
20194 case 1:
20195 /* ADDQ_S_PH */
20196 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20197 gen_store_gpr(v1_t, ret);
20198 break;
20200 break;
20201 case NM_ADDQH_R_PH:
20202 check_dsp_r2(ctx);
20203 switch (extract32(ctx->opcode, 10, 1)) {
20204 case 0:
20205 /* ADDQH_PH */
20206 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20207 gen_store_gpr(v1_t, ret);
20208 break;
20209 case 1:
20210 /* ADDQH_R_PH */
20211 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20212 gen_store_gpr(v1_t, ret);
20213 break;
20215 break;
20216 case NM_ADDQH_R_W:
20217 check_dsp_r2(ctx);
20218 switch (extract32(ctx->opcode, 10, 1)) {
20219 case 0:
20220 /* ADDQH_W */
20221 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20222 gen_store_gpr(v1_t, ret);
20223 break;
20224 case 1:
20225 /* ADDQH_R_W */
20226 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20227 gen_store_gpr(v1_t, ret);
20228 break;
20230 break;
20231 case NM_ADDU_S_QB:
20232 check_dsp(ctx);
20233 switch (extract32(ctx->opcode, 10, 1)) {
20234 case 0:
20235 /* ADDU_QB */
20236 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20237 gen_store_gpr(v1_t, ret);
20238 break;
20239 case 1:
20240 /* ADDU_S_QB */
20241 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20242 gen_store_gpr(v1_t, ret);
20243 break;
20245 break;
20246 case NM_ADDU_S_PH:
20247 check_dsp_r2(ctx);
20248 switch (extract32(ctx->opcode, 10, 1)) {
20249 case 0:
20250 /* ADDU_PH */
20251 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20252 gen_store_gpr(v1_t, ret);
20253 break;
20254 case 1:
20255 /* ADDU_S_PH */
20256 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20257 gen_store_gpr(v1_t, ret);
20258 break;
20260 break;
20261 case NM_ADDUH_R_QB:
20262 check_dsp_r2(ctx);
20263 switch (extract32(ctx->opcode, 10, 1)) {
20264 case 0:
20265 /* ADDUH_QB */
20266 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20267 gen_store_gpr(v1_t, ret);
20268 break;
20269 case 1:
20270 /* ADDUH_R_QB */
20271 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20272 gen_store_gpr(v1_t, ret);
20273 break;
20275 break;
20276 case NM_SHRAV_R_PH:
20277 check_dsp(ctx);
20278 switch (extract32(ctx->opcode, 10, 1)) {
20279 case 0:
20280 /* SHRAV_PH */
20281 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20282 gen_store_gpr(v1_t, ret);
20283 break;
20284 case 1:
20285 /* SHRAV_R_PH */
20286 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20287 gen_store_gpr(v1_t, ret);
20288 break;
20290 break;
20291 case NM_SHRAV_R_QB:
20292 check_dsp_r2(ctx);
20293 switch (extract32(ctx->opcode, 10, 1)) {
20294 case 0:
20295 /* SHRAV_QB */
20296 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20297 gen_store_gpr(v1_t, ret);
20298 break;
20299 case 1:
20300 /* SHRAV_R_QB */
20301 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20302 gen_store_gpr(v1_t, ret);
20303 break;
20305 break;
20306 case NM_SUBQ_S_PH:
20307 check_dsp(ctx);
20308 switch (extract32(ctx->opcode, 10, 1)) {
20309 case 0:
20310 /* SUBQ_PH */
20311 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20312 gen_store_gpr(v1_t, ret);
20313 break;
20314 case 1:
20315 /* SUBQ_S_PH */
20316 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20317 gen_store_gpr(v1_t, ret);
20318 break;
20320 break;
20321 case NM_SUBQH_R_PH:
20322 check_dsp_r2(ctx);
20323 switch (extract32(ctx->opcode, 10, 1)) {
20324 case 0:
20325 /* SUBQH_PH */
20326 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20327 gen_store_gpr(v1_t, ret);
20328 break;
20329 case 1:
20330 /* SUBQH_R_PH */
20331 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20332 gen_store_gpr(v1_t, ret);
20333 break;
20335 break;
20336 case NM_SUBQH_R_W:
20337 check_dsp_r2(ctx);
20338 switch (extract32(ctx->opcode, 10, 1)) {
20339 case 0:
20340 /* SUBQH_W */
20341 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20342 gen_store_gpr(v1_t, ret);
20343 break;
20344 case 1:
20345 /* SUBQH_R_W */
20346 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20347 gen_store_gpr(v1_t, ret);
20348 break;
20350 break;
20351 case NM_SUBU_S_QB:
20352 check_dsp(ctx);
20353 switch (extract32(ctx->opcode, 10, 1)) {
20354 case 0:
20355 /* SUBU_QB */
20356 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20357 gen_store_gpr(v1_t, ret);
20358 break;
20359 case 1:
20360 /* SUBU_S_QB */
20361 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20362 gen_store_gpr(v1_t, ret);
20363 break;
20365 break;
20366 case NM_SUBU_S_PH:
20367 check_dsp_r2(ctx);
20368 switch (extract32(ctx->opcode, 10, 1)) {
20369 case 0:
20370 /* SUBU_PH */
20371 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20372 gen_store_gpr(v1_t, ret);
20373 break;
20374 case 1:
20375 /* SUBU_S_PH */
20376 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20377 gen_store_gpr(v1_t, ret);
20378 break;
20380 break;
20381 case NM_SUBUH_R_QB:
20382 check_dsp_r2(ctx);
20383 switch (extract32(ctx->opcode, 10, 1)) {
20384 case 0:
20385 /* SUBUH_QB */
20386 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20387 gen_store_gpr(v1_t, ret);
20388 break;
20389 case 1:
20390 /* SUBUH_R_QB */
20391 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20392 gen_store_gpr(v1_t, ret);
20393 break;
20395 break;
20396 case NM_SHLLV_S_PH:
20397 check_dsp(ctx);
20398 switch (extract32(ctx->opcode, 10, 1)) {
20399 case 0:
20400 /* SHLLV_PH */
20401 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20402 gen_store_gpr(v1_t, ret);
20403 break;
20404 case 1:
20405 /* SHLLV_S_PH */
20406 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20407 gen_store_gpr(v1_t, ret);
20408 break;
20410 break;
20411 case NM_PRECR_SRA_R_PH_W:
20412 check_dsp_r2(ctx);
20413 switch (extract32(ctx->opcode, 10, 1)) {
20414 case 0:
20415 /* PRECR_SRA_PH_W */
20417 TCGv_i32 sa_t = tcg_const_i32(rd);
20418 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20419 cpu_gpr[rt]);
20420 gen_store_gpr(v1_t, rt);
20421 tcg_temp_free_i32(sa_t);
20423 break;
20424 case 1:
20425 /* PRECR_SRA_R_PH_W */
20427 TCGv_i32 sa_t = tcg_const_i32(rd);
20428 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20429 cpu_gpr[rt]);
20430 gen_store_gpr(v1_t, rt);
20431 tcg_temp_free_i32(sa_t);
20433 break;
20435 break;
20436 case NM_MULEU_S_PH_QBL:
20437 check_dsp(ctx);
20438 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20439 gen_store_gpr(v1_t, ret);
20440 break;
20441 case NM_MULEU_S_PH_QBR:
20442 check_dsp(ctx);
20443 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20444 gen_store_gpr(v1_t, ret);
20445 break;
20446 case NM_MULQ_RS_PH:
20447 check_dsp(ctx);
20448 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20449 gen_store_gpr(v1_t, ret);
20450 break;
20451 case NM_MULQ_S_PH:
20452 check_dsp_r2(ctx);
20453 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20454 gen_store_gpr(v1_t, ret);
20455 break;
20456 case NM_MULQ_RS_W:
20457 check_dsp_r2(ctx);
20458 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20459 gen_store_gpr(v1_t, ret);
20460 break;
20461 case NM_MULQ_S_W:
20462 check_dsp_r2(ctx);
20463 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20464 gen_store_gpr(v1_t, ret);
20465 break;
20466 case NM_APPEND:
20467 check_dsp_r2(ctx);
20468 gen_load_gpr(t0, rs);
20469 if (rd != 0) {
20470 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20472 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20473 break;
20474 case NM_MODSUB:
20475 check_dsp(ctx);
20476 gen_helper_modsub(v1_t, v1_t, v2_t);
20477 gen_store_gpr(v1_t, ret);
20478 break;
20479 case NM_SHRAV_R_W:
20480 check_dsp(ctx);
20481 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20482 gen_store_gpr(v1_t, ret);
20483 break;
20484 case NM_SHRLV_PH:
20485 check_dsp_r2(ctx);
20486 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20487 gen_store_gpr(v1_t, ret);
20488 break;
20489 case NM_SHRLV_QB:
20490 check_dsp(ctx);
20491 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20492 gen_store_gpr(v1_t, ret);
20493 break;
20494 case NM_SHLLV_QB:
20495 check_dsp(ctx);
20496 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20497 gen_store_gpr(v1_t, ret);
20498 break;
20499 case NM_SHLLV_S_W:
20500 check_dsp(ctx);
20501 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20502 gen_store_gpr(v1_t, ret);
20503 break;
20504 case NM_SHILO:
20505 check_dsp(ctx);
20507 TCGv tv0 = tcg_temp_new();
20508 TCGv tv1 = tcg_temp_new();
20509 int16_t imm = extract32(ctx->opcode, 16, 7);
20511 tcg_gen_movi_tl(tv0, rd >> 3);
20512 tcg_gen_movi_tl(tv1, imm);
20513 gen_helper_shilo(tv0, tv1, cpu_env);
20515 break;
20516 case NM_MULEQ_S_W_PHL:
20517 check_dsp(ctx);
20518 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20519 gen_store_gpr(v1_t, ret);
20520 break;
20521 case NM_MULEQ_S_W_PHR:
20522 check_dsp(ctx);
20523 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20524 gen_store_gpr(v1_t, ret);
20525 break;
20526 case NM_MUL_S_PH:
20527 check_dsp_r2(ctx);
20528 switch (extract32(ctx->opcode, 10, 1)) {
20529 case 0:
20530 /* MUL_PH */
20531 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20532 gen_store_gpr(v1_t, ret);
20533 break;
20534 case 1:
20535 /* MUL_S_PH */
20536 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20537 gen_store_gpr(v1_t, ret);
20538 break;
20540 break;
20541 case NM_PRECR_QB_PH:
20542 check_dsp_r2(ctx);
20543 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20544 gen_store_gpr(v1_t, ret);
20545 break;
20546 case NM_PRECRQ_QB_PH:
20547 check_dsp(ctx);
20548 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20549 gen_store_gpr(v1_t, ret);
20550 break;
20551 case NM_PRECRQ_PH_W:
20552 check_dsp(ctx);
20553 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20554 gen_store_gpr(v1_t, ret);
20555 break;
20556 case NM_PRECRQ_RS_PH_W:
20557 check_dsp(ctx);
20558 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20559 gen_store_gpr(v1_t, ret);
20560 break;
20561 case NM_PRECRQU_S_QB_PH:
20562 check_dsp(ctx);
20563 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20564 gen_store_gpr(v1_t, ret);
20565 break;
20566 case NM_SHRA_R_W:
20567 check_dsp(ctx);
20568 tcg_gen_movi_tl(t0, rd);
20569 gen_helper_shra_r_w(v1_t, t0, v1_t);
20570 gen_store_gpr(v1_t, rt);
20571 break;
20572 case NM_SHRA_R_PH:
20573 check_dsp(ctx);
20574 tcg_gen_movi_tl(t0, rd >> 1);
20575 switch (extract32(ctx->opcode, 10, 1)) {
20576 case 0:
20577 /* SHRA_PH */
20578 gen_helper_shra_ph(v1_t, t0, v1_t);
20579 gen_store_gpr(v1_t, rt);
20580 break;
20581 case 1:
20582 /* SHRA_R_PH */
20583 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20584 gen_store_gpr(v1_t, rt);
20585 break;
20587 break;
20588 case NM_SHLL_S_PH:
20589 check_dsp(ctx);
20590 tcg_gen_movi_tl(t0, rd >> 1);
20591 switch (extract32(ctx->opcode, 10, 2)) {
20592 case 0:
20593 /* SHLL_PH */
20594 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20595 gen_store_gpr(v1_t, rt);
20596 break;
20597 case 2:
20598 /* SHLL_S_PH */
20599 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20600 gen_store_gpr(v1_t, rt);
20601 break;
20602 default:
20603 generate_exception_end(ctx, EXCP_RI);
20604 break;
20606 break;
20607 case NM_SHLL_S_W:
20608 check_dsp(ctx);
20609 tcg_gen_movi_tl(t0, rd);
20610 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20611 gen_store_gpr(v1_t, rt);
20612 break;
20613 case NM_REPL_PH:
20614 check_dsp(ctx);
20616 int16_t imm;
20617 imm = sextract32(ctx->opcode, 11, 11);
20618 imm = (int16_t)(imm << 6) >> 6;
20619 if (rt != 0) {
20620 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20623 break;
20624 default:
20625 generate_exception_end(ctx, EXCP_RI);
20626 break;
20630 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20632 uint16_t insn;
20633 uint32_t op;
20634 int rt, rs, rd;
20635 int offset;
20636 int imm;
20638 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20639 ctx->opcode = (ctx->opcode << 16) | insn;
20641 rt = extract32(ctx->opcode, 21, 5);
20642 rs = extract32(ctx->opcode, 16, 5);
20643 rd = extract32(ctx->opcode, 11, 5);
20645 op = extract32(ctx->opcode, 26, 6);
20646 switch (op) {
20647 case NM_P_ADDIU:
20648 if (rt == 0) {
20649 /* P.RI */
20650 switch (extract32(ctx->opcode, 19, 2)) {
20651 case NM_SIGRIE:
20652 default:
20653 generate_exception_end(ctx, EXCP_RI);
20654 break;
20655 case NM_P_SYSCALL:
20656 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20657 generate_exception_end(ctx, EXCP_SYSCALL);
20658 } else {
20659 generate_exception_end(ctx, EXCP_RI);
20661 break;
20662 case NM_BREAK:
20663 generate_exception_end(ctx, EXCP_BREAK);
20664 break;
20665 case NM_SDBBP:
20666 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20667 gen_helper_do_semihosting(cpu_env);
20668 } else {
20669 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20670 generate_exception_end(ctx, EXCP_RI);
20671 } else {
20672 generate_exception_end(ctx, EXCP_DBp);
20675 break;
20677 } else {
20678 /* NM_ADDIU */
20679 imm = extract32(ctx->opcode, 0, 16);
20680 if (rs != 0) {
20681 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20682 } else {
20683 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20685 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20687 break;
20688 case NM_ADDIUPC:
20689 if (rt != 0) {
20690 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20691 extract32(ctx->opcode, 1, 20) << 1;
20692 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20693 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20695 break;
20696 case NM_POOL32A:
20697 switch (ctx->opcode & 0x07) {
20698 case NM_POOL32A0:
20699 gen_pool32a0_nanomips_insn(env, ctx);
20700 break;
20701 case NM_POOL32A5:
20703 int32_t op1 = extract32(ctx->opcode, 3, 7);
20704 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20706 break;
20707 case NM_POOL32A7:
20708 switch (extract32(ctx->opcode, 3, 3)) {
20709 case NM_P_LSX:
20710 gen_p_lsx(ctx, rd, rs, rt);
20711 break;
20712 case NM_LSA:
20713 /* In nanoMIPS, the shift field directly encodes the shift
20714 * amount, meaning that the supported shift values are in
20715 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20716 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20717 extract32(ctx->opcode, 9, 2) - 1);
20718 break;
20719 case NM_EXTW:
20720 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20721 break;
20722 case NM_POOL32AXF:
20723 gen_pool32axf_nanomips_insn(env, ctx);
20724 break;
20725 default:
20726 generate_exception_end(ctx, EXCP_RI);
20727 break;
20729 break;
20730 default:
20731 generate_exception_end(ctx, EXCP_RI);
20732 break;
20734 break;
20735 case NM_P_GP_W:
20736 switch (ctx->opcode & 0x03) {
20737 case NM_ADDIUGP_W:
20738 if (rt != 0) {
20739 offset = extract32(ctx->opcode, 0, 21);
20740 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20742 break;
20743 case NM_LWGP:
20744 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20745 break;
20746 case NM_SWGP:
20747 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20748 break;
20749 default:
20750 generate_exception_end(ctx, EXCP_RI);
20751 break;
20753 break;
20754 case NM_P48I:
20756 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20757 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20758 switch (extract32(ctx->opcode, 16, 5)) {
20759 case NM_LI48:
20760 check_nms(ctx);
20761 if (rt != 0) {
20762 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20764 break;
20765 case NM_ADDIU48:
20766 check_nms(ctx);
20767 if (rt != 0) {
20768 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20769 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20771 break;
20772 case NM_ADDIUGP48:
20773 check_nms(ctx);
20774 if (rt != 0) {
20775 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20777 break;
20778 case NM_ADDIUPC48:
20779 check_nms(ctx);
20780 if (rt != 0) {
20781 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20782 addr_off);
20784 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20786 break;
20787 case NM_LWPC48:
20788 check_nms(ctx);
20789 if (rt != 0) {
20790 TCGv t0;
20791 t0 = tcg_temp_new();
20793 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20794 addr_off);
20796 tcg_gen_movi_tl(t0, addr);
20797 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20798 tcg_temp_free(t0);
20800 break;
20801 case NM_SWPC48:
20802 check_nms(ctx);
20804 TCGv t0, t1;
20805 t0 = tcg_temp_new();
20806 t1 = tcg_temp_new();
20808 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20809 addr_off);
20811 tcg_gen_movi_tl(t0, addr);
20812 gen_load_gpr(t1, rt);
20814 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20816 tcg_temp_free(t0);
20817 tcg_temp_free(t1);
20819 break;
20820 default:
20821 generate_exception_end(ctx, EXCP_RI);
20822 break;
20824 return 6;
20826 case NM_P_U12:
20827 switch (extract32(ctx->opcode, 12, 4)) {
20828 case NM_ORI:
20829 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20830 break;
20831 case NM_XORI:
20832 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20833 break;
20834 case NM_ANDI:
20835 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20836 break;
20837 case NM_P_SR:
20838 switch (extract32(ctx->opcode, 20, 1)) {
20839 case NM_PP_SR:
20840 switch (ctx->opcode & 3) {
20841 case NM_SAVE:
20842 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20843 extract32(ctx->opcode, 2, 1),
20844 extract32(ctx->opcode, 3, 9) << 3);
20845 break;
20846 case NM_RESTORE:
20847 case NM_RESTORE_JRC:
20848 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20849 extract32(ctx->opcode, 2, 1),
20850 extract32(ctx->opcode, 3, 9) << 3);
20851 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20852 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20854 break;
20855 default:
20856 generate_exception_end(ctx, EXCP_RI);
20857 break;
20859 break;
20860 case NM_P_SR_F:
20861 generate_exception_end(ctx, EXCP_RI);
20862 break;
20864 break;
20865 case NM_SLTI:
20866 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20867 break;
20868 case NM_SLTIU:
20869 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20870 break;
20871 case NM_SEQI:
20873 TCGv t0 = tcg_temp_new();
20875 imm = extract32(ctx->opcode, 0, 12);
20876 gen_load_gpr(t0, rs);
20877 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20878 gen_store_gpr(t0, rt);
20880 tcg_temp_free(t0);
20882 break;
20883 case NM_ADDIUNEG:
20884 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20885 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20886 break;
20887 case NM_P_SHIFT:
20889 int shift = extract32(ctx->opcode, 0, 5);
20890 switch (extract32(ctx->opcode, 5, 4)) {
20891 case NM_P_SLL:
20892 if (rt == 0 && shift == 0) {
20893 /* NOP */
20894 } else if (rt == 0 && shift == 3) {
20895 /* EHB - treat as NOP */
20896 } else if (rt == 0 && shift == 5) {
20897 /* PAUSE - treat as NOP */
20898 } else if (rt == 0 && shift == 6) {
20899 /* SYNC */
20900 gen_sync(extract32(ctx->opcode, 16, 5));
20901 } else {
20902 /* SLL */
20903 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20904 extract32(ctx->opcode, 0, 5));
20906 break;
20907 case NM_SRL:
20908 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20909 extract32(ctx->opcode, 0, 5));
20910 break;
20911 case NM_SRA:
20912 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20913 extract32(ctx->opcode, 0, 5));
20914 break;
20915 case NM_ROTR:
20916 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20917 extract32(ctx->opcode, 0, 5));
20918 break;
20921 break;
20922 case NM_P_ROTX:
20923 check_nms(ctx);
20924 if (rt != 0) {
20925 TCGv t0 = tcg_temp_new();
20926 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20927 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20928 << 1);
20929 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20931 gen_load_gpr(t0, rs);
20932 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20933 tcg_temp_free(t0);
20935 tcg_temp_free_i32(shift);
20936 tcg_temp_free_i32(shiftx);
20937 tcg_temp_free_i32(stripe);
20939 break;
20940 case NM_P_INS:
20941 switch (((ctx->opcode >> 10) & 2) |
20942 (extract32(ctx->opcode, 5, 1))) {
20943 case NM_INS:
20944 check_nms(ctx);
20945 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20946 extract32(ctx->opcode, 6, 5));
20947 break;
20948 default:
20949 generate_exception_end(ctx, EXCP_RI);
20950 break;
20952 break;
20953 case NM_P_EXT:
20954 switch (((ctx->opcode >> 10) & 2) |
20955 (extract32(ctx->opcode, 5, 1))) {
20956 case NM_EXT:
20957 check_nms(ctx);
20958 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20959 extract32(ctx->opcode, 6, 5));
20960 break;
20961 default:
20962 generate_exception_end(ctx, EXCP_RI);
20963 break;
20965 break;
20966 default:
20967 generate_exception_end(ctx, EXCP_RI);
20968 break;
20970 break;
20971 case NM_POOL32F:
20972 gen_pool32f_nanomips_insn(ctx);
20973 break;
20974 case NM_POOL32S:
20975 break;
20976 case NM_P_LUI:
20977 switch (extract32(ctx->opcode, 1, 1)) {
20978 case NM_LUI:
20979 if (rt != 0) {
20980 tcg_gen_movi_tl(cpu_gpr[rt],
20981 sextract32(ctx->opcode, 0, 1) << 31 |
20982 extract32(ctx->opcode, 2, 10) << 21 |
20983 extract32(ctx->opcode, 12, 9) << 12);
20985 break;
20986 case NM_ALUIPC:
20987 if (rt != 0) {
20988 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20989 extract32(ctx->opcode, 2, 10) << 21 |
20990 extract32(ctx->opcode, 12, 9) << 12;
20991 target_long addr;
20992 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20993 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20995 break;
20997 break;
20998 case NM_P_GP_BH:
21000 uint32_t u = extract32(ctx->opcode, 0, 18);
21002 switch (extract32(ctx->opcode, 18, 3)) {
21003 case NM_LBGP:
21004 gen_ld(ctx, OPC_LB, rt, 28, u);
21005 break;
21006 case NM_SBGP:
21007 gen_st(ctx, OPC_SB, rt, 28, u);
21008 break;
21009 case NM_LBUGP:
21010 gen_ld(ctx, OPC_LBU, rt, 28, u);
21011 break;
21012 case NM_ADDIUGP_B:
21013 if (rt != 0) {
21014 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21016 break;
21017 case NM_P_GP_LH:
21018 u &= ~1;
21019 switch (ctx->opcode & 1) {
21020 case NM_LHGP:
21021 gen_ld(ctx, OPC_LH, rt, 28, u);
21022 break;
21023 case NM_LHUGP:
21024 gen_ld(ctx, OPC_LHU, rt, 28, u);
21025 break;
21027 break;
21028 case NM_P_GP_SH:
21029 u &= ~1;
21030 switch (ctx->opcode & 1) {
21031 case NM_SHGP:
21032 gen_st(ctx, OPC_SH, rt, 28, u);
21033 break;
21034 default:
21035 generate_exception_end(ctx, EXCP_RI);
21036 break;
21038 break;
21039 case NM_P_GP_CP1:
21040 u &= ~0x3;
21041 switch (ctx->opcode & 0x3) {
21042 case NM_LWC1GP:
21043 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21044 break;
21045 case NM_LDC1GP:
21046 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21047 break;
21048 case NM_SWC1GP:
21049 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21050 break;
21051 case NM_SDC1GP:
21052 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21053 break;
21055 break;
21056 default:
21057 generate_exception_end(ctx, EXCP_RI);
21058 break;
21061 break;
21062 case NM_P_LS_U12:
21064 uint32_t u = extract32(ctx->opcode, 0, 12);
21066 switch (extract32(ctx->opcode, 12, 4)) {
21067 case NM_P_PREFU12:
21068 if (rt == 31) {
21069 /* SYNCI */
21070 /* Break the TB to be able to sync copied instructions
21071 immediately */
21072 ctx->base.is_jmp = DISAS_STOP;
21073 } else {
21074 /* PREF */
21075 /* Treat as NOP. */
21077 break;
21078 case NM_LB:
21079 gen_ld(ctx, OPC_LB, rt, rs, u);
21080 break;
21081 case NM_LH:
21082 gen_ld(ctx, OPC_LH, rt, rs, u);
21083 break;
21084 case NM_LW:
21085 gen_ld(ctx, OPC_LW, rt, rs, u);
21086 break;
21087 case NM_LBU:
21088 gen_ld(ctx, OPC_LBU, rt, rs, u);
21089 break;
21090 case NM_LHU:
21091 gen_ld(ctx, OPC_LHU, rt, rs, u);
21092 break;
21093 case NM_SB:
21094 gen_st(ctx, OPC_SB, rt, rs, u);
21095 break;
21096 case NM_SH:
21097 gen_st(ctx, OPC_SH, rt, rs, u);
21098 break;
21099 case NM_SW:
21100 gen_st(ctx, OPC_SW, rt, rs, u);
21101 break;
21102 case NM_LWC1:
21103 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21104 break;
21105 case NM_LDC1:
21106 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21107 break;
21108 case NM_SWC1:
21109 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21110 break;
21111 case NM_SDC1:
21112 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21113 break;
21114 default:
21115 generate_exception_end(ctx, EXCP_RI);
21116 break;
21119 break;
21120 case NM_P_LS_S9:
21122 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21123 extract32(ctx->opcode, 0, 8);
21125 switch (extract32(ctx->opcode, 8, 3)) {
21126 case NM_P_LS_S0:
21127 switch (extract32(ctx->opcode, 11, 4)) {
21128 case NM_LBS9:
21129 gen_ld(ctx, OPC_LB, rt, rs, s);
21130 break;
21131 case NM_LHS9:
21132 gen_ld(ctx, OPC_LH, rt, rs, s);
21133 break;
21134 case NM_LWS9:
21135 gen_ld(ctx, OPC_LW, rt, rs, s);
21136 break;
21137 case NM_LBUS9:
21138 gen_ld(ctx, OPC_LBU, rt, rs, s);
21139 break;
21140 case NM_LHUS9:
21141 gen_ld(ctx, OPC_LHU, rt, rs, s);
21142 break;
21143 case NM_SBS9:
21144 gen_st(ctx, OPC_SB, rt, rs, s);
21145 break;
21146 case NM_SHS9:
21147 gen_st(ctx, OPC_SH, rt, rs, s);
21148 break;
21149 case NM_SWS9:
21150 gen_st(ctx, OPC_SW, rt, rs, s);
21151 break;
21152 case NM_LWC1S9:
21153 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21154 break;
21155 case NM_LDC1S9:
21156 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21157 break;
21158 case NM_SWC1S9:
21159 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21160 break;
21161 case NM_SDC1S9:
21162 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21163 break;
21164 case NM_P_PREFS9:
21165 if (rt == 31) {
21166 /* SYNCI */
21167 /* Break the TB to be able to sync copied instructions
21168 immediately */
21169 ctx->base.is_jmp = DISAS_STOP;
21170 } else {
21171 /* PREF */
21172 /* Treat as NOP. */
21174 break;
21175 default:
21176 generate_exception_end(ctx, EXCP_RI);
21177 break;
21179 break;
21180 case NM_P_LS_S1:
21181 switch (extract32(ctx->opcode, 11, 4)) {
21182 case NM_UALH:
21183 case NM_UASH:
21184 check_nms(ctx);
21186 TCGv t0 = tcg_temp_new();
21187 TCGv t1 = tcg_temp_new();
21189 gen_base_offset_addr(ctx, t0, rs, s);
21191 switch (extract32(ctx->opcode, 11, 4)) {
21192 case NM_UALH:
21193 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21194 MO_UNALN);
21195 gen_store_gpr(t0, rt);
21196 break;
21197 case NM_UASH:
21198 gen_load_gpr(t1, rt);
21199 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21200 MO_UNALN);
21201 break;
21203 tcg_temp_free(t0);
21204 tcg_temp_free(t1);
21206 break;
21207 case NM_P_LL:
21208 switch (ctx->opcode & 0x03) {
21209 case NM_LL:
21210 gen_ld(ctx, OPC_LL, rt, rs, s);
21211 break;
21212 case NM_LLWP:
21213 check_xnp(ctx);
21214 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21215 break;
21217 break;
21218 case NM_P_SC:
21219 switch (ctx->opcode & 0x03) {
21220 case NM_SC:
21221 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21222 break;
21223 case NM_SCWP:
21224 check_xnp(ctx);
21225 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21226 break;
21228 break;
21229 case NM_CACHE:
21230 check_cp0_enabled(ctx);
21231 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21232 gen_cache_operation(ctx, rt, rs, s);
21234 break;
21236 break;
21237 case NM_P_LS_E0:
21238 switch (extract32(ctx->opcode, 11, 4)) {
21239 case NM_LBE:
21240 check_eva(ctx);
21241 check_cp0_enabled(ctx);
21242 gen_ld(ctx, OPC_LBE, rt, rs, s);
21243 break;
21244 case NM_SBE:
21245 check_eva(ctx);
21246 check_cp0_enabled(ctx);
21247 gen_st(ctx, OPC_SBE, rt, rs, s);
21248 break;
21249 case NM_LBUE:
21250 check_eva(ctx);
21251 check_cp0_enabled(ctx);
21252 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21253 break;
21254 case NM_P_PREFE:
21255 if (rt == 31) {
21256 /* case NM_SYNCIE */
21257 check_eva(ctx);
21258 check_cp0_enabled(ctx);
21259 /* Break the TB to be able to sync copied instructions
21260 immediately */
21261 ctx->base.is_jmp = DISAS_STOP;
21262 } else {
21263 /* case NM_PREFE */
21264 check_eva(ctx);
21265 check_cp0_enabled(ctx);
21266 /* Treat as NOP. */
21268 break;
21269 case NM_LHE:
21270 check_eva(ctx);
21271 check_cp0_enabled(ctx);
21272 gen_ld(ctx, OPC_LHE, rt, rs, s);
21273 break;
21274 case NM_SHE:
21275 check_eva(ctx);
21276 check_cp0_enabled(ctx);
21277 gen_st(ctx, OPC_SHE, rt, rs, s);
21278 break;
21279 case NM_LHUE:
21280 check_eva(ctx);
21281 check_cp0_enabled(ctx);
21282 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21283 break;
21284 case NM_CACHEE:
21285 check_nms_dl_il_sl_tl_l2c(ctx);
21286 gen_cache_operation(ctx, rt, rs, s);
21287 break;
21288 case NM_LWE:
21289 check_eva(ctx);
21290 check_cp0_enabled(ctx);
21291 gen_ld(ctx, OPC_LWE, rt, rs, s);
21292 break;
21293 case NM_SWE:
21294 check_eva(ctx);
21295 check_cp0_enabled(ctx);
21296 gen_st(ctx, OPC_SWE, rt, rs, s);
21297 break;
21298 case NM_P_LLE:
21299 switch (extract32(ctx->opcode, 2, 2)) {
21300 case NM_LLE:
21301 check_xnp(ctx);
21302 check_eva(ctx);
21303 check_cp0_enabled(ctx);
21304 gen_ld(ctx, OPC_LLE, rt, rs, s);
21305 break;
21306 case NM_LLWPE:
21307 check_xnp(ctx);
21308 check_eva(ctx);
21309 check_cp0_enabled(ctx);
21310 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21311 break;
21312 default:
21313 generate_exception_end(ctx, EXCP_RI);
21314 break;
21316 break;
21317 case NM_P_SCE:
21318 switch (extract32(ctx->opcode, 2, 2)) {
21319 case NM_SCE:
21320 check_xnp(ctx);
21321 check_eva(ctx);
21322 check_cp0_enabled(ctx);
21323 gen_st_cond(ctx, OPC_SCE, rt, rs, s);
21324 break;
21325 case NM_SCWPE:
21326 check_xnp(ctx);
21327 check_eva(ctx);
21328 check_cp0_enabled(ctx);
21329 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21330 break;
21331 default:
21332 generate_exception_end(ctx, EXCP_RI);
21333 break;
21335 break;
21337 break;
21338 case NM_P_LS_WM:
21339 case NM_P_LS_UAWM:
21340 check_nms(ctx);
21342 int count = extract32(ctx->opcode, 12, 3);
21343 int counter = 0;
21345 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21346 extract32(ctx->opcode, 0, 8);
21347 TCGv va = tcg_temp_new();
21348 TCGv t1 = tcg_temp_new();
21349 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21350 NM_P_LS_UAWM ? MO_UNALN : 0;
21352 count = (count == 0) ? 8 : count;
21353 while (counter != count) {
21354 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21355 int this_offset = offset + (counter << 2);
21357 gen_base_offset_addr(ctx, va, rs, this_offset);
21359 switch (extract32(ctx->opcode, 11, 1)) {
21360 case NM_LWM:
21361 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21362 memop | MO_TESL);
21363 gen_store_gpr(t1, this_rt);
21364 if ((this_rt == rs) &&
21365 (counter != (count - 1))) {
21366 /* UNPREDICTABLE */
21368 break;
21369 case NM_SWM:
21370 this_rt = (rt == 0) ? 0 : this_rt;
21371 gen_load_gpr(t1, this_rt);
21372 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21373 memop | MO_TEUL);
21374 break;
21376 counter++;
21378 tcg_temp_free(va);
21379 tcg_temp_free(t1);
21381 break;
21382 default:
21383 generate_exception_end(ctx, EXCP_RI);
21384 break;
21387 break;
21388 case NM_MOVE_BALC:
21389 check_nms(ctx);
21391 TCGv t0 = tcg_temp_new();
21392 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21393 extract32(ctx->opcode, 1, 20) << 1;
21394 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21395 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21396 extract32(ctx->opcode, 21, 3));
21397 gen_load_gpr(t0, rt);
21398 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21399 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21400 tcg_temp_free(t0);
21402 break;
21403 case NM_P_BAL:
21405 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21406 extract32(ctx->opcode, 1, 24) << 1;
21408 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21409 /* BC */
21410 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21411 } else {
21412 /* BALC */
21413 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21416 break;
21417 case NM_P_J:
21418 switch (extract32(ctx->opcode, 12, 4)) {
21419 case NM_JALRC:
21420 case NM_JALRC_HB:
21421 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21422 break;
21423 case NM_P_BALRSC:
21424 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21425 break;
21426 default:
21427 generate_exception_end(ctx, EXCP_RI);
21428 break;
21430 break;
21431 case NM_P_BR1:
21433 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21434 extract32(ctx->opcode, 1, 13) << 1;
21435 switch (extract32(ctx->opcode, 14, 2)) {
21436 case NM_BEQC:
21437 check_nms(ctx);
21438 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21439 break;
21440 case NM_P_BR3A:
21441 s = sextract32(ctx->opcode, 0, 1) << 14 |
21442 extract32(ctx->opcode, 1, 13) << 1;
21443 check_cp1_enabled(ctx);
21444 switch (extract32(ctx->opcode, 16, 5)) {
21445 case NM_BC1EQZC:
21446 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21447 break;
21448 case NM_BC1NEZC:
21449 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21450 break;
21451 case NM_BPOSGE32C:
21452 check_dsp_r3(ctx);
21454 int32_t imm = extract32(ctx->opcode, 1, 13) |
21455 extract32(ctx->opcode, 0, 1) << 13;
21457 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21458 imm);
21460 break;
21461 default:
21462 generate_exception_end(ctx, EXCP_RI);
21463 break;
21465 break;
21466 case NM_BGEC:
21467 if (rs == rt) {
21468 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21469 } else {
21470 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21472 break;
21473 case NM_BGEUC:
21474 if (rs == rt || rt == 0) {
21475 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21476 } else if (rs == 0) {
21477 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21478 } else {
21479 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21481 break;
21484 break;
21485 case NM_P_BR2:
21487 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21488 extract32(ctx->opcode, 1, 13) << 1;
21489 switch (extract32(ctx->opcode, 14, 2)) {
21490 case NM_BNEC:
21491 check_nms(ctx);
21492 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21493 break;
21494 case NM_BLTC:
21495 if (rs != 0 && rt != 0 && rs == rt) {
21496 /* NOP */
21497 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21498 } else {
21499 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21501 break;
21502 case NM_BLTUC:
21503 if (rs == 0 || rs == rt) {
21504 /* NOP */
21505 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21506 } else {
21507 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21509 break;
21510 default:
21511 generate_exception_end(ctx, EXCP_RI);
21512 break;
21515 break;
21516 case NM_P_BRI:
21518 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21519 extract32(ctx->opcode, 1, 10) << 1;
21520 uint32_t u = extract32(ctx->opcode, 11, 7);
21522 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21523 rt, u, s);
21525 break;
21526 default:
21527 generate_exception_end(ctx, EXCP_RI);
21528 break;
21530 return 4;
21533 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21535 uint32_t op;
21536 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21537 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21538 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21539 int offset;
21540 int imm;
21542 /* make sure instructions are on a halfword boundary */
21543 if (ctx->base.pc_next & 0x1) {
21544 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21545 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21546 tcg_temp_free(tmp);
21547 generate_exception_end(ctx, EXCP_AdEL);
21548 return 2;
21551 op = extract32(ctx->opcode, 10, 6);
21552 switch (op) {
21553 case NM_P16_MV:
21554 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21555 if (rt != 0) {
21556 /* MOVE */
21557 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21558 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21559 } else {
21560 /* P16.RI */
21561 switch (extract32(ctx->opcode, 3, 2)) {
21562 case NM_P16_SYSCALL:
21563 if (extract32(ctx->opcode, 2, 1) == 0) {
21564 generate_exception_end(ctx, EXCP_SYSCALL);
21565 } else {
21566 generate_exception_end(ctx, EXCP_RI);
21568 break;
21569 case NM_BREAK16:
21570 generate_exception_end(ctx, EXCP_BREAK);
21571 break;
21572 case NM_SDBBP16:
21573 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21574 gen_helper_do_semihosting(cpu_env);
21575 } else {
21576 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21577 generate_exception_end(ctx, EXCP_RI);
21578 } else {
21579 generate_exception_end(ctx, EXCP_DBp);
21582 break;
21583 default:
21584 generate_exception_end(ctx, EXCP_RI);
21585 break;
21588 break;
21589 case NM_P16_SHIFT:
21591 int shift = extract32(ctx->opcode, 0, 3);
21592 uint32_t opc = 0;
21593 shift = (shift == 0) ? 8 : shift;
21595 switch (extract32(ctx->opcode, 3, 1)) {
21596 case NM_SLL16:
21597 opc = OPC_SLL;
21598 break;
21599 case NM_SRL16:
21600 opc = OPC_SRL;
21601 break;
21603 gen_shift_imm(ctx, opc, rt, rs, shift);
21605 break;
21606 case NM_P16C:
21607 switch (ctx->opcode & 1) {
21608 case NM_POOL16C_0:
21609 gen_pool16c_nanomips_insn(ctx);
21610 break;
21611 case NM_LWXS16:
21612 gen_ldxs(ctx, rt, rs, rd);
21613 break;
21615 break;
21616 case NM_P16_A1:
21617 switch (extract32(ctx->opcode, 6, 1)) {
21618 case NM_ADDIUR1SP:
21619 imm = extract32(ctx->opcode, 0, 6) << 2;
21620 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21621 break;
21622 default:
21623 generate_exception_end(ctx, EXCP_RI);
21624 break;
21626 break;
21627 case NM_P16_A2:
21628 switch (extract32(ctx->opcode, 3, 1)) {
21629 case NM_ADDIUR2:
21630 imm = extract32(ctx->opcode, 0, 3) << 2;
21631 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21632 break;
21633 case NM_P_ADDIURS5:
21634 rt = extract32(ctx->opcode, 5, 5);
21635 if (rt != 0) {
21636 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21637 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21638 (extract32(ctx->opcode, 0, 3));
21639 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21641 break;
21643 break;
21644 case NM_P16_ADDU:
21645 switch (ctx->opcode & 0x1) {
21646 case NM_ADDU16:
21647 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21648 break;
21649 case NM_SUBU16:
21650 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21651 break;
21653 break;
21654 case NM_P16_4X4:
21655 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21656 extract32(ctx->opcode, 5, 3);
21657 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21658 extract32(ctx->opcode, 0, 3);
21659 rt = decode_gpr_gpr4(rt);
21660 rs = decode_gpr_gpr4(rs);
21661 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21662 (extract32(ctx->opcode, 3, 1))) {
21663 case NM_ADDU4X4:
21664 check_nms(ctx);
21665 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21666 break;
21667 case NM_MUL4X4:
21668 check_nms(ctx);
21669 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21670 break;
21671 default:
21672 generate_exception_end(ctx, EXCP_RI);
21673 break;
21675 break;
21676 case NM_LI16:
21678 int imm = extract32(ctx->opcode, 0, 7);
21679 imm = (imm == 0x7f ? -1 : imm);
21680 if (rt != 0) {
21681 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21684 break;
21685 case NM_ANDI16:
21687 uint32_t u = extract32(ctx->opcode, 0, 4);
21688 u = (u == 12) ? 0xff :
21689 (u == 13) ? 0xffff : u;
21690 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21692 break;
21693 case NM_P16_LB:
21694 offset = extract32(ctx->opcode, 0, 2);
21695 switch (extract32(ctx->opcode, 2, 2)) {
21696 case NM_LB16:
21697 gen_ld(ctx, OPC_LB, rt, rs, offset);
21698 break;
21699 case NM_SB16:
21700 rt = decode_gpr_gpr3_src_store(
21701 NANOMIPS_EXTRACT_RD(ctx->opcode));
21702 gen_st(ctx, OPC_SB, rt, rs, offset);
21703 break;
21704 case NM_LBU16:
21705 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21706 break;
21707 default:
21708 generate_exception_end(ctx, EXCP_RI);
21709 break;
21711 break;
21712 case NM_P16_LH:
21713 offset = extract32(ctx->opcode, 1, 2) << 1;
21714 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21715 case NM_LH16:
21716 gen_ld(ctx, OPC_LH, rt, rs, offset);
21717 break;
21718 case NM_SH16:
21719 rt = decode_gpr_gpr3_src_store(
21720 NANOMIPS_EXTRACT_RD(ctx->opcode));
21721 gen_st(ctx, OPC_SH, rt, rs, offset);
21722 break;
21723 case NM_LHU16:
21724 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21725 break;
21726 default:
21727 generate_exception_end(ctx, EXCP_RI);
21728 break;
21730 break;
21731 case NM_LW16:
21732 offset = extract32(ctx->opcode, 0, 4) << 2;
21733 gen_ld(ctx, OPC_LW, rt, rs, offset);
21734 break;
21735 case NM_LWSP16:
21736 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21737 offset = extract32(ctx->opcode, 0, 5) << 2;
21738 gen_ld(ctx, OPC_LW, rt, 29, offset);
21739 break;
21740 case NM_LW4X4:
21741 check_nms(ctx);
21742 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21743 extract32(ctx->opcode, 5, 3);
21744 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21745 extract32(ctx->opcode, 0, 3);
21746 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21747 (extract32(ctx->opcode, 8, 1) << 2);
21748 rt = decode_gpr_gpr4(rt);
21749 rs = decode_gpr_gpr4(rs);
21750 gen_ld(ctx, OPC_LW, rt, rs, offset);
21751 break;
21752 case NM_SW4X4:
21753 check_nms(ctx);
21754 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21755 extract32(ctx->opcode, 5, 3);
21756 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21757 extract32(ctx->opcode, 0, 3);
21758 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21759 (extract32(ctx->opcode, 8, 1) << 2);
21760 rt = decode_gpr_gpr4_zero(rt);
21761 rs = decode_gpr_gpr4(rs);
21762 gen_st(ctx, OPC_SW, rt, rs, offset);
21763 break;
21764 case NM_LWGP16:
21765 offset = extract32(ctx->opcode, 0, 7) << 2;
21766 gen_ld(ctx, OPC_LW, rt, 28, offset);
21767 break;
21768 case NM_SWSP16:
21769 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21770 offset = extract32(ctx->opcode, 0, 5) << 2;
21771 gen_st(ctx, OPC_SW, rt, 29, offset);
21772 break;
21773 case NM_SW16:
21774 rt = decode_gpr_gpr3_src_store(
21775 NANOMIPS_EXTRACT_RD(ctx->opcode));
21776 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21777 offset = extract32(ctx->opcode, 0, 4) << 2;
21778 gen_st(ctx, OPC_SW, rt, rs, offset);
21779 break;
21780 case NM_SWGP16:
21781 rt = decode_gpr_gpr3_src_store(
21782 NANOMIPS_EXTRACT_RD(ctx->opcode));
21783 offset = extract32(ctx->opcode, 0, 7) << 2;
21784 gen_st(ctx, OPC_SW, rt, 28, offset);
21785 break;
21786 case NM_BC16:
21787 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21788 (sextract32(ctx->opcode, 0, 1) << 10) |
21789 (extract32(ctx->opcode, 1, 9) << 1));
21790 break;
21791 case NM_BALC16:
21792 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21793 (sextract32(ctx->opcode, 0, 1) << 10) |
21794 (extract32(ctx->opcode, 1, 9) << 1));
21795 break;
21796 case NM_BEQZC16:
21797 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21798 (sextract32(ctx->opcode, 0, 1) << 7) |
21799 (extract32(ctx->opcode, 1, 6) << 1));
21800 break;
21801 case NM_BNEZC16:
21802 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21803 (sextract32(ctx->opcode, 0, 1) << 7) |
21804 (extract32(ctx->opcode, 1, 6) << 1));
21805 break;
21806 case NM_P16_BR:
21807 switch (ctx->opcode & 0xf) {
21808 case 0:
21809 /* P16.JRC */
21810 switch (extract32(ctx->opcode, 4, 1)) {
21811 case NM_JRC:
21812 gen_compute_branch_nm(ctx, OPC_JR, 2,
21813 extract32(ctx->opcode, 5, 5), 0, 0);
21814 break;
21815 case NM_JALRC16:
21816 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21817 extract32(ctx->opcode, 5, 5), 31, 0);
21818 break;
21820 break;
21821 default:
21823 /* P16.BRI */
21824 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21825 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21826 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21827 extract32(ctx->opcode, 0, 4) << 1);
21829 break;
21831 break;
21832 case NM_P16_SR:
21834 int count = extract32(ctx->opcode, 0, 4);
21835 int u = extract32(ctx->opcode, 4, 4) << 4;
21837 rt = 30 + extract32(ctx->opcode, 9, 1);
21838 switch (extract32(ctx->opcode, 8, 1)) {
21839 case NM_SAVE16:
21840 gen_save(ctx, rt, count, 0, u);
21841 break;
21842 case NM_RESTORE_JRC16:
21843 gen_restore(ctx, rt, count, 0, u);
21844 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21845 break;
21848 break;
21849 case NM_MOVEP:
21850 case NM_MOVEPREV:
21851 check_nms(ctx);
21853 static const int gpr2reg1[] = {4, 5, 6, 7};
21854 static const int gpr2reg2[] = {5, 6, 7, 8};
21855 int re;
21856 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21857 extract32(ctx->opcode, 8, 1);
21858 int r1 = gpr2reg1[rd2];
21859 int r2 = gpr2reg2[rd2];
21860 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21861 extract32(ctx->opcode, 0, 3);
21862 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21863 extract32(ctx->opcode, 5, 3);
21864 TCGv t0 = tcg_temp_new();
21865 TCGv t1 = tcg_temp_new();
21866 if (op == NM_MOVEP) {
21867 rd = r1;
21868 re = r2;
21869 rs = decode_gpr_gpr4_zero(r3);
21870 rt = decode_gpr_gpr4_zero(r4);
21871 } else {
21872 rd = decode_gpr_gpr4(r3);
21873 re = decode_gpr_gpr4(r4);
21874 rs = r1;
21875 rt = r2;
21877 gen_load_gpr(t0, rs);
21878 gen_load_gpr(t1, rt);
21879 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21880 tcg_gen_mov_tl(cpu_gpr[re], t1);
21881 tcg_temp_free(t0);
21882 tcg_temp_free(t1);
21884 break;
21885 default:
21886 return decode_nanomips_32_48_opc(env, ctx);
21889 return 2;
21893 /* SmartMIPS extension to MIPS32 */
21895 #if defined(TARGET_MIPS64)
21897 /* MDMX extension to MIPS64 */
21899 #endif
21901 /* MIPSDSP functions. */
21902 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21903 int rd, int base, int offset)
21905 TCGv t0;
21907 check_dsp(ctx);
21908 t0 = tcg_temp_new();
21910 if (base == 0) {
21911 gen_load_gpr(t0, offset);
21912 } else if (offset == 0) {
21913 gen_load_gpr(t0, base);
21914 } else {
21915 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21918 switch (opc) {
21919 case OPC_LBUX:
21920 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21921 gen_store_gpr(t0, rd);
21922 break;
21923 case OPC_LHX:
21924 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21925 gen_store_gpr(t0, rd);
21926 break;
21927 case OPC_LWX:
21928 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21929 gen_store_gpr(t0, rd);
21930 break;
21931 #if defined(TARGET_MIPS64)
21932 case OPC_LDX:
21933 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21934 gen_store_gpr(t0, rd);
21935 break;
21936 #endif
21938 tcg_temp_free(t0);
21941 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21942 int ret, int v1, int v2)
21944 TCGv v1_t;
21945 TCGv v2_t;
21947 if (ret == 0) {
21948 /* Treat as NOP. */
21949 return;
21952 v1_t = tcg_temp_new();
21953 v2_t = tcg_temp_new();
21955 gen_load_gpr(v1_t, v1);
21956 gen_load_gpr(v2_t, v2);
21958 switch (op1) {
21959 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21960 case OPC_MULT_G_2E:
21961 check_dsp_r2(ctx);
21962 switch (op2) {
21963 case OPC_ADDUH_QB:
21964 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21965 break;
21966 case OPC_ADDUH_R_QB:
21967 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21968 break;
21969 case OPC_ADDQH_PH:
21970 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21971 break;
21972 case OPC_ADDQH_R_PH:
21973 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21974 break;
21975 case OPC_ADDQH_W:
21976 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21977 break;
21978 case OPC_ADDQH_R_W:
21979 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21980 break;
21981 case OPC_SUBUH_QB:
21982 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21983 break;
21984 case OPC_SUBUH_R_QB:
21985 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21986 break;
21987 case OPC_SUBQH_PH:
21988 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21989 break;
21990 case OPC_SUBQH_R_PH:
21991 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21992 break;
21993 case OPC_SUBQH_W:
21994 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21995 break;
21996 case OPC_SUBQH_R_W:
21997 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21998 break;
22000 break;
22001 case OPC_ABSQ_S_PH_DSP:
22002 switch (op2) {
22003 case OPC_ABSQ_S_QB:
22004 check_dsp_r2(ctx);
22005 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22006 break;
22007 case OPC_ABSQ_S_PH:
22008 check_dsp(ctx);
22009 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22010 break;
22011 case OPC_ABSQ_S_W:
22012 check_dsp(ctx);
22013 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22014 break;
22015 case OPC_PRECEQ_W_PHL:
22016 check_dsp(ctx);
22017 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22018 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22019 break;
22020 case OPC_PRECEQ_W_PHR:
22021 check_dsp(ctx);
22022 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22023 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22024 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22025 break;
22026 case OPC_PRECEQU_PH_QBL:
22027 check_dsp(ctx);
22028 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22029 break;
22030 case OPC_PRECEQU_PH_QBR:
22031 check_dsp(ctx);
22032 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22033 break;
22034 case OPC_PRECEQU_PH_QBLA:
22035 check_dsp(ctx);
22036 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22037 break;
22038 case OPC_PRECEQU_PH_QBRA:
22039 check_dsp(ctx);
22040 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22041 break;
22042 case OPC_PRECEU_PH_QBL:
22043 check_dsp(ctx);
22044 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22045 break;
22046 case OPC_PRECEU_PH_QBR:
22047 check_dsp(ctx);
22048 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22049 break;
22050 case OPC_PRECEU_PH_QBLA:
22051 check_dsp(ctx);
22052 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22053 break;
22054 case OPC_PRECEU_PH_QBRA:
22055 check_dsp(ctx);
22056 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22057 break;
22059 break;
22060 case OPC_ADDU_QB_DSP:
22061 switch (op2) {
22062 case OPC_ADDQ_PH:
22063 check_dsp(ctx);
22064 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22065 break;
22066 case OPC_ADDQ_S_PH:
22067 check_dsp(ctx);
22068 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22069 break;
22070 case OPC_ADDQ_S_W:
22071 check_dsp(ctx);
22072 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22073 break;
22074 case OPC_ADDU_QB:
22075 check_dsp(ctx);
22076 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22077 break;
22078 case OPC_ADDU_S_QB:
22079 check_dsp(ctx);
22080 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22081 break;
22082 case OPC_ADDU_PH:
22083 check_dsp_r2(ctx);
22084 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22085 break;
22086 case OPC_ADDU_S_PH:
22087 check_dsp_r2(ctx);
22088 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22089 break;
22090 case OPC_SUBQ_PH:
22091 check_dsp(ctx);
22092 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22093 break;
22094 case OPC_SUBQ_S_PH:
22095 check_dsp(ctx);
22096 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22097 break;
22098 case OPC_SUBQ_S_W:
22099 check_dsp(ctx);
22100 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22101 break;
22102 case OPC_SUBU_QB:
22103 check_dsp(ctx);
22104 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22105 break;
22106 case OPC_SUBU_S_QB:
22107 check_dsp(ctx);
22108 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22109 break;
22110 case OPC_SUBU_PH:
22111 check_dsp_r2(ctx);
22112 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22113 break;
22114 case OPC_SUBU_S_PH:
22115 check_dsp_r2(ctx);
22116 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22117 break;
22118 case OPC_ADDSC:
22119 check_dsp(ctx);
22120 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22121 break;
22122 case OPC_ADDWC:
22123 check_dsp(ctx);
22124 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22125 break;
22126 case OPC_MODSUB:
22127 check_dsp(ctx);
22128 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22129 break;
22130 case OPC_RADDU_W_QB:
22131 check_dsp(ctx);
22132 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22133 break;
22135 break;
22136 case OPC_CMPU_EQ_QB_DSP:
22137 switch (op2) {
22138 case OPC_PRECR_QB_PH:
22139 check_dsp_r2(ctx);
22140 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22141 break;
22142 case OPC_PRECRQ_QB_PH:
22143 check_dsp(ctx);
22144 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22145 break;
22146 case OPC_PRECR_SRA_PH_W:
22147 check_dsp_r2(ctx);
22149 TCGv_i32 sa_t = tcg_const_i32(v2);
22150 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22151 cpu_gpr[ret]);
22152 tcg_temp_free_i32(sa_t);
22153 break;
22155 case OPC_PRECR_SRA_R_PH_W:
22156 check_dsp_r2(ctx);
22158 TCGv_i32 sa_t = tcg_const_i32(v2);
22159 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22160 cpu_gpr[ret]);
22161 tcg_temp_free_i32(sa_t);
22162 break;
22164 case OPC_PRECRQ_PH_W:
22165 check_dsp(ctx);
22166 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22167 break;
22168 case OPC_PRECRQ_RS_PH_W:
22169 check_dsp(ctx);
22170 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22171 break;
22172 case OPC_PRECRQU_S_QB_PH:
22173 check_dsp(ctx);
22174 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22175 break;
22177 break;
22178 #ifdef TARGET_MIPS64
22179 case OPC_ABSQ_S_QH_DSP:
22180 switch (op2) {
22181 case OPC_PRECEQ_L_PWL:
22182 check_dsp(ctx);
22183 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22184 break;
22185 case OPC_PRECEQ_L_PWR:
22186 check_dsp(ctx);
22187 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22188 break;
22189 case OPC_PRECEQ_PW_QHL:
22190 check_dsp(ctx);
22191 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22192 break;
22193 case OPC_PRECEQ_PW_QHR:
22194 check_dsp(ctx);
22195 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22196 break;
22197 case OPC_PRECEQ_PW_QHLA:
22198 check_dsp(ctx);
22199 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22200 break;
22201 case OPC_PRECEQ_PW_QHRA:
22202 check_dsp(ctx);
22203 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22204 break;
22205 case OPC_PRECEQU_QH_OBL:
22206 check_dsp(ctx);
22207 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22208 break;
22209 case OPC_PRECEQU_QH_OBR:
22210 check_dsp(ctx);
22211 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22212 break;
22213 case OPC_PRECEQU_QH_OBLA:
22214 check_dsp(ctx);
22215 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22216 break;
22217 case OPC_PRECEQU_QH_OBRA:
22218 check_dsp(ctx);
22219 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22220 break;
22221 case OPC_PRECEU_QH_OBL:
22222 check_dsp(ctx);
22223 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22224 break;
22225 case OPC_PRECEU_QH_OBR:
22226 check_dsp(ctx);
22227 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22228 break;
22229 case OPC_PRECEU_QH_OBLA:
22230 check_dsp(ctx);
22231 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22232 break;
22233 case OPC_PRECEU_QH_OBRA:
22234 check_dsp(ctx);
22235 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22236 break;
22237 case OPC_ABSQ_S_OB:
22238 check_dsp_r2(ctx);
22239 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22240 break;
22241 case OPC_ABSQ_S_PW:
22242 check_dsp(ctx);
22243 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22244 break;
22245 case OPC_ABSQ_S_QH:
22246 check_dsp(ctx);
22247 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22248 break;
22250 break;
22251 case OPC_ADDU_OB_DSP:
22252 switch (op2) {
22253 case OPC_RADDU_L_OB:
22254 check_dsp(ctx);
22255 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22256 break;
22257 case OPC_SUBQ_PW:
22258 check_dsp(ctx);
22259 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22260 break;
22261 case OPC_SUBQ_S_PW:
22262 check_dsp(ctx);
22263 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22264 break;
22265 case OPC_SUBQ_QH:
22266 check_dsp(ctx);
22267 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22268 break;
22269 case OPC_SUBQ_S_QH:
22270 check_dsp(ctx);
22271 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22272 break;
22273 case OPC_SUBU_OB:
22274 check_dsp(ctx);
22275 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22276 break;
22277 case OPC_SUBU_S_OB:
22278 check_dsp(ctx);
22279 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22280 break;
22281 case OPC_SUBU_QH:
22282 check_dsp_r2(ctx);
22283 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22284 break;
22285 case OPC_SUBU_S_QH:
22286 check_dsp_r2(ctx);
22287 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22288 break;
22289 case OPC_SUBUH_OB:
22290 check_dsp_r2(ctx);
22291 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22292 break;
22293 case OPC_SUBUH_R_OB:
22294 check_dsp_r2(ctx);
22295 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22296 break;
22297 case OPC_ADDQ_PW:
22298 check_dsp(ctx);
22299 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22300 break;
22301 case OPC_ADDQ_S_PW:
22302 check_dsp(ctx);
22303 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22304 break;
22305 case OPC_ADDQ_QH:
22306 check_dsp(ctx);
22307 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22308 break;
22309 case OPC_ADDQ_S_QH:
22310 check_dsp(ctx);
22311 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22312 break;
22313 case OPC_ADDU_OB:
22314 check_dsp(ctx);
22315 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22316 break;
22317 case OPC_ADDU_S_OB:
22318 check_dsp(ctx);
22319 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22320 break;
22321 case OPC_ADDU_QH:
22322 check_dsp_r2(ctx);
22323 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22324 break;
22325 case OPC_ADDU_S_QH:
22326 check_dsp_r2(ctx);
22327 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22328 break;
22329 case OPC_ADDUH_OB:
22330 check_dsp_r2(ctx);
22331 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22332 break;
22333 case OPC_ADDUH_R_OB:
22334 check_dsp_r2(ctx);
22335 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22336 break;
22338 break;
22339 case OPC_CMPU_EQ_OB_DSP:
22340 switch (op2) {
22341 case OPC_PRECR_OB_QH:
22342 check_dsp_r2(ctx);
22343 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22344 break;
22345 case OPC_PRECR_SRA_QH_PW:
22346 check_dsp_r2(ctx);
22348 TCGv_i32 ret_t = tcg_const_i32(ret);
22349 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22350 tcg_temp_free_i32(ret_t);
22351 break;
22353 case OPC_PRECR_SRA_R_QH_PW:
22354 check_dsp_r2(ctx);
22356 TCGv_i32 sa_v = tcg_const_i32(ret);
22357 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22358 tcg_temp_free_i32(sa_v);
22359 break;
22361 case OPC_PRECRQ_OB_QH:
22362 check_dsp(ctx);
22363 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22364 break;
22365 case OPC_PRECRQ_PW_L:
22366 check_dsp(ctx);
22367 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22368 break;
22369 case OPC_PRECRQ_QH_PW:
22370 check_dsp(ctx);
22371 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22372 break;
22373 case OPC_PRECRQ_RS_QH_PW:
22374 check_dsp(ctx);
22375 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22376 break;
22377 case OPC_PRECRQU_S_OB_QH:
22378 check_dsp(ctx);
22379 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22380 break;
22382 break;
22383 #endif
22386 tcg_temp_free(v1_t);
22387 tcg_temp_free(v2_t);
22390 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22391 int ret, int v1, int v2)
22393 uint32_t op2;
22394 TCGv t0;
22395 TCGv v1_t;
22396 TCGv v2_t;
22398 if (ret == 0) {
22399 /* Treat as NOP. */
22400 return;
22403 t0 = tcg_temp_new();
22404 v1_t = tcg_temp_new();
22405 v2_t = tcg_temp_new();
22407 tcg_gen_movi_tl(t0, v1);
22408 gen_load_gpr(v1_t, v1);
22409 gen_load_gpr(v2_t, v2);
22411 switch (opc) {
22412 case OPC_SHLL_QB_DSP:
22414 op2 = MASK_SHLL_QB(ctx->opcode);
22415 switch (op2) {
22416 case OPC_SHLL_QB:
22417 check_dsp(ctx);
22418 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22419 break;
22420 case OPC_SHLLV_QB:
22421 check_dsp(ctx);
22422 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22423 break;
22424 case OPC_SHLL_PH:
22425 check_dsp(ctx);
22426 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22427 break;
22428 case OPC_SHLLV_PH:
22429 check_dsp(ctx);
22430 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22431 break;
22432 case OPC_SHLL_S_PH:
22433 check_dsp(ctx);
22434 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22435 break;
22436 case OPC_SHLLV_S_PH:
22437 check_dsp(ctx);
22438 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22439 break;
22440 case OPC_SHLL_S_W:
22441 check_dsp(ctx);
22442 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22443 break;
22444 case OPC_SHLLV_S_W:
22445 check_dsp(ctx);
22446 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22447 break;
22448 case OPC_SHRL_QB:
22449 check_dsp(ctx);
22450 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22451 break;
22452 case OPC_SHRLV_QB:
22453 check_dsp(ctx);
22454 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22455 break;
22456 case OPC_SHRL_PH:
22457 check_dsp_r2(ctx);
22458 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22459 break;
22460 case OPC_SHRLV_PH:
22461 check_dsp_r2(ctx);
22462 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22463 break;
22464 case OPC_SHRA_QB:
22465 check_dsp_r2(ctx);
22466 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22467 break;
22468 case OPC_SHRA_R_QB:
22469 check_dsp_r2(ctx);
22470 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22471 break;
22472 case OPC_SHRAV_QB:
22473 check_dsp_r2(ctx);
22474 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22475 break;
22476 case OPC_SHRAV_R_QB:
22477 check_dsp_r2(ctx);
22478 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22479 break;
22480 case OPC_SHRA_PH:
22481 check_dsp(ctx);
22482 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22483 break;
22484 case OPC_SHRA_R_PH:
22485 check_dsp(ctx);
22486 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22487 break;
22488 case OPC_SHRAV_PH:
22489 check_dsp(ctx);
22490 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22491 break;
22492 case OPC_SHRAV_R_PH:
22493 check_dsp(ctx);
22494 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22495 break;
22496 case OPC_SHRA_R_W:
22497 check_dsp(ctx);
22498 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22499 break;
22500 case OPC_SHRAV_R_W:
22501 check_dsp(ctx);
22502 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22503 break;
22504 default: /* Invalid */
22505 MIPS_INVAL("MASK SHLL.QB");
22506 generate_exception_end(ctx, EXCP_RI);
22507 break;
22509 break;
22511 #ifdef TARGET_MIPS64
22512 case OPC_SHLL_OB_DSP:
22513 op2 = MASK_SHLL_OB(ctx->opcode);
22514 switch (op2) {
22515 case OPC_SHLL_PW:
22516 check_dsp(ctx);
22517 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22518 break;
22519 case OPC_SHLLV_PW:
22520 check_dsp(ctx);
22521 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22522 break;
22523 case OPC_SHLL_S_PW:
22524 check_dsp(ctx);
22525 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22526 break;
22527 case OPC_SHLLV_S_PW:
22528 check_dsp(ctx);
22529 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22530 break;
22531 case OPC_SHLL_OB:
22532 check_dsp(ctx);
22533 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22534 break;
22535 case OPC_SHLLV_OB:
22536 check_dsp(ctx);
22537 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22538 break;
22539 case OPC_SHLL_QH:
22540 check_dsp(ctx);
22541 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22542 break;
22543 case OPC_SHLLV_QH:
22544 check_dsp(ctx);
22545 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22546 break;
22547 case OPC_SHLL_S_QH:
22548 check_dsp(ctx);
22549 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22550 break;
22551 case OPC_SHLLV_S_QH:
22552 check_dsp(ctx);
22553 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22554 break;
22555 case OPC_SHRA_OB:
22556 check_dsp_r2(ctx);
22557 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22558 break;
22559 case OPC_SHRAV_OB:
22560 check_dsp_r2(ctx);
22561 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22562 break;
22563 case OPC_SHRA_R_OB:
22564 check_dsp_r2(ctx);
22565 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22566 break;
22567 case OPC_SHRAV_R_OB:
22568 check_dsp_r2(ctx);
22569 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22570 break;
22571 case OPC_SHRA_PW:
22572 check_dsp(ctx);
22573 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22574 break;
22575 case OPC_SHRAV_PW:
22576 check_dsp(ctx);
22577 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22578 break;
22579 case OPC_SHRA_R_PW:
22580 check_dsp(ctx);
22581 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22582 break;
22583 case OPC_SHRAV_R_PW:
22584 check_dsp(ctx);
22585 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22586 break;
22587 case OPC_SHRA_QH:
22588 check_dsp(ctx);
22589 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22590 break;
22591 case OPC_SHRAV_QH:
22592 check_dsp(ctx);
22593 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22594 break;
22595 case OPC_SHRA_R_QH:
22596 check_dsp(ctx);
22597 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22598 break;
22599 case OPC_SHRAV_R_QH:
22600 check_dsp(ctx);
22601 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22602 break;
22603 case OPC_SHRL_OB:
22604 check_dsp(ctx);
22605 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22606 break;
22607 case OPC_SHRLV_OB:
22608 check_dsp(ctx);
22609 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22610 break;
22611 case OPC_SHRL_QH:
22612 check_dsp_r2(ctx);
22613 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22614 break;
22615 case OPC_SHRLV_QH:
22616 check_dsp_r2(ctx);
22617 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22618 break;
22619 default: /* Invalid */
22620 MIPS_INVAL("MASK SHLL.OB");
22621 generate_exception_end(ctx, EXCP_RI);
22622 break;
22624 break;
22625 #endif
22628 tcg_temp_free(t0);
22629 tcg_temp_free(v1_t);
22630 tcg_temp_free(v2_t);
22633 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22634 int ret, int v1, int v2, int check_ret)
22636 TCGv_i32 t0;
22637 TCGv v1_t;
22638 TCGv v2_t;
22640 if ((ret == 0) && (check_ret == 1)) {
22641 /* Treat as NOP. */
22642 return;
22645 t0 = tcg_temp_new_i32();
22646 v1_t = tcg_temp_new();
22647 v2_t = tcg_temp_new();
22649 tcg_gen_movi_i32(t0, ret);
22650 gen_load_gpr(v1_t, v1);
22651 gen_load_gpr(v2_t, v2);
22653 switch (op1) {
22654 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22655 * the same mask and op1. */
22656 case OPC_MULT_G_2E:
22657 check_dsp_r2(ctx);
22658 switch (op2) {
22659 case OPC_MUL_PH:
22660 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22661 break;
22662 case OPC_MUL_S_PH:
22663 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22664 break;
22665 case OPC_MULQ_S_W:
22666 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22667 break;
22668 case OPC_MULQ_RS_W:
22669 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22670 break;
22672 break;
22673 case OPC_DPA_W_PH_DSP:
22674 switch (op2) {
22675 case OPC_DPAU_H_QBL:
22676 check_dsp(ctx);
22677 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22678 break;
22679 case OPC_DPAU_H_QBR:
22680 check_dsp(ctx);
22681 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22682 break;
22683 case OPC_DPSU_H_QBL:
22684 check_dsp(ctx);
22685 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22686 break;
22687 case OPC_DPSU_H_QBR:
22688 check_dsp(ctx);
22689 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22690 break;
22691 case OPC_DPA_W_PH:
22692 check_dsp_r2(ctx);
22693 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22694 break;
22695 case OPC_DPAX_W_PH:
22696 check_dsp_r2(ctx);
22697 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22698 break;
22699 case OPC_DPAQ_S_W_PH:
22700 check_dsp(ctx);
22701 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22702 break;
22703 case OPC_DPAQX_S_W_PH:
22704 check_dsp_r2(ctx);
22705 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22706 break;
22707 case OPC_DPAQX_SA_W_PH:
22708 check_dsp_r2(ctx);
22709 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22710 break;
22711 case OPC_DPS_W_PH:
22712 check_dsp_r2(ctx);
22713 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22714 break;
22715 case OPC_DPSX_W_PH:
22716 check_dsp_r2(ctx);
22717 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22718 break;
22719 case OPC_DPSQ_S_W_PH:
22720 check_dsp(ctx);
22721 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22722 break;
22723 case OPC_DPSQX_S_W_PH:
22724 check_dsp_r2(ctx);
22725 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22726 break;
22727 case OPC_DPSQX_SA_W_PH:
22728 check_dsp_r2(ctx);
22729 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22730 break;
22731 case OPC_MULSAQ_S_W_PH:
22732 check_dsp(ctx);
22733 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22734 break;
22735 case OPC_DPAQ_SA_L_W:
22736 check_dsp(ctx);
22737 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22738 break;
22739 case OPC_DPSQ_SA_L_W:
22740 check_dsp(ctx);
22741 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22742 break;
22743 case OPC_MAQ_S_W_PHL:
22744 check_dsp(ctx);
22745 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22746 break;
22747 case OPC_MAQ_S_W_PHR:
22748 check_dsp(ctx);
22749 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22750 break;
22751 case OPC_MAQ_SA_W_PHL:
22752 check_dsp(ctx);
22753 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22754 break;
22755 case OPC_MAQ_SA_W_PHR:
22756 check_dsp(ctx);
22757 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22758 break;
22759 case OPC_MULSA_W_PH:
22760 check_dsp_r2(ctx);
22761 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22762 break;
22764 break;
22765 #ifdef TARGET_MIPS64
22766 case OPC_DPAQ_W_QH_DSP:
22768 int ac = ret & 0x03;
22769 tcg_gen_movi_i32(t0, ac);
22771 switch (op2) {
22772 case OPC_DMADD:
22773 check_dsp(ctx);
22774 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22775 break;
22776 case OPC_DMADDU:
22777 check_dsp(ctx);
22778 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22779 break;
22780 case OPC_DMSUB:
22781 check_dsp(ctx);
22782 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22783 break;
22784 case OPC_DMSUBU:
22785 check_dsp(ctx);
22786 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22787 break;
22788 case OPC_DPA_W_QH:
22789 check_dsp_r2(ctx);
22790 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22791 break;
22792 case OPC_DPAQ_S_W_QH:
22793 check_dsp(ctx);
22794 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22795 break;
22796 case OPC_DPAQ_SA_L_PW:
22797 check_dsp(ctx);
22798 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22799 break;
22800 case OPC_DPAU_H_OBL:
22801 check_dsp(ctx);
22802 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22803 break;
22804 case OPC_DPAU_H_OBR:
22805 check_dsp(ctx);
22806 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22807 break;
22808 case OPC_DPS_W_QH:
22809 check_dsp_r2(ctx);
22810 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22811 break;
22812 case OPC_DPSQ_S_W_QH:
22813 check_dsp(ctx);
22814 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22815 break;
22816 case OPC_DPSQ_SA_L_PW:
22817 check_dsp(ctx);
22818 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22819 break;
22820 case OPC_DPSU_H_OBL:
22821 check_dsp(ctx);
22822 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22823 break;
22824 case OPC_DPSU_H_OBR:
22825 check_dsp(ctx);
22826 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22827 break;
22828 case OPC_MAQ_S_L_PWL:
22829 check_dsp(ctx);
22830 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22831 break;
22832 case OPC_MAQ_S_L_PWR:
22833 check_dsp(ctx);
22834 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22835 break;
22836 case OPC_MAQ_S_W_QHLL:
22837 check_dsp(ctx);
22838 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22839 break;
22840 case OPC_MAQ_SA_W_QHLL:
22841 check_dsp(ctx);
22842 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22843 break;
22844 case OPC_MAQ_S_W_QHLR:
22845 check_dsp(ctx);
22846 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22847 break;
22848 case OPC_MAQ_SA_W_QHLR:
22849 check_dsp(ctx);
22850 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22851 break;
22852 case OPC_MAQ_S_W_QHRL:
22853 check_dsp(ctx);
22854 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22855 break;
22856 case OPC_MAQ_SA_W_QHRL:
22857 check_dsp(ctx);
22858 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22859 break;
22860 case OPC_MAQ_S_W_QHRR:
22861 check_dsp(ctx);
22862 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22863 break;
22864 case OPC_MAQ_SA_W_QHRR:
22865 check_dsp(ctx);
22866 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22867 break;
22868 case OPC_MULSAQ_S_L_PW:
22869 check_dsp(ctx);
22870 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22871 break;
22872 case OPC_MULSAQ_S_W_QH:
22873 check_dsp(ctx);
22874 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22875 break;
22878 break;
22879 #endif
22880 case OPC_ADDU_QB_DSP:
22881 switch (op2) {
22882 case OPC_MULEU_S_PH_QBL:
22883 check_dsp(ctx);
22884 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22885 break;
22886 case OPC_MULEU_S_PH_QBR:
22887 check_dsp(ctx);
22888 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22889 break;
22890 case OPC_MULQ_RS_PH:
22891 check_dsp(ctx);
22892 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22893 break;
22894 case OPC_MULEQ_S_W_PHL:
22895 check_dsp(ctx);
22896 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22897 break;
22898 case OPC_MULEQ_S_W_PHR:
22899 check_dsp(ctx);
22900 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22901 break;
22902 case OPC_MULQ_S_PH:
22903 check_dsp_r2(ctx);
22904 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22905 break;
22907 break;
22908 #ifdef TARGET_MIPS64
22909 case OPC_ADDU_OB_DSP:
22910 switch (op2) {
22911 case OPC_MULEQ_S_PW_QHL:
22912 check_dsp(ctx);
22913 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22914 break;
22915 case OPC_MULEQ_S_PW_QHR:
22916 check_dsp(ctx);
22917 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22918 break;
22919 case OPC_MULEU_S_QH_OBL:
22920 check_dsp(ctx);
22921 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22922 break;
22923 case OPC_MULEU_S_QH_OBR:
22924 check_dsp(ctx);
22925 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22926 break;
22927 case OPC_MULQ_RS_QH:
22928 check_dsp(ctx);
22929 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22930 break;
22932 break;
22933 #endif
22936 tcg_temp_free_i32(t0);
22937 tcg_temp_free(v1_t);
22938 tcg_temp_free(v2_t);
22941 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22942 int ret, int val)
22944 int16_t imm;
22945 TCGv t0;
22946 TCGv val_t;
22948 if (ret == 0) {
22949 /* Treat as NOP. */
22950 return;
22953 t0 = tcg_temp_new();
22954 val_t = tcg_temp_new();
22955 gen_load_gpr(val_t, val);
22957 switch (op1) {
22958 case OPC_ABSQ_S_PH_DSP:
22959 switch (op2) {
22960 case OPC_BITREV:
22961 check_dsp(ctx);
22962 gen_helper_bitrev(cpu_gpr[ret], val_t);
22963 break;
22964 case OPC_REPL_QB:
22965 check_dsp(ctx);
22967 target_long result;
22968 imm = (ctx->opcode >> 16) & 0xFF;
22969 result = (uint32_t)imm << 24 |
22970 (uint32_t)imm << 16 |
22971 (uint32_t)imm << 8 |
22972 (uint32_t)imm;
22973 result = (int32_t)result;
22974 tcg_gen_movi_tl(cpu_gpr[ret], result);
22976 break;
22977 case OPC_REPLV_QB:
22978 check_dsp(ctx);
22979 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22980 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22981 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22982 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22983 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22984 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22985 break;
22986 case OPC_REPL_PH:
22987 check_dsp(ctx);
22989 imm = (ctx->opcode >> 16) & 0x03FF;
22990 imm = (int16_t)(imm << 6) >> 6;
22991 tcg_gen_movi_tl(cpu_gpr[ret], \
22992 (target_long)((int32_t)imm << 16 | \
22993 (uint16_t)imm));
22995 break;
22996 case OPC_REPLV_PH:
22997 check_dsp(ctx);
22998 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22999 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23000 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23001 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23002 break;
23004 break;
23005 #ifdef TARGET_MIPS64
23006 case OPC_ABSQ_S_QH_DSP:
23007 switch (op2) {
23008 case OPC_REPL_OB:
23009 check_dsp(ctx);
23011 target_long temp;
23013 imm = (ctx->opcode >> 16) & 0xFF;
23014 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23015 temp = (temp << 16) | temp;
23016 temp = (temp << 32) | temp;
23017 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23018 break;
23020 case OPC_REPL_PW:
23021 check_dsp(ctx);
23023 target_long temp;
23025 imm = (ctx->opcode >> 16) & 0x03FF;
23026 imm = (int16_t)(imm << 6) >> 6;
23027 temp = ((target_long)imm << 32) \
23028 | ((target_long)imm & 0xFFFFFFFF);
23029 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23030 break;
23032 case OPC_REPL_QH:
23033 check_dsp(ctx);
23035 target_long temp;
23037 imm = (ctx->opcode >> 16) & 0x03FF;
23038 imm = (int16_t)(imm << 6) >> 6;
23040 temp = ((uint64_t)(uint16_t)imm << 48) |
23041 ((uint64_t)(uint16_t)imm << 32) |
23042 ((uint64_t)(uint16_t)imm << 16) |
23043 (uint64_t)(uint16_t)imm;
23044 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23045 break;
23047 case OPC_REPLV_OB:
23048 check_dsp(ctx);
23049 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23050 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23051 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23052 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23053 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23054 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23055 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23056 break;
23057 case OPC_REPLV_PW:
23058 check_dsp(ctx);
23059 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23060 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23061 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23062 break;
23063 case OPC_REPLV_QH:
23064 check_dsp(ctx);
23065 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23066 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23067 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23068 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23069 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23070 break;
23072 break;
23073 #endif
23075 tcg_temp_free(t0);
23076 tcg_temp_free(val_t);
23079 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23080 uint32_t op1, uint32_t op2,
23081 int ret, int v1, int v2, int check_ret)
23083 TCGv t1;
23084 TCGv v1_t;
23085 TCGv v2_t;
23087 if ((ret == 0) && (check_ret == 1)) {
23088 /* Treat as NOP. */
23089 return;
23092 t1 = tcg_temp_new();
23093 v1_t = tcg_temp_new();
23094 v2_t = tcg_temp_new();
23096 gen_load_gpr(v1_t, v1);
23097 gen_load_gpr(v2_t, v2);
23099 switch (op1) {
23100 case OPC_CMPU_EQ_QB_DSP:
23101 switch (op2) {
23102 case OPC_CMPU_EQ_QB:
23103 check_dsp(ctx);
23104 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23105 break;
23106 case OPC_CMPU_LT_QB:
23107 check_dsp(ctx);
23108 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23109 break;
23110 case OPC_CMPU_LE_QB:
23111 check_dsp(ctx);
23112 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23113 break;
23114 case OPC_CMPGU_EQ_QB:
23115 check_dsp(ctx);
23116 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23117 break;
23118 case OPC_CMPGU_LT_QB:
23119 check_dsp(ctx);
23120 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23121 break;
23122 case OPC_CMPGU_LE_QB:
23123 check_dsp(ctx);
23124 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23125 break;
23126 case OPC_CMPGDU_EQ_QB:
23127 check_dsp_r2(ctx);
23128 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23129 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23130 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23131 tcg_gen_shli_tl(t1, t1, 24);
23132 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23133 break;
23134 case OPC_CMPGDU_LT_QB:
23135 check_dsp_r2(ctx);
23136 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23137 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23138 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23139 tcg_gen_shli_tl(t1, t1, 24);
23140 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23141 break;
23142 case OPC_CMPGDU_LE_QB:
23143 check_dsp_r2(ctx);
23144 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23145 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23146 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23147 tcg_gen_shli_tl(t1, t1, 24);
23148 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23149 break;
23150 case OPC_CMP_EQ_PH:
23151 check_dsp(ctx);
23152 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23153 break;
23154 case OPC_CMP_LT_PH:
23155 check_dsp(ctx);
23156 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23157 break;
23158 case OPC_CMP_LE_PH:
23159 check_dsp(ctx);
23160 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23161 break;
23162 case OPC_PICK_QB:
23163 check_dsp(ctx);
23164 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23165 break;
23166 case OPC_PICK_PH:
23167 check_dsp(ctx);
23168 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23169 break;
23170 case OPC_PACKRL_PH:
23171 check_dsp(ctx);
23172 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23173 break;
23175 break;
23176 #ifdef TARGET_MIPS64
23177 case OPC_CMPU_EQ_OB_DSP:
23178 switch (op2) {
23179 case OPC_CMP_EQ_PW:
23180 check_dsp(ctx);
23181 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23182 break;
23183 case OPC_CMP_LT_PW:
23184 check_dsp(ctx);
23185 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23186 break;
23187 case OPC_CMP_LE_PW:
23188 check_dsp(ctx);
23189 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23190 break;
23191 case OPC_CMP_EQ_QH:
23192 check_dsp(ctx);
23193 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23194 break;
23195 case OPC_CMP_LT_QH:
23196 check_dsp(ctx);
23197 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23198 break;
23199 case OPC_CMP_LE_QH:
23200 check_dsp(ctx);
23201 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23202 break;
23203 case OPC_CMPGDU_EQ_OB:
23204 check_dsp_r2(ctx);
23205 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23206 break;
23207 case OPC_CMPGDU_LT_OB:
23208 check_dsp_r2(ctx);
23209 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23210 break;
23211 case OPC_CMPGDU_LE_OB:
23212 check_dsp_r2(ctx);
23213 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23214 break;
23215 case OPC_CMPGU_EQ_OB:
23216 check_dsp(ctx);
23217 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23218 break;
23219 case OPC_CMPGU_LT_OB:
23220 check_dsp(ctx);
23221 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23222 break;
23223 case OPC_CMPGU_LE_OB:
23224 check_dsp(ctx);
23225 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23226 break;
23227 case OPC_CMPU_EQ_OB:
23228 check_dsp(ctx);
23229 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23230 break;
23231 case OPC_CMPU_LT_OB:
23232 check_dsp(ctx);
23233 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23234 break;
23235 case OPC_CMPU_LE_OB:
23236 check_dsp(ctx);
23237 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23238 break;
23239 case OPC_PACKRL_PW:
23240 check_dsp(ctx);
23241 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23242 break;
23243 case OPC_PICK_OB:
23244 check_dsp(ctx);
23245 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23246 break;
23247 case OPC_PICK_PW:
23248 check_dsp(ctx);
23249 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23250 break;
23251 case OPC_PICK_QH:
23252 check_dsp(ctx);
23253 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23254 break;
23256 break;
23257 #endif
23260 tcg_temp_free(t1);
23261 tcg_temp_free(v1_t);
23262 tcg_temp_free(v2_t);
23265 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23266 uint32_t op1, int rt, int rs, int sa)
23268 TCGv t0;
23270 check_dsp_r2(ctx);
23272 if (rt == 0) {
23273 /* Treat as NOP. */
23274 return;
23277 t0 = tcg_temp_new();
23278 gen_load_gpr(t0, rs);
23280 switch (op1) {
23281 case OPC_APPEND_DSP:
23282 switch (MASK_APPEND(ctx->opcode)) {
23283 case OPC_APPEND:
23284 if (sa != 0) {
23285 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23287 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23288 break;
23289 case OPC_PREPEND:
23290 if (sa != 0) {
23291 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23292 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23293 tcg_gen_shli_tl(t0, t0, 32 - sa);
23294 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23296 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23297 break;
23298 case OPC_BALIGN:
23299 sa &= 3;
23300 if (sa != 0 && sa != 2) {
23301 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23302 tcg_gen_ext32u_tl(t0, t0);
23303 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23304 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23306 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23307 break;
23308 default: /* Invalid */
23309 MIPS_INVAL("MASK APPEND");
23310 generate_exception_end(ctx, EXCP_RI);
23311 break;
23313 break;
23314 #ifdef TARGET_MIPS64
23315 case OPC_DAPPEND_DSP:
23316 switch (MASK_DAPPEND(ctx->opcode)) {
23317 case OPC_DAPPEND:
23318 if (sa != 0) {
23319 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23321 break;
23322 case OPC_PREPENDD:
23323 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23324 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23325 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23326 break;
23327 case OPC_PREPENDW:
23328 if (sa != 0) {
23329 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23330 tcg_gen_shli_tl(t0, t0, 64 - sa);
23331 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23333 break;
23334 case OPC_DBALIGN:
23335 sa &= 7;
23336 if (sa != 0 && sa != 2 && sa != 4) {
23337 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23338 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23339 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23341 break;
23342 default: /* Invalid */
23343 MIPS_INVAL("MASK DAPPEND");
23344 generate_exception_end(ctx, EXCP_RI);
23345 break;
23347 break;
23348 #endif
23350 tcg_temp_free(t0);
23353 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23354 int ret, int v1, int v2, int check_ret)
23357 TCGv t0;
23358 TCGv t1;
23359 TCGv v1_t;
23360 TCGv v2_t;
23361 int16_t imm;
23363 if ((ret == 0) && (check_ret == 1)) {
23364 /* Treat as NOP. */
23365 return;
23368 t0 = tcg_temp_new();
23369 t1 = tcg_temp_new();
23370 v1_t = tcg_temp_new();
23371 v2_t = tcg_temp_new();
23373 gen_load_gpr(v1_t, v1);
23374 gen_load_gpr(v2_t, v2);
23376 switch (op1) {
23377 case OPC_EXTR_W_DSP:
23378 check_dsp(ctx);
23379 switch (op2) {
23380 case OPC_EXTR_W:
23381 tcg_gen_movi_tl(t0, v2);
23382 tcg_gen_movi_tl(t1, v1);
23383 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23384 break;
23385 case OPC_EXTR_R_W:
23386 tcg_gen_movi_tl(t0, v2);
23387 tcg_gen_movi_tl(t1, v1);
23388 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23389 break;
23390 case OPC_EXTR_RS_W:
23391 tcg_gen_movi_tl(t0, v2);
23392 tcg_gen_movi_tl(t1, v1);
23393 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23394 break;
23395 case OPC_EXTR_S_H:
23396 tcg_gen_movi_tl(t0, v2);
23397 tcg_gen_movi_tl(t1, v1);
23398 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23399 break;
23400 case OPC_EXTRV_S_H:
23401 tcg_gen_movi_tl(t0, v2);
23402 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23403 break;
23404 case OPC_EXTRV_W:
23405 tcg_gen_movi_tl(t0, v2);
23406 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23407 break;
23408 case OPC_EXTRV_R_W:
23409 tcg_gen_movi_tl(t0, v2);
23410 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23411 break;
23412 case OPC_EXTRV_RS_W:
23413 tcg_gen_movi_tl(t0, v2);
23414 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23415 break;
23416 case OPC_EXTP:
23417 tcg_gen_movi_tl(t0, v2);
23418 tcg_gen_movi_tl(t1, v1);
23419 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23420 break;
23421 case OPC_EXTPV:
23422 tcg_gen_movi_tl(t0, v2);
23423 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23424 break;
23425 case OPC_EXTPDP:
23426 tcg_gen_movi_tl(t0, v2);
23427 tcg_gen_movi_tl(t1, v1);
23428 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23429 break;
23430 case OPC_EXTPDPV:
23431 tcg_gen_movi_tl(t0, v2);
23432 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23433 break;
23434 case OPC_SHILO:
23435 imm = (ctx->opcode >> 20) & 0x3F;
23436 tcg_gen_movi_tl(t0, ret);
23437 tcg_gen_movi_tl(t1, imm);
23438 gen_helper_shilo(t0, t1, cpu_env);
23439 break;
23440 case OPC_SHILOV:
23441 tcg_gen_movi_tl(t0, ret);
23442 gen_helper_shilo(t0, v1_t, cpu_env);
23443 break;
23444 case OPC_MTHLIP:
23445 tcg_gen_movi_tl(t0, ret);
23446 gen_helper_mthlip(t0, v1_t, cpu_env);
23447 break;
23448 case OPC_WRDSP:
23449 imm = (ctx->opcode >> 11) & 0x3FF;
23450 tcg_gen_movi_tl(t0, imm);
23451 gen_helper_wrdsp(v1_t, t0, cpu_env);
23452 break;
23453 case OPC_RDDSP:
23454 imm = (ctx->opcode >> 16) & 0x03FF;
23455 tcg_gen_movi_tl(t0, imm);
23456 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23457 break;
23459 break;
23460 #ifdef TARGET_MIPS64
23461 case OPC_DEXTR_W_DSP:
23462 check_dsp(ctx);
23463 switch (op2) {
23464 case OPC_DMTHLIP:
23465 tcg_gen_movi_tl(t0, ret);
23466 gen_helper_dmthlip(v1_t, t0, cpu_env);
23467 break;
23468 case OPC_DSHILO:
23470 int shift = (ctx->opcode >> 19) & 0x7F;
23471 int ac = (ctx->opcode >> 11) & 0x03;
23472 tcg_gen_movi_tl(t0, shift);
23473 tcg_gen_movi_tl(t1, ac);
23474 gen_helper_dshilo(t0, t1, cpu_env);
23475 break;
23477 case OPC_DSHILOV:
23479 int ac = (ctx->opcode >> 11) & 0x03;
23480 tcg_gen_movi_tl(t0, ac);
23481 gen_helper_dshilo(v1_t, t0, cpu_env);
23482 break;
23484 case OPC_DEXTP:
23485 tcg_gen_movi_tl(t0, v2);
23486 tcg_gen_movi_tl(t1, v1);
23488 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23489 break;
23490 case OPC_DEXTPV:
23491 tcg_gen_movi_tl(t0, v2);
23492 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23493 break;
23494 case OPC_DEXTPDP:
23495 tcg_gen_movi_tl(t0, v2);
23496 tcg_gen_movi_tl(t1, v1);
23497 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23498 break;
23499 case OPC_DEXTPDPV:
23500 tcg_gen_movi_tl(t0, v2);
23501 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23502 break;
23503 case OPC_DEXTR_L:
23504 tcg_gen_movi_tl(t0, v2);
23505 tcg_gen_movi_tl(t1, v1);
23506 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23507 break;
23508 case OPC_DEXTR_R_L:
23509 tcg_gen_movi_tl(t0, v2);
23510 tcg_gen_movi_tl(t1, v1);
23511 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23512 break;
23513 case OPC_DEXTR_RS_L:
23514 tcg_gen_movi_tl(t0, v2);
23515 tcg_gen_movi_tl(t1, v1);
23516 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23517 break;
23518 case OPC_DEXTR_W:
23519 tcg_gen_movi_tl(t0, v2);
23520 tcg_gen_movi_tl(t1, v1);
23521 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23522 break;
23523 case OPC_DEXTR_R_W:
23524 tcg_gen_movi_tl(t0, v2);
23525 tcg_gen_movi_tl(t1, v1);
23526 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23527 break;
23528 case OPC_DEXTR_RS_W:
23529 tcg_gen_movi_tl(t0, v2);
23530 tcg_gen_movi_tl(t1, v1);
23531 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23532 break;
23533 case OPC_DEXTR_S_H:
23534 tcg_gen_movi_tl(t0, v2);
23535 tcg_gen_movi_tl(t1, v1);
23536 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23537 break;
23538 case OPC_DEXTRV_S_H:
23539 tcg_gen_movi_tl(t0, v2);
23540 tcg_gen_movi_tl(t1, v1);
23541 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23542 break;
23543 case OPC_DEXTRV_L:
23544 tcg_gen_movi_tl(t0, v2);
23545 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23546 break;
23547 case OPC_DEXTRV_R_L:
23548 tcg_gen_movi_tl(t0, v2);
23549 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23550 break;
23551 case OPC_DEXTRV_RS_L:
23552 tcg_gen_movi_tl(t0, v2);
23553 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23554 break;
23555 case OPC_DEXTRV_W:
23556 tcg_gen_movi_tl(t0, v2);
23557 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23558 break;
23559 case OPC_DEXTRV_R_W:
23560 tcg_gen_movi_tl(t0, v2);
23561 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23562 break;
23563 case OPC_DEXTRV_RS_W:
23564 tcg_gen_movi_tl(t0, v2);
23565 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23566 break;
23568 break;
23569 #endif
23572 tcg_temp_free(t0);
23573 tcg_temp_free(t1);
23574 tcg_temp_free(v1_t);
23575 tcg_temp_free(v2_t);
23578 /* End MIPSDSP functions. */
23580 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23582 int rs, rt, rd, sa;
23583 uint32_t op1, op2;
23585 rs = (ctx->opcode >> 21) & 0x1f;
23586 rt = (ctx->opcode >> 16) & 0x1f;
23587 rd = (ctx->opcode >> 11) & 0x1f;
23588 sa = (ctx->opcode >> 6) & 0x1f;
23590 op1 = MASK_SPECIAL(ctx->opcode);
23591 switch (op1) {
23592 case OPC_LSA:
23593 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23594 break;
23595 case OPC_MULT:
23596 case OPC_MULTU:
23597 case OPC_DIV:
23598 case OPC_DIVU:
23599 op2 = MASK_R6_MULDIV(ctx->opcode);
23600 switch (op2) {
23601 case R6_OPC_MUL:
23602 case R6_OPC_MUH:
23603 case R6_OPC_MULU:
23604 case R6_OPC_MUHU:
23605 case R6_OPC_DIV:
23606 case R6_OPC_MOD:
23607 case R6_OPC_DIVU:
23608 case R6_OPC_MODU:
23609 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23610 break;
23611 default:
23612 MIPS_INVAL("special_r6 muldiv");
23613 generate_exception_end(ctx, EXCP_RI);
23614 break;
23616 break;
23617 case OPC_SELEQZ:
23618 case OPC_SELNEZ:
23619 gen_cond_move(ctx, op1, rd, rs, rt);
23620 break;
23621 case R6_OPC_CLO:
23622 case R6_OPC_CLZ:
23623 if (rt == 0 && sa == 1) {
23624 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23625 We need additionally to check other fields */
23626 gen_cl(ctx, op1, rd, rs);
23627 } else {
23628 generate_exception_end(ctx, EXCP_RI);
23630 break;
23631 case R6_OPC_SDBBP:
23632 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23633 gen_helper_do_semihosting(cpu_env);
23634 } else {
23635 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23636 generate_exception_end(ctx, EXCP_RI);
23637 } else {
23638 generate_exception_end(ctx, EXCP_DBp);
23641 break;
23642 #if defined(TARGET_MIPS64)
23643 case OPC_DLSA:
23644 check_mips_64(ctx);
23645 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23646 break;
23647 case R6_OPC_DCLO:
23648 case R6_OPC_DCLZ:
23649 if (rt == 0 && sa == 1) {
23650 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23651 We need additionally to check other fields */
23652 check_mips_64(ctx);
23653 gen_cl(ctx, op1, rd, rs);
23654 } else {
23655 generate_exception_end(ctx, EXCP_RI);
23657 break;
23658 case OPC_DMULT:
23659 case OPC_DMULTU:
23660 case OPC_DDIV:
23661 case OPC_DDIVU:
23663 op2 = MASK_R6_MULDIV(ctx->opcode);
23664 switch (op2) {
23665 case R6_OPC_DMUL:
23666 case R6_OPC_DMUH:
23667 case R6_OPC_DMULU:
23668 case R6_OPC_DMUHU:
23669 case R6_OPC_DDIV:
23670 case R6_OPC_DMOD:
23671 case R6_OPC_DDIVU:
23672 case R6_OPC_DMODU:
23673 check_mips_64(ctx);
23674 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23675 break;
23676 default:
23677 MIPS_INVAL("special_r6 muldiv");
23678 generate_exception_end(ctx, EXCP_RI);
23679 break;
23681 break;
23682 #endif
23683 default: /* Invalid */
23684 MIPS_INVAL("special_r6");
23685 generate_exception_end(ctx, EXCP_RI);
23686 break;
23690 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23692 int rs, rt, rd, sa;
23693 uint32_t op1;
23695 rs = (ctx->opcode >> 21) & 0x1f;
23696 rt = (ctx->opcode >> 16) & 0x1f;
23697 rd = (ctx->opcode >> 11) & 0x1f;
23698 sa = (ctx->opcode >> 6) & 0x1f;
23700 op1 = MASK_SPECIAL(ctx->opcode);
23701 switch (op1) {
23702 case OPC_MOVN: /* Conditional move */
23703 case OPC_MOVZ:
23704 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23705 INSN_LOONGSON2E | INSN_LOONGSON2F | INSN_R5900);
23706 gen_cond_move(ctx, op1, rd, rs, rt);
23707 break;
23708 case OPC_MFHI: /* Move from HI/LO */
23709 case OPC_MFLO:
23710 gen_HILO(ctx, op1, rs & 3, rd);
23711 break;
23712 case OPC_MTHI:
23713 case OPC_MTLO: /* Move to HI/LO */
23714 gen_HILO(ctx, op1, rd & 3, rs);
23715 break;
23716 case OPC_MOVCI:
23717 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23718 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23719 check_cp1_enabled(ctx);
23720 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23721 (ctx->opcode >> 16) & 1);
23722 } else {
23723 generate_exception_err(ctx, EXCP_CpU, 1);
23725 break;
23726 case OPC_MULT:
23727 case OPC_MULTU:
23728 if (sa) {
23729 check_insn(ctx, INSN_VR54XX);
23730 op1 = MASK_MUL_VR54XX(ctx->opcode);
23731 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23732 } else if (ctx->insn_flags & INSN_R5900) {
23733 gen_mul_txx9(ctx, op1, rd, rs, rt);
23734 } else {
23735 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23737 break;
23738 case OPC_DIV:
23739 case OPC_DIVU:
23740 gen_muldiv(ctx, op1, 0, rs, rt);
23741 break;
23742 #if defined(TARGET_MIPS64)
23743 case OPC_DMULT:
23744 case OPC_DMULTU:
23745 case OPC_DDIV:
23746 case OPC_DDIVU:
23747 check_insn(ctx, ISA_MIPS3);
23748 check_insn_opc_user_only(ctx, INSN_R5900);
23749 check_mips_64(ctx);
23750 gen_muldiv(ctx, op1, 0, rs, rt);
23751 break;
23752 #endif
23753 case OPC_JR:
23754 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23755 break;
23756 case OPC_SPIM:
23757 #ifdef MIPS_STRICT_STANDARD
23758 MIPS_INVAL("SPIM");
23759 generate_exception_end(ctx, EXCP_RI);
23760 #else
23761 /* Implemented as RI exception for now. */
23762 MIPS_INVAL("spim (unofficial)");
23763 generate_exception_end(ctx, EXCP_RI);
23764 #endif
23765 break;
23766 default: /* Invalid */
23767 MIPS_INVAL("special_legacy");
23768 generate_exception_end(ctx, EXCP_RI);
23769 break;
23773 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23775 int rs, rt, rd, sa;
23776 uint32_t op1;
23778 rs = (ctx->opcode >> 21) & 0x1f;
23779 rt = (ctx->opcode >> 16) & 0x1f;
23780 rd = (ctx->opcode >> 11) & 0x1f;
23781 sa = (ctx->opcode >> 6) & 0x1f;
23783 op1 = MASK_SPECIAL(ctx->opcode);
23784 switch (op1) {
23785 case OPC_SLL: /* Shift with immediate */
23786 if (sa == 5 && rd == 0 &&
23787 rs == 0 && rt == 0) { /* PAUSE */
23788 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23789 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23790 generate_exception_end(ctx, EXCP_RI);
23791 break;
23794 /* Fallthrough */
23795 case OPC_SRA:
23796 gen_shift_imm(ctx, op1, rd, rt, sa);
23797 break;
23798 case OPC_SRL:
23799 switch ((ctx->opcode >> 21) & 0x1f) {
23800 case 1:
23801 /* rotr is decoded as srl on non-R2 CPUs */
23802 if (ctx->insn_flags & ISA_MIPS32R2) {
23803 op1 = OPC_ROTR;
23805 /* Fallthrough */
23806 case 0:
23807 gen_shift_imm(ctx, op1, rd, rt, sa);
23808 break;
23809 default:
23810 generate_exception_end(ctx, EXCP_RI);
23811 break;
23813 break;
23814 case OPC_ADD:
23815 case OPC_ADDU:
23816 case OPC_SUB:
23817 case OPC_SUBU:
23818 gen_arith(ctx, op1, rd, rs, rt);
23819 break;
23820 case OPC_SLLV: /* Shifts */
23821 case OPC_SRAV:
23822 gen_shift(ctx, op1, rd, rs, rt);
23823 break;
23824 case OPC_SRLV:
23825 switch ((ctx->opcode >> 6) & 0x1f) {
23826 case 1:
23827 /* rotrv is decoded as srlv on non-R2 CPUs */
23828 if (ctx->insn_flags & ISA_MIPS32R2) {
23829 op1 = OPC_ROTRV;
23831 /* Fallthrough */
23832 case 0:
23833 gen_shift(ctx, op1, rd, rs, rt);
23834 break;
23835 default:
23836 generate_exception_end(ctx, EXCP_RI);
23837 break;
23839 break;
23840 case OPC_SLT: /* Set on less than */
23841 case OPC_SLTU:
23842 gen_slt(ctx, op1, rd, rs, rt);
23843 break;
23844 case OPC_AND: /* Logic*/
23845 case OPC_OR:
23846 case OPC_NOR:
23847 case OPC_XOR:
23848 gen_logic(ctx, op1, rd, rs, rt);
23849 break;
23850 case OPC_JALR:
23851 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23852 break;
23853 case OPC_TGE: /* Traps */
23854 case OPC_TGEU:
23855 case OPC_TLT:
23856 case OPC_TLTU:
23857 case OPC_TEQ:
23858 case OPC_TNE:
23859 check_insn(ctx, ISA_MIPS2);
23860 gen_trap(ctx, op1, rs, rt, -1);
23861 break;
23862 case OPC_LSA: /* OPC_PMON */
23863 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23864 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23865 decode_opc_special_r6(env, ctx);
23866 } else {
23867 /* Pmon entry point, also R4010 selsl */
23868 #ifdef MIPS_STRICT_STANDARD
23869 MIPS_INVAL("PMON / selsl");
23870 generate_exception_end(ctx, EXCP_RI);
23871 #else
23872 gen_helper_0e0i(pmon, sa);
23873 #endif
23875 break;
23876 case OPC_SYSCALL:
23877 generate_exception_end(ctx, EXCP_SYSCALL);
23878 break;
23879 case OPC_BREAK:
23880 generate_exception_end(ctx, EXCP_BREAK);
23881 break;
23882 case OPC_SYNC:
23883 check_insn(ctx, ISA_MIPS2);
23884 gen_sync(extract32(ctx->opcode, 6, 5));
23885 break;
23887 #if defined(TARGET_MIPS64)
23888 /* MIPS64 specific opcodes */
23889 case OPC_DSLL:
23890 case OPC_DSRA:
23891 case OPC_DSLL32:
23892 case OPC_DSRA32:
23893 check_insn(ctx, ISA_MIPS3);
23894 check_mips_64(ctx);
23895 gen_shift_imm(ctx, op1, rd, rt, sa);
23896 break;
23897 case OPC_DSRL:
23898 switch ((ctx->opcode >> 21) & 0x1f) {
23899 case 1:
23900 /* drotr is decoded as dsrl on non-R2 CPUs */
23901 if (ctx->insn_flags & ISA_MIPS32R2) {
23902 op1 = OPC_DROTR;
23904 /* Fallthrough */
23905 case 0:
23906 check_insn(ctx, ISA_MIPS3);
23907 check_mips_64(ctx);
23908 gen_shift_imm(ctx, op1, rd, rt, sa);
23909 break;
23910 default:
23911 generate_exception_end(ctx, EXCP_RI);
23912 break;
23914 break;
23915 case OPC_DSRL32:
23916 switch ((ctx->opcode >> 21) & 0x1f) {
23917 case 1:
23918 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23919 if (ctx->insn_flags & ISA_MIPS32R2) {
23920 op1 = OPC_DROTR32;
23922 /* Fallthrough */
23923 case 0:
23924 check_insn(ctx, ISA_MIPS3);
23925 check_mips_64(ctx);
23926 gen_shift_imm(ctx, op1, rd, rt, sa);
23927 break;
23928 default:
23929 generate_exception_end(ctx, EXCP_RI);
23930 break;
23932 break;
23933 case OPC_DADD:
23934 case OPC_DADDU:
23935 case OPC_DSUB:
23936 case OPC_DSUBU:
23937 check_insn(ctx, ISA_MIPS3);
23938 check_mips_64(ctx);
23939 gen_arith(ctx, op1, rd, rs, rt);
23940 break;
23941 case OPC_DSLLV:
23942 case OPC_DSRAV:
23943 check_insn(ctx, ISA_MIPS3);
23944 check_mips_64(ctx);
23945 gen_shift(ctx, op1, rd, rs, rt);
23946 break;
23947 case OPC_DSRLV:
23948 switch ((ctx->opcode >> 6) & 0x1f) {
23949 case 1:
23950 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23951 if (ctx->insn_flags & ISA_MIPS32R2) {
23952 op1 = OPC_DROTRV;
23954 /* Fallthrough */
23955 case 0:
23956 check_insn(ctx, ISA_MIPS3);
23957 check_mips_64(ctx);
23958 gen_shift(ctx, op1, rd, rs, rt);
23959 break;
23960 default:
23961 generate_exception_end(ctx, EXCP_RI);
23962 break;
23964 break;
23965 case OPC_DLSA:
23966 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23967 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23968 decode_opc_special_r6(env, ctx);
23970 break;
23971 #endif
23972 default:
23973 if (ctx->insn_flags & ISA_MIPS32R6) {
23974 decode_opc_special_r6(env, ctx);
23975 } else {
23976 decode_opc_special_legacy(env, ctx);
23982 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
23983 #define MXU_APTN1_A 0
23984 #define MXU_APTN1_S 1
23986 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
23987 #define MXU_APTN2_AA 0
23988 #define MXU_APTN2_AS 1
23989 #define MXU_APTN2_SA 2
23990 #define MXU_APTN2_SS 3
23995 * Decode MXU pool00
23997 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
23998 * +-----------+---------+-----+-------+-------+-------+-----------+
23999 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
24000 * +-----------+---------+-----+-------+-------+-------+-----------+
24003 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
24005 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24007 switch (opcode) {
24008 case OPC_MXU_S32MAX:
24009 /* TODO: Implement emulation of S32MAX instruction. */
24010 MIPS_INVAL("OPC_MXU_S32MAX");
24011 generate_exception_end(ctx, EXCP_RI);
24012 break;
24013 case OPC_MXU_S32MIN:
24014 /* TODO: Implement emulation of S32MIN instruction. */
24015 MIPS_INVAL("OPC_MXU_S32MIN");
24016 generate_exception_end(ctx, EXCP_RI);
24017 break;
24018 case OPC_MXU_D16MAX:
24019 /* TODO: Implement emulation of D16MAX instruction. */
24020 MIPS_INVAL("OPC_MXU_D16MAX");
24021 generate_exception_end(ctx, EXCP_RI);
24022 break;
24023 case OPC_MXU_D16MIN:
24024 /* TODO: Implement emulation of D16MIN instruction. */
24025 MIPS_INVAL("OPC_MXU_D16MIN");
24026 generate_exception_end(ctx, EXCP_RI);
24027 break;
24028 case OPC_MXU_Q8MAX:
24029 /* TODO: Implement emulation of Q8MAX instruction. */
24030 MIPS_INVAL("OPC_MXU_Q8MAX");
24031 generate_exception_end(ctx, EXCP_RI);
24032 break;
24033 case OPC_MXU_Q8MIN:
24034 /* TODO: Implement emulation of Q8MIN instruction. */
24035 MIPS_INVAL("OPC_MXU_Q8MIN");
24036 generate_exception_end(ctx, EXCP_RI);
24037 break;
24038 case OPC_MXU_Q8SLT:
24039 /* TODO: Implement emulation of Q8SLT instruction. */
24040 MIPS_INVAL("OPC_MXU_Q8SLT");
24041 generate_exception_end(ctx, EXCP_RI);
24042 break;
24043 case OPC_MXU_Q8SLTU:
24044 /* TODO: Implement emulation of Q8SLTU instruction. */
24045 MIPS_INVAL("OPC_MXU_Q8SLTU");
24046 generate_exception_end(ctx, EXCP_RI);
24047 break;
24048 default:
24049 MIPS_INVAL("decode_opc_mxu");
24050 generate_exception_end(ctx, EXCP_RI);
24051 break;
24057 * Decode MXU pool01
24059 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
24060 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24061 * +-----------+---------+-----+-------+-------+-------+-----------+
24062 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
24063 * +-----------+---------+-----+-------+-------+-------+-----------+
24065 * Q8ADD:
24066 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24067 * +-----------+---+-----+-----+-------+-------+-------+-----------+
24068 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
24069 * +-----------+---+-----+-----+-------+-------+-------+-----------+
24072 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
24074 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24076 switch (opcode) {
24077 case OPC_MXU_S32SLT:
24078 /* TODO: Implement emulation of S32SLT instruction. */
24079 MIPS_INVAL("OPC_MXU_S32SLT");
24080 generate_exception_end(ctx, EXCP_RI);
24081 break;
24082 case OPC_MXU_D16SLT:
24083 /* TODO: Implement emulation of D16SLT instruction. */
24084 MIPS_INVAL("OPC_MXU_D16SLT");
24085 generate_exception_end(ctx, EXCP_RI);
24086 break;
24087 case OPC_MXU_D16AVG:
24088 /* TODO: Implement emulation of D16AVG instruction. */
24089 MIPS_INVAL("OPC_MXU_D16AVG");
24090 generate_exception_end(ctx, EXCP_RI);
24091 break;
24092 case OPC_MXU_D16AVGR:
24093 /* TODO: Implement emulation of D16AVGR instruction. */
24094 MIPS_INVAL("OPC_MXU_D16AVGR");
24095 generate_exception_end(ctx, EXCP_RI);
24096 break;
24097 case OPC_MXU_Q8AVG:
24098 /* TODO: Implement emulation of Q8AVG instruction. */
24099 MIPS_INVAL("OPC_MXU_Q8AVG");
24100 generate_exception_end(ctx, EXCP_RI);
24101 break;
24102 case OPC_MXU_Q8AVGR:
24103 /* TODO: Implement emulation of Q8AVGR instruction. */
24104 MIPS_INVAL("OPC_MXU_Q8AVGR");
24105 generate_exception_end(ctx, EXCP_RI);
24106 break;
24107 case OPC_MXU_Q8ADD:
24108 /* TODO: Implement emulation of Q8ADD instruction. */
24109 MIPS_INVAL("OPC_MXU_Q8ADD");
24110 generate_exception_end(ctx, EXCP_RI);
24111 break;
24112 default:
24113 MIPS_INVAL("decode_opc_mxu");
24114 generate_exception_end(ctx, EXCP_RI);
24115 break;
24121 * Decode MXU pool02
24123 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24124 * +-----------+---------+-----+-------+-------+-------+-----------+
24125 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
24126 * +-----------+---------+-----+-------+-------+-------+-----------+
24129 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
24131 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24133 switch (opcode) {
24134 case OPC_MXU_S32CPS:
24135 /* TODO: Implement emulation of S32CPS instruction. */
24136 MIPS_INVAL("OPC_MXU_S32CPS");
24137 generate_exception_end(ctx, EXCP_RI);
24138 break;
24139 case OPC_MXU_D16CPS:
24140 /* TODO: Implement emulation of D16CPS instruction. */
24141 MIPS_INVAL("OPC_MXU_D16CPS");
24142 generate_exception_end(ctx, EXCP_RI);
24143 break;
24144 case OPC_MXU_Q8ABD:
24145 /* TODO: Implement emulation of Q8ABD instruction. */
24146 MIPS_INVAL("OPC_MXU_Q8ABD");
24147 generate_exception_end(ctx, EXCP_RI);
24148 break;
24149 case OPC_MXU_Q16SAT:
24150 /* TODO: Implement emulation of Q16SAT instruction. */
24151 MIPS_INVAL("OPC_MXU_Q16SAT");
24152 generate_exception_end(ctx, EXCP_RI);
24153 break;
24154 default:
24155 MIPS_INVAL("decode_opc_mxu");
24156 generate_exception_end(ctx, EXCP_RI);
24157 break;
24163 * Decode MXU pool03
24165 * D16MULF:
24166 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24167 * +-----------+---+---+-------+-------+-------+-------+-----------+
24168 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
24169 * +-----------+---+---+-------+-------+-------+-------+-----------+
24171 * D16MULE:
24172 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24173 * +-----------+---+---+-------+-------+-------+-------+-----------+
24174 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
24175 * +-----------+---+---+-------+-------+-------+-------+-----------+
24178 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
24180 uint32_t opcode = extract32(ctx->opcode, 24, 2);
24182 switch (opcode) {
24183 case OPC_MXU_D16MULF:
24184 /* TODO: Implement emulation of D16MULF instruction. */
24185 MIPS_INVAL("OPC_MXU_D16MULF");
24186 generate_exception_end(ctx, EXCP_RI);
24187 break;
24188 case OPC_MXU_D16MULE:
24189 /* TODO: Implement emulation of D16MULE instruction. */
24190 MIPS_INVAL("OPC_MXU_D16MULE");
24191 generate_exception_end(ctx, EXCP_RI);
24192 break;
24193 default:
24194 MIPS_INVAL("decode_opc_mxu");
24195 generate_exception_end(ctx, EXCP_RI);
24196 break;
24202 * Decode MXU pool04
24204 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24205 * +-----------+---------+-+-------------------+-------+-----------+
24206 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
24207 * +-----------+---------+-+-------------------+-------+-----------+
24210 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
24212 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24214 switch (opcode) {
24215 case OPC_MXU_S32LDD:
24216 /* TODO: Implement emulation of S32LDD instruction. */
24217 MIPS_INVAL("OPC_MXU_S32LDD");
24218 generate_exception_end(ctx, EXCP_RI);
24219 break;
24220 case OPC_MXU_S32LDDR:
24221 /* TODO: Implement emulation of S32LDDR instruction. */
24222 MIPS_INVAL("OPC_MXU_S32LDDR");
24223 generate_exception_end(ctx, EXCP_RI);
24224 break;
24225 default:
24226 MIPS_INVAL("decode_opc_mxu");
24227 generate_exception_end(ctx, EXCP_RI);
24228 break;
24234 * Decode MXU pool05
24236 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24237 * +-----------+---------+-+-------------------+-------+-----------+
24238 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
24239 * +-----------+---------+-+-------------------+-------+-----------+
24242 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
24244 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24246 switch (opcode) {
24247 case OPC_MXU_S32STD:
24248 /* TODO: Implement emulation of S32STD instruction. */
24249 MIPS_INVAL("OPC_MXU_S32STD");
24250 generate_exception_end(ctx, EXCP_RI);
24251 break;
24252 case OPC_MXU_S32STDR:
24253 /* TODO: Implement emulation of S32STDR instruction. */
24254 MIPS_INVAL("OPC_MXU_S32STDR");
24255 generate_exception_end(ctx, EXCP_RI);
24256 break;
24257 default:
24258 MIPS_INVAL("decode_opc_mxu");
24259 generate_exception_end(ctx, EXCP_RI);
24260 break;
24266 * Decode MXU pool06
24268 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24269 * +-----------+---------+---------+---+-------+-------+-----------+
24270 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
24271 * +-----------+---------+---------+---+-------+-------+-----------+
24274 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
24276 uint32_t opcode = extract32(ctx->opcode, 10, 4);
24278 switch (opcode) {
24279 case OPC_MXU_S32LDDV:
24280 /* TODO: Implement emulation of S32LDDV instruction. */
24281 MIPS_INVAL("OPC_MXU_S32LDDV");
24282 generate_exception_end(ctx, EXCP_RI);
24283 break;
24284 case OPC_MXU_S32LDDVR:
24285 /* TODO: Implement emulation of S32LDDVR instruction. */
24286 MIPS_INVAL("OPC_MXU_S32LDDVR");
24287 generate_exception_end(ctx, EXCP_RI);
24288 break;
24289 default:
24290 MIPS_INVAL("decode_opc_mxu");
24291 generate_exception_end(ctx, EXCP_RI);
24292 break;
24298 * Decode MXU pool07
24300 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24301 * +-----------+---------+---------+---+-------+-------+-----------+
24302 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
24303 * +-----------+---------+---------+---+-------+-------+-----------+
24306 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
24308 uint32_t opcode = extract32(ctx->opcode, 10, 4);
24310 switch (opcode) {
24311 case OPC_MXU_S32STDV:
24312 /* TODO: Implement emulation of S32TDV instruction. */
24313 MIPS_INVAL("OPC_MXU_S32TDV");
24314 generate_exception_end(ctx, EXCP_RI);
24315 break;
24316 case OPC_MXU_S32STDVR:
24317 /* TODO: Implement emulation of S32TDVR instruction. */
24318 MIPS_INVAL("OPC_MXU_S32TDVR");
24319 generate_exception_end(ctx, EXCP_RI);
24320 break;
24321 default:
24322 MIPS_INVAL("decode_opc_mxu");
24323 generate_exception_end(ctx, EXCP_RI);
24324 break;
24330 * Decode MXU pool08
24332 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24333 * +-----------+---------+-+-------------------+-------+-----------+
24334 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
24335 * +-----------+---------+-+-------------------+-------+-----------+
24338 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
24340 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24342 switch (opcode) {
24343 case OPC_MXU_S32LDI:
24344 /* TODO: Implement emulation of S32LDI instruction. */
24345 MIPS_INVAL("OPC_MXU_S32LDI");
24346 generate_exception_end(ctx, EXCP_RI);
24347 break;
24348 case OPC_MXU_S32LDIR:
24349 /* TODO: Implement emulation of S32LDIR instruction. */
24350 MIPS_INVAL("OPC_MXU_S32LDIR");
24351 generate_exception_end(ctx, EXCP_RI);
24352 break;
24353 default:
24354 MIPS_INVAL("decode_opc_mxu");
24355 generate_exception_end(ctx, EXCP_RI);
24356 break;
24362 * Decode MXU pool09
24364 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24365 * +-----------+---------+-+-------------------+-------+-----------+
24366 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
24367 * +-----------+---------+-+-------------------+-------+-----------+
24370 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
24372 uint32_t opcode = extract32(ctx->opcode, 5, 0);
24374 switch (opcode) {
24375 case OPC_MXU_S32SDI:
24376 /* TODO: Implement emulation of S32SDI instruction. */
24377 MIPS_INVAL("OPC_MXU_S32SDI");
24378 generate_exception_end(ctx, EXCP_RI);
24379 break;
24380 case OPC_MXU_S32SDIR:
24381 /* TODO: Implement emulation of S32SDIR instruction. */
24382 MIPS_INVAL("OPC_MXU_S32SDIR");
24383 generate_exception_end(ctx, EXCP_RI);
24384 break;
24385 default:
24386 MIPS_INVAL("decode_opc_mxu");
24387 generate_exception_end(ctx, EXCP_RI);
24388 break;
24394 * Decode MXU pool10
24396 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24397 * +-----------+---------+---------+---+-------+-------+-----------+
24398 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
24399 * +-----------+---------+---------+---+-------+-------+-----------+
24402 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
24404 uint32_t opcode = extract32(ctx->opcode, 5, 0);
24406 switch (opcode) {
24407 case OPC_MXU_S32LDIV:
24408 /* TODO: Implement emulation of S32LDIV instruction. */
24409 MIPS_INVAL("OPC_MXU_S32LDIV");
24410 generate_exception_end(ctx, EXCP_RI);
24411 break;
24412 case OPC_MXU_S32LDIVR:
24413 /* TODO: Implement emulation of S32LDIVR instruction. */
24414 MIPS_INVAL("OPC_MXU_S32LDIVR");
24415 generate_exception_end(ctx, EXCP_RI);
24416 break;
24417 default:
24418 MIPS_INVAL("decode_opc_mxu");
24419 generate_exception_end(ctx, EXCP_RI);
24420 break;
24426 * Decode MXU pool11
24428 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24429 * +-----------+---------+---------+---+-------+-------+-----------+
24430 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
24431 * +-----------+---------+---------+---+-------+-------+-----------+
24434 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
24436 uint32_t opcode = extract32(ctx->opcode, 10, 4);
24438 switch (opcode) {
24439 case OPC_MXU_S32SDIV:
24440 /* TODO: Implement emulation of S32SDIV instruction. */
24441 MIPS_INVAL("OPC_MXU_S32SDIV");
24442 generate_exception_end(ctx, EXCP_RI);
24443 break;
24444 case OPC_MXU_S32SDIVR:
24445 /* TODO: Implement emulation of S32SDIVR instruction. */
24446 MIPS_INVAL("OPC_MXU_S32SDIVR");
24447 generate_exception_end(ctx, EXCP_RI);
24448 break;
24449 default:
24450 MIPS_INVAL("decode_opc_mxu");
24451 generate_exception_end(ctx, EXCP_RI);
24452 break;
24458 * Decode MXU pool12
24460 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24461 * +-----------+---+---+-------+-------+-------+-------+-----------+
24462 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
24463 * +-----------+---+---+-------+-------+-------+-------+-----------+
24466 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
24468 uint32_t opcode = extract32(ctx->opcode, 22, 2);
24470 switch (opcode) {
24471 case OPC_MXU_D32ACC:
24472 /* TODO: Implement emulation of D32ACC instruction. */
24473 MIPS_INVAL("OPC_MXU_D32ACC");
24474 generate_exception_end(ctx, EXCP_RI);
24475 break;
24476 case OPC_MXU_D32ACCM:
24477 /* TODO: Implement emulation of D32ACCM instruction. */
24478 MIPS_INVAL("OPC_MXU_D32ACCM");
24479 generate_exception_end(ctx, EXCP_RI);
24480 break;
24481 case OPC_MXU_D32ASUM:
24482 /* TODO: Implement emulation of D32ASUM instruction. */
24483 MIPS_INVAL("OPC_MXU_D32ASUM");
24484 generate_exception_end(ctx, EXCP_RI);
24485 break;
24486 default:
24487 MIPS_INVAL("decode_opc_mxu");
24488 generate_exception_end(ctx, EXCP_RI);
24489 break;
24495 * Decode MXU pool13
24497 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24498 * +-----------+---+---+-------+-------+-------+-------+-----------+
24499 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
24500 * +-----------+---+---+-------+-------+-------+-------+-----------+
24503 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
24505 uint32_t opcode = extract32(ctx->opcode, 22, 2);
24507 switch (opcode) {
24508 case OPC_MXU_Q16ACC:
24509 /* TODO: Implement emulation of Q16ACC instruction. */
24510 MIPS_INVAL("OPC_MXU_Q16ACC");
24511 generate_exception_end(ctx, EXCP_RI);
24512 break;
24513 case OPC_MXU_Q16ACCM:
24514 /* TODO: Implement emulation of Q16ACCM instruction. */
24515 MIPS_INVAL("OPC_MXU_Q16ACCM");
24516 generate_exception_end(ctx, EXCP_RI);
24517 break;
24518 case OPC_MXU_Q16ASUM:
24519 /* TODO: Implement emulation of Q16ASUM instruction. */
24520 MIPS_INVAL("OPC_MXU_Q16ASUM");
24521 generate_exception_end(ctx, EXCP_RI);
24522 break;
24523 default:
24524 MIPS_INVAL("decode_opc_mxu");
24525 generate_exception_end(ctx, EXCP_RI);
24526 break;
24532 * Decode MXU pool14
24534 * Q8ADDE, Q8ACCE:
24535 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24536 * +-----------+---+---+-------+-------+-------+-------+-----------+
24537 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
24538 * +-----------+---+---+-------+-------+-------+-------+-----------+
24540 * D8SUM, D8SUMC:
24541 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24542 * +-----------+---+---+-------+-------+-------+-------+-----------+
24543 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
24544 * +-----------+---+---+-------+-------+-------+-------+-----------+
24547 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
24549 uint32_t opcode = extract32(ctx->opcode, 22, 2);
24551 switch (opcode) {
24552 case OPC_MXU_Q8ADDE:
24553 /* TODO: Implement emulation of Q8ADDE instruction. */
24554 MIPS_INVAL("OPC_MXU_Q8ADDE");
24555 generate_exception_end(ctx, EXCP_RI);
24556 break;
24557 case OPC_MXU_D8SUM:
24558 /* TODO: Implement emulation of D8SUM instruction. */
24559 MIPS_INVAL("OPC_MXU_D8SUM");
24560 generate_exception_end(ctx, EXCP_RI);
24561 break;
24562 case OPC_MXU_D8SUMC:
24563 /* TODO: Implement emulation of D8SUMC instruction. */
24564 MIPS_INVAL("OPC_MXU_D8SUMC");
24565 generate_exception_end(ctx, EXCP_RI);
24566 break;
24567 default:
24568 MIPS_INVAL("decode_opc_mxu");
24569 generate_exception_end(ctx, EXCP_RI);
24570 break;
24576 * Decode MXU pool15
24578 * S32MUL, S32MULU, S32EXTRV:
24579 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24580 * +-----------+---------+---------+---+-------+-------+-----------+
24581 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
24582 * +-----------+---------+---------+---+-------+-------+-----------+
24584 * S32EXTR:
24585 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24586 * +-----------+---------+---------+---+-------+-------+-----------+
24587 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
24588 * +-----------+---------+---------+---+-------+-------+-----------+
24591 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
24593 uint32_t opcode = extract32(ctx->opcode, 14, 2);
24595 switch (opcode) {
24596 case OPC_MXU_S32MUL:
24597 /* TODO: Implement emulation of S32MUL instruction. */
24598 MIPS_INVAL("OPC_MXU_S32MUL");
24599 generate_exception_end(ctx, EXCP_RI);
24600 break;
24601 case OPC_MXU_S32MULU:
24602 /* TODO: Implement emulation of S32MULU instruction. */
24603 MIPS_INVAL("OPC_MXU_S32MULU");
24604 generate_exception_end(ctx, EXCP_RI);
24605 break;
24606 case OPC_MXU_S32EXTR:
24607 /* TODO: Implement emulation of S32EXTR instruction. */
24608 MIPS_INVAL("OPC_MXU_S32EXTR");
24609 generate_exception_end(ctx, EXCP_RI);
24610 break;
24611 case OPC_MXU_S32EXTRV:
24612 /* TODO: Implement emulation of S32EXTRV instruction. */
24613 MIPS_INVAL("OPC_MXU_S32EXTRV");
24614 generate_exception_end(ctx, EXCP_RI);
24615 break;
24616 default:
24617 MIPS_INVAL("decode_opc_mxu");
24618 generate_exception_end(ctx, EXCP_RI);
24619 break;
24625 * Decode MXU pool16
24627 * D32SARW:
24628 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24629 * +-----------+---------+-----+-------+-------+-------+-----------+
24630 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
24631 * +-----------+---------+-----+-------+-------+-------+-----------+
24633 * S32ALN:
24634 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24635 * +-----------+---------+-----+-------+-------+-------+-----------+
24636 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
24637 * +-----------+---------+-----+-------+-------+-------+-----------+
24639 * S32ALNI:
24640 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24641 * +-----------+-----+---+-----+-------+-------+-------+-----------+
24642 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
24643 * +-----------+-----+---+-----+-------+-------+-------+-----------+
24645 * S32NOR, S32AND, S32OR, S32XOR:
24646 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24647 * +-----------+---------+-----+-------+-------+-------+-----------+
24648 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
24649 * +-----------+---------+-----+-------+-------+-------+-----------+
24651 * S32LUI:
24652 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24653 * +-----------+-----+---+-----+-------+---------------+-----------+
24654 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
24655 * +-----------+-----+---+-----+-------+---------------+-----------+
24658 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
24660 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24662 switch (opcode) {
24663 case OPC_MXU_D32SARW:
24664 /* TODO: Implement emulation of D32SARW instruction. */
24665 MIPS_INVAL("OPC_MXU_D32SARW");
24666 generate_exception_end(ctx, EXCP_RI);
24667 break;
24668 case OPC_MXU_S32ALN:
24669 /* TODO: Implement emulation of S32ALN instruction. */
24670 MIPS_INVAL("OPC_MXU_S32ALN");
24671 generate_exception_end(ctx, EXCP_RI);
24672 break;
24673 case OPC_MXU_S32ALNI:
24674 /* TODO: Implement emulation of S32ALNI instruction. */
24675 MIPS_INVAL("OPC_MXU_S32ALNI");
24676 generate_exception_end(ctx, EXCP_RI);
24677 break;
24678 case OPC_MXU_S32NOR:
24679 /* TODO: Implement emulation of S32NOR instruction. */
24680 MIPS_INVAL("OPC_MXU_S32NOR");
24681 generate_exception_end(ctx, EXCP_RI);
24682 break;
24683 case OPC_MXU_S32AND:
24684 /* TODO: Implement emulation of S32AND instruction. */
24685 MIPS_INVAL("OPC_MXU_S32AND");
24686 generate_exception_end(ctx, EXCP_RI);
24687 break;
24688 case OPC_MXU_S32OR:
24689 /* TODO: Implement emulation of S32OR instruction. */
24690 MIPS_INVAL("OPC_MXU_S32OR");
24691 generate_exception_end(ctx, EXCP_RI);
24692 break;
24693 case OPC_MXU_S32XOR:
24694 /* TODO: Implement emulation of S32XOR instruction. */
24695 MIPS_INVAL("OPC_MXU_S32XOR");
24696 generate_exception_end(ctx, EXCP_RI);
24697 break;
24698 case OPC_MXU_S32LUI:
24699 /* TODO: Implement emulation of S32LUI instruction. */
24700 MIPS_INVAL("OPC_MXU_S32LUI");
24701 generate_exception_end(ctx, EXCP_RI);
24702 break;
24703 default:
24704 MIPS_INVAL("decode_opc_mxu");
24705 generate_exception_end(ctx, EXCP_RI);
24706 break;
24712 * Decode MXU pool17
24714 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24715 * +-----------+---------+-----+-------+-------+-------+-----------+
24716 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL17|
24717 * +-----------+---------+-----+-------+-------+-------+-----------+
24720 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
24722 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24724 switch (opcode) {
24725 case OPC_MXU_D32SLLV:
24726 /* TODO: Implement emulation of D32SLLV instruction. */
24727 MIPS_INVAL("OPC_MXU_D32SLLV");
24728 generate_exception_end(ctx, EXCP_RI);
24729 break;
24730 case OPC_MXU_D32SLRV:
24731 /* TODO: Implement emulation of D32SLRV instruction. */
24732 MIPS_INVAL("OPC_MXU_D32SLRV");
24733 generate_exception_end(ctx, EXCP_RI);
24734 break;
24735 case OPC_MXU_D32SARV:
24736 /* TODO: Implement emulation of D32SARV instruction. */
24737 MIPS_INVAL("OPC_MXU_D32SARV");
24738 generate_exception_end(ctx, EXCP_RI);
24739 break;
24740 case OPC_MXU_Q16SLLV:
24741 /* TODO: Implement emulation of Q16SLLV instruction. */
24742 MIPS_INVAL("OPC_MXU_Q16SLLV");
24743 generate_exception_end(ctx, EXCP_RI);
24744 break;
24745 case OPC_MXU_Q16SLRV:
24746 /* TODO: Implement emulation of Q16SLRV instruction. */
24747 MIPS_INVAL("OPC_MXU_Q16SLRV");
24748 generate_exception_end(ctx, EXCP_RI);
24749 break;
24750 case OPC_MXU_Q16SARV:
24751 /* TODO: Implement emulation of Q16SARV instruction. */
24752 MIPS_INVAL("OPC_MXU_Q16SARV");
24753 generate_exception_end(ctx, EXCP_RI);
24754 break;
24755 default:
24756 MIPS_INVAL("decode_opc_mxu");
24757 generate_exception_end(ctx, EXCP_RI);
24758 break;
24764 * Decode MXU pool18
24766 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24767 * +-----------+---+---+-------+-------+-------+-------+-----------+
24768 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL18|
24769 * +-----------+---+---+-------+-------+-------+-------+-----------+
24772 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
24774 uint32_t opcode = extract32(ctx->opcode, 22, 2);
24776 switch (opcode) {
24777 case OPC_MXU_Q8MUL:
24778 /* TODO: Implement emulation of Q8MUL instruction. */
24779 MIPS_INVAL("OPC_MXU_Q8MUL");
24780 generate_exception_end(ctx, EXCP_RI);
24781 break;
24782 case OPC_MXU_Q8MULSU:
24783 /* TODO: Implement emulation of Q8MULSU instruction. */
24784 MIPS_INVAL("OPC_MXU_Q8MULSU");
24785 generate_exception_end(ctx, EXCP_RI);
24786 break;
24787 default:
24788 MIPS_INVAL("decode_opc_mxu");
24789 generate_exception_end(ctx, EXCP_RI);
24790 break;
24796 * Decode MXU pool19
24798 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24799 * +-----------+---------+-----+-------+-------+-------+-----------+
24800 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL19|
24801 * +-----------+---------+-----+-------+-------+-------+-----------+
24804 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
24806 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24808 switch (opcode) {
24809 case OPC_MXU_Q8MOVZ:
24810 /* TODO: Implement emulation of Q8MOVZ instruction. */
24811 MIPS_INVAL("OPC_MXU_Q8MOVZ");
24812 generate_exception_end(ctx, EXCP_RI);
24813 break;
24814 case OPC_MXU_Q8MOVN:
24815 /* TODO: Implement emulation of Q8MOVN instruction. */
24816 MIPS_INVAL("OPC_MXU_Q8MOVN");
24817 generate_exception_end(ctx, EXCP_RI);
24818 break;
24819 case OPC_MXU_D16MOVZ:
24820 /* TODO: Implement emulation of D16MOVZ instruction. */
24821 MIPS_INVAL("OPC_MXU_D16MOVZ");
24822 generate_exception_end(ctx, EXCP_RI);
24823 break;
24824 case OPC_MXU_D16MOVN:
24825 /* TODO: Implement emulation of D16MOVN instruction. */
24826 MIPS_INVAL("OPC_MXU_D16MOVN");
24827 generate_exception_end(ctx, EXCP_RI);
24828 break;
24829 case OPC_MXU_S32MOVZ:
24830 /* TODO: Implement emulation of S32MOVZ instruction. */
24831 MIPS_INVAL("OPC_MXU_S32MOVZ");
24832 generate_exception_end(ctx, EXCP_RI);
24833 break;
24834 case OPC_MXU_S32MOVN:
24835 /* TODO: Implement emulation of S32MOVN instruction. */
24836 MIPS_INVAL("OPC_MXU_S32MOVN");
24837 generate_exception_end(ctx, EXCP_RI);
24838 break;
24839 default:
24840 MIPS_INVAL("decode_opc_mxu");
24841 generate_exception_end(ctx, EXCP_RI);
24842 break;
24848 * Decode MXU pool20
24850 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24851 * +-----------+---+---+-------+-------+-------+-------+-----------+
24852 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL20|
24853 * +-----------+---+---+-------+-------+-------+-------+-----------+
24856 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
24858 uint32_t opcode = extract32(ctx->opcode, 22, 2);
24860 switch (opcode) {
24861 case OPC_MXU_Q8MAC:
24862 /* TODO: Implement emulation of Q8MAC instruction. */
24863 MIPS_INVAL("OPC_MXU_Q8MAC");
24864 generate_exception_end(ctx, EXCP_RI);
24865 break;
24866 case OPC_MXU_Q8MACSU:
24867 /* TODO: Implement emulation of Q8MACSU instruction. */
24868 MIPS_INVAL("OPC_MXU_Q8MACSU");
24869 generate_exception_end(ctx, EXCP_RI);
24870 break;
24871 default:
24872 MIPS_INVAL("decode_opc_mxu");
24873 generate_exception_end(ctx, EXCP_RI);
24874 break;
24880 * Main MXU decoding function
24882 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24883 * +-----------+---------------------------------------+-----------+
24884 * | SPECIAL2 | |x x x x x x|
24885 * +-----------+---------------------------------------+-----------+
24888 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
24890 uint32_t opcode = extract32(ctx->opcode, 0, 6);
24892 switch (opcode) {
24893 case OPC_MXU_S32MADD:
24894 /* TODO: Implement emulation of S32MADD instruction. */
24895 MIPS_INVAL("OPC_MXU_S32MADD");
24896 generate_exception_end(ctx, EXCP_RI);
24897 break;
24898 case OPC_MXU_S32MADDU:
24899 /* TODO: Implement emulation of S32MADDU instruction. */
24900 MIPS_INVAL("OPC_MXU_S32MADDU");
24901 generate_exception_end(ctx, EXCP_RI);
24902 break;
24903 case OPC_MXU__POOL00:
24904 decode_opc_mxu__pool00(env, ctx);
24905 break;
24906 case OPC_MXU_S32MSUB:
24907 /* TODO: Implement emulation of S32MSUB instruction. */
24908 MIPS_INVAL("OPC_MXU_S32MSUB");
24909 generate_exception_end(ctx, EXCP_RI);
24910 break;
24911 case OPC_MXU_S32MSUBU:
24912 /* TODO: Implement emulation of S32MSUBU instruction. */
24913 MIPS_INVAL("OPC_MXU_S32MSUBU");
24914 generate_exception_end(ctx, EXCP_RI);
24915 break;
24916 case OPC_MXU__POOL01:
24917 decode_opc_mxu__pool01(env, ctx);
24918 break;
24919 case OPC_MXU__POOL02:
24920 decode_opc_mxu__pool02(env, ctx);
24921 break;
24922 case OPC_MXU_D16MUL:
24923 /* TODO: Implement emulation of D16MUL instruction. */
24924 MIPS_INVAL("OPC_MXU_D16MUL");
24925 generate_exception_end(ctx, EXCP_RI);
24926 break;
24927 case OPC_MXU__POOL03:
24928 decode_opc_mxu__pool03(env, ctx);
24929 break;
24930 case OPC_MXU_D16MAC:
24931 /* TODO: Implement emulation of D16MAC instruction. */
24932 MIPS_INVAL("OPC_MXU_D16MAC");
24933 generate_exception_end(ctx, EXCP_RI);
24934 break;
24935 case OPC_MXU_D16MACF:
24936 /* TODO: Implement emulation of D16MACF instruction. */
24937 MIPS_INVAL("OPC_MXU_D16MACF");
24938 generate_exception_end(ctx, EXCP_RI);
24939 break;
24940 case OPC_MXU_D16MADL:
24941 /* TODO: Implement emulation of D16MADL instruction. */
24942 MIPS_INVAL("OPC_MXU_D16MADL");
24943 generate_exception_end(ctx, EXCP_RI);
24944 break;
24945 case OPC_MXU_S16MAD:
24946 /* TODO: Implement emulation of S16MAD instruction. */
24947 MIPS_INVAL("OPC_MXU_S16MAD");
24948 generate_exception_end(ctx, EXCP_RI);
24949 break;
24950 case OPC_MXU_Q16ADD:
24951 /* TODO: Implement emulation of Q16ADD instruction. */
24952 MIPS_INVAL("OPC_MXU_Q16ADD");
24953 generate_exception_end(ctx, EXCP_RI);
24954 break;
24955 case OPC_MXU_D16MACE:
24956 /* TODO: Implement emulation of D16MACE instruction. */
24957 MIPS_INVAL("OPC_MXU_D16MACE");
24958 generate_exception_end(ctx, EXCP_RI);
24959 break;
24960 case OPC_MXU__POOL04:
24961 decode_opc_mxu__pool04(env, ctx);
24962 break;
24963 case OPC_MXU__POOL05:
24964 decode_opc_mxu__pool05(env, ctx);
24965 break;
24966 case OPC_MXU__POOL06:
24967 decode_opc_mxu__pool06(env, ctx);
24968 break;
24969 case OPC_MXU__POOL07:
24970 decode_opc_mxu__pool07(env, ctx);
24971 break;
24972 case OPC_MXU__POOL08:
24973 decode_opc_mxu__pool08(env, ctx);
24974 break;
24975 case OPC_MXU__POOL09:
24976 decode_opc_mxu__pool09(env, ctx);
24977 break;
24978 case OPC_MXU__POOL10:
24979 decode_opc_mxu__pool10(env, ctx);
24980 break;
24981 case OPC_MXU__POOL11:
24982 decode_opc_mxu__pool11(env, ctx);
24983 break;
24984 case OPC_MXU_D32ADD:
24985 /* TODO: Implement emulation of D32ADD instruction. */
24986 MIPS_INVAL("OPC_MXU_D32ADD");
24987 generate_exception_end(ctx, EXCP_RI);
24988 break;
24989 case OPC_MXU__POOL12:
24990 decode_opc_mxu__pool12(env, ctx);
24991 break;
24992 case OPC_MXU__POOL13:
24993 decode_opc_mxu__pool13(env, ctx);
24994 break;
24995 case OPC_MXU__POOL14:
24996 decode_opc_mxu__pool14(env, ctx);
24997 break;
24998 case OPC_MXU_Q8ACCE:
24999 /* TODO: Implement emulation of Q8ACCE instruction. */
25000 MIPS_INVAL("OPC_MXU_Q8ACCE");
25001 generate_exception_end(ctx, EXCP_RI);
25002 break;
25003 case OPC_MXU_S8LDD:
25004 /* TODO: Implement emulation of S8LDD instruction. */
25005 MIPS_INVAL("OPC_MXU_S8LDD");
25006 generate_exception_end(ctx, EXCP_RI);
25007 break;
25008 case OPC_MXU_S8STD:
25009 /* TODO: Implement emulation of S8STD instruction. */
25010 MIPS_INVAL("OPC_MXU_S8STD");
25011 generate_exception_end(ctx, EXCP_RI);
25012 break;
25013 case OPC_MXU_S8LDI:
25014 /* TODO: Implement emulation of S8LDI instruction. */
25015 MIPS_INVAL("OPC_MXU_S8LDI");
25016 generate_exception_end(ctx, EXCP_RI);
25017 break;
25018 case OPC_MXU_S8SDI:
25019 /* TODO: Implement emulation of S8SDI instruction. */
25020 MIPS_INVAL("OPC_MXU_S8SDI");
25021 generate_exception_end(ctx, EXCP_RI);
25022 break;
25023 case OPC_MXU__POOL15:
25024 decode_opc_mxu__pool15(env, ctx);
25025 break;
25026 case OPC_MXU__POOL16:
25027 decode_opc_mxu__pool16(env, ctx);
25028 break;
25029 case OPC_MXU_LXB:
25030 /* TODO: Implement emulation of LXB instruction. */
25031 MIPS_INVAL("OPC_MXU_LXB");
25032 generate_exception_end(ctx, EXCP_RI);
25033 break;
25034 case OPC_MXU_S16LDD:
25035 /* TODO: Implement emulation of S16LDD instruction. */
25036 MIPS_INVAL("OPC_MXU_S16LDD");
25037 generate_exception_end(ctx, EXCP_RI);
25038 break;
25039 case OPC_MXU_S16STD:
25040 /* TODO: Implement emulation of S16STD instruction. */
25041 MIPS_INVAL("OPC_MXU_S16STD");
25042 generate_exception_end(ctx, EXCP_RI);
25043 break;
25044 case OPC_MXU_S16LDI:
25045 /* TODO: Implement emulation of S16LDI instruction. */
25046 MIPS_INVAL("OPC_MXU_S16LDI");
25047 generate_exception_end(ctx, EXCP_RI);
25048 break;
25049 case OPC_MXU_S16SDI:
25050 /* TODO: Implement emulation of S16SDI instruction. */
25051 MIPS_INVAL("OPC_MXU_S16SDI");
25052 generate_exception_end(ctx, EXCP_RI);
25053 break;
25054 case OPC_MXU_S32M2I:
25055 /* TODO: Implement emulation of S32M2I instruction. */
25056 MIPS_INVAL("OPC_MXU_S32M2I");
25057 generate_exception_end(ctx, EXCP_RI);
25058 break;
25059 case OPC_MXU_S32I2M:
25060 /* TODO: Implement emulation of S32I2M instruction. */
25061 MIPS_INVAL("OPC_MXU_S32I2M");
25062 generate_exception_end(ctx, EXCP_RI);
25063 break;
25064 case OPC_MXU_D32SLL:
25065 /* TODO: Implement emulation of D32SLL instruction. */
25066 MIPS_INVAL("OPC_MXU_D32SLL");
25067 generate_exception_end(ctx, EXCP_RI);
25068 break;
25069 case OPC_MXU_D32SLR:
25070 /* TODO: Implement emulation of D32SLR instruction. */
25071 MIPS_INVAL("OPC_MXU_D32SLR");
25072 generate_exception_end(ctx, EXCP_RI);
25073 break;
25074 case OPC_MXU_D32SARL:
25075 /* TODO: Implement emulation of D32SARL instruction. */
25076 MIPS_INVAL("OPC_MXU_D32SARL");
25077 generate_exception_end(ctx, EXCP_RI);
25078 break;
25079 case OPC_MXU_D32SAR:
25080 /* TODO: Implement emulation of D32SAR instruction. */
25081 MIPS_INVAL("OPC_MXU_D32SAR");
25082 generate_exception_end(ctx, EXCP_RI);
25083 break;
25084 case OPC_MXU_Q16SLL:
25085 /* TODO: Implement emulation of Q16SLL instruction. */
25086 MIPS_INVAL("OPC_MXU_Q16SLL");
25087 generate_exception_end(ctx, EXCP_RI);
25088 break;
25089 case OPC_MXU_Q16SLR:
25090 /* TODO: Implement emulation of Q16SLR instruction. */
25091 MIPS_INVAL("OPC_MXU_Q16SLR");
25092 generate_exception_end(ctx, EXCP_RI);
25093 break;
25094 case OPC_MXU__POOL17:
25095 decode_opc_mxu__pool17(env, ctx);
25096 break;
25097 case OPC_MXU_Q16SAR:
25098 /* TODO: Implement emulation of Q16SAR instruction. */
25099 MIPS_INVAL("OPC_MXU_Q16SAR");
25100 generate_exception_end(ctx, EXCP_RI);
25101 break;
25102 case OPC_MXU__POOL18:
25103 decode_opc_mxu__pool18(env, ctx);
25104 break;
25105 case OPC_MXU__POOL19:
25106 decode_opc_mxu__pool19(env, ctx);
25107 break;
25108 case OPC_MXU__POOL20:
25109 decode_opc_mxu__pool20(env, ctx);
25110 break;
25111 case OPC_MXU_Q16SCOP:
25112 /* TODO: Implement emulation of Q16SCOP instruction. */
25113 MIPS_INVAL("OPC_MXU_Q16SCOP");
25114 generate_exception_end(ctx, EXCP_RI);
25115 break;
25116 case OPC_MXU_Q8MADL:
25117 /* TODO: Implement emulation of Q8MADL instruction. */
25118 MIPS_INVAL("OPC_MXU_Q8MADL");
25119 generate_exception_end(ctx, EXCP_RI);
25120 break;
25121 case OPC_MXU_S32SFL:
25122 /* TODO: Implement emulation of S32SFL instruction. */
25123 MIPS_INVAL("OPC_MXU_S32SFL");
25124 generate_exception_end(ctx, EXCP_RI);
25125 break;
25126 case OPC_MXU_Q8SAD:
25127 /* TODO: Implement emulation of Q8SAD instruction. */
25128 MIPS_INVAL("OPC_MXU_Q8SAD");
25129 generate_exception_end(ctx, EXCP_RI);
25130 break;
25131 default:
25132 MIPS_INVAL("decode_opc_mxu");
25133 generate_exception_end(ctx, EXCP_RI);
25138 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
25140 int rs, rt, rd;
25141 uint32_t op1;
25143 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25145 rs = (ctx->opcode >> 21) & 0x1f;
25146 rt = (ctx->opcode >> 16) & 0x1f;
25147 rd = (ctx->opcode >> 11) & 0x1f;
25149 op1 = MASK_SPECIAL2(ctx->opcode);
25150 switch (op1) {
25151 case OPC_MADD: /* Multiply and add/sub */
25152 case OPC_MADDU:
25153 case OPC_MSUB:
25154 case OPC_MSUBU:
25155 check_insn(ctx, ISA_MIPS32);
25156 gen_muldiv(ctx, op1, rd & 3, rs, rt);
25157 break;
25158 case OPC_MUL:
25159 gen_arith(ctx, op1, rd, rs, rt);
25160 break;
25161 case OPC_DIV_G_2F:
25162 case OPC_DIVU_G_2F:
25163 case OPC_MULT_G_2F:
25164 case OPC_MULTU_G_2F:
25165 case OPC_MOD_G_2F:
25166 case OPC_MODU_G_2F:
25167 check_insn(ctx, INSN_LOONGSON2F);
25168 gen_loongson_integer(ctx, op1, rd, rs, rt);
25169 break;
25170 case OPC_CLO:
25171 case OPC_CLZ:
25172 check_insn(ctx, ISA_MIPS32);
25173 gen_cl(ctx, op1, rd, rs);
25174 break;
25175 case OPC_SDBBP:
25176 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
25177 gen_helper_do_semihosting(cpu_env);
25178 } else {
25179 /* XXX: not clear which exception should be raised
25180 * when in debug mode...
25182 check_insn(ctx, ISA_MIPS32);
25183 generate_exception_end(ctx, EXCP_DBp);
25185 break;
25186 #if defined(TARGET_MIPS64)
25187 case OPC_DCLO:
25188 case OPC_DCLZ:
25189 check_insn(ctx, ISA_MIPS64);
25190 check_mips_64(ctx);
25191 gen_cl(ctx, op1, rd, rs);
25192 break;
25193 case OPC_DMULT_G_2F:
25194 case OPC_DMULTU_G_2F:
25195 case OPC_DDIV_G_2F:
25196 case OPC_DDIVU_G_2F:
25197 case OPC_DMOD_G_2F:
25198 case OPC_DMODU_G_2F:
25199 check_insn(ctx, INSN_LOONGSON2F);
25200 gen_loongson_integer(ctx, op1, rd, rs, rt);
25201 break;
25202 #endif
25203 default: /* Invalid */
25204 MIPS_INVAL("special2_legacy");
25205 generate_exception_end(ctx, EXCP_RI);
25206 break;
25210 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
25212 int rs, rt, rd, sa;
25213 uint32_t op1, op2;
25214 int16_t imm;
25216 rs = (ctx->opcode >> 21) & 0x1f;
25217 rt = (ctx->opcode >> 16) & 0x1f;
25218 rd = (ctx->opcode >> 11) & 0x1f;
25219 sa = (ctx->opcode >> 6) & 0x1f;
25220 imm = (int16_t)ctx->opcode >> 7;
25222 op1 = MASK_SPECIAL3(ctx->opcode);
25223 switch (op1) {
25224 case R6_OPC_PREF:
25225 if (rt >= 24) {
25226 /* hint codes 24-31 are reserved and signal RI */
25227 generate_exception_end(ctx, EXCP_RI);
25229 /* Treat as NOP. */
25230 break;
25231 case R6_OPC_CACHE:
25232 check_cp0_enabled(ctx);
25233 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25234 gen_cache_operation(ctx, rt, rs, imm);
25236 break;
25237 case R6_OPC_SC:
25238 gen_st_cond(ctx, op1, rt, rs, imm);
25239 break;
25240 case R6_OPC_LL:
25241 gen_ld(ctx, op1, rt, rs, imm);
25242 break;
25243 case OPC_BSHFL:
25245 if (rd == 0) {
25246 /* Treat as NOP. */
25247 break;
25249 op2 = MASK_BSHFL(ctx->opcode);
25250 switch (op2) {
25251 case OPC_ALIGN:
25252 case OPC_ALIGN_1:
25253 case OPC_ALIGN_2:
25254 case OPC_ALIGN_3:
25255 gen_align(ctx, 32, rd, rs, rt, sa & 3);
25256 break;
25257 case OPC_BITSWAP:
25258 gen_bitswap(ctx, op2, rd, rt);
25259 break;
25262 break;
25263 #if defined(TARGET_MIPS64)
25264 case R6_OPC_SCD:
25265 gen_st_cond(ctx, op1, rt, rs, imm);
25266 break;
25267 case R6_OPC_LLD:
25268 gen_ld(ctx, op1, rt, rs, imm);
25269 break;
25270 case OPC_DBSHFL:
25271 check_mips_64(ctx);
25273 if (rd == 0) {
25274 /* Treat as NOP. */
25275 break;
25277 op2 = MASK_DBSHFL(ctx->opcode);
25278 switch (op2) {
25279 case OPC_DALIGN:
25280 case OPC_DALIGN_1:
25281 case OPC_DALIGN_2:
25282 case OPC_DALIGN_3:
25283 case OPC_DALIGN_4:
25284 case OPC_DALIGN_5:
25285 case OPC_DALIGN_6:
25286 case OPC_DALIGN_7:
25287 gen_align(ctx, 64, rd, rs, rt, sa & 7);
25288 break;
25289 case OPC_DBITSWAP:
25290 gen_bitswap(ctx, op2, rd, rt);
25291 break;
25295 break;
25296 #endif
25297 default: /* Invalid */
25298 MIPS_INVAL("special3_r6");
25299 generate_exception_end(ctx, EXCP_RI);
25300 break;
25304 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
25306 int rs, rt, rd;
25307 uint32_t op1, op2;
25309 rs = (ctx->opcode >> 21) & 0x1f;
25310 rt = (ctx->opcode >> 16) & 0x1f;
25311 rd = (ctx->opcode >> 11) & 0x1f;
25313 op1 = MASK_SPECIAL3(ctx->opcode);
25314 switch (op1) {
25315 case OPC_DIV_G_2E:
25316 case OPC_DIVU_G_2E:
25317 case OPC_MOD_G_2E:
25318 case OPC_MODU_G_2E:
25319 case OPC_MULT_G_2E:
25320 case OPC_MULTU_G_2E:
25321 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
25322 * the same mask and op1. */
25323 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
25324 op2 = MASK_ADDUH_QB(ctx->opcode);
25325 switch (op2) {
25326 case OPC_ADDUH_QB:
25327 case OPC_ADDUH_R_QB:
25328 case OPC_ADDQH_PH:
25329 case OPC_ADDQH_R_PH:
25330 case OPC_ADDQH_W:
25331 case OPC_ADDQH_R_W:
25332 case OPC_SUBUH_QB:
25333 case OPC_SUBUH_R_QB:
25334 case OPC_SUBQH_PH:
25335 case OPC_SUBQH_R_PH:
25336 case OPC_SUBQH_W:
25337 case OPC_SUBQH_R_W:
25338 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25339 break;
25340 case OPC_MUL_PH:
25341 case OPC_MUL_S_PH:
25342 case OPC_MULQ_S_W:
25343 case OPC_MULQ_RS_W:
25344 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
25345 break;
25346 default:
25347 MIPS_INVAL("MASK ADDUH.QB");
25348 generate_exception_end(ctx, EXCP_RI);
25349 break;
25351 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
25352 gen_loongson_integer(ctx, op1, rd, rs, rt);
25353 } else {
25354 generate_exception_end(ctx, EXCP_RI);
25356 break;
25357 case OPC_LX_DSP:
25358 op2 = MASK_LX(ctx->opcode);
25359 switch (op2) {
25360 #if defined(TARGET_MIPS64)
25361 case OPC_LDX:
25362 #endif
25363 case OPC_LBUX:
25364 case OPC_LHX:
25365 case OPC_LWX:
25366 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
25367 break;
25368 default: /* Invalid */
25369 MIPS_INVAL("MASK LX");
25370 generate_exception_end(ctx, EXCP_RI);
25371 break;
25373 break;
25374 case OPC_ABSQ_S_PH_DSP:
25375 op2 = MASK_ABSQ_S_PH(ctx->opcode);
25376 switch (op2) {
25377 case OPC_ABSQ_S_QB:
25378 case OPC_ABSQ_S_PH:
25379 case OPC_ABSQ_S_W:
25380 case OPC_PRECEQ_W_PHL:
25381 case OPC_PRECEQ_W_PHR:
25382 case OPC_PRECEQU_PH_QBL:
25383 case OPC_PRECEQU_PH_QBR:
25384 case OPC_PRECEQU_PH_QBLA:
25385 case OPC_PRECEQU_PH_QBRA:
25386 case OPC_PRECEU_PH_QBL:
25387 case OPC_PRECEU_PH_QBR:
25388 case OPC_PRECEU_PH_QBLA:
25389 case OPC_PRECEU_PH_QBRA:
25390 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25391 break;
25392 case OPC_BITREV:
25393 case OPC_REPL_QB:
25394 case OPC_REPLV_QB:
25395 case OPC_REPL_PH:
25396 case OPC_REPLV_PH:
25397 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
25398 break;
25399 default:
25400 MIPS_INVAL("MASK ABSQ_S.PH");
25401 generate_exception_end(ctx, EXCP_RI);
25402 break;
25404 break;
25405 case OPC_ADDU_QB_DSP:
25406 op2 = MASK_ADDU_QB(ctx->opcode);
25407 switch (op2) {
25408 case OPC_ADDQ_PH:
25409 case OPC_ADDQ_S_PH:
25410 case OPC_ADDQ_S_W:
25411 case OPC_ADDU_QB:
25412 case OPC_ADDU_S_QB:
25413 case OPC_ADDU_PH:
25414 case OPC_ADDU_S_PH:
25415 case OPC_SUBQ_PH:
25416 case OPC_SUBQ_S_PH:
25417 case OPC_SUBQ_S_W:
25418 case OPC_SUBU_QB:
25419 case OPC_SUBU_S_QB:
25420 case OPC_SUBU_PH:
25421 case OPC_SUBU_S_PH:
25422 case OPC_ADDSC:
25423 case OPC_ADDWC:
25424 case OPC_MODSUB:
25425 case OPC_RADDU_W_QB:
25426 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25427 break;
25428 case OPC_MULEU_S_PH_QBL:
25429 case OPC_MULEU_S_PH_QBR:
25430 case OPC_MULQ_RS_PH:
25431 case OPC_MULEQ_S_W_PHL:
25432 case OPC_MULEQ_S_W_PHR:
25433 case OPC_MULQ_S_PH:
25434 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
25435 break;
25436 default: /* Invalid */
25437 MIPS_INVAL("MASK ADDU.QB");
25438 generate_exception_end(ctx, EXCP_RI);
25439 break;
25442 break;
25443 case OPC_CMPU_EQ_QB_DSP:
25444 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
25445 switch (op2) {
25446 case OPC_PRECR_SRA_PH_W:
25447 case OPC_PRECR_SRA_R_PH_W:
25448 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
25449 break;
25450 case OPC_PRECR_QB_PH:
25451 case OPC_PRECRQ_QB_PH:
25452 case OPC_PRECRQ_PH_W:
25453 case OPC_PRECRQ_RS_PH_W:
25454 case OPC_PRECRQU_S_QB_PH:
25455 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25456 break;
25457 case OPC_CMPU_EQ_QB:
25458 case OPC_CMPU_LT_QB:
25459 case OPC_CMPU_LE_QB:
25460 case OPC_CMP_EQ_PH:
25461 case OPC_CMP_LT_PH:
25462 case OPC_CMP_LE_PH:
25463 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
25464 break;
25465 case OPC_CMPGU_EQ_QB:
25466 case OPC_CMPGU_LT_QB:
25467 case OPC_CMPGU_LE_QB:
25468 case OPC_CMPGDU_EQ_QB:
25469 case OPC_CMPGDU_LT_QB:
25470 case OPC_CMPGDU_LE_QB:
25471 case OPC_PICK_QB:
25472 case OPC_PICK_PH:
25473 case OPC_PACKRL_PH:
25474 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
25475 break;
25476 default: /* Invalid */
25477 MIPS_INVAL("MASK CMPU.EQ.QB");
25478 generate_exception_end(ctx, EXCP_RI);
25479 break;
25481 break;
25482 case OPC_SHLL_QB_DSP:
25483 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
25484 break;
25485 case OPC_DPA_W_PH_DSP:
25486 op2 = MASK_DPA_W_PH(ctx->opcode);
25487 switch (op2) {
25488 case OPC_DPAU_H_QBL:
25489 case OPC_DPAU_H_QBR:
25490 case OPC_DPSU_H_QBL:
25491 case OPC_DPSU_H_QBR:
25492 case OPC_DPA_W_PH:
25493 case OPC_DPAX_W_PH:
25494 case OPC_DPAQ_S_W_PH:
25495 case OPC_DPAQX_S_W_PH:
25496 case OPC_DPAQX_SA_W_PH:
25497 case OPC_DPS_W_PH:
25498 case OPC_DPSX_W_PH:
25499 case OPC_DPSQ_S_W_PH:
25500 case OPC_DPSQX_S_W_PH:
25501 case OPC_DPSQX_SA_W_PH:
25502 case OPC_MULSAQ_S_W_PH:
25503 case OPC_DPAQ_SA_L_W:
25504 case OPC_DPSQ_SA_L_W:
25505 case OPC_MAQ_S_W_PHL:
25506 case OPC_MAQ_S_W_PHR:
25507 case OPC_MAQ_SA_W_PHL:
25508 case OPC_MAQ_SA_W_PHR:
25509 case OPC_MULSA_W_PH:
25510 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
25511 break;
25512 default: /* Invalid */
25513 MIPS_INVAL("MASK DPAW.PH");
25514 generate_exception_end(ctx, EXCP_RI);
25515 break;
25517 break;
25518 case OPC_INSV_DSP:
25519 op2 = MASK_INSV(ctx->opcode);
25520 switch (op2) {
25521 case OPC_INSV:
25522 check_dsp(ctx);
25524 TCGv t0, t1;
25526 if (rt == 0) {
25527 break;
25530 t0 = tcg_temp_new();
25531 t1 = tcg_temp_new();
25533 gen_load_gpr(t0, rt);
25534 gen_load_gpr(t1, rs);
25536 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
25538 tcg_temp_free(t0);
25539 tcg_temp_free(t1);
25540 break;
25542 default: /* Invalid */
25543 MIPS_INVAL("MASK INSV");
25544 generate_exception_end(ctx, EXCP_RI);
25545 break;
25547 break;
25548 case OPC_APPEND_DSP:
25549 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
25550 break;
25551 case OPC_EXTR_W_DSP:
25552 op2 = MASK_EXTR_W(ctx->opcode);
25553 switch (op2) {
25554 case OPC_EXTR_W:
25555 case OPC_EXTR_R_W:
25556 case OPC_EXTR_RS_W:
25557 case OPC_EXTR_S_H:
25558 case OPC_EXTRV_S_H:
25559 case OPC_EXTRV_W:
25560 case OPC_EXTRV_R_W:
25561 case OPC_EXTRV_RS_W:
25562 case OPC_EXTP:
25563 case OPC_EXTPV:
25564 case OPC_EXTPDP:
25565 case OPC_EXTPDPV:
25566 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
25567 break;
25568 case OPC_RDDSP:
25569 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
25570 break;
25571 case OPC_SHILO:
25572 case OPC_SHILOV:
25573 case OPC_MTHLIP:
25574 case OPC_WRDSP:
25575 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
25576 break;
25577 default: /* Invalid */
25578 MIPS_INVAL("MASK EXTR.W");
25579 generate_exception_end(ctx, EXCP_RI);
25580 break;
25582 break;
25583 #if defined(TARGET_MIPS64)
25584 case OPC_DDIV_G_2E:
25585 case OPC_DDIVU_G_2E:
25586 case OPC_DMULT_G_2E:
25587 case OPC_DMULTU_G_2E:
25588 case OPC_DMOD_G_2E:
25589 case OPC_DMODU_G_2E:
25590 check_insn(ctx, INSN_LOONGSON2E);
25591 gen_loongson_integer(ctx, op1, rd, rs, rt);
25592 break;
25593 case OPC_ABSQ_S_QH_DSP:
25594 op2 = MASK_ABSQ_S_QH(ctx->opcode);
25595 switch (op2) {
25596 case OPC_PRECEQ_L_PWL:
25597 case OPC_PRECEQ_L_PWR:
25598 case OPC_PRECEQ_PW_QHL:
25599 case OPC_PRECEQ_PW_QHR:
25600 case OPC_PRECEQ_PW_QHLA:
25601 case OPC_PRECEQ_PW_QHRA:
25602 case OPC_PRECEQU_QH_OBL:
25603 case OPC_PRECEQU_QH_OBR:
25604 case OPC_PRECEQU_QH_OBLA:
25605 case OPC_PRECEQU_QH_OBRA:
25606 case OPC_PRECEU_QH_OBL:
25607 case OPC_PRECEU_QH_OBR:
25608 case OPC_PRECEU_QH_OBLA:
25609 case OPC_PRECEU_QH_OBRA:
25610 case OPC_ABSQ_S_OB:
25611 case OPC_ABSQ_S_PW:
25612 case OPC_ABSQ_S_QH:
25613 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25614 break;
25615 case OPC_REPL_OB:
25616 case OPC_REPL_PW:
25617 case OPC_REPL_QH:
25618 case OPC_REPLV_OB:
25619 case OPC_REPLV_PW:
25620 case OPC_REPLV_QH:
25621 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
25622 break;
25623 default: /* Invalid */
25624 MIPS_INVAL("MASK ABSQ_S.QH");
25625 generate_exception_end(ctx, EXCP_RI);
25626 break;
25628 break;
25629 case OPC_ADDU_OB_DSP:
25630 op2 = MASK_ADDU_OB(ctx->opcode);
25631 switch (op2) {
25632 case OPC_RADDU_L_OB:
25633 case OPC_SUBQ_PW:
25634 case OPC_SUBQ_S_PW:
25635 case OPC_SUBQ_QH:
25636 case OPC_SUBQ_S_QH:
25637 case OPC_SUBU_OB:
25638 case OPC_SUBU_S_OB:
25639 case OPC_SUBU_QH:
25640 case OPC_SUBU_S_QH:
25641 case OPC_SUBUH_OB:
25642 case OPC_SUBUH_R_OB:
25643 case OPC_ADDQ_PW:
25644 case OPC_ADDQ_S_PW:
25645 case OPC_ADDQ_QH:
25646 case OPC_ADDQ_S_QH:
25647 case OPC_ADDU_OB:
25648 case OPC_ADDU_S_OB:
25649 case OPC_ADDU_QH:
25650 case OPC_ADDU_S_QH:
25651 case OPC_ADDUH_OB:
25652 case OPC_ADDUH_R_OB:
25653 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25654 break;
25655 case OPC_MULEQ_S_PW_QHL:
25656 case OPC_MULEQ_S_PW_QHR:
25657 case OPC_MULEU_S_QH_OBL:
25658 case OPC_MULEU_S_QH_OBR:
25659 case OPC_MULQ_RS_QH:
25660 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
25661 break;
25662 default: /* Invalid */
25663 MIPS_INVAL("MASK ADDU.OB");
25664 generate_exception_end(ctx, EXCP_RI);
25665 break;
25667 break;
25668 case OPC_CMPU_EQ_OB_DSP:
25669 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
25670 switch (op2) {
25671 case OPC_PRECR_SRA_QH_PW:
25672 case OPC_PRECR_SRA_R_QH_PW:
25673 /* Return value is rt. */
25674 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
25675 break;
25676 case OPC_PRECR_OB_QH:
25677 case OPC_PRECRQ_OB_QH:
25678 case OPC_PRECRQ_PW_L:
25679 case OPC_PRECRQ_QH_PW:
25680 case OPC_PRECRQ_RS_QH_PW:
25681 case OPC_PRECRQU_S_OB_QH:
25682 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25683 break;
25684 case OPC_CMPU_EQ_OB:
25685 case OPC_CMPU_LT_OB:
25686 case OPC_CMPU_LE_OB:
25687 case OPC_CMP_EQ_QH:
25688 case OPC_CMP_LT_QH:
25689 case OPC_CMP_LE_QH:
25690 case OPC_CMP_EQ_PW:
25691 case OPC_CMP_LT_PW:
25692 case OPC_CMP_LE_PW:
25693 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
25694 break;
25695 case OPC_CMPGDU_EQ_OB:
25696 case OPC_CMPGDU_LT_OB:
25697 case OPC_CMPGDU_LE_OB:
25698 case OPC_CMPGU_EQ_OB:
25699 case OPC_CMPGU_LT_OB:
25700 case OPC_CMPGU_LE_OB:
25701 case OPC_PACKRL_PW:
25702 case OPC_PICK_OB:
25703 case OPC_PICK_PW:
25704 case OPC_PICK_QH:
25705 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
25706 break;
25707 default: /* Invalid */
25708 MIPS_INVAL("MASK CMPU_EQ.OB");
25709 generate_exception_end(ctx, EXCP_RI);
25710 break;
25712 break;
25713 case OPC_DAPPEND_DSP:
25714 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
25715 break;
25716 case OPC_DEXTR_W_DSP:
25717 op2 = MASK_DEXTR_W(ctx->opcode);
25718 switch (op2) {
25719 case OPC_DEXTP:
25720 case OPC_DEXTPDP:
25721 case OPC_DEXTPDPV:
25722 case OPC_DEXTPV:
25723 case OPC_DEXTR_L:
25724 case OPC_DEXTR_R_L:
25725 case OPC_DEXTR_RS_L:
25726 case OPC_DEXTR_W:
25727 case OPC_DEXTR_R_W:
25728 case OPC_DEXTR_RS_W:
25729 case OPC_DEXTR_S_H:
25730 case OPC_DEXTRV_L:
25731 case OPC_DEXTRV_R_L:
25732 case OPC_DEXTRV_RS_L:
25733 case OPC_DEXTRV_S_H:
25734 case OPC_DEXTRV_W:
25735 case OPC_DEXTRV_R_W:
25736 case OPC_DEXTRV_RS_W:
25737 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
25738 break;
25739 case OPC_DMTHLIP:
25740 case OPC_DSHILO:
25741 case OPC_DSHILOV:
25742 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
25743 break;
25744 default: /* Invalid */
25745 MIPS_INVAL("MASK EXTR.W");
25746 generate_exception_end(ctx, EXCP_RI);
25747 break;
25749 break;
25750 case OPC_DPAQ_W_QH_DSP:
25751 op2 = MASK_DPAQ_W_QH(ctx->opcode);
25752 switch (op2) {
25753 case OPC_DPAU_H_OBL:
25754 case OPC_DPAU_H_OBR:
25755 case OPC_DPSU_H_OBL:
25756 case OPC_DPSU_H_OBR:
25757 case OPC_DPA_W_QH:
25758 case OPC_DPAQ_S_W_QH:
25759 case OPC_DPS_W_QH:
25760 case OPC_DPSQ_S_W_QH:
25761 case OPC_MULSAQ_S_W_QH:
25762 case OPC_DPAQ_SA_L_PW:
25763 case OPC_DPSQ_SA_L_PW:
25764 case OPC_MULSAQ_S_L_PW:
25765 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
25766 break;
25767 case OPC_MAQ_S_W_QHLL:
25768 case OPC_MAQ_S_W_QHLR:
25769 case OPC_MAQ_S_W_QHRL:
25770 case OPC_MAQ_S_W_QHRR:
25771 case OPC_MAQ_SA_W_QHLL:
25772 case OPC_MAQ_SA_W_QHLR:
25773 case OPC_MAQ_SA_W_QHRL:
25774 case OPC_MAQ_SA_W_QHRR:
25775 case OPC_MAQ_S_L_PWL:
25776 case OPC_MAQ_S_L_PWR:
25777 case OPC_DMADD:
25778 case OPC_DMADDU:
25779 case OPC_DMSUB:
25780 case OPC_DMSUBU:
25781 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
25782 break;
25783 default: /* Invalid */
25784 MIPS_INVAL("MASK DPAQ.W.QH");
25785 generate_exception_end(ctx, EXCP_RI);
25786 break;
25788 break;
25789 case OPC_DINSV_DSP:
25790 op2 = MASK_INSV(ctx->opcode);
25791 switch (op2) {
25792 case OPC_DINSV:
25794 TCGv t0, t1;
25796 if (rt == 0) {
25797 break;
25799 check_dsp(ctx);
25801 t0 = tcg_temp_new();
25802 t1 = tcg_temp_new();
25804 gen_load_gpr(t0, rt);
25805 gen_load_gpr(t1, rs);
25807 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
25809 tcg_temp_free(t0);
25810 tcg_temp_free(t1);
25811 break;
25813 default: /* Invalid */
25814 MIPS_INVAL("MASK DINSV");
25815 generate_exception_end(ctx, EXCP_RI);
25816 break;
25818 break;
25819 case OPC_SHLL_OB_DSP:
25820 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
25821 break;
25822 #endif
25823 default: /* Invalid */
25824 MIPS_INVAL("special3_legacy");
25825 generate_exception_end(ctx, EXCP_RI);
25826 break;
25830 static void decode_tx79_mmi0(CPUMIPSState *env, DisasContext *ctx)
25832 uint32_t opc = MASK_TX79_MMI0(ctx->opcode);
25834 switch (opc) {
25835 case TX79_MMI0_PADDW: /* TODO: TX79_MMI0_PADDW */
25836 case TX79_MMI0_PSUBW: /* TODO: TX79_MMI0_PSUBW */
25837 case TX79_MMI0_PCGTW: /* TODO: TX79_MMI0_PCGTW */
25838 case TX79_MMI0_PMAXW: /* TODO: TX79_MMI0_PMAXW */
25839 case TX79_MMI0_PADDH: /* TODO: TX79_MMI0_PADDH */
25840 case TX79_MMI0_PSUBH: /* TODO: TX79_MMI0_PSUBH */
25841 case TX79_MMI0_PCGTH: /* TODO: TX79_MMI0_PCGTH */
25842 case TX79_MMI0_PMAXH: /* TODO: TX79_MMI0_PMAXH */
25843 case TX79_MMI0_PADDB: /* TODO: TX79_MMI0_PADDB */
25844 case TX79_MMI0_PSUBB: /* TODO: TX79_MMI0_PSUBB */
25845 case TX79_MMI0_PCGTB: /* TODO: TX79_MMI0_PCGTB */
25846 case TX79_MMI0_PADDSW: /* TODO: TX79_MMI0_PADDSW */
25847 case TX79_MMI0_PSUBSW: /* TODO: TX79_MMI0_PSUBSW */
25848 case TX79_MMI0_PEXTLW: /* TODO: TX79_MMI0_PEXTLW */
25849 case TX79_MMI0_PPACW: /* TODO: TX79_MMI0_PPACW */
25850 case TX79_MMI0_PADDSH: /* TODO: TX79_MMI0_PADDSH */
25851 case TX79_MMI0_PSUBSH: /* TODO: TX79_MMI0_PSUBSH */
25852 case TX79_MMI0_PEXTLH: /* TODO: TX79_MMI0_PEXTLH */
25853 case TX79_MMI0_PPACH: /* TODO: TX79_MMI0_PPACH */
25854 case TX79_MMI0_PADDSB: /* TODO: TX79_MMI0_PADDSB */
25855 case TX79_MMI0_PSUBSB: /* TODO: TX79_MMI0_PSUBSB */
25856 case TX79_MMI0_PEXTLB: /* TODO: TX79_MMI0_PEXTLB */
25857 case TX79_MMI0_PPACB: /* TODO: TX79_MMI0_PPACB */
25858 case TX79_MMI0_PEXT5: /* TODO: TX79_MMI0_PEXT5 */
25859 case TX79_MMI0_PPAC5: /* TODO: TX79_MMI0_PPAC5 */
25860 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI0 */
25861 break;
25862 default:
25863 MIPS_INVAL("TX79 MMI class MMI0");
25864 generate_exception_end(ctx, EXCP_RI);
25865 break;
25869 static void decode_tx79_mmi1(CPUMIPSState *env, DisasContext *ctx)
25871 uint32_t opc = MASK_TX79_MMI1(ctx->opcode);
25873 switch (opc) {
25874 case TX79_MMI1_PABSW: /* TODO: TX79_MMI1_PABSW */
25875 case TX79_MMI1_PCEQW: /* TODO: TX79_MMI1_PCEQW */
25876 case TX79_MMI1_PMINW: /* TODO: TX79_MMI1_PMINW */
25877 case TX79_MMI1_PADSBH: /* TODO: TX79_MMI1_PADSBH */
25878 case TX79_MMI1_PABSH: /* TODO: TX79_MMI1_PABSH */
25879 case TX79_MMI1_PCEQH: /* TODO: TX79_MMI1_PCEQH */
25880 case TX79_MMI1_PMINH: /* TODO: TX79_MMI1_PMINH */
25881 case TX79_MMI1_PCEQB: /* TODO: TX79_MMI1_PCEQB */
25882 case TX79_MMI1_PADDUW: /* TODO: TX79_MMI1_PADDUW */
25883 case TX79_MMI1_PSUBUW: /* TODO: TX79_MMI1_PSUBUW */
25884 case TX79_MMI1_PEXTUW: /* TODO: TX79_MMI1_PEXTUW */
25885 case TX79_MMI1_PADDUH: /* TODO: TX79_MMI1_PADDUH */
25886 case TX79_MMI1_PSUBUH: /* TODO: TX79_MMI1_PSUBUH */
25887 case TX79_MMI1_PEXTUH: /* TODO: TX79_MMI1_PEXTUH */
25888 case TX79_MMI1_PADDUB: /* TODO: TX79_MMI1_PADDUB */
25889 case TX79_MMI1_PSUBUB: /* TODO: TX79_MMI1_PSUBUB */
25890 case TX79_MMI1_PEXTUB: /* TODO: TX79_MMI1_PEXTUB */
25891 case TX79_MMI1_QFSRV: /* TODO: TX79_MMI1_QFSRV */
25892 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI1 */
25893 break;
25894 default:
25895 MIPS_INVAL("TX79 MMI class MMI1");
25896 generate_exception_end(ctx, EXCP_RI);
25897 break;
25901 static void decode_tx79_mmi2(CPUMIPSState *env, DisasContext *ctx)
25903 uint32_t opc = MASK_TX79_MMI2(ctx->opcode);
25905 switch (opc) {
25906 case TX79_MMI2_PMADDW: /* TODO: TX79_MMI2_PMADDW */
25907 case TX79_MMI2_PSLLVW: /* TODO: TX79_MMI2_PSLLVW */
25908 case TX79_MMI2_PSRLVW: /* TODO: TX79_MMI2_PSRLVW */
25909 case TX79_MMI2_PMSUBW: /* TODO: TX79_MMI2_PMSUBW */
25910 case TX79_MMI2_PMFHI: /* TODO: TX79_MMI2_PMFHI */
25911 case TX79_MMI2_PMFLO: /* TODO: TX79_MMI2_PMFLO */
25912 case TX79_MMI2_PINTH: /* TODO: TX79_MMI2_PINTH */
25913 case TX79_MMI2_PMULTW: /* TODO: TX79_MMI2_PMULTW */
25914 case TX79_MMI2_PDIVW: /* TODO: TX79_MMI2_PDIVW */
25915 case TX79_MMI2_PCPYLD: /* TODO: TX79_MMI2_PCPYLD */
25916 case TX79_MMI2_PMADDH: /* TODO: TX79_MMI2_PMADDH */
25917 case TX79_MMI2_PHMADH: /* TODO: TX79_MMI2_PHMADH */
25918 case TX79_MMI2_PAND: /* TODO: TX79_MMI2_PAND */
25919 case TX79_MMI2_PXOR: /* TODO: TX79_MMI2_PXOR */
25920 case TX79_MMI2_PMSUBH: /* TODO: TX79_MMI2_PMSUBH */
25921 case TX79_MMI2_PHMSBH: /* TODO: TX79_MMI2_PHMSBH */
25922 case TX79_MMI2_PEXEH: /* TODO: TX79_MMI2_PEXEH */
25923 case TX79_MMI2_PREVH: /* TODO: TX79_MMI2_PREVH */
25924 case TX79_MMI2_PMULTH: /* TODO: TX79_MMI2_PMULTH */
25925 case TX79_MMI2_PDIVBW: /* TODO: TX79_MMI2_PDIVBW */
25926 case TX79_MMI2_PEXEW: /* TODO: TX79_MMI2_PEXEW */
25927 case TX79_MMI2_PROT3W: /* TODO: TX79_MMI2_PROT3W */
25928 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI2 */
25929 break;
25930 default:
25931 MIPS_INVAL("TX79 MMI class MMI2");
25932 generate_exception_end(ctx, EXCP_RI);
25933 break;
25937 static void decode_tx79_mmi3(CPUMIPSState *env, DisasContext *ctx)
25939 uint32_t opc = MASK_TX79_MMI3(ctx->opcode);
25941 switch (opc) {
25942 case TX79_MMI3_PMADDUW: /* TODO: TX79_MMI3_PMADDUW */
25943 case TX79_MMI3_PSRAVW: /* TODO: TX79_MMI3_PSRAVW */
25944 case TX79_MMI3_PMTHI: /* TODO: TX79_MMI3_PMTHI */
25945 case TX79_MMI3_PMTLO: /* TODO: TX79_MMI3_PMTLO */
25946 case TX79_MMI3_PINTEH: /* TODO: TX79_MMI3_PINTEH */
25947 case TX79_MMI3_PMULTUW: /* TODO: TX79_MMI3_PMULTUW */
25948 case TX79_MMI3_PDIVUW: /* TODO: TX79_MMI3_PDIVUW */
25949 case TX79_MMI3_PCPYUD: /* TODO: TX79_MMI3_PCPYUD */
25950 case TX79_MMI3_POR: /* TODO: TX79_MMI3_POR */
25951 case TX79_MMI3_PNOR: /* TODO: TX79_MMI3_PNOR */
25952 case TX79_MMI3_PEXCH: /* TODO: TX79_MMI3_PEXCH */
25953 case TX79_MMI3_PCPYH: /* TODO: TX79_MMI3_PCPYH */
25954 case TX79_MMI3_PEXCW: /* TODO: TX79_MMI3_PEXCW */
25955 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI3 */
25956 break;
25957 default:
25958 MIPS_INVAL("TX79 MMI class MMI3");
25959 generate_exception_end(ctx, EXCP_RI);
25960 break;
25964 static void decode_tx79_mmi(CPUMIPSState *env, DisasContext *ctx)
25966 uint32_t opc = MASK_TX79_MMI(ctx->opcode);
25967 int rs = extract32(ctx->opcode, 21, 5);
25968 int rt = extract32(ctx->opcode, 16, 5);
25969 int rd = extract32(ctx->opcode, 11, 5);
25971 switch (opc) {
25972 case TX79_MMI_CLASS_MMI0:
25973 decode_tx79_mmi0(env, ctx);
25974 break;
25975 case TX79_MMI_CLASS_MMI1:
25976 decode_tx79_mmi1(env, ctx);
25977 break;
25978 case TX79_MMI_CLASS_MMI2:
25979 decode_tx79_mmi2(env, ctx);
25980 break;
25981 case TX79_MMI_CLASS_MMI3:
25982 decode_tx79_mmi3(env, ctx);
25983 break;
25984 case TX79_MMI_MULT1:
25985 case TX79_MMI_MULTU1:
25986 gen_mul_txx9(ctx, opc, rd, rs, rt);
25987 break;
25988 case TX79_MMI_DIV1:
25989 case TX79_MMI_DIVU1:
25990 gen_muldiv(ctx, opc, 1, rs, rt);
25991 break;
25992 case TX79_MMI_MTLO1:
25993 case TX79_MMI_MTHI1:
25994 gen_HILO(ctx, opc, 1, rs);
25995 break;
25996 case TX79_MMI_MFLO1:
25997 case TX79_MMI_MFHI1:
25998 gen_HILO(ctx, opc, 1, rd);
25999 break;
26000 case TX79_MMI_MADD: /* TODO: TX79_MMI_MADD */
26001 case TX79_MMI_MADDU: /* TODO: TX79_MMI_MADDU */
26002 case TX79_MMI_PLZCW: /* TODO: TX79_MMI_PLZCW */
26003 case TX79_MMI_MADD1: /* TODO: TX79_MMI_MADD1 */
26004 case TX79_MMI_MADDU1: /* TODO: TX79_MMI_MADDU1 */
26005 case TX79_MMI_PMFHL: /* TODO: TX79_MMI_PMFHL */
26006 case TX79_MMI_PMTHL: /* TODO: TX79_MMI_PMTHL */
26007 case TX79_MMI_PSLLH: /* TODO: TX79_MMI_PSLLH */
26008 case TX79_MMI_PSRLH: /* TODO: TX79_MMI_PSRLH */
26009 case TX79_MMI_PSRAH: /* TODO: TX79_MMI_PSRAH */
26010 case TX79_MMI_PSLLW: /* TODO: TX79_MMI_PSLLW */
26011 case TX79_MMI_PSRLW: /* TODO: TX79_MMI_PSRLW */
26012 case TX79_MMI_PSRAW: /* TODO: TX79_MMI_PSRAW */
26013 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_CLASS_MMI */
26014 break;
26015 default:
26016 MIPS_INVAL("TX79 MMI class");
26017 generate_exception_end(ctx, EXCP_RI);
26018 break;
26022 static void decode_tx79_lq(CPUMIPSState *env, DisasContext *ctx)
26024 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_LQ */
26027 static void gen_tx79_sq(DisasContext *ctx, int base, int rt, int offset)
26029 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_SQ */
26033 * The TX79-specific instruction Store Quadword
26035 * +--------+-------+-------+------------------------+
26036 * | 011111 | base | rt | offset | SQ
26037 * +--------+-------+-------+------------------------+
26038 * 6 5 5 16
26040 * has the same opcode as the Read Hardware Register instruction
26042 * +--------+-------+-------+-------+-------+--------+
26043 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
26044 * +--------+-------+-------+-------+-------+--------+
26045 * 6 5 5 5 5 6
26047 * that is required, trapped and emulated by the Linux kernel. However, all
26048 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
26049 * offset is odd. Therefore all valid SQ instructions can execute normally.
26050 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
26051 * between SQ and RDHWR, as the Linux kernel does.
26053 static void decode_tx79_sq(CPUMIPSState *env, DisasContext *ctx)
26055 int base = extract32(ctx->opcode, 21, 5);
26056 int rt = extract32(ctx->opcode, 16, 5);
26057 int offset = extract32(ctx->opcode, 0, 16);
26059 #ifdef CONFIG_USER_ONLY
26060 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
26061 uint32_t op2 = extract32(ctx->opcode, 6, 5);
26063 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
26064 int rd = extract32(ctx->opcode, 11, 5);
26066 gen_rdhwr(ctx, rt, rd, 0);
26067 return;
26069 #endif
26071 gen_tx79_sq(ctx, base, rt, offset);
26074 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
26076 int rs, rt, rd, sa;
26077 uint32_t op1, op2;
26078 int16_t imm;
26080 rs = (ctx->opcode >> 21) & 0x1f;
26081 rt = (ctx->opcode >> 16) & 0x1f;
26082 rd = (ctx->opcode >> 11) & 0x1f;
26083 sa = (ctx->opcode >> 6) & 0x1f;
26084 imm = sextract32(ctx->opcode, 7, 9);
26086 op1 = MASK_SPECIAL3(ctx->opcode);
26089 * EVA loads and stores overlap Loongson 2E instructions decoded by
26090 * decode_opc_special3_legacy(), so be careful to allow their decoding when
26091 * EVA is absent.
26093 if (ctx->eva) {
26094 switch (op1) {
26095 case OPC_LWLE:
26096 case OPC_LWRE:
26097 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26098 /* fall through */
26099 case OPC_LBUE:
26100 case OPC_LHUE:
26101 case OPC_LBE:
26102 case OPC_LHE:
26103 case OPC_LLE:
26104 case OPC_LWE:
26105 check_cp0_enabled(ctx);
26106 gen_ld(ctx, op1, rt, rs, imm);
26107 return;
26108 case OPC_SWLE:
26109 case OPC_SWRE:
26110 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26111 /* fall through */
26112 case OPC_SBE:
26113 case OPC_SHE:
26114 case OPC_SWE:
26115 check_cp0_enabled(ctx);
26116 gen_st(ctx, op1, rt, rs, imm);
26117 return;
26118 case OPC_SCE:
26119 check_cp0_enabled(ctx);
26120 gen_st_cond(ctx, op1, rt, rs, imm);
26121 return;
26122 case OPC_CACHEE:
26123 check_cp0_enabled(ctx);
26124 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26125 gen_cache_operation(ctx, rt, rs, imm);
26127 /* Treat as NOP. */
26128 return;
26129 case OPC_PREFE:
26130 check_cp0_enabled(ctx);
26131 /* Treat as NOP. */
26132 return;
26136 switch (op1) {
26137 case OPC_EXT:
26138 case OPC_INS:
26139 check_insn(ctx, ISA_MIPS32R2);
26140 gen_bitops(ctx, op1, rt, rs, sa, rd);
26141 break;
26142 case OPC_BSHFL:
26143 op2 = MASK_BSHFL(ctx->opcode);
26144 switch (op2) {
26145 case OPC_ALIGN:
26146 case OPC_ALIGN_1:
26147 case OPC_ALIGN_2:
26148 case OPC_ALIGN_3:
26149 case OPC_BITSWAP:
26150 check_insn(ctx, ISA_MIPS32R6);
26151 decode_opc_special3_r6(env, ctx);
26152 break;
26153 default:
26154 check_insn(ctx, ISA_MIPS32R2);
26155 gen_bshfl(ctx, op2, rt, rd);
26156 break;
26158 break;
26159 #if defined(TARGET_MIPS64)
26160 case OPC_DEXTM:
26161 case OPC_DEXTU:
26162 case OPC_DEXT:
26163 case OPC_DINSM:
26164 case OPC_DINSU:
26165 case OPC_DINS:
26166 check_insn(ctx, ISA_MIPS64R2);
26167 check_mips_64(ctx);
26168 gen_bitops(ctx, op1, rt, rs, sa, rd);
26169 break;
26170 case OPC_DBSHFL:
26171 op2 = MASK_DBSHFL(ctx->opcode);
26172 switch (op2) {
26173 case OPC_DALIGN:
26174 case OPC_DALIGN_1:
26175 case OPC_DALIGN_2:
26176 case OPC_DALIGN_3:
26177 case OPC_DALIGN_4:
26178 case OPC_DALIGN_5:
26179 case OPC_DALIGN_6:
26180 case OPC_DALIGN_7:
26181 case OPC_DBITSWAP:
26182 check_insn(ctx, ISA_MIPS32R6);
26183 decode_opc_special3_r6(env, ctx);
26184 break;
26185 default:
26186 check_insn(ctx, ISA_MIPS64R2);
26187 check_mips_64(ctx);
26188 op2 = MASK_DBSHFL(ctx->opcode);
26189 gen_bshfl(ctx, op2, rt, rd);
26190 break;
26192 break;
26193 #endif
26194 case OPC_RDHWR:
26195 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
26196 break;
26197 case OPC_FORK:
26198 check_mt(ctx);
26200 TCGv t0 = tcg_temp_new();
26201 TCGv t1 = tcg_temp_new();
26203 gen_load_gpr(t0, rt);
26204 gen_load_gpr(t1, rs);
26205 gen_helper_fork(t0, t1);
26206 tcg_temp_free(t0);
26207 tcg_temp_free(t1);
26209 break;
26210 case OPC_YIELD:
26211 check_mt(ctx);
26213 TCGv t0 = tcg_temp_new();
26215 gen_load_gpr(t0, rs);
26216 gen_helper_yield(t0, cpu_env, t0);
26217 gen_store_gpr(t0, rd);
26218 tcg_temp_free(t0);
26220 break;
26221 default:
26222 if (ctx->insn_flags & ISA_MIPS32R6) {
26223 decode_opc_special3_r6(env, ctx);
26224 } else {
26225 decode_opc_special3_legacy(env, ctx);
26230 /* MIPS SIMD Architecture (MSA) */
26231 static inline int check_msa_access(DisasContext *ctx)
26233 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
26234 !(ctx->hflags & MIPS_HFLAG_F64))) {
26235 generate_exception_end(ctx, EXCP_RI);
26236 return 0;
26239 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
26240 if (ctx->insn_flags & ASE_MSA) {
26241 generate_exception_end(ctx, EXCP_MSADIS);
26242 return 0;
26243 } else {
26244 generate_exception_end(ctx, EXCP_RI);
26245 return 0;
26248 return 1;
26251 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
26253 /* generates tcg ops to check if any element is 0 */
26254 /* Note this function only works with MSA_WRLEN = 128 */
26255 uint64_t eval_zero_or_big = 0;
26256 uint64_t eval_big = 0;
26257 TCGv_i64 t0 = tcg_temp_new_i64();
26258 TCGv_i64 t1 = tcg_temp_new_i64();
26259 switch (df) {
26260 case DF_BYTE:
26261 eval_zero_or_big = 0x0101010101010101ULL;
26262 eval_big = 0x8080808080808080ULL;
26263 break;
26264 case DF_HALF:
26265 eval_zero_or_big = 0x0001000100010001ULL;
26266 eval_big = 0x8000800080008000ULL;
26267 break;
26268 case DF_WORD:
26269 eval_zero_or_big = 0x0000000100000001ULL;
26270 eval_big = 0x8000000080000000ULL;
26271 break;
26272 case DF_DOUBLE:
26273 eval_zero_or_big = 0x0000000000000001ULL;
26274 eval_big = 0x8000000000000000ULL;
26275 break;
26277 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
26278 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
26279 tcg_gen_andi_i64(t0, t0, eval_big);
26280 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
26281 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
26282 tcg_gen_andi_i64(t1, t1, eval_big);
26283 tcg_gen_or_i64(t0, t0, t1);
26284 /* if all bits are zero then all elements are not zero */
26285 /* if some bit is non-zero then some element is zero */
26286 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
26287 tcg_gen_trunc_i64_tl(tresult, t0);
26288 tcg_temp_free_i64(t0);
26289 tcg_temp_free_i64(t1);
26292 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
26294 uint8_t df = (ctx->opcode >> 21) & 0x3;
26295 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
26296 int64_t s16 = (int16_t)ctx->opcode;
26298 check_msa_access(ctx);
26300 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26301 generate_exception_end(ctx, EXCP_RI);
26302 return;
26304 switch (op1) {
26305 case OPC_BZ_V:
26306 case OPC_BNZ_V:
26308 TCGv_i64 t0 = tcg_temp_new_i64();
26309 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
26310 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
26311 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
26312 tcg_gen_trunc_i64_tl(bcond, t0);
26313 tcg_temp_free_i64(t0);
26315 break;
26316 case OPC_BZ_B:
26317 case OPC_BZ_H:
26318 case OPC_BZ_W:
26319 case OPC_BZ_D:
26320 gen_check_zero_element(bcond, df, wt);
26321 break;
26322 case OPC_BNZ_B:
26323 case OPC_BNZ_H:
26324 case OPC_BNZ_W:
26325 case OPC_BNZ_D:
26326 gen_check_zero_element(bcond, df, wt);
26327 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
26328 break;
26331 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
26333 ctx->hflags |= MIPS_HFLAG_BC;
26334 ctx->hflags |= MIPS_HFLAG_BDS32;
26337 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
26339 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
26340 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
26341 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26342 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26344 TCGv_i32 twd = tcg_const_i32(wd);
26345 TCGv_i32 tws = tcg_const_i32(ws);
26346 TCGv_i32 ti8 = tcg_const_i32(i8);
26348 switch (MASK_MSA_I8(ctx->opcode)) {
26349 case OPC_ANDI_B:
26350 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
26351 break;
26352 case OPC_ORI_B:
26353 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
26354 break;
26355 case OPC_NORI_B:
26356 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
26357 break;
26358 case OPC_XORI_B:
26359 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
26360 break;
26361 case OPC_BMNZI_B:
26362 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
26363 break;
26364 case OPC_BMZI_B:
26365 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
26366 break;
26367 case OPC_BSELI_B:
26368 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
26369 break;
26370 case OPC_SHF_B:
26371 case OPC_SHF_H:
26372 case OPC_SHF_W:
26374 uint8_t df = (ctx->opcode >> 24) & 0x3;
26375 if (df == DF_DOUBLE) {
26376 generate_exception_end(ctx, EXCP_RI);
26377 } else {
26378 TCGv_i32 tdf = tcg_const_i32(df);
26379 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
26380 tcg_temp_free_i32(tdf);
26383 break;
26384 default:
26385 MIPS_INVAL("MSA instruction");
26386 generate_exception_end(ctx, EXCP_RI);
26387 break;
26390 tcg_temp_free_i32(twd);
26391 tcg_temp_free_i32(tws);
26392 tcg_temp_free_i32(ti8);
26395 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
26397 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
26398 uint8_t df = (ctx->opcode >> 21) & 0x3;
26399 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
26400 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
26401 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26402 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26404 TCGv_i32 tdf = tcg_const_i32(df);
26405 TCGv_i32 twd = tcg_const_i32(wd);
26406 TCGv_i32 tws = tcg_const_i32(ws);
26407 TCGv_i32 timm = tcg_temp_new_i32();
26408 tcg_gen_movi_i32(timm, u5);
26410 switch (MASK_MSA_I5(ctx->opcode)) {
26411 case OPC_ADDVI_df:
26412 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
26413 break;
26414 case OPC_SUBVI_df:
26415 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
26416 break;
26417 case OPC_MAXI_S_df:
26418 tcg_gen_movi_i32(timm, s5);
26419 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
26420 break;
26421 case OPC_MAXI_U_df:
26422 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
26423 break;
26424 case OPC_MINI_S_df:
26425 tcg_gen_movi_i32(timm, s5);
26426 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
26427 break;
26428 case OPC_MINI_U_df:
26429 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
26430 break;
26431 case OPC_CEQI_df:
26432 tcg_gen_movi_i32(timm, s5);
26433 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
26434 break;
26435 case OPC_CLTI_S_df:
26436 tcg_gen_movi_i32(timm, s5);
26437 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
26438 break;
26439 case OPC_CLTI_U_df:
26440 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
26441 break;
26442 case OPC_CLEI_S_df:
26443 tcg_gen_movi_i32(timm, s5);
26444 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
26445 break;
26446 case OPC_CLEI_U_df:
26447 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
26448 break;
26449 case OPC_LDI_df:
26451 int32_t s10 = sextract32(ctx->opcode, 11, 10);
26452 tcg_gen_movi_i32(timm, s10);
26453 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
26455 break;
26456 default:
26457 MIPS_INVAL("MSA instruction");
26458 generate_exception_end(ctx, EXCP_RI);
26459 break;
26462 tcg_temp_free_i32(tdf);
26463 tcg_temp_free_i32(twd);
26464 tcg_temp_free_i32(tws);
26465 tcg_temp_free_i32(timm);
26468 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
26470 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
26471 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
26472 uint32_t df = 0, m = 0;
26473 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26474 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26476 TCGv_i32 tdf;
26477 TCGv_i32 tm;
26478 TCGv_i32 twd;
26479 TCGv_i32 tws;
26481 if ((dfm & 0x40) == 0x00) {
26482 m = dfm & 0x3f;
26483 df = DF_DOUBLE;
26484 } else if ((dfm & 0x60) == 0x40) {
26485 m = dfm & 0x1f;
26486 df = DF_WORD;
26487 } else if ((dfm & 0x70) == 0x60) {
26488 m = dfm & 0x0f;
26489 df = DF_HALF;
26490 } else if ((dfm & 0x78) == 0x70) {
26491 m = dfm & 0x7;
26492 df = DF_BYTE;
26493 } else {
26494 generate_exception_end(ctx, EXCP_RI);
26495 return;
26498 tdf = tcg_const_i32(df);
26499 tm = tcg_const_i32(m);
26500 twd = tcg_const_i32(wd);
26501 tws = tcg_const_i32(ws);
26503 switch (MASK_MSA_BIT(ctx->opcode)) {
26504 case OPC_SLLI_df:
26505 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
26506 break;
26507 case OPC_SRAI_df:
26508 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
26509 break;
26510 case OPC_SRLI_df:
26511 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
26512 break;
26513 case OPC_BCLRI_df:
26514 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
26515 break;
26516 case OPC_BSETI_df:
26517 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
26518 break;
26519 case OPC_BNEGI_df:
26520 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
26521 break;
26522 case OPC_BINSLI_df:
26523 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
26524 break;
26525 case OPC_BINSRI_df:
26526 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
26527 break;
26528 case OPC_SAT_S_df:
26529 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
26530 break;
26531 case OPC_SAT_U_df:
26532 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
26533 break;
26534 case OPC_SRARI_df:
26535 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
26536 break;
26537 case OPC_SRLRI_df:
26538 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
26539 break;
26540 default:
26541 MIPS_INVAL("MSA instruction");
26542 generate_exception_end(ctx, EXCP_RI);
26543 break;
26546 tcg_temp_free_i32(tdf);
26547 tcg_temp_free_i32(tm);
26548 tcg_temp_free_i32(twd);
26549 tcg_temp_free_i32(tws);
26552 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
26554 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
26555 uint8_t df = (ctx->opcode >> 21) & 0x3;
26556 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
26557 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26558 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26560 TCGv_i32 tdf = tcg_const_i32(df);
26561 TCGv_i32 twd = tcg_const_i32(wd);
26562 TCGv_i32 tws = tcg_const_i32(ws);
26563 TCGv_i32 twt = tcg_const_i32(wt);
26565 switch (MASK_MSA_3R(ctx->opcode)) {
26566 case OPC_SLL_df:
26567 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
26568 break;
26569 case OPC_ADDV_df:
26570 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
26571 break;
26572 case OPC_CEQ_df:
26573 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
26574 break;
26575 case OPC_ADD_A_df:
26576 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
26577 break;
26578 case OPC_SUBS_S_df:
26579 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
26580 break;
26581 case OPC_MULV_df:
26582 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
26583 break;
26584 case OPC_SLD_df:
26585 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
26586 break;
26587 case OPC_VSHF_df:
26588 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
26589 break;
26590 case OPC_SRA_df:
26591 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
26592 break;
26593 case OPC_SUBV_df:
26594 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
26595 break;
26596 case OPC_ADDS_A_df:
26597 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
26598 break;
26599 case OPC_SUBS_U_df:
26600 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
26601 break;
26602 case OPC_MADDV_df:
26603 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
26604 break;
26605 case OPC_SPLAT_df:
26606 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
26607 break;
26608 case OPC_SRAR_df:
26609 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
26610 break;
26611 case OPC_SRL_df:
26612 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
26613 break;
26614 case OPC_MAX_S_df:
26615 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
26616 break;
26617 case OPC_CLT_S_df:
26618 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
26619 break;
26620 case OPC_ADDS_S_df:
26621 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
26622 break;
26623 case OPC_SUBSUS_U_df:
26624 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
26625 break;
26626 case OPC_MSUBV_df:
26627 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
26628 break;
26629 case OPC_PCKEV_df:
26630 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
26631 break;
26632 case OPC_SRLR_df:
26633 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
26634 break;
26635 case OPC_BCLR_df:
26636 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
26637 break;
26638 case OPC_MAX_U_df:
26639 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
26640 break;
26641 case OPC_CLT_U_df:
26642 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
26643 break;
26644 case OPC_ADDS_U_df:
26645 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
26646 break;
26647 case OPC_SUBSUU_S_df:
26648 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
26649 break;
26650 case OPC_PCKOD_df:
26651 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
26652 break;
26653 case OPC_BSET_df:
26654 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
26655 break;
26656 case OPC_MIN_S_df:
26657 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
26658 break;
26659 case OPC_CLE_S_df:
26660 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
26661 break;
26662 case OPC_AVE_S_df:
26663 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
26664 break;
26665 case OPC_ASUB_S_df:
26666 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
26667 break;
26668 case OPC_DIV_S_df:
26669 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
26670 break;
26671 case OPC_ILVL_df:
26672 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
26673 break;
26674 case OPC_BNEG_df:
26675 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
26676 break;
26677 case OPC_MIN_U_df:
26678 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
26679 break;
26680 case OPC_CLE_U_df:
26681 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
26682 break;
26683 case OPC_AVE_U_df:
26684 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
26685 break;
26686 case OPC_ASUB_U_df:
26687 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
26688 break;
26689 case OPC_DIV_U_df:
26690 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
26691 break;
26692 case OPC_ILVR_df:
26693 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
26694 break;
26695 case OPC_BINSL_df:
26696 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
26697 break;
26698 case OPC_MAX_A_df:
26699 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
26700 break;
26701 case OPC_AVER_S_df:
26702 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
26703 break;
26704 case OPC_MOD_S_df:
26705 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
26706 break;
26707 case OPC_ILVEV_df:
26708 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
26709 break;
26710 case OPC_BINSR_df:
26711 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
26712 break;
26713 case OPC_MIN_A_df:
26714 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
26715 break;
26716 case OPC_AVER_U_df:
26717 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
26718 break;
26719 case OPC_MOD_U_df:
26720 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
26721 break;
26722 case OPC_ILVOD_df:
26723 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
26724 break;
26726 case OPC_DOTP_S_df:
26727 case OPC_DOTP_U_df:
26728 case OPC_DPADD_S_df:
26729 case OPC_DPADD_U_df:
26730 case OPC_DPSUB_S_df:
26731 case OPC_HADD_S_df:
26732 case OPC_DPSUB_U_df:
26733 case OPC_HADD_U_df:
26734 case OPC_HSUB_S_df:
26735 case OPC_HSUB_U_df:
26736 if (df == DF_BYTE) {
26737 generate_exception_end(ctx, EXCP_RI);
26738 break;
26740 switch (MASK_MSA_3R(ctx->opcode)) {
26741 case OPC_DOTP_S_df:
26742 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
26743 break;
26744 case OPC_DOTP_U_df:
26745 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
26746 break;
26747 case OPC_DPADD_S_df:
26748 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
26749 break;
26750 case OPC_DPADD_U_df:
26751 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
26752 break;
26753 case OPC_DPSUB_S_df:
26754 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
26755 break;
26756 case OPC_HADD_S_df:
26757 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
26758 break;
26759 case OPC_DPSUB_U_df:
26760 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
26761 break;
26762 case OPC_HADD_U_df:
26763 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
26764 break;
26765 case OPC_HSUB_S_df:
26766 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
26767 break;
26768 case OPC_HSUB_U_df:
26769 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
26770 break;
26772 break;
26773 default:
26774 MIPS_INVAL("MSA instruction");
26775 generate_exception_end(ctx, EXCP_RI);
26776 break;
26778 tcg_temp_free_i32(twd);
26779 tcg_temp_free_i32(tws);
26780 tcg_temp_free_i32(twt);
26781 tcg_temp_free_i32(tdf);
26784 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
26786 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
26787 uint8_t source = (ctx->opcode >> 11) & 0x1f;
26788 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
26789 TCGv telm = tcg_temp_new();
26790 TCGv_i32 tsr = tcg_const_i32(source);
26791 TCGv_i32 tdt = tcg_const_i32(dest);
26793 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
26794 case OPC_CTCMSA:
26795 gen_load_gpr(telm, source);
26796 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
26797 break;
26798 case OPC_CFCMSA:
26799 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
26800 gen_store_gpr(telm, dest);
26801 break;
26802 case OPC_MOVE_V:
26803 gen_helper_msa_move_v(cpu_env, tdt, tsr);
26804 break;
26805 default:
26806 MIPS_INVAL("MSA instruction");
26807 generate_exception_end(ctx, EXCP_RI);
26808 break;
26811 tcg_temp_free(telm);
26812 tcg_temp_free_i32(tdt);
26813 tcg_temp_free_i32(tsr);
26816 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
26817 uint32_t n)
26819 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
26820 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26821 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26823 TCGv_i32 tws = tcg_const_i32(ws);
26824 TCGv_i32 twd = tcg_const_i32(wd);
26825 TCGv_i32 tn = tcg_const_i32(n);
26826 TCGv_i32 tdf = tcg_const_i32(df);
26828 switch (MASK_MSA_ELM(ctx->opcode)) {
26829 case OPC_SLDI_df:
26830 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
26831 break;
26832 case OPC_SPLATI_df:
26833 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
26834 break;
26835 case OPC_INSVE_df:
26836 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
26837 break;
26838 case OPC_COPY_S_df:
26839 case OPC_COPY_U_df:
26840 case OPC_INSERT_df:
26841 #if !defined(TARGET_MIPS64)
26842 /* Double format valid only for MIPS64 */
26843 if (df == DF_DOUBLE) {
26844 generate_exception_end(ctx, EXCP_RI);
26845 break;
26847 #endif
26848 switch (MASK_MSA_ELM(ctx->opcode)) {
26849 case OPC_COPY_S_df:
26850 if (likely(wd != 0)) {
26851 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
26853 break;
26854 case OPC_COPY_U_df:
26855 if (likely(wd != 0)) {
26856 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
26858 break;
26859 case OPC_INSERT_df:
26860 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
26861 break;
26863 break;
26864 default:
26865 MIPS_INVAL("MSA instruction");
26866 generate_exception_end(ctx, EXCP_RI);
26868 tcg_temp_free_i32(twd);
26869 tcg_temp_free_i32(tws);
26870 tcg_temp_free_i32(tn);
26871 tcg_temp_free_i32(tdf);
26874 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
26876 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
26877 uint32_t df = 0, n = 0;
26879 if ((dfn & 0x30) == 0x00) {
26880 n = dfn & 0x0f;
26881 df = DF_BYTE;
26882 } else if ((dfn & 0x38) == 0x20) {
26883 n = dfn & 0x07;
26884 df = DF_HALF;
26885 } else if ((dfn & 0x3c) == 0x30) {
26886 n = dfn & 0x03;
26887 df = DF_WORD;
26888 } else if ((dfn & 0x3e) == 0x38) {
26889 n = dfn & 0x01;
26890 df = DF_DOUBLE;
26891 } else if (dfn == 0x3E) {
26892 /* CTCMSA, CFCMSA, MOVE.V */
26893 gen_msa_elm_3e(env, ctx);
26894 return;
26895 } else {
26896 generate_exception_end(ctx, EXCP_RI);
26897 return;
26900 gen_msa_elm_df(env, ctx, df, n);
26903 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
26905 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
26906 uint8_t df = (ctx->opcode >> 21) & 0x1;
26907 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
26908 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26909 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26911 TCGv_i32 twd = tcg_const_i32(wd);
26912 TCGv_i32 tws = tcg_const_i32(ws);
26913 TCGv_i32 twt = tcg_const_i32(wt);
26914 TCGv_i32 tdf = tcg_temp_new_i32();
26916 /* adjust df value for floating-point instruction */
26917 tcg_gen_movi_i32(tdf, df + 2);
26919 switch (MASK_MSA_3RF(ctx->opcode)) {
26920 case OPC_FCAF_df:
26921 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
26922 break;
26923 case OPC_FADD_df:
26924 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
26925 break;
26926 case OPC_FCUN_df:
26927 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
26928 break;
26929 case OPC_FSUB_df:
26930 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
26931 break;
26932 case OPC_FCOR_df:
26933 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
26934 break;
26935 case OPC_FCEQ_df:
26936 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
26937 break;
26938 case OPC_FMUL_df:
26939 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
26940 break;
26941 case OPC_FCUNE_df:
26942 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
26943 break;
26944 case OPC_FCUEQ_df:
26945 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
26946 break;
26947 case OPC_FDIV_df:
26948 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
26949 break;
26950 case OPC_FCNE_df:
26951 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
26952 break;
26953 case OPC_FCLT_df:
26954 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
26955 break;
26956 case OPC_FMADD_df:
26957 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
26958 break;
26959 case OPC_MUL_Q_df:
26960 tcg_gen_movi_i32(tdf, df + 1);
26961 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
26962 break;
26963 case OPC_FCULT_df:
26964 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
26965 break;
26966 case OPC_FMSUB_df:
26967 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
26968 break;
26969 case OPC_MADD_Q_df:
26970 tcg_gen_movi_i32(tdf, df + 1);
26971 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
26972 break;
26973 case OPC_FCLE_df:
26974 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
26975 break;
26976 case OPC_MSUB_Q_df:
26977 tcg_gen_movi_i32(tdf, df + 1);
26978 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
26979 break;
26980 case OPC_FCULE_df:
26981 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
26982 break;
26983 case OPC_FEXP2_df:
26984 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
26985 break;
26986 case OPC_FSAF_df:
26987 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
26988 break;
26989 case OPC_FEXDO_df:
26990 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
26991 break;
26992 case OPC_FSUN_df:
26993 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
26994 break;
26995 case OPC_FSOR_df:
26996 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
26997 break;
26998 case OPC_FSEQ_df:
26999 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
27000 break;
27001 case OPC_FTQ_df:
27002 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
27003 break;
27004 case OPC_FSUNE_df:
27005 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
27006 break;
27007 case OPC_FSUEQ_df:
27008 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
27009 break;
27010 case OPC_FSNE_df:
27011 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
27012 break;
27013 case OPC_FSLT_df:
27014 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
27015 break;
27016 case OPC_FMIN_df:
27017 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
27018 break;
27019 case OPC_MULR_Q_df:
27020 tcg_gen_movi_i32(tdf, df + 1);
27021 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
27022 break;
27023 case OPC_FSULT_df:
27024 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
27025 break;
27026 case OPC_FMIN_A_df:
27027 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
27028 break;
27029 case OPC_MADDR_Q_df:
27030 tcg_gen_movi_i32(tdf, df + 1);
27031 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
27032 break;
27033 case OPC_FSLE_df:
27034 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
27035 break;
27036 case OPC_FMAX_df:
27037 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
27038 break;
27039 case OPC_MSUBR_Q_df:
27040 tcg_gen_movi_i32(tdf, df + 1);
27041 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
27042 break;
27043 case OPC_FSULE_df:
27044 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
27045 break;
27046 case OPC_FMAX_A_df:
27047 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
27048 break;
27049 default:
27050 MIPS_INVAL("MSA instruction");
27051 generate_exception_end(ctx, EXCP_RI);
27052 break;
27055 tcg_temp_free_i32(twd);
27056 tcg_temp_free_i32(tws);
27057 tcg_temp_free_i32(twt);
27058 tcg_temp_free_i32(tdf);
27061 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
27063 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
27064 (op & (0x7 << 18)))
27065 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27066 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27067 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27068 uint8_t df = (ctx->opcode >> 16) & 0x3;
27069 TCGv_i32 twd = tcg_const_i32(wd);
27070 TCGv_i32 tws = tcg_const_i32(ws);
27071 TCGv_i32 twt = tcg_const_i32(wt);
27072 TCGv_i32 tdf = tcg_const_i32(df);
27074 switch (MASK_MSA_2R(ctx->opcode)) {
27075 case OPC_FILL_df:
27076 #if !defined(TARGET_MIPS64)
27077 /* Double format valid only for MIPS64 */
27078 if (df == DF_DOUBLE) {
27079 generate_exception_end(ctx, EXCP_RI);
27080 break;
27082 #endif
27083 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
27084 break;
27085 case OPC_PCNT_df:
27086 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
27087 break;
27088 case OPC_NLOC_df:
27089 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
27090 break;
27091 case OPC_NLZC_df:
27092 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
27093 break;
27094 default:
27095 MIPS_INVAL("MSA instruction");
27096 generate_exception_end(ctx, EXCP_RI);
27097 break;
27100 tcg_temp_free_i32(twd);
27101 tcg_temp_free_i32(tws);
27102 tcg_temp_free_i32(twt);
27103 tcg_temp_free_i32(tdf);
27106 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
27108 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
27109 (op & (0xf << 17)))
27110 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27111 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27112 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27113 uint8_t df = (ctx->opcode >> 16) & 0x1;
27114 TCGv_i32 twd = tcg_const_i32(wd);
27115 TCGv_i32 tws = tcg_const_i32(ws);
27116 TCGv_i32 twt = tcg_const_i32(wt);
27117 /* adjust df value for floating-point instruction */
27118 TCGv_i32 tdf = tcg_const_i32(df + 2);
27120 switch (MASK_MSA_2RF(ctx->opcode)) {
27121 case OPC_FCLASS_df:
27122 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
27123 break;
27124 case OPC_FTRUNC_S_df:
27125 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
27126 break;
27127 case OPC_FTRUNC_U_df:
27128 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
27129 break;
27130 case OPC_FSQRT_df:
27131 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
27132 break;
27133 case OPC_FRSQRT_df:
27134 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
27135 break;
27136 case OPC_FRCP_df:
27137 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
27138 break;
27139 case OPC_FRINT_df:
27140 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
27141 break;
27142 case OPC_FLOG2_df:
27143 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
27144 break;
27145 case OPC_FEXUPL_df:
27146 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
27147 break;
27148 case OPC_FEXUPR_df:
27149 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
27150 break;
27151 case OPC_FFQL_df:
27152 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
27153 break;
27154 case OPC_FFQR_df:
27155 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
27156 break;
27157 case OPC_FTINT_S_df:
27158 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
27159 break;
27160 case OPC_FTINT_U_df:
27161 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
27162 break;
27163 case OPC_FFINT_S_df:
27164 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
27165 break;
27166 case OPC_FFINT_U_df:
27167 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
27168 break;
27171 tcg_temp_free_i32(twd);
27172 tcg_temp_free_i32(tws);
27173 tcg_temp_free_i32(twt);
27174 tcg_temp_free_i32(tdf);
27177 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
27179 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
27180 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27181 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27182 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27183 TCGv_i32 twd = tcg_const_i32(wd);
27184 TCGv_i32 tws = tcg_const_i32(ws);
27185 TCGv_i32 twt = tcg_const_i32(wt);
27187 switch (MASK_MSA_VEC(ctx->opcode)) {
27188 case OPC_AND_V:
27189 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
27190 break;
27191 case OPC_OR_V:
27192 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
27193 break;
27194 case OPC_NOR_V:
27195 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
27196 break;
27197 case OPC_XOR_V:
27198 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
27199 break;
27200 case OPC_BMNZ_V:
27201 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
27202 break;
27203 case OPC_BMZ_V:
27204 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
27205 break;
27206 case OPC_BSEL_V:
27207 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
27208 break;
27209 default:
27210 MIPS_INVAL("MSA instruction");
27211 generate_exception_end(ctx, EXCP_RI);
27212 break;
27215 tcg_temp_free_i32(twd);
27216 tcg_temp_free_i32(tws);
27217 tcg_temp_free_i32(twt);
27220 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
27222 switch (MASK_MSA_VEC(ctx->opcode)) {
27223 case OPC_AND_V:
27224 case OPC_OR_V:
27225 case OPC_NOR_V:
27226 case OPC_XOR_V:
27227 case OPC_BMNZ_V:
27228 case OPC_BMZ_V:
27229 case OPC_BSEL_V:
27230 gen_msa_vec_v(env, ctx);
27231 break;
27232 case OPC_MSA_2R:
27233 gen_msa_2r(env, ctx);
27234 break;
27235 case OPC_MSA_2RF:
27236 gen_msa_2rf(env, ctx);
27237 break;
27238 default:
27239 MIPS_INVAL("MSA instruction");
27240 generate_exception_end(ctx, EXCP_RI);
27241 break;
27245 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
27247 uint32_t opcode = ctx->opcode;
27248 check_insn(ctx, ASE_MSA);
27249 check_msa_access(ctx);
27251 switch (MASK_MSA_MINOR(opcode)) {
27252 case OPC_MSA_I8_00:
27253 case OPC_MSA_I8_01:
27254 case OPC_MSA_I8_02:
27255 gen_msa_i8(env, ctx);
27256 break;
27257 case OPC_MSA_I5_06:
27258 case OPC_MSA_I5_07:
27259 gen_msa_i5(env, ctx);
27260 break;
27261 case OPC_MSA_BIT_09:
27262 case OPC_MSA_BIT_0A:
27263 gen_msa_bit(env, ctx);
27264 break;
27265 case OPC_MSA_3R_0D:
27266 case OPC_MSA_3R_0E:
27267 case OPC_MSA_3R_0F:
27268 case OPC_MSA_3R_10:
27269 case OPC_MSA_3R_11:
27270 case OPC_MSA_3R_12:
27271 case OPC_MSA_3R_13:
27272 case OPC_MSA_3R_14:
27273 case OPC_MSA_3R_15:
27274 gen_msa_3r(env, ctx);
27275 break;
27276 case OPC_MSA_ELM:
27277 gen_msa_elm(env, ctx);
27278 break;
27279 case OPC_MSA_3RF_1A:
27280 case OPC_MSA_3RF_1B:
27281 case OPC_MSA_3RF_1C:
27282 gen_msa_3rf(env, ctx);
27283 break;
27284 case OPC_MSA_VEC:
27285 gen_msa_vec(env, ctx);
27286 break;
27287 case OPC_LD_B:
27288 case OPC_LD_H:
27289 case OPC_LD_W:
27290 case OPC_LD_D:
27291 case OPC_ST_B:
27292 case OPC_ST_H:
27293 case OPC_ST_W:
27294 case OPC_ST_D:
27296 int32_t s10 = sextract32(ctx->opcode, 16, 10);
27297 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
27298 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27299 uint8_t df = (ctx->opcode >> 0) & 0x3;
27301 TCGv_i32 twd = tcg_const_i32(wd);
27302 TCGv taddr = tcg_temp_new();
27303 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
27305 switch (MASK_MSA_MINOR(opcode)) {
27306 case OPC_LD_B:
27307 gen_helper_msa_ld_b(cpu_env, twd, taddr);
27308 break;
27309 case OPC_LD_H:
27310 gen_helper_msa_ld_h(cpu_env, twd, taddr);
27311 break;
27312 case OPC_LD_W:
27313 gen_helper_msa_ld_w(cpu_env, twd, taddr);
27314 break;
27315 case OPC_LD_D:
27316 gen_helper_msa_ld_d(cpu_env, twd, taddr);
27317 break;
27318 case OPC_ST_B:
27319 gen_helper_msa_st_b(cpu_env, twd, taddr);
27320 break;
27321 case OPC_ST_H:
27322 gen_helper_msa_st_h(cpu_env, twd, taddr);
27323 break;
27324 case OPC_ST_W:
27325 gen_helper_msa_st_w(cpu_env, twd, taddr);
27326 break;
27327 case OPC_ST_D:
27328 gen_helper_msa_st_d(cpu_env, twd, taddr);
27329 break;
27332 tcg_temp_free_i32(twd);
27333 tcg_temp_free(taddr);
27335 break;
27336 default:
27337 MIPS_INVAL("MSA instruction");
27338 generate_exception_end(ctx, EXCP_RI);
27339 break;
27344 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
27346 int32_t offset;
27347 int rs, rt, rd, sa;
27348 uint32_t op, op1;
27349 int16_t imm;
27351 /* make sure instructions are on a word boundary */
27352 if (ctx->base.pc_next & 0x3) {
27353 env->CP0_BadVAddr = ctx->base.pc_next;
27354 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
27355 return;
27358 /* Handle blikely not taken case */
27359 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
27360 TCGLabel *l1 = gen_new_label();
27362 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
27363 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
27364 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
27365 gen_set_label(l1);
27368 op = MASK_OP_MAJOR(ctx->opcode);
27369 rs = (ctx->opcode >> 21) & 0x1f;
27370 rt = (ctx->opcode >> 16) & 0x1f;
27371 rd = (ctx->opcode >> 11) & 0x1f;
27372 sa = (ctx->opcode >> 6) & 0x1f;
27373 imm = (int16_t)ctx->opcode;
27374 switch (op) {
27375 case OPC_SPECIAL:
27376 decode_opc_special(env, ctx);
27377 break;
27378 case OPC_SPECIAL2:
27379 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
27380 decode_tx79_mmi(env, ctx);
27381 } else if (ctx->insn_flags & ASE_MXU) {
27382 decode_opc_mxu(env, ctx);
27383 } else {
27384 decode_opc_special2_legacy(env, ctx);
27386 break;
27387 case OPC_SPECIAL3:
27388 if (ctx->insn_flags & INSN_R5900) {
27389 decode_tx79_sq(env, ctx); /* TX79_SQ */
27390 } else {
27391 decode_opc_special3(env, ctx);
27393 break;
27394 case OPC_REGIMM:
27395 op1 = MASK_REGIMM(ctx->opcode);
27396 switch (op1) {
27397 case OPC_BLTZL: /* REGIMM branches */
27398 case OPC_BGEZL:
27399 case OPC_BLTZALL:
27400 case OPC_BGEZALL:
27401 check_insn(ctx, ISA_MIPS2);
27402 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27403 /* Fallthrough */
27404 case OPC_BLTZ:
27405 case OPC_BGEZ:
27406 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
27407 break;
27408 case OPC_BLTZAL:
27409 case OPC_BGEZAL:
27410 if (ctx->insn_flags & ISA_MIPS32R6) {
27411 if (rs == 0) {
27412 /* OPC_NAL, OPC_BAL */
27413 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
27414 } else {
27415 generate_exception_end(ctx, EXCP_RI);
27417 } else {
27418 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
27420 break;
27421 case OPC_TGEI: /* REGIMM traps */
27422 case OPC_TGEIU:
27423 case OPC_TLTI:
27424 case OPC_TLTIU:
27425 case OPC_TEQI:
27427 case OPC_TNEI:
27428 check_insn(ctx, ISA_MIPS2);
27429 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27430 gen_trap(ctx, op1, rs, -1, imm);
27431 break;
27432 case OPC_SIGRIE:
27433 check_insn(ctx, ISA_MIPS32R6);
27434 generate_exception_end(ctx, EXCP_RI);
27435 break;
27436 case OPC_SYNCI:
27437 check_insn(ctx, ISA_MIPS32R2);
27438 /* Break the TB to be able to sync copied instructions
27439 immediately */
27440 ctx->base.is_jmp = DISAS_STOP;
27441 break;
27442 case OPC_BPOSGE32: /* MIPS DSP branch */
27443 #if defined(TARGET_MIPS64)
27444 case OPC_BPOSGE64:
27445 #endif
27446 check_dsp(ctx);
27447 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
27448 break;
27449 #if defined(TARGET_MIPS64)
27450 case OPC_DAHI:
27451 check_insn(ctx, ISA_MIPS32R6);
27452 check_mips_64(ctx);
27453 if (rs != 0) {
27454 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
27456 break;
27457 case OPC_DATI:
27458 check_insn(ctx, ISA_MIPS32R6);
27459 check_mips_64(ctx);
27460 if (rs != 0) {
27461 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
27463 break;
27464 #endif
27465 default: /* Invalid */
27466 MIPS_INVAL("regimm");
27467 generate_exception_end(ctx, EXCP_RI);
27468 break;
27470 break;
27471 case OPC_CP0:
27472 check_cp0_enabled(ctx);
27473 op1 = MASK_CP0(ctx->opcode);
27474 switch (op1) {
27475 case OPC_MFC0:
27476 case OPC_MTC0:
27477 case OPC_MFTR:
27478 case OPC_MTTR:
27479 case OPC_MFHC0:
27480 case OPC_MTHC0:
27481 #if defined(TARGET_MIPS64)
27482 case OPC_DMFC0:
27483 case OPC_DMTC0:
27484 #endif
27485 #ifndef CONFIG_USER_ONLY
27486 gen_cp0(env, ctx, op1, rt, rd);
27487 #endif /* !CONFIG_USER_ONLY */
27488 break;
27489 case OPC_C0:
27490 case OPC_C0_1:
27491 case OPC_C0_2:
27492 case OPC_C0_3:
27493 case OPC_C0_4:
27494 case OPC_C0_5:
27495 case OPC_C0_6:
27496 case OPC_C0_7:
27497 case OPC_C0_8:
27498 case OPC_C0_9:
27499 case OPC_C0_A:
27500 case OPC_C0_B:
27501 case OPC_C0_C:
27502 case OPC_C0_D:
27503 case OPC_C0_E:
27504 case OPC_C0_F:
27505 #ifndef CONFIG_USER_ONLY
27506 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
27507 #endif /* !CONFIG_USER_ONLY */
27508 break;
27509 case OPC_MFMC0:
27510 #ifndef CONFIG_USER_ONLY
27512 uint32_t op2;
27513 TCGv t0 = tcg_temp_new();
27515 op2 = MASK_MFMC0(ctx->opcode);
27516 switch (op2) {
27517 case OPC_DMT:
27518 check_cp0_mt(ctx);
27519 gen_helper_dmt(t0);
27520 gen_store_gpr(t0, rt);
27521 break;
27522 case OPC_EMT:
27523 check_cp0_mt(ctx);
27524 gen_helper_emt(t0);
27525 gen_store_gpr(t0, rt);
27526 break;
27527 case OPC_DVPE:
27528 check_cp0_mt(ctx);
27529 gen_helper_dvpe(t0, cpu_env);
27530 gen_store_gpr(t0, rt);
27531 break;
27532 case OPC_EVPE:
27533 check_cp0_mt(ctx);
27534 gen_helper_evpe(t0, cpu_env);
27535 gen_store_gpr(t0, rt);
27536 break;
27537 case OPC_DVP:
27538 check_insn(ctx, ISA_MIPS32R6);
27539 if (ctx->vp) {
27540 gen_helper_dvp(t0, cpu_env);
27541 gen_store_gpr(t0, rt);
27543 break;
27544 case OPC_EVP:
27545 check_insn(ctx, ISA_MIPS32R6);
27546 if (ctx->vp) {
27547 gen_helper_evp(t0, cpu_env);
27548 gen_store_gpr(t0, rt);
27550 break;
27551 case OPC_DI:
27552 check_insn(ctx, ISA_MIPS32R2);
27553 save_cpu_state(ctx, 1);
27554 gen_helper_di(t0, cpu_env);
27555 gen_store_gpr(t0, rt);
27556 /* Stop translation as we may have switched
27557 the execution mode. */
27558 ctx->base.is_jmp = DISAS_STOP;
27559 break;
27560 case OPC_EI:
27561 check_insn(ctx, ISA_MIPS32R2);
27562 save_cpu_state(ctx, 1);
27563 gen_helper_ei(t0, cpu_env);
27564 gen_store_gpr(t0, rt);
27565 /* DISAS_STOP isn't sufficient, we need to ensure we break
27566 out of translated code to check for pending interrupts */
27567 gen_save_pc(ctx->base.pc_next + 4);
27568 ctx->base.is_jmp = DISAS_EXIT;
27569 break;
27570 default: /* Invalid */
27571 MIPS_INVAL("mfmc0");
27572 generate_exception_end(ctx, EXCP_RI);
27573 break;
27575 tcg_temp_free(t0);
27577 #endif /* !CONFIG_USER_ONLY */
27578 break;
27579 case OPC_RDPGPR:
27580 check_insn(ctx, ISA_MIPS32R2);
27581 gen_load_srsgpr(rt, rd);
27582 break;
27583 case OPC_WRPGPR:
27584 check_insn(ctx, ISA_MIPS32R2);
27585 gen_store_srsgpr(rt, rd);
27586 break;
27587 default:
27588 MIPS_INVAL("cp0");
27589 generate_exception_end(ctx, EXCP_RI);
27590 break;
27592 break;
27593 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
27594 if (ctx->insn_flags & ISA_MIPS32R6) {
27595 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
27596 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27597 } else {
27598 /* OPC_ADDI */
27599 /* Arithmetic with immediate opcode */
27600 gen_arith_imm(ctx, op, rt, rs, imm);
27602 break;
27603 case OPC_ADDIU:
27604 gen_arith_imm(ctx, op, rt, rs, imm);
27605 break;
27606 case OPC_SLTI: /* Set on less than with immediate opcode */
27607 case OPC_SLTIU:
27608 gen_slt_imm(ctx, op, rt, rs, imm);
27609 break;
27610 case OPC_ANDI: /* Arithmetic with immediate opcode */
27611 case OPC_LUI: /* OPC_AUI */
27612 case OPC_ORI:
27613 case OPC_XORI:
27614 gen_logic_imm(ctx, op, rt, rs, imm);
27615 break;
27616 case OPC_J: /* Jump */
27617 case OPC_JAL:
27618 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
27619 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
27620 break;
27621 /* Branch */
27622 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
27623 if (ctx->insn_flags & ISA_MIPS32R6) {
27624 if (rt == 0) {
27625 generate_exception_end(ctx, EXCP_RI);
27626 break;
27628 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
27629 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27630 } else {
27631 /* OPC_BLEZL */
27632 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27634 break;
27635 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
27636 if (ctx->insn_flags & ISA_MIPS32R6) {
27637 if (rt == 0) {
27638 generate_exception_end(ctx, EXCP_RI);
27639 break;
27641 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
27642 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27643 } else {
27644 /* OPC_BGTZL */
27645 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27647 break;
27648 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
27649 if (rt == 0) {
27650 /* OPC_BLEZ */
27651 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27652 } else {
27653 check_insn(ctx, ISA_MIPS32R6);
27654 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
27655 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27657 break;
27658 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
27659 if (rt == 0) {
27660 /* OPC_BGTZ */
27661 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27662 } else {
27663 check_insn(ctx, ISA_MIPS32R6);
27664 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
27665 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27667 break;
27668 case OPC_BEQL:
27669 case OPC_BNEL:
27670 check_insn(ctx, ISA_MIPS2);
27671 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27672 /* Fallthrough */
27673 case OPC_BEQ:
27674 case OPC_BNE:
27675 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27676 break;
27677 case OPC_LL: /* Load and stores */
27678 check_insn(ctx, ISA_MIPS2);
27679 check_insn_opc_user_only(ctx, INSN_R5900);
27680 /* Fallthrough */
27681 case OPC_LWL:
27682 case OPC_LWR:
27683 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27684 /* Fallthrough */
27685 case OPC_LB:
27686 case OPC_LH:
27687 case OPC_LW:
27688 case OPC_LWPC:
27689 case OPC_LBU:
27690 case OPC_LHU:
27691 gen_ld(ctx, op, rt, rs, imm);
27692 break;
27693 case OPC_SWL:
27694 case OPC_SWR:
27695 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27696 /* fall through */
27697 case OPC_SB:
27698 case OPC_SH:
27699 case OPC_SW:
27700 gen_st(ctx, op, rt, rs, imm);
27701 break;
27702 case OPC_SC:
27703 check_insn(ctx, ISA_MIPS2);
27704 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27705 check_insn_opc_user_only(ctx, INSN_R5900);
27706 gen_st_cond(ctx, op, rt, rs, imm);
27707 break;
27708 case OPC_CACHE:
27709 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27710 check_cp0_enabled(ctx);
27711 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
27712 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27713 gen_cache_operation(ctx, rt, rs, imm);
27715 /* Treat as NOP. */
27716 break;
27717 case OPC_PREF:
27718 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27719 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
27720 INSN_R5900);
27721 /* Treat as NOP. */
27722 break;
27724 /* Floating point (COP1). */
27725 case OPC_LWC1:
27726 case OPC_LDC1:
27727 case OPC_SWC1:
27728 case OPC_SDC1:
27729 gen_cop1_ldst(ctx, op, rt, rs, imm);
27730 break;
27732 case OPC_CP1:
27733 op1 = MASK_CP1(ctx->opcode);
27735 switch (op1) {
27736 case OPC_MFHC1:
27737 case OPC_MTHC1:
27738 check_cp1_enabled(ctx);
27739 check_insn(ctx, ISA_MIPS32R2);
27740 /* fall through */
27741 case OPC_MFC1:
27742 case OPC_CFC1:
27743 case OPC_MTC1:
27744 case OPC_CTC1:
27745 check_cp1_enabled(ctx);
27746 gen_cp1(ctx, op1, rt, rd);
27747 break;
27748 #if defined(TARGET_MIPS64)
27749 case OPC_DMFC1:
27750 case OPC_DMTC1:
27751 check_cp1_enabled(ctx);
27752 check_insn(ctx, ISA_MIPS3);
27753 check_mips_64(ctx);
27754 gen_cp1(ctx, op1, rt, rd);
27755 break;
27756 #endif
27757 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
27758 check_cp1_enabled(ctx);
27759 if (ctx->insn_flags & ISA_MIPS32R6) {
27760 /* OPC_BC1EQZ */
27761 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
27762 rt, imm << 2, 4);
27763 } else {
27764 /* OPC_BC1ANY2 */
27765 check_cop1x(ctx);
27766 check_insn(ctx, ASE_MIPS3D);
27767 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
27768 (rt >> 2) & 0x7, imm << 2);
27770 break;
27771 case OPC_BC1NEZ:
27772 check_cp1_enabled(ctx);
27773 check_insn(ctx, ISA_MIPS32R6);
27774 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
27775 rt, imm << 2, 4);
27776 break;
27777 case OPC_BC1ANY4:
27778 check_cp1_enabled(ctx);
27779 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27780 check_cop1x(ctx);
27781 check_insn(ctx, ASE_MIPS3D);
27782 /* fall through */
27783 case OPC_BC1:
27784 check_cp1_enabled(ctx);
27785 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27786 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
27787 (rt >> 2) & 0x7, imm << 2);
27788 break;
27789 case OPC_PS_FMT:
27790 check_ps(ctx);
27791 /* fall through */
27792 case OPC_S_FMT:
27793 case OPC_D_FMT:
27794 check_cp1_enabled(ctx);
27795 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
27796 (imm >> 8) & 0x7);
27797 break;
27798 case OPC_W_FMT:
27799 case OPC_L_FMT:
27801 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
27802 check_cp1_enabled(ctx);
27803 if (ctx->insn_flags & ISA_MIPS32R6) {
27804 switch (r6_op) {
27805 case R6_OPC_CMP_AF_S:
27806 case R6_OPC_CMP_UN_S:
27807 case R6_OPC_CMP_EQ_S:
27808 case R6_OPC_CMP_UEQ_S:
27809 case R6_OPC_CMP_LT_S:
27810 case R6_OPC_CMP_ULT_S:
27811 case R6_OPC_CMP_LE_S:
27812 case R6_OPC_CMP_ULE_S:
27813 case R6_OPC_CMP_SAF_S:
27814 case R6_OPC_CMP_SUN_S:
27815 case R6_OPC_CMP_SEQ_S:
27816 case R6_OPC_CMP_SEUQ_S:
27817 case R6_OPC_CMP_SLT_S:
27818 case R6_OPC_CMP_SULT_S:
27819 case R6_OPC_CMP_SLE_S:
27820 case R6_OPC_CMP_SULE_S:
27821 case R6_OPC_CMP_OR_S:
27822 case R6_OPC_CMP_UNE_S:
27823 case R6_OPC_CMP_NE_S:
27824 case R6_OPC_CMP_SOR_S:
27825 case R6_OPC_CMP_SUNE_S:
27826 case R6_OPC_CMP_SNE_S:
27827 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
27828 break;
27829 case R6_OPC_CMP_AF_D:
27830 case R6_OPC_CMP_UN_D:
27831 case R6_OPC_CMP_EQ_D:
27832 case R6_OPC_CMP_UEQ_D:
27833 case R6_OPC_CMP_LT_D:
27834 case R6_OPC_CMP_ULT_D:
27835 case R6_OPC_CMP_LE_D:
27836 case R6_OPC_CMP_ULE_D:
27837 case R6_OPC_CMP_SAF_D:
27838 case R6_OPC_CMP_SUN_D:
27839 case R6_OPC_CMP_SEQ_D:
27840 case R6_OPC_CMP_SEUQ_D:
27841 case R6_OPC_CMP_SLT_D:
27842 case R6_OPC_CMP_SULT_D:
27843 case R6_OPC_CMP_SLE_D:
27844 case R6_OPC_CMP_SULE_D:
27845 case R6_OPC_CMP_OR_D:
27846 case R6_OPC_CMP_UNE_D:
27847 case R6_OPC_CMP_NE_D:
27848 case R6_OPC_CMP_SOR_D:
27849 case R6_OPC_CMP_SUNE_D:
27850 case R6_OPC_CMP_SNE_D:
27851 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
27852 break;
27853 default:
27854 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
27855 rt, rd, sa, (imm >> 8) & 0x7);
27857 break;
27859 } else {
27860 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
27861 (imm >> 8) & 0x7);
27863 break;
27865 case OPC_BZ_V:
27866 case OPC_BNZ_V:
27867 case OPC_BZ_B:
27868 case OPC_BZ_H:
27869 case OPC_BZ_W:
27870 case OPC_BZ_D:
27871 case OPC_BNZ_B:
27872 case OPC_BNZ_H:
27873 case OPC_BNZ_W:
27874 case OPC_BNZ_D:
27875 check_insn(ctx, ASE_MSA);
27876 gen_msa_branch(env, ctx, op1);
27877 break;
27878 default:
27879 MIPS_INVAL("cp1");
27880 generate_exception_end(ctx, EXCP_RI);
27881 break;
27883 break;
27885 /* Compact branches [R6] and COP2 [non-R6] */
27886 case OPC_BC: /* OPC_LWC2 */
27887 case OPC_BALC: /* OPC_SWC2 */
27888 if (ctx->insn_flags & ISA_MIPS32R6) {
27889 /* OPC_BC, OPC_BALC */
27890 gen_compute_compact_branch(ctx, op, 0, 0,
27891 sextract32(ctx->opcode << 2, 0, 28));
27892 } else {
27893 /* OPC_LWC2, OPC_SWC2 */
27894 /* COP2: Not implemented. */
27895 generate_exception_err(ctx, EXCP_CpU, 2);
27897 break;
27898 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
27899 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
27900 if (ctx->insn_flags & ISA_MIPS32R6) {
27901 if (rs != 0) {
27902 /* OPC_BEQZC, OPC_BNEZC */
27903 gen_compute_compact_branch(ctx, op, rs, 0,
27904 sextract32(ctx->opcode << 2, 0, 23));
27905 } else {
27906 /* OPC_JIC, OPC_JIALC */
27907 gen_compute_compact_branch(ctx, op, 0, rt, imm);
27909 } else {
27910 /* OPC_LWC2, OPC_SWC2 */
27911 /* COP2: Not implemented. */
27912 generate_exception_err(ctx, EXCP_CpU, 2);
27914 break;
27915 case OPC_CP2:
27916 check_insn(ctx, INSN_LOONGSON2F);
27917 /* Note that these instructions use different fields. */
27918 gen_loongson_multimedia(ctx, sa, rd, rt);
27919 break;
27921 case OPC_CP3:
27922 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27923 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
27924 check_cp1_enabled(ctx);
27925 op1 = MASK_CP3(ctx->opcode);
27926 switch (op1) {
27927 case OPC_LUXC1:
27928 case OPC_SUXC1:
27929 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
27930 /* Fallthrough */
27931 case OPC_LWXC1:
27932 case OPC_LDXC1:
27933 case OPC_SWXC1:
27934 case OPC_SDXC1:
27935 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
27936 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
27937 break;
27938 case OPC_PREFX:
27939 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
27940 /* Treat as NOP. */
27941 break;
27942 case OPC_ALNV_PS:
27943 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
27944 /* Fallthrough */
27945 case OPC_MADD_S:
27946 case OPC_MADD_D:
27947 case OPC_MADD_PS:
27948 case OPC_MSUB_S:
27949 case OPC_MSUB_D:
27950 case OPC_MSUB_PS:
27951 case OPC_NMADD_S:
27952 case OPC_NMADD_D:
27953 case OPC_NMADD_PS:
27954 case OPC_NMSUB_S:
27955 case OPC_NMSUB_D:
27956 case OPC_NMSUB_PS:
27957 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
27958 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
27959 break;
27960 default:
27961 MIPS_INVAL("cp3");
27962 generate_exception_end(ctx, EXCP_RI);
27963 break;
27965 } else {
27966 generate_exception_err(ctx, EXCP_CpU, 1);
27968 break;
27970 #if defined(TARGET_MIPS64)
27971 /* MIPS64 opcodes */
27972 case OPC_LLD:
27973 check_insn_opc_user_only(ctx, INSN_R5900);
27974 /* fall through */
27975 case OPC_LDL:
27976 case OPC_LDR:
27977 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27978 /* fall through */
27979 case OPC_LWU:
27980 case OPC_LD:
27981 check_insn(ctx, ISA_MIPS3);
27982 check_mips_64(ctx);
27983 gen_ld(ctx, op, rt, rs, imm);
27984 break;
27985 case OPC_SDL:
27986 case OPC_SDR:
27987 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27988 /* fall through */
27989 case OPC_SD:
27990 check_insn(ctx, ISA_MIPS3);
27991 check_mips_64(ctx);
27992 gen_st(ctx, op, rt, rs, imm);
27993 break;
27994 case OPC_SCD:
27995 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27996 check_insn(ctx, ISA_MIPS3);
27997 check_insn_opc_user_only(ctx, INSN_R5900);
27998 check_mips_64(ctx);
27999 gen_st_cond(ctx, op, rt, rs, imm);
28000 break;
28001 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
28002 if (ctx->insn_flags & ISA_MIPS32R6) {
28003 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
28004 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28005 } else {
28006 /* OPC_DADDI */
28007 check_insn(ctx, ISA_MIPS3);
28008 check_mips_64(ctx);
28009 gen_arith_imm(ctx, op, rt, rs, imm);
28011 break;
28012 case OPC_DADDIU:
28013 check_insn(ctx, ISA_MIPS3);
28014 check_mips_64(ctx);
28015 gen_arith_imm(ctx, op, rt, rs, imm);
28016 break;
28017 #else
28018 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
28019 if (ctx->insn_flags & ISA_MIPS32R6) {
28020 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28021 } else {
28022 MIPS_INVAL("major opcode");
28023 generate_exception_end(ctx, EXCP_RI);
28025 break;
28026 #endif
28027 case OPC_DAUI: /* OPC_JALX */
28028 if (ctx->insn_flags & ISA_MIPS32R6) {
28029 #if defined(TARGET_MIPS64)
28030 /* OPC_DAUI */
28031 check_mips_64(ctx);
28032 if (rs == 0) {
28033 generate_exception(ctx, EXCP_RI);
28034 } else if (rt != 0) {
28035 TCGv t0 = tcg_temp_new();
28036 gen_load_gpr(t0, rs);
28037 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
28038 tcg_temp_free(t0);
28040 #else
28041 generate_exception_end(ctx, EXCP_RI);
28042 MIPS_INVAL("major opcode");
28043 #endif
28044 } else {
28045 /* OPC_JALX */
28046 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
28047 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
28048 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
28050 break;
28051 case OPC_MSA: /* OPC_MDMX */
28052 if (ctx->insn_flags & INSN_R5900) {
28053 decode_tx79_lq(env, ctx); /* TX79_LQ */
28054 } else {
28055 /* MDMX: Not implemented. */
28056 gen_msa(env, ctx);
28058 break;
28059 case OPC_PCREL:
28060 check_insn(ctx, ISA_MIPS32R6);
28061 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
28062 break;
28063 default: /* Invalid */
28064 MIPS_INVAL("major opcode");
28065 generate_exception_end(ctx, EXCP_RI);
28066 break;
28070 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
28072 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28073 CPUMIPSState *env = cs->env_ptr;
28075 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
28076 ctx->saved_pc = -1;
28077 ctx->insn_flags = env->insn_flags;
28078 ctx->CP0_Config1 = env->CP0_Config1;
28079 ctx->CP0_Config2 = env->CP0_Config2;
28080 ctx->CP0_Config3 = env->CP0_Config3;
28081 ctx->CP0_Config5 = env->CP0_Config5;
28082 ctx->btarget = 0;
28083 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
28084 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
28085 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
28086 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
28087 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
28088 ctx->PAMask = env->PAMask;
28089 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
28090 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
28091 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
28092 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
28093 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
28094 /* Restore delay slot state from the tb context. */
28095 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
28096 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
28097 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
28098 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
28099 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
28100 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
28101 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
28102 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
28103 restore_cpu_state(env, ctx);
28104 #ifdef CONFIG_USER_ONLY
28105 ctx->mem_idx = MIPS_HFLAG_UM;
28106 #else
28107 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
28108 #endif
28109 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
28110 MO_UNALN : MO_ALIGN;
28112 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
28113 ctx->hflags);
28116 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
28120 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
28122 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28124 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
28125 ctx->btarget);
28128 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
28129 const CPUBreakpoint *bp)
28131 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28133 save_cpu_state(ctx, 1);
28134 ctx->base.is_jmp = DISAS_NORETURN;
28135 gen_helper_raise_exception_debug(cpu_env);
28136 /* The address covered by the breakpoint must be included in
28137 [tb->pc, tb->pc + tb->size) in order to for it to be
28138 properly cleared -- thus we increment the PC here so that
28139 the logic setting tb->size below does the right thing. */
28140 ctx->base.pc_next += 4;
28141 return true;
28144 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
28146 CPUMIPSState *env = cs->env_ptr;
28147 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28148 int insn_bytes;
28149 int is_slot;
28151 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
28152 if (ctx->insn_flags & ISA_NANOMIPS32) {
28153 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28154 insn_bytes = decode_nanomips_opc(env, ctx);
28155 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
28156 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
28157 insn_bytes = 4;
28158 decode_opc(env, ctx);
28159 } else if (ctx->insn_flags & ASE_MICROMIPS) {
28160 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28161 insn_bytes = decode_micromips_opc(env, ctx);
28162 } else if (ctx->insn_flags & ASE_MIPS16) {
28163 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28164 insn_bytes = decode_mips16_opc(env, ctx);
28165 } else {
28166 generate_exception_end(ctx, EXCP_RI);
28167 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
28168 return;
28171 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28172 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
28173 MIPS_HFLAG_FBNSLOT))) {
28174 /* force to generate branch as there is neither delay nor
28175 forbidden slot */
28176 is_slot = 1;
28178 if ((ctx->hflags & MIPS_HFLAG_M16) &&
28179 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
28180 /* Force to generate branch as microMIPS R6 doesn't restrict
28181 branches in the forbidden slot. */
28182 is_slot = 1;
28185 if (is_slot) {
28186 gen_branch(ctx, insn_bytes);
28188 ctx->base.pc_next += insn_bytes;
28190 if (ctx->base.is_jmp != DISAS_NEXT) {
28191 return;
28193 /* Execute a branch and its delay slot as a single instruction.
28194 This is what GDB expects and is consistent with what the
28195 hardware does (e.g. if a delay slot instruction faults, the
28196 reported PC is the PC of the branch). */
28197 if (ctx->base.singlestep_enabled &&
28198 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
28199 ctx->base.is_jmp = DISAS_TOO_MANY;
28201 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
28202 ctx->base.is_jmp = DISAS_TOO_MANY;
28206 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
28208 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28210 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
28211 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
28212 gen_helper_raise_exception_debug(cpu_env);
28213 } else {
28214 switch (ctx->base.is_jmp) {
28215 case DISAS_STOP:
28216 gen_save_pc(ctx->base.pc_next);
28217 tcg_gen_lookup_and_goto_ptr();
28218 break;
28219 case DISAS_NEXT:
28220 case DISAS_TOO_MANY:
28221 save_cpu_state(ctx, 0);
28222 gen_goto_tb(ctx, 0, ctx->base.pc_next);
28223 break;
28224 case DISAS_EXIT:
28225 tcg_gen_exit_tb(NULL, 0);
28226 break;
28227 case DISAS_NORETURN:
28228 break;
28229 default:
28230 g_assert_not_reached();
28235 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
28237 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
28238 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
28241 static const TranslatorOps mips_tr_ops = {
28242 .init_disas_context = mips_tr_init_disas_context,
28243 .tb_start = mips_tr_tb_start,
28244 .insn_start = mips_tr_insn_start,
28245 .breakpoint_check = mips_tr_breakpoint_check,
28246 .translate_insn = mips_tr_translate_insn,
28247 .tb_stop = mips_tr_tb_stop,
28248 .disas_log = mips_tr_disas_log,
28251 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
28253 DisasContext ctx;
28255 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
28258 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
28259 int flags)
28261 int i;
28262 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
28264 #define printfpr(fp) \
28265 do { \
28266 if (is_fpu64) \
28267 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
28268 " fd:%13g fs:%13g psu: %13g\n", \
28269 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
28270 (double)(fp)->fd, \
28271 (double)(fp)->fs[FP_ENDIAN_IDX], \
28272 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
28273 else { \
28274 fpr_t tmp; \
28275 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
28276 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
28277 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
28278 " fd:%13g fs:%13g psu:%13g\n", \
28279 tmp.w[FP_ENDIAN_IDX], tmp.d, \
28280 (double)tmp.fd, \
28281 (double)tmp.fs[FP_ENDIAN_IDX], \
28282 (double)tmp.fs[!FP_ENDIAN_IDX]); \
28284 } while(0)
28287 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
28288 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
28289 get_float_exception_flags(&env->active_fpu.fp_status));
28290 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
28291 fpu_fprintf(f, "%3s: ", fregnames[i]);
28292 printfpr(&env->active_fpu.fpr[i]);
28295 #undef printfpr
28298 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
28299 int flags)
28301 MIPSCPU *cpu = MIPS_CPU(cs);
28302 CPUMIPSState *env = &cpu->env;
28303 int i;
28305 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
28306 " LO=0x" TARGET_FMT_lx " ds %04x "
28307 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
28308 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
28309 env->hflags, env->btarget, env->bcond);
28310 for (i = 0; i < 32; i++) {
28311 if ((i & 3) == 0)
28312 cpu_fprintf(f, "GPR%02d:", i);
28313 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
28314 if ((i & 3) == 3)
28315 cpu_fprintf(f, "\n");
28318 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
28319 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
28320 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
28321 PRIx64 "\n",
28322 env->CP0_Config0, env->CP0_Config1, env->lladdr);
28323 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
28324 env->CP0_Config2, env->CP0_Config3);
28325 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
28326 env->CP0_Config4, env->CP0_Config5);
28327 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
28328 fpu_dump_state(env, f, cpu_fprintf, flags);
28332 void mips_tcg_init(void)
28334 int i;
28336 cpu_gpr[0] = NULL;
28337 for (i = 1; i < 32; i++)
28338 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
28339 offsetof(CPUMIPSState, active_tc.gpr[i]),
28340 regnames[i]);
28342 for (i = 0; i < 32; i++) {
28343 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
28344 msa_wr_d[i * 2] =
28345 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
28346 /* The scalar floating-point unit (FPU) registers are mapped on
28347 * the MSA vector registers. */
28348 fpu_f64[i] = msa_wr_d[i * 2];
28349 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
28350 msa_wr_d[i * 2 + 1] =
28351 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
28354 cpu_PC = tcg_global_mem_new(cpu_env,
28355 offsetof(CPUMIPSState, active_tc.PC), "PC");
28356 for (i = 0; i < MIPS_DSP_ACC; i++) {
28357 cpu_HI[i] = tcg_global_mem_new(cpu_env,
28358 offsetof(CPUMIPSState, active_tc.HI[i]),
28359 regnames_HI[i]);
28360 cpu_LO[i] = tcg_global_mem_new(cpu_env,
28361 offsetof(CPUMIPSState, active_tc.LO[i]),
28362 regnames_LO[i]);
28364 cpu_dspctrl = tcg_global_mem_new(cpu_env,
28365 offsetof(CPUMIPSState, active_tc.DSPControl),
28366 "DSPControl");
28367 bcond = tcg_global_mem_new(cpu_env,
28368 offsetof(CPUMIPSState, bcond), "bcond");
28369 btarget = tcg_global_mem_new(cpu_env,
28370 offsetof(CPUMIPSState, btarget), "btarget");
28371 hflags = tcg_global_mem_new_i32(cpu_env,
28372 offsetof(CPUMIPSState, hflags), "hflags");
28374 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
28375 offsetof(CPUMIPSState, active_fpu.fcr0),
28376 "fcr0");
28377 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
28378 offsetof(CPUMIPSState, active_fpu.fcr31),
28379 "fcr31");
28381 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
28382 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
28383 offsetof(CPUMIPSState,
28384 active_tc.mxu_gpr[i]),
28385 mxuregnames[i]);
28388 mxu_CR = tcg_global_mem_new(cpu_env,
28389 offsetof(CPUMIPSState, active_tc.mxu_cr),
28390 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
28393 #include "translate_init.inc.c"
28395 void cpu_mips_realize_env(CPUMIPSState *env)
28397 env->exception_base = (int32_t)0xBFC00000;
28399 #ifndef CONFIG_USER_ONLY
28400 mmu_init(env, env->cpu_model);
28401 #endif
28402 fpu_init(env, env->cpu_model);
28403 mvp_init(env, env->cpu_model);
28406 bool cpu_supports_cps_smp(const char *cpu_type)
28408 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
28409 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
28412 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
28414 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
28415 return (mcc->cpu_def->insn_flags & isa) != 0;
28418 void cpu_set_exception_base(int vp_index, target_ulong address)
28420 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
28421 vp->env.exception_base = address;
28424 void cpu_state_reset(CPUMIPSState *env)
28426 MIPSCPU *cpu = mips_env_get_cpu(env);
28427 CPUState *cs = CPU(cpu);
28429 /* Reset registers to their default values */
28430 env->CP0_PRid = env->cpu_model->CP0_PRid;
28431 env->CP0_Config0 = env->cpu_model->CP0_Config0;
28432 #ifdef TARGET_WORDS_BIGENDIAN
28433 env->CP0_Config0 |= (1 << CP0C0_BE);
28434 #endif
28435 env->CP0_Config1 = env->cpu_model->CP0_Config1;
28436 env->CP0_Config2 = env->cpu_model->CP0_Config2;
28437 env->CP0_Config3 = env->cpu_model->CP0_Config3;
28438 env->CP0_Config4 = env->cpu_model->CP0_Config4;
28439 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
28440 env->CP0_Config5 = env->cpu_model->CP0_Config5;
28441 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
28442 env->CP0_Config6 = env->cpu_model->CP0_Config6;
28443 env->CP0_Config7 = env->cpu_model->CP0_Config7;
28444 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
28445 << env->cpu_model->CP0_LLAddr_shift;
28446 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
28447 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
28448 env->CCRes = env->cpu_model->CCRes;
28449 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
28450 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
28451 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
28452 env->current_tc = 0;
28453 env->SEGBITS = env->cpu_model->SEGBITS;
28454 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
28455 #if defined(TARGET_MIPS64)
28456 if (env->cpu_model->insn_flags & ISA_MIPS3) {
28457 env->SEGMask |= 3ULL << 62;
28459 #endif
28460 env->PABITS = env->cpu_model->PABITS;
28461 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
28462 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
28463 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
28464 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
28465 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
28466 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
28467 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
28468 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
28469 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
28470 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
28471 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
28472 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
28473 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
28474 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
28475 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
28476 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
28477 env->msair = env->cpu_model->MSAIR;
28478 env->insn_flags = env->cpu_model->insn_flags;
28480 #if defined(CONFIG_USER_ONLY)
28481 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
28482 # ifdef TARGET_MIPS64
28483 /* Enable 64-bit register mode. */
28484 env->CP0_Status |= (1 << CP0St_PX);
28485 # endif
28486 # ifdef TARGET_ABI_MIPSN64
28487 /* Enable 64-bit address mode. */
28488 env->CP0_Status |= (1 << CP0St_UX);
28489 # endif
28490 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
28491 hardware registers. */
28492 env->CP0_HWREna |= 0x0000000F;
28493 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
28494 env->CP0_Status |= (1 << CP0St_CU1);
28496 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
28497 env->CP0_Status |= (1 << CP0St_MX);
28499 # if defined(TARGET_MIPS64)
28500 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
28501 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
28502 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
28503 env->CP0_Status |= (1 << CP0St_FR);
28505 # endif
28506 #else
28507 if (env->hflags & MIPS_HFLAG_BMASK) {
28508 /* If the exception was raised from a delay slot,
28509 come back to the jump. */
28510 env->CP0_ErrorEPC = (env->active_tc.PC
28511 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
28512 } else {
28513 env->CP0_ErrorEPC = env->active_tc.PC;
28515 env->active_tc.PC = env->exception_base;
28516 env->CP0_Random = env->tlb->nb_tlb - 1;
28517 env->tlb->tlb_in_use = env->tlb->nb_tlb;
28518 env->CP0_Wired = 0;
28519 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
28520 env->CP0_EBase = (cs->cpu_index & 0x3FF);
28521 if (mips_um_ksegs_enabled()) {
28522 env->CP0_EBase |= 0x40000000;
28523 } else {
28524 env->CP0_EBase |= (int32_t)0x80000000;
28526 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
28527 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
28529 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
28530 0x3ff : 0xff;
28531 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
28532 /* vectored interrupts not implemented, timer on int 7,
28533 no performance counters. */
28534 env->CP0_IntCtl = 0xe0000000;
28536 int i;
28538 for (i = 0; i < 7; i++) {
28539 env->CP0_WatchLo[i] = 0;
28540 env->CP0_WatchHi[i] = 0x80000000;
28542 env->CP0_WatchLo[7] = 0;
28543 env->CP0_WatchHi[7] = 0;
28545 /* Count register increments in debug mode, EJTAG version 1 */
28546 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
28548 cpu_mips_store_count(env, 1);
28550 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
28551 int i;
28553 /* Only TC0 on VPE 0 starts as active. */
28554 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
28555 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
28556 env->tcs[i].CP0_TCHalt = 1;
28558 env->active_tc.CP0_TCHalt = 1;
28559 cs->halted = 1;
28561 if (cs->cpu_index == 0) {
28562 /* VPE0 starts up enabled. */
28563 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
28564 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
28566 /* TC0 starts up unhalted. */
28567 cs->halted = 0;
28568 env->active_tc.CP0_TCHalt = 0;
28569 env->tcs[0].CP0_TCHalt = 0;
28570 /* With thread 0 active. */
28571 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
28572 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
28577 * Configure default legacy segmentation control. We use this regardless of
28578 * whether segmentation control is presented to the guest.
28580 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
28581 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
28582 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
28583 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
28584 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
28585 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
28586 (2 << CP0SC_C);
28587 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
28588 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
28589 (3 << CP0SC_C)) << 16;
28590 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
28591 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
28592 (1 << CP0SC_EU) | (2 << CP0SC_C);
28593 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
28594 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
28595 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
28596 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
28597 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
28598 #endif
28599 if ((env->insn_flags & ISA_MIPS32R6) &&
28600 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
28601 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
28602 env->CP0_Status |= (1 << CP0St_FR);
28605 if (env->insn_flags & ISA_MIPS32R6) {
28606 /* PTW = 1 */
28607 env->CP0_PWSize = 0x40;
28608 /* GDI = 12 */
28609 /* UDI = 12 */
28610 /* MDI = 12 */
28611 /* PRI = 12 */
28612 /* PTEI = 2 */
28613 env->CP0_PWField = 0x0C30C302;
28614 } else {
28615 /* GDI = 0 */
28616 /* UDI = 0 */
28617 /* MDI = 0 */
28618 /* PRI = 0 */
28619 /* PTEI = 2 */
28620 env->CP0_PWField = 0x02;
28623 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
28624 /* microMIPS on reset when Config3.ISA is 3 */
28625 env->hflags |= MIPS_HFLAG_M16;
28628 /* MSA */
28629 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
28630 msa_reset(env);
28633 compute_hflags(env);
28634 restore_fp_status(env);
28635 restore_pamask(env);
28636 cs->exception_index = EXCP_NONE;
28638 if (semihosting_get_argc()) {
28639 /* UHI interface can be used to obtain argc and argv */
28640 env->active_tc.gpr[4] = -1;
28644 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
28645 target_ulong *data)
28647 env->active_tc.PC = data[0];
28648 env->hflags &= ~MIPS_HFLAG_BMASK;
28649 env->hflags |= data[1];
28650 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
28651 case MIPS_HFLAG_BR:
28652 break;
28653 case MIPS_HFLAG_BC:
28654 case MIPS_HFLAG_BL:
28655 case MIPS_HFLAG_B:
28656 env->btarget = data[2];
28657 break;