target/mips: Fix emulation of microMIPS R6 <SELEQZ|SELNEZ>.<D|S>
[qemu/ar7.git] / target / mips / translate.c
blob2890219f0b0472764a15c494aedfbaebbb4ae5cd
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
467 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
468 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
471 /* DBSHFL opcodes */
472 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
474 enum {
475 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
476 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
477 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
478 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
479 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
482 /* MIPS DSP REGIMM opcodes */
483 enum {
484 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
485 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
488 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
489 /* MIPS DSP Load */
490 enum {
491 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
492 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
493 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
494 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
497 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498 enum {
499 /* MIPS DSP Arithmetic Sub-class */
500 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
501 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
502 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
503 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
507 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
508 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
509 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
516 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
517 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
518 /* MIPS DSP Multiply Sub-class insns */
519 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
521 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
522 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
527 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
528 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
532 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
533 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
543 /* MIPS DSP Multiply Sub-class insns */
544 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
545 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
546 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
550 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551 enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
554 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
555 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
566 /* DSP Bit/Manipulation Sub-class */
567 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
574 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
584 /* DSP Compare-Pick Sub-class */
585 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
602 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
603 enum {
604 /* MIPS DSP GPR-Based Shift Sub-class */
605 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
607 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
629 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
630 enum {
631 /* MIPS DSP Multiply Sub-class insns */
632 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
634 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
656 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657 enum {
658 /* DSP Bit/Manipulation Sub-class */
659 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
662 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
663 enum {
664 /* MIPS DSP Append Sub-class */
665 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
666 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
667 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
670 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
673 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
674 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
675 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
685 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
686 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
687 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
688 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
689 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
692 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
693 enum {
694 /* MIPS DSP Arithmetic Sub-class */
695 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
721 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
722 enum {
723 /* MIPS DSP Multiply Sub-class insns */
724 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
725 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
726 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
729 /* MIPS DSP Arithmetic Sub-class */
730 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
731 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
732 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
741 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
742 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
753 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
754 enum {
755 /* DSP Compare-Pick Sub-class */
756 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
786 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
787 enum {
788 /* DSP Append Sub-class */
789 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
790 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
791 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
792 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
795 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
798 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
799 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
800 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
801 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
821 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
822 enum {
823 /* DSP Bit/Manipulation Sub-class */
824 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
827 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
828 enum {
829 /* MIPS DSP Multiply Sub-class insns */
830 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
858 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
859 enum {
860 /* MIPS DSP GPR-Based Shift Sub-class */
861 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
889 /* Coprocessor 0 (rs field) */
890 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
892 enum {
893 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
894 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
895 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
896 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
897 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
898 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
899 OPC_MFTR = (0x08 << 21) | OPC_CP0,
900 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
901 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
902 OPC_MTTR = (0x0C << 21) | OPC_CP0,
903 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
904 OPC_C0 = (0x10 << 21) | OPC_CP0,
905 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
906 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
907 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
908 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
909 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
910 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
911 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
912 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
913 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
914 OPC_C0_A = (0x1A << 21) | OPC_CP0,
915 OPC_C0_B = (0x1B << 21) | OPC_CP0,
916 OPC_C0_C = (0x1C << 21) | OPC_CP0,
917 OPC_C0_D = (0x1D << 21) | OPC_CP0,
918 OPC_C0_E = (0x1E << 21) | OPC_CP0,
919 OPC_C0_F = (0x1F << 21) | OPC_CP0,
922 /* MFMC0 opcodes */
923 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
925 enum {
926 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
927 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
928 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
929 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
930 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
931 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
932 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
933 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
936 /* Coprocessor 0 (with rs == C0) */
937 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
939 enum {
940 OPC_TLBR = 0x01 | OPC_C0,
941 OPC_TLBWI = 0x02 | OPC_C0,
942 OPC_TLBINV = 0x03 | OPC_C0,
943 OPC_TLBINVF = 0x04 | OPC_C0,
944 OPC_TLBWR = 0x06 | OPC_C0,
945 OPC_TLBP = 0x08 | OPC_C0,
946 OPC_RFE = 0x10 | OPC_C0,
947 OPC_ERET = 0x18 | OPC_C0,
948 OPC_DERET = 0x1F | OPC_C0,
949 OPC_WAIT = 0x20 | OPC_C0,
952 /* Coprocessor 1 (rs field) */
953 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
955 /* Values for the fmt field in FP instructions */
956 enum {
957 /* 0 - 15 are reserved */
958 FMT_S = 16, /* single fp */
959 FMT_D = 17, /* double fp */
960 FMT_E = 18, /* extended fp */
961 FMT_Q = 19, /* quad fp */
962 FMT_W = 20, /* 32-bit fixed */
963 FMT_L = 21, /* 64-bit fixed */
964 FMT_PS = 22, /* paired single fp */
965 /* 23 - 31 are reserved */
968 enum {
969 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
970 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
971 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
972 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
973 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
974 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
975 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
976 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
977 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
978 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
979 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
980 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
981 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
982 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
983 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
984 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
985 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
986 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
987 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
988 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
989 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
990 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
991 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
992 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
993 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
994 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
995 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
996 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
997 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
998 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1001 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1002 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1004 enum {
1005 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1006 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1007 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1008 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1011 enum {
1012 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1013 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1016 enum {
1017 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1018 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1021 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1023 enum {
1024 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1025 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1026 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1027 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1028 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1029 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1030 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1031 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1032 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1033 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1034 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1037 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1039 enum {
1040 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1041 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1042 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1043 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1044 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1045 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1046 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1047 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1049 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1050 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1051 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1052 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1053 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1054 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1055 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1056 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1059 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1060 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1061 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1062 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1063 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1064 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1065 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1067 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1068 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1069 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1070 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1071 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1072 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1073 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1074 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1076 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1077 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1078 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1079 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1080 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1081 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1083 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1084 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1085 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1086 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1087 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1088 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1090 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1091 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1092 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1093 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1094 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1095 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1097 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1098 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1099 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1100 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1101 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1102 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1104 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1105 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1106 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1107 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1108 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1109 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1111 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1112 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1113 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1114 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1115 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1116 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1118 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1119 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1120 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1121 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1122 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1123 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1125 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1126 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1127 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1128 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1129 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1130 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1134 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1136 enum {
1137 OPC_LWXC1 = 0x00 | OPC_CP3,
1138 OPC_LDXC1 = 0x01 | OPC_CP3,
1139 OPC_LUXC1 = 0x05 | OPC_CP3,
1140 OPC_SWXC1 = 0x08 | OPC_CP3,
1141 OPC_SDXC1 = 0x09 | OPC_CP3,
1142 OPC_SUXC1 = 0x0D | OPC_CP3,
1143 OPC_PREFX = 0x0F | OPC_CP3,
1144 OPC_ALNV_PS = 0x1E | OPC_CP3,
1145 OPC_MADD_S = 0x20 | OPC_CP3,
1146 OPC_MADD_D = 0x21 | OPC_CP3,
1147 OPC_MADD_PS = 0x26 | OPC_CP3,
1148 OPC_MSUB_S = 0x28 | OPC_CP3,
1149 OPC_MSUB_D = 0x29 | OPC_CP3,
1150 OPC_MSUB_PS = 0x2E | OPC_CP3,
1151 OPC_NMADD_S = 0x30 | OPC_CP3,
1152 OPC_NMADD_D = 0x31 | OPC_CP3,
1153 OPC_NMADD_PS= 0x36 | OPC_CP3,
1154 OPC_NMSUB_S = 0x38 | OPC_CP3,
1155 OPC_NMSUB_D = 0x39 | OPC_CP3,
1156 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1159 /* MSA Opcodes */
1160 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1161 enum {
1162 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1163 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1164 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1165 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1166 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1167 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1168 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1169 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1170 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1171 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1172 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1173 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1174 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1175 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1176 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1177 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1178 OPC_MSA_ELM = 0x19 | OPC_MSA,
1179 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1180 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1181 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1182 OPC_MSA_VEC = 0x1E | OPC_MSA,
1184 /* MI10 instruction */
1185 OPC_LD_B = (0x20) | OPC_MSA,
1186 OPC_LD_H = (0x21) | OPC_MSA,
1187 OPC_LD_W = (0x22) | OPC_MSA,
1188 OPC_LD_D = (0x23) | OPC_MSA,
1189 OPC_ST_B = (0x24) | OPC_MSA,
1190 OPC_ST_H = (0x25) | OPC_MSA,
1191 OPC_ST_W = (0x26) | OPC_MSA,
1192 OPC_ST_D = (0x27) | OPC_MSA,
1195 enum {
1196 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1197 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1198 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1199 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1200 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1201 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1202 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1203 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1204 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1205 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1206 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1207 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1208 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1210 /* I8 instruction */
1211 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1212 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1213 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1214 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1215 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1216 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1217 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1218 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1219 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1220 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1222 /* VEC/2R/2RF instruction */
1223 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1224 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1225 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1226 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1227 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1228 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1229 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1231 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1232 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1234 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1235 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1236 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1237 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1238 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1240 /* 2RF instruction df(bit 16) = _w, _d */
1241 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1242 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1243 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1244 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1245 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1246 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1247 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1248 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1249 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1250 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1251 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1252 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1253 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1254 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1255 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1256 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1258 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1259 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1260 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1261 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1262 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1263 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1264 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1265 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1266 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1267 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1268 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1269 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1270 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1272 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1274 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1275 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1276 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1278 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1279 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1281 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1282 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1283 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1284 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1285 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1290 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1292 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1293 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1294 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1295 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1296 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1297 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1298 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1299 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1300 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1301 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1310 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1311 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1312 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1313 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1314 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1315 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1316 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1317 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1318 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1319 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1320 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1321 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1323 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1324 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1325 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1326 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1327 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1328 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1329 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1330 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1331 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1332 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1334 /* 3RF instruction _df(bit 21) = _w, _d */
1335 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1337 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1338 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1339 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1340 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1342 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1343 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1346 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1348 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1351 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1353 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1357 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1358 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1361 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1362 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1363 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1364 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1365 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1366 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1367 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1369 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1370 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1372 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1373 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1377 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1378 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1379 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1380 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1381 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1382 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1383 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1384 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1385 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1386 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1387 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1388 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1389 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1394 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1395 * ============================================
1397 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1398 * instructions set. It is designed to fit the needs of signal, graphical and
1399 * video processing applications. MXU instruction set is used in Xburst family
1400 * of microprocessors by Ingenic.
1402 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1403 * the control register.
1405 * The notation used in MXU assembler mnemonics:
1407 * XRa, XRb, XRc, XRd - MXU registers
1408 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1409 * s12 - a subfield of an instruction code
1410 * strd2 - a subfield of an instruction code
1411 * eptn2 - a subfield of an instruction code
1412 * eptn3 - a subfield of an instruction code
1413 * optn2 - a subfield of an instruction code
1414 * optn3 - a subfield of an instruction code
1415 * sft4 - a subfield of an instruction code
1417 * Load/Store instructions Multiplication instructions
1418 * ----------------------- ---------------------------
1420 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1421 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1422 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1423 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1424 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1425 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1426 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1427 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1428 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1429 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1430 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1431 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1432 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1433 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1434 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1435 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1436 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1437 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1438 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1439 * S16SDI XRa, Rb, s10, eptn2
1440 * S8LDD XRa, Rb, s8, eptn3
1441 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1442 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1443 * S8SDI XRa, Rb, s8, eptn3
1444 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1445 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1446 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1447 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1448 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1449 * S32CPS XRa, XRb, XRc
1450 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1451 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1452 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1453 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1454 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1455 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1456 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1457 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1458 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1459 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1460 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1461 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1462 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1463 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1464 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1465 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1466 * Q8SLT XRa, XRb, XRc
1467 * Q8SLTU XRa, XRb, XRc
1468 * Q8MOVZ XRa, XRb, XRc Shift instructions
1469 * Q8MOVN XRa, XRb, XRc ------------------
1471 * D32SLL XRa, XRb, XRc, XRd, sft4
1472 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1473 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1474 * D32SARL XRa, XRb, XRc, sft4
1475 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1476 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1477 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1478 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1479 * Q16SLL XRa, XRb, XRc, XRd, sft4
1480 * Q16SLR XRa, XRb, XRc, XRd, sft4
1481 * Miscelaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1482 * ------------------------- Q16SLLV XRa, XRb, Rb
1483 * Q16SLRV XRa, XRb, Rb
1484 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1485 * S32ALN XRa, XRb, XRc, Rb
1486 * S32ALNI XRa, XRb, XRc, s3
1487 * S32LUI XRa, s8, optn3 Move instructions
1488 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1489 * S32EXTRV XRa, XRb, Rs, Rt
1490 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1491 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1494 * bits
1495 * 05..00
1497 * ┌─ 000000 ─ OPC_MXU_S32MADD
1498 * ├─ 000001 ─ OPC_MXU_S32MADDU
1499 * ├─ 000010 ─ <not assigned>
1500 * │ 20..18
1501 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1502 * │ ├─ 001 ─ OPC_MXU_S32MIN
1503 * │ ├─ 010 ─ OPC_MXU_D16MAX
1504 * │ ├─ 011 ─ OPC_MXU_D16MIN
1505 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1506 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1507 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1508 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1509 * ├─ 000100 ─ OPC_MXU_S32MSUB
1510 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1511 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1512 * │ ├─ 001 ─ OPC_MXU_D16SLT
1513 * │ ├─ 010 ─ OPC_MXU_D16AVG
1514 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1515 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1516 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1517 * │ └─ 111 ─ OPC_MXU_Q8ADD
1518 * │
1519 * │ 20..18
1520 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1521 * │ ├─ 010 ─ OPC_MXU_D16CPS
1522 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1523 * │ └─ 110 ─ OPC_MXU_Q16SAT
1524 * ├─ 001000 ─ OPC_MXU_D16MUL
1525 * │ 25..24
1526 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1527 * │ └─ 01 ─ OPC_MXU_D16MULE
1528 * ├─ 001010 ─ OPC_MXU_D16MAC
1529 * ├─ 001011 ─ OPC_MXU_D16MACF
1530 * ├─ 001100 ─ OPC_MXU_D16MADL
1531 * │ 25..24
1532 * ├─ 001101 ─ OPC_MXU__POOL04 ─┬─ 00 ─ OPC_MXU_S16MAD
1533 * │ └─ 01 ─ OPC_MXU_S16MAD_1
1534 * ├─ 001110 ─ OPC_MXU_Q16ADD
1535 * ├─ 001111 ─ OPC_MXU_D16MACE
1536 * │ 23
1537 * ├─ 010000 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32LDD
1538 * │ └─ 1 ─ OPC_MXU_S32LDDR
1539 * │
1540 * │ 23
1541 * ├─ 010001 ─ OPC_MXU__POOL06 ─┬─ 0 ─ OPC_MXU_S32STD
1542 * │ └─ 1 ─ OPC_MXU_S32STDR
1543 * │
1544 * │ 13..10
1545 * ├─ 010010 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1546 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1547 * │
1548 * │ 13..10
1549 * ├─ 010011 ─ OPC_MXU__POOL08 ─┬─ 0000 ─ OPC_MXU_S32STDV
1550 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1551 * │
1552 * │ 23
1553 * ├─ 010100 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32LDI
1554 * │ └─ 1 ─ OPC_MXU_S32LDIR
1555 * │
1556 * │ 23
1557 * ├─ 010101 ─ OPC_MXU__POOL10 ─┬─ 0 ─ OPC_MXU_S32SDI
1558 * │ └─ 1 ─ OPC_MXU_S32SDIR
1559 * │
1560 * │ 13..10
1561 * ├─ 010110 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1562 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1563 * │
1564 * │ 13..10
1565 * ├─ 010111 ─ OPC_MXU__POOL12 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1566 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1567 * ├─ 011000 ─ OPC_MXU_D32ADD
1568 * │ 23..22
1569 * MXU ├─ 011001 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_D32ACC
1570 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1571 * │ └─ 10 ─ OPC_MXU_D32ASUM
1572 * ├─ 011010 ─ <not assigned>
1573 * │ 23..22
1574 * ├─ 011011 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q16ACC
1575 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1576 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1577 * │
1578 * │ 23..22
1579 * ├─ 011100 ─ OPC_MXU__POOL15 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1580 * │ ├─ 01 ─ OPC_MXU_D8SUM
1581 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1582 * ├─ 011110 ─ <not assigned>
1583 * ├─ 011111 ─ <not assigned>
1584 * ├─ 100000 ─ <not assigned>
1585 * ├─ 100001 ─ <not assigned>
1586 * ├─ 100010 ─ OPC_MXU_S8LDD
1587 * ├─ 100011 ─ OPC_MXU_S8STD
1588 * ├─ 100100 ─ OPC_MXU_S8LDI
1589 * ├─ 100101 ─ OPC_MXU_S8SDI
1590 * │ 15..14
1591 * ├─ 100110 ─ OPC_MXU__POOL16 ─┬─ 00 ─ OPC_MXU_S32MUL
1592 * │ ├─ 00 ─ OPC_MXU_S32MULU
1593 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1594 * │ └─ 00 ─ OPC_MXU_S32EXTRV
1595 * │
1596 * │ 20..18
1597 * ├─ 100111 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_D32SARW
1598 * │ ├─ 001 ─ OPC_MXU_S32ALN
1599 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1600 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1601 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1602 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1603 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1604 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1605 * ├─ 101000 ─ <not assigned>
1606 * ├─ 101001 ─ <not assigned>
1607 * ├─ 101010 ─ <not assigned>
1608 * ├─ 101011 ─ <not assigned>
1609 * ├─ 101100 ─ <not assigned>
1610 * ├─ 101101 ─ <not assigned>
1611 * ├─ 101110 ─ OPC_MXU_S32M2I
1612 * ├─ 101111 ─ OPC_MXU_S32I2M
1613 * ├─ 110000 ─ OPC_MXU_D32SLL
1614 * ├─ 110001 ─ OPC_MXU_D32SLR
1615 * ├─ 110010 ─ OPC_MXU_D32SARL
1616 * ├─ 110011 ─ OPC_MXU_D32SAR
1617 * ├─ 110100 ─ OPC_MXU_Q16SLL
1618 * ├─ 110101 ─ OPC_MXU_Q16SLR 20..18
1619 * ├─ 110110 ─ OPC_MXU__POOL18 ─┬─ 000 ─ OPC_MXU_D32SLLV
1620 * │ ├─ 001 ─ OPC_MXU_D32SLRV
1621 * │ ├─ 010 ─ OPC_MXU_D32SARV
1622 * │ ├─ 011 ─ OPC_MXU_Q16SLLV
1623 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1624 * │ └─ 101 ─ OPC_MXU_Q16SARV
1625 * ├─ 110111 ─ OPC_MXU_Q16SAR
1626 * │ 23..22
1627 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1628 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1629 * │
1630 * │ 20..18
1631 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1632 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1633 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1634 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1635 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1636 * │ └─ 101 ─ OPC_MXU_S32MOV
1637 * │
1638 * │ 23..22
1639 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1640 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1641 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1642 * ├─ 111100 ─ OPC_MXU_Q8MADL
1643 * ├─ 111101 ─ OPC_MXU_S32SFL
1644 * ├─ 111110 ─ OPC_MXU_Q8SAD
1645 * └─ 111111 ─ <not assigned>
1648 * Compiled after:
1650 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1651 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1654 enum {
1655 OPC_MXU_S32MADD = 0x00,
1656 OPC_MXU_S32MADDU = 0x01,
1657 /* not assigned 0x02 */
1658 OPC_MXU__POOL00 = 0x03,
1659 OPC_MXU_S32MSUB = 0x04,
1660 OPC_MXU_S32MSUBU = 0x05,
1661 OPC_MXU__POOL01 = 0x06,
1662 OPC_MXU__POOL02 = 0x07,
1663 OPC_MXU_D16MUL = 0x08,
1664 OPC_MXU__POOL03 = 0x09,
1665 OPC_MXU_D16MAC = 0x0A,
1666 OPC_MXU_D16MACF = 0x0B,
1667 OPC_MXU_D16MADL = 0x0C,
1668 OPC_MXU__POOL04 = 0x0D,
1669 OPC_MXU_Q16ADD = 0x0E,
1670 OPC_MXU_D16MACE = 0x0F,
1671 OPC_MXU__POOL05 = 0x10,
1672 OPC_MXU__POOL06 = 0x11,
1673 OPC_MXU__POOL07 = 0x12,
1674 OPC_MXU__POOL08 = 0x13,
1675 OPC_MXU__POOL09 = 0x14,
1676 OPC_MXU__POOL10 = 0x15,
1677 OPC_MXU__POOL11 = 0x16,
1678 OPC_MXU__POOL12 = 0x17,
1679 OPC_MXU_D32ADD = 0x18,
1680 OPC_MXU__POOL13 = 0x19,
1681 /* not assigned 0x1A */
1682 OPC_MXU__POOL14 = 0x1B,
1683 OPC_MXU__POOL15 = 0x1C,
1684 OPC_MXU_Q8ACCE = 0x1D,
1685 /* not assigned 0x1E */
1686 /* not assigned 0x1F */
1687 /* not assigned 0x20 */
1688 /* not assigned 0x21 */
1689 OPC_MXU_S8LDD = 0x22,
1690 OPC_MXU_S8STD = 0x23,
1691 OPC_MXU_S8LDI = 0x24,
1692 OPC_MXU_S8SDI = 0x25,
1693 OPC_MXU__POOL16 = 0x26,
1694 OPC_MXU__POOL17 = 0x27,
1695 OPC_MXU_LXB = 0x28,
1696 /* not assigned 0x29 */
1697 OPC_MXU_S16LDD = 0x2A,
1698 OPC_MXU_S16STD = 0x2B,
1699 OPC_MXU_S16LDI = 0x2C,
1700 OPC_MXU_S16SDI = 0x2D,
1701 OPC_MXU_S32M2I = 0x2E,
1702 OPC_MXU_S32I2M = 0x2F,
1703 OPC_MXU_D32SLL = 0x30,
1704 OPC_MXU_D32SLR = 0x31,
1705 OPC_MXU_D32SARL = 0x32,
1706 OPC_MXU_D32SAR = 0x33,
1707 OPC_MXU_Q16SLL = 0x34,
1708 OPC_MXU_Q16SLR = 0x35,
1709 OPC_MXU__POOL18 = 0x36,
1710 OPC_MXU_Q16SAR = 0x37,
1711 OPC_MXU__POOL19 = 0x38,
1712 OPC_MXU__POOL20 = 0x39,
1713 OPC_MXU__POOL21 = 0x3A,
1714 OPC_MXU_Q16SCOP = 0x3B,
1715 OPC_MXU_Q8MADL = 0x3C,
1716 OPC_MXU_S32SFL = 0x3D,
1717 OPC_MXU_Q8SAD = 0x3E,
1718 /* not assigned 0x3F */
1723 * MXU pool 00
1725 enum {
1726 OPC_MXU_S32MAX = 0x00,
1727 OPC_MXU_S32MIN = 0x01,
1728 OPC_MXU_D16MAX = 0x02,
1729 OPC_MXU_D16MIN = 0x03,
1730 OPC_MXU_Q8MAX = 0x04,
1731 OPC_MXU_Q8MIN = 0x05,
1732 OPC_MXU_Q8SLT = 0x06,
1733 OPC_MXU_Q8SLTU = 0x07,
1737 * MXU pool 01
1739 enum {
1740 OPC_MXU_S32SLT = 0x00,
1741 OPC_MXU_D16SLT = 0x01,
1742 OPC_MXU_D16AVG = 0x02,
1743 OPC_MXU_D16AVGR = 0x03,
1744 OPC_MXU_Q8AVG = 0x04,
1745 OPC_MXU_Q8AVGR = 0x05,
1746 OPC_MXU_Q8ADD = 0x07,
1750 * MXU pool 02
1752 enum {
1753 OPC_MXU_S32CPS = 0x00,
1754 OPC_MXU_D16CPS = 0x02,
1755 OPC_MXU_Q8ABD = 0x04,
1756 OPC_MXU_Q16SAT = 0x06,
1760 * MXU pool 03
1762 enum {
1763 OPC_MXU_D16MULF = 0x00,
1764 OPC_MXU_D16MULE = 0x01,
1768 * MXU pool 04
1770 enum {
1771 OPC_MXU_S16MAD = 0x00,
1772 OPC_MXU_S16MAD_1 = 0x01,
1776 * MXU pool 05
1778 enum {
1779 OPC_MXU_S32LDD = 0x00,
1780 OPC_MXU_S32LDDR = 0x01,
1784 * MXU pool 06
1786 enum {
1787 OPC_MXU_S32STD = 0x00,
1788 OPC_MXU_S32STDR = 0x01,
1792 * MXU pool 07
1794 enum {
1795 OPC_MXU_S32LDDV = 0x00,
1796 OPC_MXU_S32LDDVR = 0x01,
1800 * MXU pool 08
1802 enum {
1803 OPC_MXU_S32STDV = 0x00,
1804 OPC_MXU_S32STDVR = 0x01,
1808 * MXU pool 09
1810 enum {
1811 OPC_MXU_S32LDI = 0x00,
1812 OPC_MXU_S32LDIR = 0x01,
1816 * MXU pool 10
1818 enum {
1819 OPC_MXU_S32SDI = 0x00,
1820 OPC_MXU_S32SDIR = 0x01,
1824 * MXU pool 11
1826 enum {
1827 OPC_MXU_S32LDIV = 0x00,
1828 OPC_MXU_S32LDIVR = 0x01,
1832 * MXU pool 12
1834 enum {
1835 OPC_MXU_S32SDIV = 0x00,
1836 OPC_MXU_S32SDIVR = 0x01,
1840 * MXU pool 13
1842 enum {
1843 OPC_MXU_D32ACC = 0x00,
1844 OPC_MXU_D32ACCM = 0x01,
1845 OPC_MXU_D32ASUM = 0x02,
1849 * MXU pool 14
1851 enum {
1852 OPC_MXU_Q16ACC = 0x00,
1853 OPC_MXU_Q16ACCM = 0x01,
1854 OPC_MXU_Q16ASUM = 0x02,
1858 * MXU pool 15
1860 enum {
1861 OPC_MXU_Q8ADDE = 0x00,
1862 OPC_MXU_D8SUM = 0x01,
1863 OPC_MXU_D8SUMC = 0x02,
1867 * MXU pool 16
1869 enum {
1870 OPC_MXU_S32MUL = 0x00,
1871 OPC_MXU_S32MULU = 0x01,
1872 OPC_MXU_S32EXTR = 0x02,
1873 OPC_MXU_S32EXTRV = 0x03,
1877 * MXU pool 17
1879 enum {
1880 OPC_MXU_D32SARW = 0x00,
1881 OPC_MXU_S32ALN = 0x01,
1882 OPC_MXU_S32ALNI = 0x02,
1883 OPC_MXU_S32NOR = 0x03,
1884 OPC_MXU_S32AND = 0x04,
1885 OPC_MXU_S32OR = 0x05,
1886 OPC_MXU_S32XOR = 0x06,
1887 OPC_MXU_S32LUI = 0x07,
1891 * MXU pool 18
1893 enum {
1894 OPC_MXU_D32SLLV = 0x00,
1895 OPC_MXU_D32SLRV = 0x01,
1896 OPC_MXU_D32SARV = 0x03,
1897 OPC_MXU_Q16SLLV = 0x04,
1898 OPC_MXU_Q16SLRV = 0x05,
1899 OPC_MXU_Q16SARV = 0x07,
1903 * MXU pool 19
1905 enum {
1906 OPC_MXU_Q8MUL = 0x00,
1907 OPC_MXU_Q8MULSU = 0x01,
1911 * MXU pool 20
1913 enum {
1914 OPC_MXU_Q8MOVZ = 0x00,
1915 OPC_MXU_Q8MOVN = 0x01,
1916 OPC_MXU_D16MOVZ = 0x02,
1917 OPC_MXU_D16MOVN = 0x03,
1918 OPC_MXU_S32MOVZ = 0x04,
1919 OPC_MXU_S32MOVN = 0x05,
1923 * MXU pool 21
1925 enum {
1926 OPC_MXU_Q8MAC = 0x00,
1927 OPC_MXU_Q8MACSU = 0x01,
1931 /* global register indices */
1932 static TCGv cpu_gpr[32], cpu_PC;
1933 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1934 static TCGv cpu_dspctrl, btarget, bcond;
1935 static TCGv_i32 hflags;
1936 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1937 static TCGv_i64 fpu_f64[32];
1938 static TCGv_i64 msa_wr_d[64];
1940 #include "exec/gen-icount.h"
1942 #define gen_helper_0e0i(name, arg) do { \
1943 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1944 gen_helper_##name(cpu_env, helper_tmp); \
1945 tcg_temp_free_i32(helper_tmp); \
1946 } while(0)
1948 #define gen_helper_0e1i(name, arg1, arg2) do { \
1949 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1950 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1951 tcg_temp_free_i32(helper_tmp); \
1952 } while(0)
1954 #define gen_helper_1e0i(name, ret, arg1) do { \
1955 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1956 gen_helper_##name(ret, cpu_env, helper_tmp); \
1957 tcg_temp_free_i32(helper_tmp); \
1958 } while(0)
1960 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1961 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1962 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1963 tcg_temp_free_i32(helper_tmp); \
1964 } while(0)
1966 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1967 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1968 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1969 tcg_temp_free_i32(helper_tmp); \
1970 } while(0)
1972 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1973 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1974 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1975 tcg_temp_free_i32(helper_tmp); \
1976 } while(0)
1978 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1979 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1980 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1981 tcg_temp_free_i32(helper_tmp); \
1982 } while(0)
1984 typedef struct DisasContext {
1985 DisasContextBase base;
1986 target_ulong saved_pc;
1987 target_ulong page_start;
1988 uint32_t opcode;
1989 uint64_t insn_flags;
1990 int32_t CP0_Config1;
1991 int32_t CP0_Config2;
1992 int32_t CP0_Config3;
1993 int32_t CP0_Config5;
1994 /* Routine used to access memory */
1995 int mem_idx;
1996 TCGMemOp default_tcg_memop_mask;
1997 uint32_t hflags, saved_hflags;
1998 target_ulong btarget;
1999 bool ulri;
2000 int kscrexist;
2001 bool rxi;
2002 int ie;
2003 bool bi;
2004 bool bp;
2005 uint64_t PAMask;
2006 bool mvh;
2007 bool eva;
2008 bool sc;
2009 int CP0_LLAddr_shift;
2010 bool ps;
2011 bool vp;
2012 bool cmgcr;
2013 bool mrp;
2014 bool nan2008;
2015 bool abs2008;
2016 } DisasContext;
2018 #define DISAS_STOP DISAS_TARGET_0
2019 #define DISAS_EXIT DISAS_TARGET_1
2021 static const char * const regnames[] = {
2022 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2023 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2024 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2025 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2028 static const char * const regnames_HI[] = {
2029 "HI0", "HI1", "HI2", "HI3",
2032 static const char * const regnames_LO[] = {
2033 "LO0", "LO1", "LO2", "LO3",
2036 static const char * const fregnames[] = {
2037 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2038 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2039 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2040 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2043 static const char * const msaregnames[] = {
2044 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2045 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2046 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2047 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2048 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2049 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2050 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2051 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2052 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2053 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2054 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2055 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2056 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2057 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2058 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2059 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2062 #define LOG_DISAS(...) \
2063 do { \
2064 if (MIPS_DEBUG_DISAS) { \
2065 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2067 } while (0)
2069 #define MIPS_INVAL(op) \
2070 do { \
2071 if (MIPS_DEBUG_DISAS) { \
2072 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2073 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2074 ctx->base.pc_next, ctx->opcode, op, \
2075 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2076 ((ctx->opcode >> 16) & 0x1F)); \
2078 } while (0)
2080 /* General purpose registers moves. */
2081 static inline void gen_load_gpr (TCGv t, int reg)
2083 if (reg == 0)
2084 tcg_gen_movi_tl(t, 0);
2085 else
2086 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2089 static inline void gen_store_gpr (TCGv t, int reg)
2091 if (reg != 0)
2092 tcg_gen_mov_tl(cpu_gpr[reg], t);
2095 /* Moves to/from shadow registers. */
2096 static inline void gen_load_srsgpr (int from, int to)
2098 TCGv t0 = tcg_temp_new();
2100 if (from == 0)
2101 tcg_gen_movi_tl(t0, 0);
2102 else {
2103 TCGv_i32 t2 = tcg_temp_new_i32();
2104 TCGv_ptr addr = tcg_temp_new_ptr();
2106 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2107 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2108 tcg_gen_andi_i32(t2, t2, 0xf);
2109 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2110 tcg_gen_ext_i32_ptr(addr, t2);
2111 tcg_gen_add_ptr(addr, cpu_env, addr);
2113 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2114 tcg_temp_free_ptr(addr);
2115 tcg_temp_free_i32(t2);
2117 gen_store_gpr(t0, to);
2118 tcg_temp_free(t0);
2121 static inline void gen_store_srsgpr (int from, int to)
2123 if (to != 0) {
2124 TCGv t0 = tcg_temp_new();
2125 TCGv_i32 t2 = tcg_temp_new_i32();
2126 TCGv_ptr addr = tcg_temp_new_ptr();
2128 gen_load_gpr(t0, from);
2129 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2130 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2131 tcg_gen_andi_i32(t2, t2, 0xf);
2132 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2133 tcg_gen_ext_i32_ptr(addr, t2);
2134 tcg_gen_add_ptr(addr, cpu_env, addr);
2136 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2137 tcg_temp_free_ptr(addr);
2138 tcg_temp_free_i32(t2);
2139 tcg_temp_free(t0);
2143 /* Tests */
2144 static inline void gen_save_pc(target_ulong pc)
2146 tcg_gen_movi_tl(cpu_PC, pc);
2149 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2151 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2152 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2153 gen_save_pc(ctx->base.pc_next);
2154 ctx->saved_pc = ctx->base.pc_next;
2156 if (ctx->hflags != ctx->saved_hflags) {
2157 tcg_gen_movi_i32(hflags, ctx->hflags);
2158 ctx->saved_hflags = ctx->hflags;
2159 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2160 case MIPS_HFLAG_BR:
2161 break;
2162 case MIPS_HFLAG_BC:
2163 case MIPS_HFLAG_BL:
2164 case MIPS_HFLAG_B:
2165 tcg_gen_movi_tl(btarget, ctx->btarget);
2166 break;
2171 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2173 ctx->saved_hflags = ctx->hflags;
2174 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2175 case MIPS_HFLAG_BR:
2176 break;
2177 case MIPS_HFLAG_BC:
2178 case MIPS_HFLAG_BL:
2179 case MIPS_HFLAG_B:
2180 ctx->btarget = env->btarget;
2181 break;
2185 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2187 TCGv_i32 texcp = tcg_const_i32(excp);
2188 TCGv_i32 terr = tcg_const_i32(err);
2189 save_cpu_state(ctx, 1);
2190 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2191 tcg_temp_free_i32(terr);
2192 tcg_temp_free_i32(texcp);
2193 ctx->base.is_jmp = DISAS_NORETURN;
2196 static inline void generate_exception(DisasContext *ctx, int excp)
2198 gen_helper_0e0i(raise_exception, excp);
2201 static inline void generate_exception_end(DisasContext *ctx, int excp)
2203 generate_exception_err(ctx, excp, 0);
2206 /* Floating point register moves. */
2207 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2209 if (ctx->hflags & MIPS_HFLAG_FRE) {
2210 generate_exception(ctx, EXCP_RI);
2212 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2215 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2217 TCGv_i64 t64;
2218 if (ctx->hflags & MIPS_HFLAG_FRE) {
2219 generate_exception(ctx, EXCP_RI);
2221 t64 = tcg_temp_new_i64();
2222 tcg_gen_extu_i32_i64(t64, t);
2223 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2224 tcg_temp_free_i64(t64);
2227 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2229 if (ctx->hflags & MIPS_HFLAG_F64) {
2230 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2231 } else {
2232 gen_load_fpr32(ctx, t, reg | 1);
2236 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2238 if (ctx->hflags & MIPS_HFLAG_F64) {
2239 TCGv_i64 t64 = tcg_temp_new_i64();
2240 tcg_gen_extu_i32_i64(t64, t);
2241 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2242 tcg_temp_free_i64(t64);
2243 } else {
2244 gen_store_fpr32(ctx, t, reg | 1);
2248 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2250 if (ctx->hflags & MIPS_HFLAG_F64) {
2251 tcg_gen_mov_i64(t, fpu_f64[reg]);
2252 } else {
2253 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2257 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2259 if (ctx->hflags & MIPS_HFLAG_F64) {
2260 tcg_gen_mov_i64(fpu_f64[reg], t);
2261 } else {
2262 TCGv_i64 t0;
2263 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2264 t0 = tcg_temp_new_i64();
2265 tcg_gen_shri_i64(t0, t, 32);
2266 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2267 tcg_temp_free_i64(t0);
2271 static inline int get_fp_bit (int cc)
2273 if (cc)
2274 return 24 + cc;
2275 else
2276 return 23;
2279 /* Addresses computation */
2280 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2282 tcg_gen_add_tl(ret, arg0, arg1);
2284 #if defined(TARGET_MIPS64)
2285 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2286 tcg_gen_ext32s_i64(ret, ret);
2288 #endif
2291 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2292 target_long ofs)
2294 tcg_gen_addi_tl(ret, base, ofs);
2296 #if defined(TARGET_MIPS64)
2297 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2298 tcg_gen_ext32s_i64(ret, ret);
2300 #endif
2303 /* Addresses computation (translation time) */
2304 static target_long addr_add(DisasContext *ctx, target_long base,
2305 target_long offset)
2307 target_long sum = base + offset;
2309 #if defined(TARGET_MIPS64)
2310 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2311 sum = (int32_t)sum;
2313 #endif
2314 return sum;
2317 /* Sign-extract the low 32-bits to a target_long. */
2318 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2320 #if defined(TARGET_MIPS64)
2321 tcg_gen_ext32s_i64(ret, arg);
2322 #else
2323 tcg_gen_extrl_i64_i32(ret, arg);
2324 #endif
2327 /* Sign-extract the high 32-bits to a target_long. */
2328 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2330 #if defined(TARGET_MIPS64)
2331 tcg_gen_sari_i64(ret, arg, 32);
2332 #else
2333 tcg_gen_extrh_i64_i32(ret, arg);
2334 #endif
2337 static inline void check_cp0_enabled(DisasContext *ctx)
2339 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2340 generate_exception_err(ctx, EXCP_CpU, 0);
2343 static inline void check_cp1_enabled(DisasContext *ctx)
2345 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2346 generate_exception_err(ctx, EXCP_CpU, 1);
2349 /* Verify that the processor is running with COP1X instructions enabled.
2350 This is associated with the nabla symbol in the MIPS32 and MIPS64
2351 opcode tables. */
2353 static inline void check_cop1x(DisasContext *ctx)
2355 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2356 generate_exception_end(ctx, EXCP_RI);
2359 /* Verify that the processor is running with 64-bit floating-point
2360 operations enabled. */
2362 static inline void check_cp1_64bitmode(DisasContext *ctx)
2364 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2365 generate_exception_end(ctx, EXCP_RI);
2369 * Verify if floating point register is valid; an operation is not defined
2370 * if bit 0 of any register specification is set and the FR bit in the
2371 * Status register equals zero, since the register numbers specify an
2372 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2373 * in the Status register equals one, both even and odd register numbers
2374 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2376 * Multiple 64 bit wide registers can be checked by calling
2377 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2379 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2381 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2382 generate_exception_end(ctx, EXCP_RI);
2385 /* Verify that the processor is running with DSP instructions enabled.
2386 This is enabled by CP0 Status register MX(24) bit.
2389 static inline void check_dsp(DisasContext *ctx)
2391 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2392 if (ctx->insn_flags & ASE_DSP) {
2393 generate_exception_end(ctx, EXCP_DSPDIS);
2394 } else {
2395 generate_exception_end(ctx, EXCP_RI);
2400 static inline void check_dsp_r2(DisasContext *ctx)
2402 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2403 if (ctx->insn_flags & ASE_DSP) {
2404 generate_exception_end(ctx, EXCP_DSPDIS);
2405 } else {
2406 generate_exception_end(ctx, EXCP_RI);
2411 static inline void check_dsp_r3(DisasContext *ctx)
2413 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2414 if (ctx->insn_flags & ASE_DSP) {
2415 generate_exception_end(ctx, EXCP_DSPDIS);
2416 } else {
2417 generate_exception_end(ctx, EXCP_RI);
2422 /* This code generates a "reserved instruction" exception if the
2423 CPU does not support the instruction set corresponding to flags. */
2424 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2426 if (unlikely(!(ctx->insn_flags & flags))) {
2427 generate_exception_end(ctx, EXCP_RI);
2431 /* This code generates a "reserved instruction" exception if the
2432 CPU has corresponding flag set which indicates that the instruction
2433 has been removed. */
2434 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2436 if (unlikely(ctx->insn_flags & flags)) {
2437 generate_exception_end(ctx, EXCP_RI);
2441 /* This code generates a "reserved instruction" exception if the
2442 CPU does not support 64-bit paired-single (PS) floating point data type */
2443 static inline void check_ps(DisasContext *ctx)
2445 if (unlikely(!ctx->ps)) {
2446 generate_exception(ctx, EXCP_RI);
2448 check_cp1_64bitmode(ctx);
2451 #ifdef TARGET_MIPS64
2452 /* This code generates a "reserved instruction" exception if 64-bit
2453 instructions are not enabled. */
2454 static inline void check_mips_64(DisasContext *ctx)
2456 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2457 generate_exception_end(ctx, EXCP_RI);
2459 #endif
2461 #ifndef CONFIG_USER_ONLY
2462 static inline void check_mvh(DisasContext *ctx)
2464 if (unlikely(!ctx->mvh)) {
2465 generate_exception(ctx, EXCP_RI);
2468 #endif
2471 * This code generates a "reserved instruction" exception if the
2472 * Config5 XNP bit is set.
2474 static inline void check_xnp(DisasContext *ctx)
2476 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2477 generate_exception_end(ctx, EXCP_RI);
2481 #ifndef CONFIG_USER_ONLY
2483 * This code generates a "reserved instruction" exception if the
2484 * Config3 PW bit is NOT set.
2486 static inline void check_pw(DisasContext *ctx)
2488 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2489 generate_exception_end(ctx, EXCP_RI);
2492 #endif
2495 * This code generates a "reserved instruction" exception if the
2496 * Config3 MT bit is NOT set.
2498 static inline void check_mt(DisasContext *ctx)
2500 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2501 generate_exception_end(ctx, EXCP_RI);
2505 #ifndef CONFIG_USER_ONLY
2507 * This code generates a "coprocessor unusable" exception if CP0 is not
2508 * available, and, if that is not the case, generates a "reserved instruction"
2509 * exception if the Config5 MT bit is NOT set. This is needed for availability
2510 * control of some of MT ASE instructions.
2512 static inline void check_cp0_mt(DisasContext *ctx)
2514 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2515 generate_exception_err(ctx, EXCP_CpU, 0);
2516 } else {
2517 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2518 generate_exception_err(ctx, EXCP_RI, 0);
2522 #endif
2525 * This code generates a "reserved instruction" exception if the
2526 * Config5 NMS bit is set.
2528 static inline void check_nms(DisasContext *ctx)
2530 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2531 generate_exception_end(ctx, EXCP_RI);
2536 /* Define small wrappers for gen_load_fpr* so that we have a uniform
2537 calling interface for 32 and 64-bit FPRs. No sense in changing
2538 all callers for gen_load_fpr32 when we need the CTX parameter for
2539 this one use. */
2540 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2541 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2542 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2543 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2544 int ft, int fs, int cc) \
2546 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
2547 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
2548 switch (ifmt) { \
2549 case FMT_PS: \
2550 check_ps(ctx); \
2551 break; \
2552 case FMT_D: \
2553 if (abs) { \
2554 check_cop1x(ctx); \
2556 check_cp1_registers(ctx, fs | ft); \
2557 break; \
2558 case FMT_S: \
2559 if (abs) { \
2560 check_cop1x(ctx); \
2562 break; \
2564 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
2565 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
2566 switch (n) { \
2567 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
2568 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
2569 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
2570 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
2571 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
2572 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
2573 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
2574 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
2575 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
2576 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
2577 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
2578 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
2579 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
2580 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
2581 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
2582 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
2583 default: abort(); \
2585 tcg_temp_free_i##bits (fp0); \
2586 tcg_temp_free_i##bits (fp1); \
2589 FOP_CONDS(, 0, d, FMT_D, 64)
2590 FOP_CONDS(abs, 1, d, FMT_D, 64)
2591 FOP_CONDS(, 0, s, FMT_S, 32)
2592 FOP_CONDS(abs, 1, s, FMT_S, 32)
2593 FOP_CONDS(, 0, ps, FMT_PS, 64)
2594 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2595 #undef FOP_CONDS
2597 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2598 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
2599 int ft, int fs, int fd) \
2601 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2602 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2603 if (ifmt == FMT_D) { \
2604 check_cp1_registers(ctx, fs | ft | fd); \
2606 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2607 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2608 switch (n) { \
2609 case 0: \
2610 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2611 break; \
2612 case 1: \
2613 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2614 break; \
2615 case 2: \
2616 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2617 break; \
2618 case 3: \
2619 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2620 break; \
2621 case 4: \
2622 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2623 break; \
2624 case 5: \
2625 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2626 break; \
2627 case 6: \
2628 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2629 break; \
2630 case 7: \
2631 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2632 break; \
2633 case 8: \
2634 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2635 break; \
2636 case 9: \
2637 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2638 break; \
2639 case 10: \
2640 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2641 break; \
2642 case 11: \
2643 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2644 break; \
2645 case 12: \
2646 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2647 break; \
2648 case 13: \
2649 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2650 break; \
2651 case 14: \
2652 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2653 break; \
2654 case 15: \
2655 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2656 break; \
2657 case 17: \
2658 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2659 break; \
2660 case 18: \
2661 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2662 break; \
2663 case 19: \
2664 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2665 break; \
2666 case 25: \
2667 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2668 break; \
2669 case 26: \
2670 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2671 break; \
2672 case 27: \
2673 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2674 break; \
2675 default: \
2676 abort(); \
2678 STORE; \
2679 tcg_temp_free_i ## bits (fp0); \
2680 tcg_temp_free_i ## bits (fp1); \
2683 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2684 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2685 #undef FOP_CONDNS
2686 #undef gen_ldcmp_fpr32
2687 #undef gen_ldcmp_fpr64
2689 /* load/store instructions. */
2690 #ifdef CONFIG_USER_ONLY
2691 #define OP_LD_ATOMIC(insn,fname) \
2692 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2693 DisasContext *ctx) \
2695 TCGv t0 = tcg_temp_new(); \
2696 tcg_gen_mov_tl(t0, arg1); \
2697 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2698 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2699 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2700 tcg_temp_free(t0); \
2702 #else
2703 #define OP_LD_ATOMIC(insn,fname) \
2704 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2705 DisasContext *ctx) \
2707 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2709 #endif
2710 OP_LD_ATOMIC(ll,ld32s);
2711 #if defined(TARGET_MIPS64)
2712 OP_LD_ATOMIC(lld,ld64);
2713 #endif
2714 #undef OP_LD_ATOMIC
2716 #ifdef CONFIG_USER_ONLY
2717 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2718 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2719 DisasContext *ctx) \
2721 TCGv t0 = tcg_temp_new(); \
2722 TCGLabel *l1 = gen_new_label(); \
2723 TCGLabel *l2 = gen_new_label(); \
2725 tcg_gen_andi_tl(t0, arg2, almask); \
2726 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2727 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2728 generate_exception(ctx, EXCP_AdES); \
2729 gen_set_label(l1); \
2730 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2731 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2732 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2733 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2734 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2735 generate_exception_end(ctx, EXCP_SC); \
2736 gen_set_label(l2); \
2737 tcg_gen_movi_tl(t0, 0); \
2738 gen_store_gpr(t0, rt); \
2739 tcg_temp_free(t0); \
2741 #else
2742 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2743 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2744 DisasContext *ctx) \
2746 TCGv t0 = tcg_temp_new(); \
2747 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
2748 gen_store_gpr(t0, rt); \
2749 tcg_temp_free(t0); \
2751 #endif
2752 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2753 #if defined(TARGET_MIPS64)
2754 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2755 #endif
2756 #undef OP_ST_ATOMIC
2758 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2759 int base, int offset)
2761 if (base == 0) {
2762 tcg_gen_movi_tl(addr, offset);
2763 } else if (offset == 0) {
2764 gen_load_gpr(addr, base);
2765 } else {
2766 tcg_gen_movi_tl(addr, offset);
2767 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2771 static target_ulong pc_relative_pc (DisasContext *ctx)
2773 target_ulong pc = ctx->base.pc_next;
2775 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2776 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2778 pc -= branch_bytes;
2781 pc &= ~(target_ulong)3;
2782 return pc;
2785 /* Load */
2786 static void gen_ld(DisasContext *ctx, uint32_t opc,
2787 int rt, int base, int offset)
2789 TCGv t0, t1, t2;
2790 int mem_idx = ctx->mem_idx;
2792 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2793 /* Loongson CPU uses a load to zero register for prefetch.
2794 We emulate it as a NOP. On other CPU we must perform the
2795 actual memory access. */
2796 return;
2799 t0 = tcg_temp_new();
2800 gen_base_offset_addr(ctx, t0, base, offset);
2802 switch (opc) {
2803 #if defined(TARGET_MIPS64)
2804 case OPC_LWU:
2805 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2806 ctx->default_tcg_memop_mask);
2807 gen_store_gpr(t0, rt);
2808 break;
2809 case OPC_LD:
2810 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2811 ctx->default_tcg_memop_mask);
2812 gen_store_gpr(t0, rt);
2813 break;
2814 case OPC_LLD:
2815 case R6_OPC_LLD:
2816 op_ld_lld(t0, t0, mem_idx, ctx);
2817 gen_store_gpr(t0, rt);
2818 break;
2819 case OPC_LDL:
2820 t1 = tcg_temp_new();
2821 /* Do a byte access to possibly trigger a page
2822 fault with the unaligned address. */
2823 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2824 tcg_gen_andi_tl(t1, t0, 7);
2825 #ifndef TARGET_WORDS_BIGENDIAN
2826 tcg_gen_xori_tl(t1, t1, 7);
2827 #endif
2828 tcg_gen_shli_tl(t1, t1, 3);
2829 tcg_gen_andi_tl(t0, t0, ~7);
2830 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2831 tcg_gen_shl_tl(t0, t0, t1);
2832 t2 = tcg_const_tl(-1);
2833 tcg_gen_shl_tl(t2, t2, t1);
2834 gen_load_gpr(t1, rt);
2835 tcg_gen_andc_tl(t1, t1, t2);
2836 tcg_temp_free(t2);
2837 tcg_gen_or_tl(t0, t0, t1);
2838 tcg_temp_free(t1);
2839 gen_store_gpr(t0, rt);
2840 break;
2841 case OPC_LDR:
2842 t1 = tcg_temp_new();
2843 /* Do a byte access to possibly trigger a page
2844 fault with the unaligned address. */
2845 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2846 tcg_gen_andi_tl(t1, t0, 7);
2847 #ifdef TARGET_WORDS_BIGENDIAN
2848 tcg_gen_xori_tl(t1, t1, 7);
2849 #endif
2850 tcg_gen_shli_tl(t1, t1, 3);
2851 tcg_gen_andi_tl(t0, t0, ~7);
2852 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2853 tcg_gen_shr_tl(t0, t0, t1);
2854 tcg_gen_xori_tl(t1, t1, 63);
2855 t2 = tcg_const_tl(0xfffffffffffffffeull);
2856 tcg_gen_shl_tl(t2, t2, t1);
2857 gen_load_gpr(t1, rt);
2858 tcg_gen_and_tl(t1, t1, t2);
2859 tcg_temp_free(t2);
2860 tcg_gen_or_tl(t0, t0, t1);
2861 tcg_temp_free(t1);
2862 gen_store_gpr(t0, rt);
2863 break;
2864 case OPC_LDPC:
2865 t1 = tcg_const_tl(pc_relative_pc(ctx));
2866 gen_op_addr_add(ctx, t0, t0, t1);
2867 tcg_temp_free(t1);
2868 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2869 gen_store_gpr(t0, rt);
2870 break;
2871 #endif
2872 case OPC_LWPC:
2873 t1 = tcg_const_tl(pc_relative_pc(ctx));
2874 gen_op_addr_add(ctx, t0, t0, t1);
2875 tcg_temp_free(t1);
2876 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2877 gen_store_gpr(t0, rt);
2878 break;
2879 case OPC_LWE:
2880 mem_idx = MIPS_HFLAG_UM;
2881 /* fall through */
2882 case OPC_LW:
2883 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2884 ctx->default_tcg_memop_mask);
2885 gen_store_gpr(t0, rt);
2886 break;
2887 case OPC_LHE:
2888 mem_idx = MIPS_HFLAG_UM;
2889 /* fall through */
2890 case OPC_LH:
2891 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2892 ctx->default_tcg_memop_mask);
2893 gen_store_gpr(t0, rt);
2894 break;
2895 case OPC_LHUE:
2896 mem_idx = MIPS_HFLAG_UM;
2897 /* fall through */
2898 case OPC_LHU:
2899 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2900 ctx->default_tcg_memop_mask);
2901 gen_store_gpr(t0, rt);
2902 break;
2903 case OPC_LBE:
2904 mem_idx = MIPS_HFLAG_UM;
2905 /* fall through */
2906 case OPC_LB:
2907 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2908 gen_store_gpr(t0, rt);
2909 break;
2910 case OPC_LBUE:
2911 mem_idx = MIPS_HFLAG_UM;
2912 /* fall through */
2913 case OPC_LBU:
2914 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2915 gen_store_gpr(t0, rt);
2916 break;
2917 case OPC_LWLE:
2918 mem_idx = MIPS_HFLAG_UM;
2919 /* fall through */
2920 case OPC_LWL:
2921 t1 = tcg_temp_new();
2922 /* Do a byte access to possibly trigger a page
2923 fault with the unaligned address. */
2924 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2925 tcg_gen_andi_tl(t1, t0, 3);
2926 #ifndef TARGET_WORDS_BIGENDIAN
2927 tcg_gen_xori_tl(t1, t1, 3);
2928 #endif
2929 tcg_gen_shli_tl(t1, t1, 3);
2930 tcg_gen_andi_tl(t0, t0, ~3);
2931 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2932 tcg_gen_shl_tl(t0, t0, t1);
2933 t2 = tcg_const_tl(-1);
2934 tcg_gen_shl_tl(t2, t2, t1);
2935 gen_load_gpr(t1, rt);
2936 tcg_gen_andc_tl(t1, t1, t2);
2937 tcg_temp_free(t2);
2938 tcg_gen_or_tl(t0, t0, t1);
2939 tcg_temp_free(t1);
2940 tcg_gen_ext32s_tl(t0, t0);
2941 gen_store_gpr(t0, rt);
2942 break;
2943 case OPC_LWRE:
2944 mem_idx = MIPS_HFLAG_UM;
2945 /* fall through */
2946 case OPC_LWR:
2947 t1 = tcg_temp_new();
2948 /* Do a byte access to possibly trigger a page
2949 fault with the unaligned address. */
2950 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2951 tcg_gen_andi_tl(t1, t0, 3);
2952 #ifdef TARGET_WORDS_BIGENDIAN
2953 tcg_gen_xori_tl(t1, t1, 3);
2954 #endif
2955 tcg_gen_shli_tl(t1, t1, 3);
2956 tcg_gen_andi_tl(t0, t0, ~3);
2957 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2958 tcg_gen_shr_tl(t0, t0, t1);
2959 tcg_gen_xori_tl(t1, t1, 31);
2960 t2 = tcg_const_tl(0xfffffffeull);
2961 tcg_gen_shl_tl(t2, t2, t1);
2962 gen_load_gpr(t1, rt);
2963 tcg_gen_and_tl(t1, t1, t2);
2964 tcg_temp_free(t2);
2965 tcg_gen_or_tl(t0, t0, t1);
2966 tcg_temp_free(t1);
2967 tcg_gen_ext32s_tl(t0, t0);
2968 gen_store_gpr(t0, rt);
2969 break;
2970 case OPC_LLE:
2971 mem_idx = MIPS_HFLAG_UM;
2972 /* fall through */
2973 case OPC_LL:
2974 case R6_OPC_LL:
2975 op_ld_ll(t0, t0, mem_idx, ctx);
2976 gen_store_gpr(t0, rt);
2977 break;
2979 tcg_temp_free(t0);
2982 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2983 uint32_t reg1, uint32_t reg2)
2985 TCGv taddr = tcg_temp_new();
2986 TCGv_i64 tval = tcg_temp_new_i64();
2987 TCGv tmp1 = tcg_temp_new();
2988 TCGv tmp2 = tcg_temp_new();
2990 gen_base_offset_addr(ctx, taddr, base, offset);
2991 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2992 #ifdef TARGET_WORDS_BIGENDIAN
2993 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2994 #else
2995 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2996 #endif
2997 gen_store_gpr(tmp1, reg1);
2998 tcg_temp_free(tmp1);
2999 gen_store_gpr(tmp2, reg2);
3000 tcg_temp_free(tmp2);
3001 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3002 tcg_temp_free_i64(tval);
3003 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3004 tcg_temp_free(taddr);
3007 /* Store */
3008 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3009 int base, int offset)
3011 TCGv t0 = tcg_temp_new();
3012 TCGv t1 = tcg_temp_new();
3013 int mem_idx = ctx->mem_idx;
3015 gen_base_offset_addr(ctx, t0, base, offset);
3016 gen_load_gpr(t1, rt);
3017 switch (opc) {
3018 #if defined(TARGET_MIPS64)
3019 case OPC_SD:
3020 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3021 ctx->default_tcg_memop_mask);
3022 break;
3023 case OPC_SDL:
3024 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3025 break;
3026 case OPC_SDR:
3027 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3028 break;
3029 #endif
3030 case OPC_SWE:
3031 mem_idx = MIPS_HFLAG_UM;
3032 /* fall through */
3033 case OPC_SW:
3034 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3035 ctx->default_tcg_memop_mask);
3036 break;
3037 case OPC_SHE:
3038 mem_idx = MIPS_HFLAG_UM;
3039 /* fall through */
3040 case OPC_SH:
3041 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3042 ctx->default_tcg_memop_mask);
3043 break;
3044 case OPC_SBE:
3045 mem_idx = MIPS_HFLAG_UM;
3046 /* fall through */
3047 case OPC_SB:
3048 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3049 break;
3050 case OPC_SWLE:
3051 mem_idx = MIPS_HFLAG_UM;
3052 /* fall through */
3053 case OPC_SWL:
3054 gen_helper_0e2i(swl, t1, t0, mem_idx);
3055 break;
3056 case OPC_SWRE:
3057 mem_idx = MIPS_HFLAG_UM;
3058 /* fall through */
3059 case OPC_SWR:
3060 gen_helper_0e2i(swr, t1, t0, mem_idx);
3061 break;
3063 tcg_temp_free(t0);
3064 tcg_temp_free(t1);
3068 /* Store conditional */
3069 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3070 int base, int16_t offset)
3072 TCGv t0, t1;
3073 int mem_idx = ctx->mem_idx;
3075 #ifdef CONFIG_USER_ONLY
3076 t0 = tcg_temp_local_new();
3077 t1 = tcg_temp_local_new();
3078 #else
3079 t0 = tcg_temp_new();
3080 t1 = tcg_temp_new();
3081 #endif
3082 gen_base_offset_addr(ctx, t0, base, offset);
3083 gen_load_gpr(t1, rt);
3084 switch (opc) {
3085 #if defined(TARGET_MIPS64)
3086 case OPC_SCD:
3087 case R6_OPC_SCD:
3088 op_st_scd(t1, t0, rt, mem_idx, ctx);
3089 break;
3090 #endif
3091 case OPC_SCE:
3092 mem_idx = MIPS_HFLAG_UM;
3093 /* fall through */
3094 case OPC_SC:
3095 case R6_OPC_SC:
3096 op_st_sc(t1, t0, rt, mem_idx, ctx);
3097 break;
3099 tcg_temp_free(t1);
3100 tcg_temp_free(t0);
3103 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3104 uint32_t reg1, uint32_t reg2)
3106 TCGv taddr = tcg_temp_local_new();
3107 TCGv lladdr = tcg_temp_local_new();
3108 TCGv_i64 tval = tcg_temp_new_i64();
3109 TCGv_i64 llval = tcg_temp_new_i64();
3110 TCGv_i64 val = tcg_temp_new_i64();
3111 TCGv tmp1 = tcg_temp_new();
3112 TCGv tmp2 = tcg_temp_new();
3113 TCGLabel *lab_fail = gen_new_label();
3114 TCGLabel *lab_done = gen_new_label();
3116 gen_base_offset_addr(ctx, taddr, base, offset);
3118 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3119 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3121 gen_load_gpr(tmp1, reg1);
3122 gen_load_gpr(tmp2, reg2);
3124 #ifdef TARGET_WORDS_BIGENDIAN
3125 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3126 #else
3127 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3128 #endif
3130 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3131 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3132 ctx->mem_idx, MO_64);
3133 if (reg1 != 0) {
3134 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3136 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3138 gen_set_label(lab_fail);
3140 if (reg1 != 0) {
3141 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3143 gen_set_label(lab_done);
3144 tcg_gen_movi_tl(lladdr, -1);
3145 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3148 /* Load and store */
3149 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3150 TCGv t0)
3152 /* Don't do NOP if destination is zero: we must perform the actual
3153 memory access. */
3154 switch (opc) {
3155 case OPC_LWC1:
3157 TCGv_i32 fp0 = tcg_temp_new_i32();
3158 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3159 ctx->default_tcg_memop_mask);
3160 gen_store_fpr32(ctx, fp0, ft);
3161 tcg_temp_free_i32(fp0);
3163 break;
3164 case OPC_SWC1:
3166 TCGv_i32 fp0 = tcg_temp_new_i32();
3167 gen_load_fpr32(ctx, fp0, ft);
3168 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3169 ctx->default_tcg_memop_mask);
3170 tcg_temp_free_i32(fp0);
3172 break;
3173 case OPC_LDC1:
3175 TCGv_i64 fp0 = tcg_temp_new_i64();
3176 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3177 ctx->default_tcg_memop_mask);
3178 gen_store_fpr64(ctx, fp0, ft);
3179 tcg_temp_free_i64(fp0);
3181 break;
3182 case OPC_SDC1:
3184 TCGv_i64 fp0 = tcg_temp_new_i64();
3185 gen_load_fpr64(ctx, fp0, ft);
3186 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3187 ctx->default_tcg_memop_mask);
3188 tcg_temp_free_i64(fp0);
3190 break;
3191 default:
3192 MIPS_INVAL("flt_ldst");
3193 generate_exception_end(ctx, EXCP_RI);
3194 break;
3198 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3199 int rs, int16_t imm)
3201 TCGv t0 = tcg_temp_new();
3203 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3204 check_cp1_enabled(ctx);
3205 switch (op) {
3206 case OPC_LDC1:
3207 case OPC_SDC1:
3208 check_insn(ctx, ISA_MIPS2);
3209 /* Fallthrough */
3210 default:
3211 gen_base_offset_addr(ctx, t0, rs, imm);
3212 gen_flt_ldst(ctx, op, rt, t0);
3214 } else {
3215 generate_exception_err(ctx, EXCP_CpU, 1);
3217 tcg_temp_free(t0);
3220 /* Arithmetic with immediate operand */
3221 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3222 int rt, int rs, int imm)
3224 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3226 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3227 /* If no destination, treat it as a NOP.
3228 For addi, we must generate the overflow exception when needed. */
3229 return;
3231 switch (opc) {
3232 case OPC_ADDI:
3234 TCGv t0 = tcg_temp_local_new();
3235 TCGv t1 = tcg_temp_new();
3236 TCGv t2 = tcg_temp_new();
3237 TCGLabel *l1 = gen_new_label();
3239 gen_load_gpr(t1, rs);
3240 tcg_gen_addi_tl(t0, t1, uimm);
3241 tcg_gen_ext32s_tl(t0, t0);
3243 tcg_gen_xori_tl(t1, t1, ~uimm);
3244 tcg_gen_xori_tl(t2, t0, uimm);
3245 tcg_gen_and_tl(t1, t1, t2);
3246 tcg_temp_free(t2);
3247 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3248 tcg_temp_free(t1);
3249 /* operands of same sign, result different sign */
3250 generate_exception(ctx, EXCP_OVERFLOW);
3251 gen_set_label(l1);
3252 tcg_gen_ext32s_tl(t0, t0);
3253 gen_store_gpr(t0, rt);
3254 tcg_temp_free(t0);
3256 break;
3257 case OPC_ADDIU:
3258 if (rs != 0) {
3259 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3260 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3261 } else {
3262 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3264 break;
3265 #if defined(TARGET_MIPS64)
3266 case OPC_DADDI:
3268 TCGv t0 = tcg_temp_local_new();
3269 TCGv t1 = tcg_temp_new();
3270 TCGv t2 = tcg_temp_new();
3271 TCGLabel *l1 = gen_new_label();
3273 gen_load_gpr(t1, rs);
3274 tcg_gen_addi_tl(t0, t1, uimm);
3276 tcg_gen_xori_tl(t1, t1, ~uimm);
3277 tcg_gen_xori_tl(t2, t0, uimm);
3278 tcg_gen_and_tl(t1, t1, t2);
3279 tcg_temp_free(t2);
3280 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3281 tcg_temp_free(t1);
3282 /* operands of same sign, result different sign */
3283 generate_exception(ctx, EXCP_OVERFLOW);
3284 gen_set_label(l1);
3285 gen_store_gpr(t0, rt);
3286 tcg_temp_free(t0);
3288 break;
3289 case OPC_DADDIU:
3290 if (rs != 0) {
3291 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3292 } else {
3293 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3295 break;
3296 #endif
3300 /* Logic with immediate operand */
3301 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3302 int rt, int rs, int16_t imm)
3304 target_ulong uimm;
3306 if (rt == 0) {
3307 /* If no destination, treat it as a NOP. */
3308 return;
3310 uimm = (uint16_t)imm;
3311 switch (opc) {
3312 case OPC_ANDI:
3313 if (likely(rs != 0))
3314 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3315 else
3316 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3317 break;
3318 case OPC_ORI:
3319 if (rs != 0)
3320 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3321 else
3322 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3323 break;
3324 case OPC_XORI:
3325 if (likely(rs != 0))
3326 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3327 else
3328 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3329 break;
3330 case OPC_LUI:
3331 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3332 /* OPC_AUI */
3333 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3334 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3335 } else {
3336 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3338 break;
3340 default:
3341 break;
3345 /* Set on less than with immediate operand */
3346 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3347 int rt, int rs, int16_t imm)
3349 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3350 TCGv t0;
3352 if (rt == 0) {
3353 /* If no destination, treat it as a NOP. */
3354 return;
3356 t0 = tcg_temp_new();
3357 gen_load_gpr(t0, rs);
3358 switch (opc) {
3359 case OPC_SLTI:
3360 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3361 break;
3362 case OPC_SLTIU:
3363 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3364 break;
3366 tcg_temp_free(t0);
3369 /* Shifts with immediate operand */
3370 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3371 int rt, int rs, int16_t imm)
3373 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3374 TCGv t0;
3376 if (rt == 0) {
3377 /* If no destination, treat it as a NOP. */
3378 return;
3381 t0 = tcg_temp_new();
3382 gen_load_gpr(t0, rs);
3383 switch (opc) {
3384 case OPC_SLL:
3385 tcg_gen_shli_tl(t0, t0, uimm);
3386 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3387 break;
3388 case OPC_SRA:
3389 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3390 break;
3391 case OPC_SRL:
3392 if (uimm != 0) {
3393 tcg_gen_ext32u_tl(t0, t0);
3394 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3395 } else {
3396 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3398 break;
3399 case OPC_ROTR:
3400 if (uimm != 0) {
3401 TCGv_i32 t1 = tcg_temp_new_i32();
3403 tcg_gen_trunc_tl_i32(t1, t0);
3404 tcg_gen_rotri_i32(t1, t1, uimm);
3405 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3406 tcg_temp_free_i32(t1);
3407 } else {
3408 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3410 break;
3411 #if defined(TARGET_MIPS64)
3412 case OPC_DSLL:
3413 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3414 break;
3415 case OPC_DSRA:
3416 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3417 break;
3418 case OPC_DSRL:
3419 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3420 break;
3421 case OPC_DROTR:
3422 if (uimm != 0) {
3423 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3424 } else {
3425 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3427 break;
3428 case OPC_DSLL32:
3429 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3430 break;
3431 case OPC_DSRA32:
3432 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3433 break;
3434 case OPC_DSRL32:
3435 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3436 break;
3437 case OPC_DROTR32:
3438 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3439 break;
3440 #endif
3442 tcg_temp_free(t0);
3445 /* Arithmetic */
3446 static void gen_arith(DisasContext *ctx, uint32_t opc,
3447 int rd, int rs, int rt)
3449 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3450 && opc != OPC_DADD && opc != OPC_DSUB) {
3451 /* If no destination, treat it as a NOP.
3452 For add & sub, we must generate the overflow exception when needed. */
3453 return;
3456 switch (opc) {
3457 case OPC_ADD:
3459 TCGv t0 = tcg_temp_local_new();
3460 TCGv t1 = tcg_temp_new();
3461 TCGv t2 = tcg_temp_new();
3462 TCGLabel *l1 = gen_new_label();
3464 gen_load_gpr(t1, rs);
3465 gen_load_gpr(t2, rt);
3466 tcg_gen_add_tl(t0, t1, t2);
3467 tcg_gen_ext32s_tl(t0, t0);
3468 tcg_gen_xor_tl(t1, t1, t2);
3469 tcg_gen_xor_tl(t2, t0, t2);
3470 tcg_gen_andc_tl(t1, t2, t1);
3471 tcg_temp_free(t2);
3472 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3473 tcg_temp_free(t1);
3474 /* operands of same sign, result different sign */
3475 generate_exception(ctx, EXCP_OVERFLOW);
3476 gen_set_label(l1);
3477 gen_store_gpr(t0, rd);
3478 tcg_temp_free(t0);
3480 break;
3481 case OPC_ADDU:
3482 if (rs != 0 && rt != 0) {
3483 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3484 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3485 } else if (rs == 0 && rt != 0) {
3486 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3487 } else if (rs != 0 && rt == 0) {
3488 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3489 } else {
3490 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3492 break;
3493 case OPC_SUB:
3495 TCGv t0 = tcg_temp_local_new();
3496 TCGv t1 = tcg_temp_new();
3497 TCGv t2 = tcg_temp_new();
3498 TCGLabel *l1 = gen_new_label();
3500 gen_load_gpr(t1, rs);
3501 gen_load_gpr(t2, rt);
3502 tcg_gen_sub_tl(t0, t1, t2);
3503 tcg_gen_ext32s_tl(t0, t0);
3504 tcg_gen_xor_tl(t2, t1, t2);
3505 tcg_gen_xor_tl(t1, t0, t1);
3506 tcg_gen_and_tl(t1, t1, t2);
3507 tcg_temp_free(t2);
3508 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3509 tcg_temp_free(t1);
3510 /* operands of different sign, first operand and result different sign */
3511 generate_exception(ctx, EXCP_OVERFLOW);
3512 gen_set_label(l1);
3513 gen_store_gpr(t0, rd);
3514 tcg_temp_free(t0);
3516 break;
3517 case OPC_SUBU:
3518 if (rs != 0 && rt != 0) {
3519 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3520 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3521 } else if (rs == 0 && rt != 0) {
3522 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3523 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3524 } else if (rs != 0 && rt == 0) {
3525 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3526 } else {
3527 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3529 break;
3530 #if defined(TARGET_MIPS64)
3531 case OPC_DADD:
3533 TCGv t0 = tcg_temp_local_new();
3534 TCGv t1 = tcg_temp_new();
3535 TCGv t2 = tcg_temp_new();
3536 TCGLabel *l1 = gen_new_label();
3538 gen_load_gpr(t1, rs);
3539 gen_load_gpr(t2, rt);
3540 tcg_gen_add_tl(t0, t1, t2);
3541 tcg_gen_xor_tl(t1, t1, t2);
3542 tcg_gen_xor_tl(t2, t0, t2);
3543 tcg_gen_andc_tl(t1, t2, t1);
3544 tcg_temp_free(t2);
3545 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3546 tcg_temp_free(t1);
3547 /* operands of same sign, result different sign */
3548 generate_exception(ctx, EXCP_OVERFLOW);
3549 gen_set_label(l1);
3550 gen_store_gpr(t0, rd);
3551 tcg_temp_free(t0);
3553 break;
3554 case OPC_DADDU:
3555 if (rs != 0 && rt != 0) {
3556 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3557 } else if (rs == 0 && rt != 0) {
3558 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3559 } else if (rs != 0 && rt == 0) {
3560 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3561 } else {
3562 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3564 break;
3565 case OPC_DSUB:
3567 TCGv t0 = tcg_temp_local_new();
3568 TCGv t1 = tcg_temp_new();
3569 TCGv t2 = tcg_temp_new();
3570 TCGLabel *l1 = gen_new_label();
3572 gen_load_gpr(t1, rs);
3573 gen_load_gpr(t2, rt);
3574 tcg_gen_sub_tl(t0, t1, t2);
3575 tcg_gen_xor_tl(t2, t1, t2);
3576 tcg_gen_xor_tl(t1, t0, t1);
3577 tcg_gen_and_tl(t1, t1, t2);
3578 tcg_temp_free(t2);
3579 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3580 tcg_temp_free(t1);
3581 /* operands of different sign, first operand and result different sign */
3582 generate_exception(ctx, EXCP_OVERFLOW);
3583 gen_set_label(l1);
3584 gen_store_gpr(t0, rd);
3585 tcg_temp_free(t0);
3587 break;
3588 case OPC_DSUBU:
3589 if (rs != 0 && rt != 0) {
3590 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3591 } else if (rs == 0 && rt != 0) {
3592 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3593 } else if (rs != 0 && rt == 0) {
3594 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3595 } else {
3596 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3598 break;
3599 #endif
3600 case OPC_MUL:
3601 if (likely(rs != 0 && rt != 0)) {
3602 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3603 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3604 } else {
3605 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3607 break;
3611 /* Conditional move */
3612 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3613 int rd, int rs, int rt)
3615 TCGv t0, t1, t2;
3617 if (rd == 0) {
3618 /* If no destination, treat it as a NOP. */
3619 return;
3622 t0 = tcg_temp_new();
3623 gen_load_gpr(t0, rt);
3624 t1 = tcg_const_tl(0);
3625 t2 = tcg_temp_new();
3626 gen_load_gpr(t2, rs);
3627 switch (opc) {
3628 case OPC_MOVN:
3629 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3630 break;
3631 case OPC_MOVZ:
3632 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3633 break;
3634 case OPC_SELNEZ:
3635 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3636 break;
3637 case OPC_SELEQZ:
3638 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3639 break;
3641 tcg_temp_free(t2);
3642 tcg_temp_free(t1);
3643 tcg_temp_free(t0);
3646 /* Logic */
3647 static void gen_logic(DisasContext *ctx, uint32_t opc,
3648 int rd, int rs, int rt)
3650 if (rd == 0) {
3651 /* If no destination, treat it as a NOP. */
3652 return;
3655 switch (opc) {
3656 case OPC_AND:
3657 if (likely(rs != 0 && rt != 0)) {
3658 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3659 } else {
3660 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3662 break;
3663 case OPC_NOR:
3664 if (rs != 0 && rt != 0) {
3665 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3666 } else if (rs == 0 && rt != 0) {
3667 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3668 } else if (rs != 0 && rt == 0) {
3669 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3670 } else {
3671 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3673 break;
3674 case OPC_OR:
3675 if (likely(rs != 0 && rt != 0)) {
3676 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3677 } else if (rs == 0 && rt != 0) {
3678 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3679 } else if (rs != 0 && rt == 0) {
3680 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3681 } else {
3682 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3684 break;
3685 case OPC_XOR:
3686 if (likely(rs != 0 && rt != 0)) {
3687 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3688 } else if (rs == 0 && rt != 0) {
3689 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3690 } else if (rs != 0 && rt == 0) {
3691 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3692 } else {
3693 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3695 break;
3699 /* Set on lower than */
3700 static void gen_slt(DisasContext *ctx, uint32_t opc,
3701 int rd, int rs, int rt)
3703 TCGv t0, t1;
3705 if (rd == 0) {
3706 /* If no destination, treat it as a NOP. */
3707 return;
3710 t0 = tcg_temp_new();
3711 t1 = tcg_temp_new();
3712 gen_load_gpr(t0, rs);
3713 gen_load_gpr(t1, rt);
3714 switch (opc) {
3715 case OPC_SLT:
3716 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3717 break;
3718 case OPC_SLTU:
3719 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3720 break;
3722 tcg_temp_free(t0);
3723 tcg_temp_free(t1);
3726 /* Shifts */
3727 static void gen_shift(DisasContext *ctx, uint32_t opc,
3728 int rd, int rs, int rt)
3730 TCGv t0, t1;
3732 if (rd == 0) {
3733 /* If no destination, treat it as a NOP.
3734 For add & sub, we must generate the overflow exception when needed. */
3735 return;
3738 t0 = tcg_temp_new();
3739 t1 = tcg_temp_new();
3740 gen_load_gpr(t0, rs);
3741 gen_load_gpr(t1, rt);
3742 switch (opc) {
3743 case OPC_SLLV:
3744 tcg_gen_andi_tl(t0, t0, 0x1f);
3745 tcg_gen_shl_tl(t0, t1, t0);
3746 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3747 break;
3748 case OPC_SRAV:
3749 tcg_gen_andi_tl(t0, t0, 0x1f);
3750 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3751 break;
3752 case OPC_SRLV:
3753 tcg_gen_ext32u_tl(t1, t1);
3754 tcg_gen_andi_tl(t0, t0, 0x1f);
3755 tcg_gen_shr_tl(t0, t1, t0);
3756 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3757 break;
3758 case OPC_ROTRV:
3760 TCGv_i32 t2 = tcg_temp_new_i32();
3761 TCGv_i32 t3 = tcg_temp_new_i32();
3763 tcg_gen_trunc_tl_i32(t2, t0);
3764 tcg_gen_trunc_tl_i32(t3, t1);
3765 tcg_gen_andi_i32(t2, t2, 0x1f);
3766 tcg_gen_rotr_i32(t2, t3, t2);
3767 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3768 tcg_temp_free_i32(t2);
3769 tcg_temp_free_i32(t3);
3771 break;
3772 #if defined(TARGET_MIPS64)
3773 case OPC_DSLLV:
3774 tcg_gen_andi_tl(t0, t0, 0x3f);
3775 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3776 break;
3777 case OPC_DSRAV:
3778 tcg_gen_andi_tl(t0, t0, 0x3f);
3779 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3780 break;
3781 case OPC_DSRLV:
3782 tcg_gen_andi_tl(t0, t0, 0x3f);
3783 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3784 break;
3785 case OPC_DROTRV:
3786 tcg_gen_andi_tl(t0, t0, 0x3f);
3787 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3788 break;
3789 #endif
3791 tcg_temp_free(t0);
3792 tcg_temp_free(t1);
3795 /* Arithmetic on HI/LO registers */
3796 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3798 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3799 /* Treat as NOP. */
3800 return;
3803 if (acc != 0) {
3804 check_dsp(ctx);
3807 switch (opc) {
3808 case OPC_MFHI:
3809 #if defined(TARGET_MIPS64)
3810 if (acc != 0) {
3811 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3812 } else
3813 #endif
3815 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3817 break;
3818 case OPC_MFLO:
3819 #if defined(TARGET_MIPS64)
3820 if (acc != 0) {
3821 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3822 } else
3823 #endif
3825 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3827 break;
3828 case OPC_MTHI:
3829 if (reg != 0) {
3830 #if defined(TARGET_MIPS64)
3831 if (acc != 0) {
3832 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3833 } else
3834 #endif
3836 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3838 } else {
3839 tcg_gen_movi_tl(cpu_HI[acc], 0);
3841 break;
3842 case OPC_MTLO:
3843 if (reg != 0) {
3844 #if defined(TARGET_MIPS64)
3845 if (acc != 0) {
3846 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3847 } else
3848 #endif
3850 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3852 } else {
3853 tcg_gen_movi_tl(cpu_LO[acc], 0);
3855 break;
3859 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3860 TCGMemOp memop)
3862 TCGv t0 = tcg_const_tl(addr);
3863 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3864 gen_store_gpr(t0, reg);
3865 tcg_temp_free(t0);
3868 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3869 int rs)
3871 target_long offset;
3872 target_long addr;
3874 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3875 case OPC_ADDIUPC:
3876 if (rs != 0) {
3877 offset = sextract32(ctx->opcode << 2, 0, 21);
3878 addr = addr_add(ctx, pc, offset);
3879 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3881 break;
3882 case R6_OPC_LWPC:
3883 offset = sextract32(ctx->opcode << 2, 0, 21);
3884 addr = addr_add(ctx, pc, offset);
3885 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3886 break;
3887 #if defined(TARGET_MIPS64)
3888 case OPC_LWUPC:
3889 check_mips_64(ctx);
3890 offset = sextract32(ctx->opcode << 2, 0, 21);
3891 addr = addr_add(ctx, pc, offset);
3892 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3893 break;
3894 #endif
3895 default:
3896 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3897 case OPC_AUIPC:
3898 if (rs != 0) {
3899 offset = sextract32(ctx->opcode, 0, 16) << 16;
3900 addr = addr_add(ctx, pc, offset);
3901 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3903 break;
3904 case OPC_ALUIPC:
3905 if (rs != 0) {
3906 offset = sextract32(ctx->opcode, 0, 16) << 16;
3907 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3908 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3910 break;
3911 #if defined(TARGET_MIPS64)
3912 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3913 case R6_OPC_LDPC + (1 << 16):
3914 case R6_OPC_LDPC + (2 << 16):
3915 case R6_OPC_LDPC + (3 << 16):
3916 check_mips_64(ctx);
3917 offset = sextract32(ctx->opcode << 3, 0, 21);
3918 addr = addr_add(ctx, (pc & ~0x7), offset);
3919 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3920 break;
3921 #endif
3922 default:
3923 MIPS_INVAL("OPC_PCREL");
3924 generate_exception_end(ctx, EXCP_RI);
3925 break;
3927 break;
3931 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3933 TCGv t0, t1;
3935 if (rd == 0) {
3936 /* Treat as NOP. */
3937 return;
3940 t0 = tcg_temp_new();
3941 t1 = tcg_temp_new();
3943 gen_load_gpr(t0, rs);
3944 gen_load_gpr(t1, rt);
3946 switch (opc) {
3947 case R6_OPC_DIV:
3949 TCGv t2 = tcg_temp_new();
3950 TCGv t3 = tcg_temp_new();
3951 tcg_gen_ext32s_tl(t0, t0);
3952 tcg_gen_ext32s_tl(t1, t1);
3953 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3954 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3955 tcg_gen_and_tl(t2, t2, t3);
3956 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3957 tcg_gen_or_tl(t2, t2, t3);
3958 tcg_gen_movi_tl(t3, 0);
3959 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3960 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3961 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3962 tcg_temp_free(t3);
3963 tcg_temp_free(t2);
3965 break;
3966 case R6_OPC_MOD:
3968 TCGv t2 = tcg_temp_new();
3969 TCGv t3 = tcg_temp_new();
3970 tcg_gen_ext32s_tl(t0, t0);
3971 tcg_gen_ext32s_tl(t1, t1);
3972 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3973 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3974 tcg_gen_and_tl(t2, t2, t3);
3975 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3976 tcg_gen_or_tl(t2, t2, t3);
3977 tcg_gen_movi_tl(t3, 0);
3978 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3979 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3980 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3981 tcg_temp_free(t3);
3982 tcg_temp_free(t2);
3984 break;
3985 case R6_OPC_DIVU:
3987 TCGv t2 = tcg_const_tl(0);
3988 TCGv t3 = tcg_const_tl(1);
3989 tcg_gen_ext32u_tl(t0, t0);
3990 tcg_gen_ext32u_tl(t1, t1);
3991 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3992 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3993 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3994 tcg_temp_free(t3);
3995 tcg_temp_free(t2);
3997 break;
3998 case R6_OPC_MODU:
4000 TCGv t2 = tcg_const_tl(0);
4001 TCGv t3 = tcg_const_tl(1);
4002 tcg_gen_ext32u_tl(t0, t0);
4003 tcg_gen_ext32u_tl(t1, t1);
4004 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4005 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4006 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4007 tcg_temp_free(t3);
4008 tcg_temp_free(t2);
4010 break;
4011 case R6_OPC_MUL:
4013 TCGv_i32 t2 = tcg_temp_new_i32();
4014 TCGv_i32 t3 = tcg_temp_new_i32();
4015 tcg_gen_trunc_tl_i32(t2, t0);
4016 tcg_gen_trunc_tl_i32(t3, t1);
4017 tcg_gen_mul_i32(t2, t2, t3);
4018 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4019 tcg_temp_free_i32(t2);
4020 tcg_temp_free_i32(t3);
4022 break;
4023 case R6_OPC_MUH:
4025 TCGv_i32 t2 = tcg_temp_new_i32();
4026 TCGv_i32 t3 = tcg_temp_new_i32();
4027 tcg_gen_trunc_tl_i32(t2, t0);
4028 tcg_gen_trunc_tl_i32(t3, t1);
4029 tcg_gen_muls2_i32(t2, t3, t2, t3);
4030 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4031 tcg_temp_free_i32(t2);
4032 tcg_temp_free_i32(t3);
4034 break;
4035 case R6_OPC_MULU:
4037 TCGv_i32 t2 = tcg_temp_new_i32();
4038 TCGv_i32 t3 = tcg_temp_new_i32();
4039 tcg_gen_trunc_tl_i32(t2, t0);
4040 tcg_gen_trunc_tl_i32(t3, t1);
4041 tcg_gen_mul_i32(t2, t2, t3);
4042 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4043 tcg_temp_free_i32(t2);
4044 tcg_temp_free_i32(t3);
4046 break;
4047 case R6_OPC_MUHU:
4049 TCGv_i32 t2 = tcg_temp_new_i32();
4050 TCGv_i32 t3 = tcg_temp_new_i32();
4051 tcg_gen_trunc_tl_i32(t2, t0);
4052 tcg_gen_trunc_tl_i32(t3, t1);
4053 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4054 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4055 tcg_temp_free_i32(t2);
4056 tcg_temp_free_i32(t3);
4058 break;
4059 #if defined(TARGET_MIPS64)
4060 case R6_OPC_DDIV:
4062 TCGv t2 = tcg_temp_new();
4063 TCGv t3 = tcg_temp_new();
4064 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4065 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4066 tcg_gen_and_tl(t2, t2, t3);
4067 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4068 tcg_gen_or_tl(t2, t2, t3);
4069 tcg_gen_movi_tl(t3, 0);
4070 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4071 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4072 tcg_temp_free(t3);
4073 tcg_temp_free(t2);
4075 break;
4076 case R6_OPC_DMOD:
4078 TCGv t2 = tcg_temp_new();
4079 TCGv t3 = tcg_temp_new();
4080 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4081 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4082 tcg_gen_and_tl(t2, t2, t3);
4083 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4084 tcg_gen_or_tl(t2, t2, t3);
4085 tcg_gen_movi_tl(t3, 0);
4086 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4087 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4088 tcg_temp_free(t3);
4089 tcg_temp_free(t2);
4091 break;
4092 case R6_OPC_DDIVU:
4094 TCGv t2 = tcg_const_tl(0);
4095 TCGv t3 = tcg_const_tl(1);
4096 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4097 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4098 tcg_temp_free(t3);
4099 tcg_temp_free(t2);
4101 break;
4102 case R6_OPC_DMODU:
4104 TCGv t2 = tcg_const_tl(0);
4105 TCGv t3 = tcg_const_tl(1);
4106 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4107 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4108 tcg_temp_free(t3);
4109 tcg_temp_free(t2);
4111 break;
4112 case R6_OPC_DMUL:
4113 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4114 break;
4115 case R6_OPC_DMUH:
4117 TCGv t2 = tcg_temp_new();
4118 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4119 tcg_temp_free(t2);
4121 break;
4122 case R6_OPC_DMULU:
4123 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4124 break;
4125 case R6_OPC_DMUHU:
4127 TCGv t2 = tcg_temp_new();
4128 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4129 tcg_temp_free(t2);
4131 break;
4132 #endif
4133 default:
4134 MIPS_INVAL("r6 mul/div");
4135 generate_exception_end(ctx, EXCP_RI);
4136 goto out;
4138 out:
4139 tcg_temp_free(t0);
4140 tcg_temp_free(t1);
4143 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4144 int acc, int rs, int rt)
4146 TCGv t0, t1;
4148 t0 = tcg_temp_new();
4149 t1 = tcg_temp_new();
4151 gen_load_gpr(t0, rs);
4152 gen_load_gpr(t1, rt);
4154 if (acc != 0) {
4155 check_dsp(ctx);
4158 switch (opc) {
4159 case OPC_DIV:
4161 TCGv t2 = tcg_temp_new();
4162 TCGv t3 = tcg_temp_new();
4163 tcg_gen_ext32s_tl(t0, t0);
4164 tcg_gen_ext32s_tl(t1, t1);
4165 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4166 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4167 tcg_gen_and_tl(t2, t2, t3);
4168 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4169 tcg_gen_or_tl(t2, t2, t3);
4170 tcg_gen_movi_tl(t3, 0);
4171 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4172 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4173 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4174 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4175 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4176 tcg_temp_free(t3);
4177 tcg_temp_free(t2);
4179 break;
4180 case OPC_DIVU:
4182 TCGv t2 = tcg_const_tl(0);
4183 TCGv t3 = tcg_const_tl(1);
4184 tcg_gen_ext32u_tl(t0, t0);
4185 tcg_gen_ext32u_tl(t1, t1);
4186 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4187 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4188 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4189 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4190 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4191 tcg_temp_free(t3);
4192 tcg_temp_free(t2);
4194 break;
4195 case OPC_MULT:
4197 TCGv_i32 t2 = tcg_temp_new_i32();
4198 TCGv_i32 t3 = tcg_temp_new_i32();
4199 tcg_gen_trunc_tl_i32(t2, t0);
4200 tcg_gen_trunc_tl_i32(t3, t1);
4201 tcg_gen_muls2_i32(t2, t3, t2, t3);
4202 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4203 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4204 tcg_temp_free_i32(t2);
4205 tcg_temp_free_i32(t3);
4207 break;
4208 case OPC_MULTU:
4210 TCGv_i32 t2 = tcg_temp_new_i32();
4211 TCGv_i32 t3 = tcg_temp_new_i32();
4212 tcg_gen_trunc_tl_i32(t2, t0);
4213 tcg_gen_trunc_tl_i32(t3, t1);
4214 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4215 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4216 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4217 tcg_temp_free_i32(t2);
4218 tcg_temp_free_i32(t3);
4220 break;
4221 #if defined(TARGET_MIPS64)
4222 case OPC_DDIV:
4224 TCGv t2 = tcg_temp_new();
4225 TCGv t3 = tcg_temp_new();
4226 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4227 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4228 tcg_gen_and_tl(t2, t2, t3);
4229 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4230 tcg_gen_or_tl(t2, t2, t3);
4231 tcg_gen_movi_tl(t3, 0);
4232 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4233 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4234 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4235 tcg_temp_free(t3);
4236 tcg_temp_free(t2);
4238 break;
4239 case OPC_DDIVU:
4241 TCGv t2 = tcg_const_tl(0);
4242 TCGv t3 = tcg_const_tl(1);
4243 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4244 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4245 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4246 tcg_temp_free(t3);
4247 tcg_temp_free(t2);
4249 break;
4250 case OPC_DMULT:
4251 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4252 break;
4253 case OPC_DMULTU:
4254 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4255 break;
4256 #endif
4257 case OPC_MADD:
4259 TCGv_i64 t2 = tcg_temp_new_i64();
4260 TCGv_i64 t3 = tcg_temp_new_i64();
4262 tcg_gen_ext_tl_i64(t2, t0);
4263 tcg_gen_ext_tl_i64(t3, t1);
4264 tcg_gen_mul_i64(t2, t2, t3);
4265 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4266 tcg_gen_add_i64(t2, t2, t3);
4267 tcg_temp_free_i64(t3);
4268 gen_move_low32(cpu_LO[acc], t2);
4269 gen_move_high32(cpu_HI[acc], t2);
4270 tcg_temp_free_i64(t2);
4272 break;
4273 case OPC_MADDU:
4275 TCGv_i64 t2 = tcg_temp_new_i64();
4276 TCGv_i64 t3 = tcg_temp_new_i64();
4278 tcg_gen_ext32u_tl(t0, t0);
4279 tcg_gen_ext32u_tl(t1, t1);
4280 tcg_gen_extu_tl_i64(t2, t0);
4281 tcg_gen_extu_tl_i64(t3, t1);
4282 tcg_gen_mul_i64(t2, t2, t3);
4283 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4284 tcg_gen_add_i64(t2, t2, t3);
4285 tcg_temp_free_i64(t3);
4286 gen_move_low32(cpu_LO[acc], t2);
4287 gen_move_high32(cpu_HI[acc], t2);
4288 tcg_temp_free_i64(t2);
4290 break;
4291 case OPC_MSUB:
4293 TCGv_i64 t2 = tcg_temp_new_i64();
4294 TCGv_i64 t3 = tcg_temp_new_i64();
4296 tcg_gen_ext_tl_i64(t2, t0);
4297 tcg_gen_ext_tl_i64(t3, t1);
4298 tcg_gen_mul_i64(t2, t2, t3);
4299 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4300 tcg_gen_sub_i64(t2, t3, t2);
4301 tcg_temp_free_i64(t3);
4302 gen_move_low32(cpu_LO[acc], t2);
4303 gen_move_high32(cpu_HI[acc], t2);
4304 tcg_temp_free_i64(t2);
4306 break;
4307 case OPC_MSUBU:
4309 TCGv_i64 t2 = tcg_temp_new_i64();
4310 TCGv_i64 t3 = tcg_temp_new_i64();
4312 tcg_gen_ext32u_tl(t0, t0);
4313 tcg_gen_ext32u_tl(t1, t1);
4314 tcg_gen_extu_tl_i64(t2, t0);
4315 tcg_gen_extu_tl_i64(t3, t1);
4316 tcg_gen_mul_i64(t2, t2, t3);
4317 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4318 tcg_gen_sub_i64(t2, t3, t2);
4319 tcg_temp_free_i64(t3);
4320 gen_move_low32(cpu_LO[acc], t2);
4321 gen_move_high32(cpu_HI[acc], t2);
4322 tcg_temp_free_i64(t2);
4324 break;
4325 default:
4326 MIPS_INVAL("mul/div");
4327 generate_exception_end(ctx, EXCP_RI);
4328 goto out;
4330 out:
4331 tcg_temp_free(t0);
4332 tcg_temp_free(t1);
4335 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4336 int rd, int rs, int rt)
4338 TCGv t0 = tcg_temp_new();
4339 TCGv t1 = tcg_temp_new();
4341 gen_load_gpr(t0, rs);
4342 gen_load_gpr(t1, rt);
4344 switch (opc) {
4345 case OPC_VR54XX_MULS:
4346 gen_helper_muls(t0, cpu_env, t0, t1);
4347 break;
4348 case OPC_VR54XX_MULSU:
4349 gen_helper_mulsu(t0, cpu_env, t0, t1);
4350 break;
4351 case OPC_VR54XX_MACC:
4352 gen_helper_macc(t0, cpu_env, t0, t1);
4353 break;
4354 case OPC_VR54XX_MACCU:
4355 gen_helper_maccu(t0, cpu_env, t0, t1);
4356 break;
4357 case OPC_VR54XX_MSAC:
4358 gen_helper_msac(t0, cpu_env, t0, t1);
4359 break;
4360 case OPC_VR54XX_MSACU:
4361 gen_helper_msacu(t0, cpu_env, t0, t1);
4362 break;
4363 case OPC_VR54XX_MULHI:
4364 gen_helper_mulhi(t0, cpu_env, t0, t1);
4365 break;
4366 case OPC_VR54XX_MULHIU:
4367 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4368 break;
4369 case OPC_VR54XX_MULSHI:
4370 gen_helper_mulshi(t0, cpu_env, t0, t1);
4371 break;
4372 case OPC_VR54XX_MULSHIU:
4373 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4374 break;
4375 case OPC_VR54XX_MACCHI:
4376 gen_helper_macchi(t0, cpu_env, t0, t1);
4377 break;
4378 case OPC_VR54XX_MACCHIU:
4379 gen_helper_macchiu(t0, cpu_env, t0, t1);
4380 break;
4381 case OPC_VR54XX_MSACHI:
4382 gen_helper_msachi(t0, cpu_env, t0, t1);
4383 break;
4384 case OPC_VR54XX_MSACHIU:
4385 gen_helper_msachiu(t0, cpu_env, t0, t1);
4386 break;
4387 default:
4388 MIPS_INVAL("mul vr54xx");
4389 generate_exception_end(ctx, EXCP_RI);
4390 goto out;
4392 gen_store_gpr(t0, rd);
4394 out:
4395 tcg_temp_free(t0);
4396 tcg_temp_free(t1);
4399 static void gen_cl (DisasContext *ctx, uint32_t opc,
4400 int rd, int rs)
4402 TCGv t0;
4404 if (rd == 0) {
4405 /* Treat as NOP. */
4406 return;
4408 t0 = cpu_gpr[rd];
4409 gen_load_gpr(t0, rs);
4411 switch (opc) {
4412 case OPC_CLO:
4413 case R6_OPC_CLO:
4414 #if defined(TARGET_MIPS64)
4415 case OPC_DCLO:
4416 case R6_OPC_DCLO:
4417 #endif
4418 tcg_gen_not_tl(t0, t0);
4419 break;
4422 switch (opc) {
4423 case OPC_CLO:
4424 case R6_OPC_CLO:
4425 case OPC_CLZ:
4426 case R6_OPC_CLZ:
4427 tcg_gen_ext32u_tl(t0, t0);
4428 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4429 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4430 break;
4431 #if defined(TARGET_MIPS64)
4432 case OPC_DCLO:
4433 case R6_OPC_DCLO:
4434 case OPC_DCLZ:
4435 case R6_OPC_DCLZ:
4436 tcg_gen_clzi_i64(t0, t0, 64);
4437 break;
4438 #endif
4442 /* Godson integer instructions */
4443 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4444 int rd, int rs, int rt)
4446 TCGv t0, t1;
4448 if (rd == 0) {
4449 /* Treat as NOP. */
4450 return;
4453 switch (opc) {
4454 case OPC_MULT_G_2E:
4455 case OPC_MULT_G_2F:
4456 case OPC_MULTU_G_2E:
4457 case OPC_MULTU_G_2F:
4458 #if defined(TARGET_MIPS64)
4459 case OPC_DMULT_G_2E:
4460 case OPC_DMULT_G_2F:
4461 case OPC_DMULTU_G_2E:
4462 case OPC_DMULTU_G_2F:
4463 #endif
4464 t0 = tcg_temp_new();
4465 t1 = tcg_temp_new();
4466 break;
4467 default:
4468 t0 = tcg_temp_local_new();
4469 t1 = tcg_temp_local_new();
4470 break;
4473 gen_load_gpr(t0, rs);
4474 gen_load_gpr(t1, rt);
4476 switch (opc) {
4477 case OPC_MULT_G_2E:
4478 case OPC_MULT_G_2F:
4479 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4480 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4481 break;
4482 case OPC_MULTU_G_2E:
4483 case OPC_MULTU_G_2F:
4484 tcg_gen_ext32u_tl(t0, t0);
4485 tcg_gen_ext32u_tl(t1, t1);
4486 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4487 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4488 break;
4489 case OPC_DIV_G_2E:
4490 case OPC_DIV_G_2F:
4492 TCGLabel *l1 = gen_new_label();
4493 TCGLabel *l2 = gen_new_label();
4494 TCGLabel *l3 = gen_new_label();
4495 tcg_gen_ext32s_tl(t0, t0);
4496 tcg_gen_ext32s_tl(t1, t1);
4497 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4498 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4499 tcg_gen_br(l3);
4500 gen_set_label(l1);
4501 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4502 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4503 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4504 tcg_gen_br(l3);
4505 gen_set_label(l2);
4506 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4507 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4508 gen_set_label(l3);
4510 break;
4511 case OPC_DIVU_G_2E:
4512 case OPC_DIVU_G_2F:
4514 TCGLabel *l1 = gen_new_label();
4515 TCGLabel *l2 = gen_new_label();
4516 tcg_gen_ext32u_tl(t0, t0);
4517 tcg_gen_ext32u_tl(t1, t1);
4518 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4519 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4520 tcg_gen_br(l2);
4521 gen_set_label(l1);
4522 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4523 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4524 gen_set_label(l2);
4526 break;
4527 case OPC_MOD_G_2E:
4528 case OPC_MOD_G_2F:
4530 TCGLabel *l1 = gen_new_label();
4531 TCGLabel *l2 = gen_new_label();
4532 TCGLabel *l3 = gen_new_label();
4533 tcg_gen_ext32u_tl(t0, t0);
4534 tcg_gen_ext32u_tl(t1, t1);
4535 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4536 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4537 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4538 gen_set_label(l1);
4539 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4540 tcg_gen_br(l3);
4541 gen_set_label(l2);
4542 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4543 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4544 gen_set_label(l3);
4546 break;
4547 case OPC_MODU_G_2E:
4548 case OPC_MODU_G_2F:
4550 TCGLabel *l1 = gen_new_label();
4551 TCGLabel *l2 = gen_new_label();
4552 tcg_gen_ext32u_tl(t0, t0);
4553 tcg_gen_ext32u_tl(t1, t1);
4554 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4555 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4556 tcg_gen_br(l2);
4557 gen_set_label(l1);
4558 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4559 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4560 gen_set_label(l2);
4562 break;
4563 #if defined(TARGET_MIPS64)
4564 case OPC_DMULT_G_2E:
4565 case OPC_DMULT_G_2F:
4566 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4567 break;
4568 case OPC_DMULTU_G_2E:
4569 case OPC_DMULTU_G_2F:
4570 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4571 break;
4572 case OPC_DDIV_G_2E:
4573 case OPC_DDIV_G_2F:
4575 TCGLabel *l1 = gen_new_label();
4576 TCGLabel *l2 = gen_new_label();
4577 TCGLabel *l3 = gen_new_label();
4578 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4579 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4580 tcg_gen_br(l3);
4581 gen_set_label(l1);
4582 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4583 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4584 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4585 tcg_gen_br(l3);
4586 gen_set_label(l2);
4587 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4588 gen_set_label(l3);
4590 break;
4591 case OPC_DDIVU_G_2E:
4592 case OPC_DDIVU_G_2F:
4594 TCGLabel *l1 = gen_new_label();
4595 TCGLabel *l2 = gen_new_label();
4596 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4597 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4598 tcg_gen_br(l2);
4599 gen_set_label(l1);
4600 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4601 gen_set_label(l2);
4603 break;
4604 case OPC_DMOD_G_2E:
4605 case OPC_DMOD_G_2F:
4607 TCGLabel *l1 = gen_new_label();
4608 TCGLabel *l2 = gen_new_label();
4609 TCGLabel *l3 = gen_new_label();
4610 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4611 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4612 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4613 gen_set_label(l1);
4614 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4615 tcg_gen_br(l3);
4616 gen_set_label(l2);
4617 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4618 gen_set_label(l3);
4620 break;
4621 case OPC_DMODU_G_2E:
4622 case OPC_DMODU_G_2F:
4624 TCGLabel *l1 = gen_new_label();
4625 TCGLabel *l2 = gen_new_label();
4626 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4627 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4628 tcg_gen_br(l2);
4629 gen_set_label(l1);
4630 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4631 gen_set_label(l2);
4633 break;
4634 #endif
4637 tcg_temp_free(t0);
4638 tcg_temp_free(t1);
4641 /* Loongson multimedia instructions */
4642 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4644 uint32_t opc, shift_max;
4645 TCGv_i64 t0, t1;
4647 opc = MASK_LMI(ctx->opcode);
4648 switch (opc) {
4649 case OPC_ADD_CP2:
4650 case OPC_SUB_CP2:
4651 case OPC_DADD_CP2:
4652 case OPC_DSUB_CP2:
4653 t0 = tcg_temp_local_new_i64();
4654 t1 = tcg_temp_local_new_i64();
4655 break;
4656 default:
4657 t0 = tcg_temp_new_i64();
4658 t1 = tcg_temp_new_i64();
4659 break;
4662 check_cp1_enabled(ctx);
4663 gen_load_fpr64(ctx, t0, rs);
4664 gen_load_fpr64(ctx, t1, rt);
4666 #define LMI_HELPER(UP, LO) \
4667 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
4668 #define LMI_HELPER_1(UP, LO) \
4669 case OPC_##UP: gen_helper_##LO(t0, t0); break
4670 #define LMI_DIRECT(UP, LO, OP) \
4671 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
4673 switch (opc) {
4674 LMI_HELPER(PADDSH, paddsh);
4675 LMI_HELPER(PADDUSH, paddush);
4676 LMI_HELPER(PADDH, paddh);
4677 LMI_HELPER(PADDW, paddw);
4678 LMI_HELPER(PADDSB, paddsb);
4679 LMI_HELPER(PADDUSB, paddusb);
4680 LMI_HELPER(PADDB, paddb);
4682 LMI_HELPER(PSUBSH, psubsh);
4683 LMI_HELPER(PSUBUSH, psubush);
4684 LMI_HELPER(PSUBH, psubh);
4685 LMI_HELPER(PSUBW, psubw);
4686 LMI_HELPER(PSUBSB, psubsb);
4687 LMI_HELPER(PSUBUSB, psubusb);
4688 LMI_HELPER(PSUBB, psubb);
4690 LMI_HELPER(PSHUFH, pshufh);
4691 LMI_HELPER(PACKSSWH, packsswh);
4692 LMI_HELPER(PACKSSHB, packsshb);
4693 LMI_HELPER(PACKUSHB, packushb);
4695 LMI_HELPER(PUNPCKLHW, punpcklhw);
4696 LMI_HELPER(PUNPCKHHW, punpckhhw);
4697 LMI_HELPER(PUNPCKLBH, punpcklbh);
4698 LMI_HELPER(PUNPCKHBH, punpckhbh);
4699 LMI_HELPER(PUNPCKLWD, punpcklwd);
4700 LMI_HELPER(PUNPCKHWD, punpckhwd);
4702 LMI_HELPER(PAVGH, pavgh);
4703 LMI_HELPER(PAVGB, pavgb);
4704 LMI_HELPER(PMAXSH, pmaxsh);
4705 LMI_HELPER(PMINSH, pminsh);
4706 LMI_HELPER(PMAXUB, pmaxub);
4707 LMI_HELPER(PMINUB, pminub);
4709 LMI_HELPER(PCMPEQW, pcmpeqw);
4710 LMI_HELPER(PCMPGTW, pcmpgtw);
4711 LMI_HELPER(PCMPEQH, pcmpeqh);
4712 LMI_HELPER(PCMPGTH, pcmpgth);
4713 LMI_HELPER(PCMPEQB, pcmpeqb);
4714 LMI_HELPER(PCMPGTB, pcmpgtb);
4716 LMI_HELPER(PSLLW, psllw);
4717 LMI_HELPER(PSLLH, psllh);
4718 LMI_HELPER(PSRLW, psrlw);
4719 LMI_HELPER(PSRLH, psrlh);
4720 LMI_HELPER(PSRAW, psraw);
4721 LMI_HELPER(PSRAH, psrah);
4723 LMI_HELPER(PMULLH, pmullh);
4724 LMI_HELPER(PMULHH, pmulhh);
4725 LMI_HELPER(PMULHUH, pmulhuh);
4726 LMI_HELPER(PMADDHW, pmaddhw);
4728 LMI_HELPER(PASUBUB, pasubub);
4729 LMI_HELPER_1(BIADD, biadd);
4730 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4732 LMI_DIRECT(PADDD, paddd, add);
4733 LMI_DIRECT(PSUBD, psubd, sub);
4734 LMI_DIRECT(XOR_CP2, xor, xor);
4735 LMI_DIRECT(NOR_CP2, nor, nor);
4736 LMI_DIRECT(AND_CP2, and, and);
4737 LMI_DIRECT(OR_CP2, or, or);
4739 case OPC_PANDN:
4740 tcg_gen_andc_i64(t0, t1, t0);
4741 break;
4743 case OPC_PINSRH_0:
4744 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4745 break;
4746 case OPC_PINSRH_1:
4747 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4748 break;
4749 case OPC_PINSRH_2:
4750 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4751 break;
4752 case OPC_PINSRH_3:
4753 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4754 break;
4756 case OPC_PEXTRH:
4757 tcg_gen_andi_i64(t1, t1, 3);
4758 tcg_gen_shli_i64(t1, t1, 4);
4759 tcg_gen_shr_i64(t0, t0, t1);
4760 tcg_gen_ext16u_i64(t0, t0);
4761 break;
4763 case OPC_ADDU_CP2:
4764 tcg_gen_add_i64(t0, t0, t1);
4765 tcg_gen_ext32s_i64(t0, t0);
4766 break;
4767 case OPC_SUBU_CP2:
4768 tcg_gen_sub_i64(t0, t0, t1);
4769 tcg_gen_ext32s_i64(t0, t0);
4770 break;
4772 case OPC_SLL_CP2:
4773 shift_max = 32;
4774 goto do_shift;
4775 case OPC_SRL_CP2:
4776 shift_max = 32;
4777 goto do_shift;
4778 case OPC_SRA_CP2:
4779 shift_max = 32;
4780 goto do_shift;
4781 case OPC_DSLL_CP2:
4782 shift_max = 64;
4783 goto do_shift;
4784 case OPC_DSRL_CP2:
4785 shift_max = 64;
4786 goto do_shift;
4787 case OPC_DSRA_CP2:
4788 shift_max = 64;
4789 goto do_shift;
4790 do_shift:
4791 /* Make sure shift count isn't TCG undefined behaviour. */
4792 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4794 switch (opc) {
4795 case OPC_SLL_CP2:
4796 case OPC_DSLL_CP2:
4797 tcg_gen_shl_i64(t0, t0, t1);
4798 break;
4799 case OPC_SRA_CP2:
4800 case OPC_DSRA_CP2:
4801 /* Since SRA is UndefinedResult without sign-extended inputs,
4802 we can treat SRA and DSRA the same. */
4803 tcg_gen_sar_i64(t0, t0, t1);
4804 break;
4805 case OPC_SRL_CP2:
4806 /* We want to shift in zeros for SRL; zero-extend first. */
4807 tcg_gen_ext32u_i64(t0, t0);
4808 /* FALLTHRU */
4809 case OPC_DSRL_CP2:
4810 tcg_gen_shr_i64(t0, t0, t1);
4811 break;
4814 if (shift_max == 32) {
4815 tcg_gen_ext32s_i64(t0, t0);
4818 /* Shifts larger than MAX produce zero. */
4819 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4820 tcg_gen_neg_i64(t1, t1);
4821 tcg_gen_and_i64(t0, t0, t1);
4822 break;
4824 case OPC_ADD_CP2:
4825 case OPC_DADD_CP2:
4827 TCGv_i64 t2 = tcg_temp_new_i64();
4828 TCGLabel *lab = gen_new_label();
4830 tcg_gen_mov_i64(t2, t0);
4831 tcg_gen_add_i64(t0, t1, t2);
4832 if (opc == OPC_ADD_CP2) {
4833 tcg_gen_ext32s_i64(t0, t0);
4835 tcg_gen_xor_i64(t1, t1, t2);
4836 tcg_gen_xor_i64(t2, t2, t0);
4837 tcg_gen_andc_i64(t1, t2, t1);
4838 tcg_temp_free_i64(t2);
4839 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4840 generate_exception(ctx, EXCP_OVERFLOW);
4841 gen_set_label(lab);
4842 break;
4845 case OPC_SUB_CP2:
4846 case OPC_DSUB_CP2:
4848 TCGv_i64 t2 = tcg_temp_new_i64();
4849 TCGLabel *lab = gen_new_label();
4851 tcg_gen_mov_i64(t2, t0);
4852 tcg_gen_sub_i64(t0, t1, t2);
4853 if (opc == OPC_SUB_CP2) {
4854 tcg_gen_ext32s_i64(t0, t0);
4856 tcg_gen_xor_i64(t1, t1, t2);
4857 tcg_gen_xor_i64(t2, t2, t0);
4858 tcg_gen_and_i64(t1, t1, t2);
4859 tcg_temp_free_i64(t2);
4860 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4861 generate_exception(ctx, EXCP_OVERFLOW);
4862 gen_set_label(lab);
4863 break;
4866 case OPC_PMULUW:
4867 tcg_gen_ext32u_i64(t0, t0);
4868 tcg_gen_ext32u_i64(t1, t1);
4869 tcg_gen_mul_i64(t0, t0, t1);
4870 break;
4872 case OPC_SEQU_CP2:
4873 case OPC_SEQ_CP2:
4874 case OPC_SLTU_CP2:
4875 case OPC_SLT_CP2:
4876 case OPC_SLEU_CP2:
4877 case OPC_SLE_CP2:
4878 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4879 FD field is the CC field? */
4880 default:
4881 MIPS_INVAL("loongson_cp2");
4882 generate_exception_end(ctx, EXCP_RI);
4883 return;
4886 #undef LMI_HELPER
4887 #undef LMI_DIRECT
4889 gen_store_fpr64(ctx, t0, rd);
4891 tcg_temp_free_i64(t0);
4892 tcg_temp_free_i64(t1);
4895 /* Traps */
4896 static void gen_trap (DisasContext *ctx, uint32_t opc,
4897 int rs, int rt, int16_t imm)
4899 int cond;
4900 TCGv t0 = tcg_temp_new();
4901 TCGv t1 = tcg_temp_new();
4903 cond = 0;
4904 /* Load needed operands */
4905 switch (opc) {
4906 case OPC_TEQ:
4907 case OPC_TGE:
4908 case OPC_TGEU:
4909 case OPC_TLT:
4910 case OPC_TLTU:
4911 case OPC_TNE:
4912 /* Compare two registers */
4913 if (rs != rt) {
4914 gen_load_gpr(t0, rs);
4915 gen_load_gpr(t1, rt);
4916 cond = 1;
4918 break;
4919 case OPC_TEQI:
4920 case OPC_TGEI:
4921 case OPC_TGEIU:
4922 case OPC_TLTI:
4923 case OPC_TLTIU:
4924 case OPC_TNEI:
4925 /* Compare register to immediate */
4926 if (rs != 0 || imm != 0) {
4927 gen_load_gpr(t0, rs);
4928 tcg_gen_movi_tl(t1, (int32_t)imm);
4929 cond = 1;
4931 break;
4933 if (cond == 0) {
4934 switch (opc) {
4935 case OPC_TEQ: /* rs == rs */
4936 case OPC_TEQI: /* r0 == 0 */
4937 case OPC_TGE: /* rs >= rs */
4938 case OPC_TGEI: /* r0 >= 0 */
4939 case OPC_TGEU: /* rs >= rs unsigned */
4940 case OPC_TGEIU: /* r0 >= 0 unsigned */
4941 /* Always trap */
4942 generate_exception_end(ctx, EXCP_TRAP);
4943 break;
4944 case OPC_TLT: /* rs < rs */
4945 case OPC_TLTI: /* r0 < 0 */
4946 case OPC_TLTU: /* rs < rs unsigned */
4947 case OPC_TLTIU: /* r0 < 0 unsigned */
4948 case OPC_TNE: /* rs != rs */
4949 case OPC_TNEI: /* r0 != 0 */
4950 /* Never trap: treat as NOP. */
4951 break;
4953 } else {
4954 TCGLabel *l1 = gen_new_label();
4956 switch (opc) {
4957 case OPC_TEQ:
4958 case OPC_TEQI:
4959 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4960 break;
4961 case OPC_TGE:
4962 case OPC_TGEI:
4963 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4964 break;
4965 case OPC_TGEU:
4966 case OPC_TGEIU:
4967 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4968 break;
4969 case OPC_TLT:
4970 case OPC_TLTI:
4971 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4972 break;
4973 case OPC_TLTU:
4974 case OPC_TLTIU:
4975 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4976 break;
4977 case OPC_TNE:
4978 case OPC_TNEI:
4979 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4980 break;
4982 generate_exception(ctx, EXCP_TRAP);
4983 gen_set_label(l1);
4985 tcg_temp_free(t0);
4986 tcg_temp_free(t1);
4989 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4991 if (unlikely(ctx->base.singlestep_enabled)) {
4992 return false;
4995 #ifndef CONFIG_USER_ONLY
4996 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4997 #else
4998 return true;
4999 #endif
5002 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5004 if (use_goto_tb(ctx, dest)) {
5005 tcg_gen_goto_tb(n);
5006 gen_save_pc(dest);
5007 tcg_gen_exit_tb(ctx->base.tb, n);
5008 } else {
5009 gen_save_pc(dest);
5010 if (ctx->base.singlestep_enabled) {
5011 save_cpu_state(ctx, 0);
5012 gen_helper_raise_exception_debug(cpu_env);
5014 tcg_gen_lookup_and_goto_ptr();
5018 /* Branches (before delay slot) */
5019 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5020 int insn_bytes,
5021 int rs, int rt, int32_t offset,
5022 int delayslot_size)
5024 target_ulong btgt = -1;
5025 int blink = 0;
5026 int bcond_compute = 0;
5027 TCGv t0 = tcg_temp_new();
5028 TCGv t1 = tcg_temp_new();
5030 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5031 #ifdef MIPS_DEBUG_DISAS
5032 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5033 TARGET_FMT_lx "\n", ctx->base.pc_next);
5034 #endif
5035 generate_exception_end(ctx, EXCP_RI);
5036 goto out;
5039 /* Load needed operands */
5040 switch (opc) {
5041 case OPC_BEQ:
5042 case OPC_BEQL:
5043 case OPC_BNE:
5044 case OPC_BNEL:
5045 /* Compare two registers */
5046 if (rs != rt) {
5047 gen_load_gpr(t0, rs);
5048 gen_load_gpr(t1, rt);
5049 bcond_compute = 1;
5051 btgt = ctx->base.pc_next + insn_bytes + offset;
5052 break;
5053 case OPC_BGEZ:
5054 case OPC_BGEZAL:
5055 case OPC_BGEZALL:
5056 case OPC_BGEZL:
5057 case OPC_BGTZ:
5058 case OPC_BGTZL:
5059 case OPC_BLEZ:
5060 case OPC_BLEZL:
5061 case OPC_BLTZ:
5062 case OPC_BLTZAL:
5063 case OPC_BLTZALL:
5064 case OPC_BLTZL:
5065 /* Compare to zero */
5066 if (rs != 0) {
5067 gen_load_gpr(t0, rs);
5068 bcond_compute = 1;
5070 btgt = ctx->base.pc_next + insn_bytes + offset;
5071 break;
5072 case OPC_BPOSGE32:
5073 #if defined(TARGET_MIPS64)
5074 case OPC_BPOSGE64:
5075 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5076 #else
5077 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5078 #endif
5079 bcond_compute = 1;
5080 btgt = ctx->base.pc_next + insn_bytes + offset;
5081 break;
5082 case OPC_J:
5083 case OPC_JAL:
5084 case OPC_JALX:
5085 /* Jump to immediate */
5086 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5087 (uint32_t)offset;
5088 break;
5089 case OPC_JR:
5090 case OPC_JALR:
5091 /* Jump to register */
5092 if (offset != 0 && offset != 16) {
5093 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5094 others are reserved. */
5095 MIPS_INVAL("jump hint");
5096 generate_exception_end(ctx, EXCP_RI);
5097 goto out;
5099 gen_load_gpr(btarget, rs);
5100 break;
5101 default:
5102 MIPS_INVAL("branch/jump");
5103 generate_exception_end(ctx, EXCP_RI);
5104 goto out;
5106 if (bcond_compute == 0) {
5107 /* No condition to be computed */
5108 switch (opc) {
5109 case OPC_BEQ: /* rx == rx */
5110 case OPC_BEQL: /* rx == rx likely */
5111 case OPC_BGEZ: /* 0 >= 0 */
5112 case OPC_BGEZL: /* 0 >= 0 likely */
5113 case OPC_BLEZ: /* 0 <= 0 */
5114 case OPC_BLEZL: /* 0 <= 0 likely */
5115 /* Always take */
5116 ctx->hflags |= MIPS_HFLAG_B;
5117 break;
5118 case OPC_BGEZAL: /* 0 >= 0 */
5119 case OPC_BGEZALL: /* 0 >= 0 likely */
5120 /* Always take and link */
5121 blink = 31;
5122 ctx->hflags |= MIPS_HFLAG_B;
5123 break;
5124 case OPC_BNE: /* rx != rx */
5125 case OPC_BGTZ: /* 0 > 0 */
5126 case OPC_BLTZ: /* 0 < 0 */
5127 /* Treat as NOP. */
5128 goto out;
5129 case OPC_BLTZAL: /* 0 < 0 */
5130 /* Handle as an unconditional branch to get correct delay
5131 slot checking. */
5132 blink = 31;
5133 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5134 ctx->hflags |= MIPS_HFLAG_B;
5135 break;
5136 case OPC_BLTZALL: /* 0 < 0 likely */
5137 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5138 /* Skip the instruction in the delay slot */
5139 ctx->base.pc_next += 4;
5140 goto out;
5141 case OPC_BNEL: /* rx != rx likely */
5142 case OPC_BGTZL: /* 0 > 0 likely */
5143 case OPC_BLTZL: /* 0 < 0 likely */
5144 /* Skip the instruction in the delay slot */
5145 ctx->base.pc_next += 4;
5146 goto out;
5147 case OPC_J:
5148 ctx->hflags |= MIPS_HFLAG_B;
5149 break;
5150 case OPC_JALX:
5151 ctx->hflags |= MIPS_HFLAG_BX;
5152 /* Fallthrough */
5153 case OPC_JAL:
5154 blink = 31;
5155 ctx->hflags |= MIPS_HFLAG_B;
5156 break;
5157 case OPC_JR:
5158 ctx->hflags |= MIPS_HFLAG_BR;
5159 break;
5160 case OPC_JALR:
5161 blink = rt;
5162 ctx->hflags |= MIPS_HFLAG_BR;
5163 break;
5164 default:
5165 MIPS_INVAL("branch/jump");
5166 generate_exception_end(ctx, EXCP_RI);
5167 goto out;
5169 } else {
5170 switch (opc) {
5171 case OPC_BEQ:
5172 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5173 goto not_likely;
5174 case OPC_BEQL:
5175 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5176 goto likely;
5177 case OPC_BNE:
5178 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5179 goto not_likely;
5180 case OPC_BNEL:
5181 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5182 goto likely;
5183 case OPC_BGEZ:
5184 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5185 goto not_likely;
5186 case OPC_BGEZL:
5187 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5188 goto likely;
5189 case OPC_BGEZAL:
5190 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5191 blink = 31;
5192 goto not_likely;
5193 case OPC_BGEZALL:
5194 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5195 blink = 31;
5196 goto likely;
5197 case OPC_BGTZ:
5198 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5199 goto not_likely;
5200 case OPC_BGTZL:
5201 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5202 goto likely;
5203 case OPC_BLEZ:
5204 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5205 goto not_likely;
5206 case OPC_BLEZL:
5207 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5208 goto likely;
5209 case OPC_BLTZ:
5210 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5211 goto not_likely;
5212 case OPC_BLTZL:
5213 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5214 goto likely;
5215 case OPC_BPOSGE32:
5216 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5217 goto not_likely;
5218 #if defined(TARGET_MIPS64)
5219 case OPC_BPOSGE64:
5220 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5221 goto not_likely;
5222 #endif
5223 case OPC_BLTZAL:
5224 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5225 blink = 31;
5226 not_likely:
5227 ctx->hflags |= MIPS_HFLAG_BC;
5228 break;
5229 case OPC_BLTZALL:
5230 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5231 blink = 31;
5232 likely:
5233 ctx->hflags |= MIPS_HFLAG_BL;
5234 break;
5235 default:
5236 MIPS_INVAL("conditional branch/jump");
5237 generate_exception_end(ctx, EXCP_RI);
5238 goto out;
5242 ctx->btarget = btgt;
5244 switch (delayslot_size) {
5245 case 2:
5246 ctx->hflags |= MIPS_HFLAG_BDS16;
5247 break;
5248 case 4:
5249 ctx->hflags |= MIPS_HFLAG_BDS32;
5250 break;
5253 if (blink > 0) {
5254 int post_delay = insn_bytes + delayslot_size;
5255 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5257 tcg_gen_movi_tl(cpu_gpr[blink],
5258 ctx->base.pc_next + post_delay + lowbit);
5261 out:
5262 if (insn_bytes == 2)
5263 ctx->hflags |= MIPS_HFLAG_B16;
5264 tcg_temp_free(t0);
5265 tcg_temp_free(t1);
5269 /* nanoMIPS Branches */
5270 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5271 int insn_bytes,
5272 int rs, int rt, int32_t offset)
5274 target_ulong btgt = -1;
5275 int bcond_compute = 0;
5276 TCGv t0 = tcg_temp_new();
5277 TCGv t1 = tcg_temp_new();
5279 /* Load needed operands */
5280 switch (opc) {
5281 case OPC_BEQ:
5282 case OPC_BNE:
5283 /* Compare two registers */
5284 if (rs != rt) {
5285 gen_load_gpr(t0, rs);
5286 gen_load_gpr(t1, rt);
5287 bcond_compute = 1;
5289 btgt = ctx->base.pc_next + insn_bytes + offset;
5290 break;
5291 case OPC_BGEZAL:
5292 /* Compare to zero */
5293 if (rs != 0) {
5294 gen_load_gpr(t0, rs);
5295 bcond_compute = 1;
5297 btgt = ctx->base.pc_next + insn_bytes + offset;
5298 break;
5299 case OPC_BPOSGE32:
5300 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5301 bcond_compute = 1;
5302 btgt = ctx->base.pc_next + insn_bytes + offset;
5303 break;
5304 case OPC_JR:
5305 case OPC_JALR:
5306 /* Jump to register */
5307 if (offset != 0 && offset != 16) {
5308 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5309 others are reserved. */
5310 MIPS_INVAL("jump hint");
5311 generate_exception_end(ctx, EXCP_RI);
5312 goto out;
5314 gen_load_gpr(btarget, rs);
5315 break;
5316 default:
5317 MIPS_INVAL("branch/jump");
5318 generate_exception_end(ctx, EXCP_RI);
5319 goto out;
5321 if (bcond_compute == 0) {
5322 /* No condition to be computed */
5323 switch (opc) {
5324 case OPC_BEQ: /* rx == rx */
5325 /* Always take */
5326 ctx->hflags |= MIPS_HFLAG_B;
5327 break;
5328 case OPC_BGEZAL: /* 0 >= 0 */
5329 /* Always take and link */
5330 tcg_gen_movi_tl(cpu_gpr[31],
5331 ctx->base.pc_next + insn_bytes);
5332 ctx->hflags |= MIPS_HFLAG_B;
5333 break;
5334 case OPC_BNE: /* rx != rx */
5335 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5336 /* Skip the instruction in the delay slot */
5337 ctx->base.pc_next += 4;
5338 goto out;
5339 case OPC_JR:
5340 ctx->hflags |= MIPS_HFLAG_BR;
5341 break;
5342 case OPC_JALR:
5343 if (rt > 0) {
5344 tcg_gen_movi_tl(cpu_gpr[rt],
5345 ctx->base.pc_next + insn_bytes);
5347 ctx->hflags |= MIPS_HFLAG_BR;
5348 break;
5349 default:
5350 MIPS_INVAL("branch/jump");
5351 generate_exception_end(ctx, EXCP_RI);
5352 goto out;
5354 } else {
5355 switch (opc) {
5356 case OPC_BEQ:
5357 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5358 goto not_likely;
5359 case OPC_BNE:
5360 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5361 goto not_likely;
5362 case OPC_BGEZAL:
5363 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5364 tcg_gen_movi_tl(cpu_gpr[31],
5365 ctx->base.pc_next + insn_bytes);
5366 goto not_likely;
5367 case OPC_BPOSGE32:
5368 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5369 not_likely:
5370 ctx->hflags |= MIPS_HFLAG_BC;
5371 break;
5372 default:
5373 MIPS_INVAL("conditional branch/jump");
5374 generate_exception_end(ctx, EXCP_RI);
5375 goto out;
5379 ctx->btarget = btgt;
5381 out:
5382 if (insn_bytes == 2) {
5383 ctx->hflags |= MIPS_HFLAG_B16;
5385 tcg_temp_free(t0);
5386 tcg_temp_free(t1);
5390 /* special3 bitfield operations */
5391 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5392 int rs, int lsb, int msb)
5394 TCGv t0 = tcg_temp_new();
5395 TCGv t1 = tcg_temp_new();
5397 gen_load_gpr(t1, rs);
5398 switch (opc) {
5399 case OPC_EXT:
5400 if (lsb + msb > 31) {
5401 goto fail;
5403 if (msb != 31) {
5404 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5405 } else {
5406 /* The two checks together imply that lsb == 0,
5407 so this is a simple sign-extension. */
5408 tcg_gen_ext32s_tl(t0, t1);
5410 break;
5411 #if defined(TARGET_MIPS64)
5412 case OPC_DEXTU:
5413 lsb += 32;
5414 goto do_dext;
5415 case OPC_DEXTM:
5416 msb += 32;
5417 goto do_dext;
5418 case OPC_DEXT:
5419 do_dext:
5420 if (lsb + msb > 63) {
5421 goto fail;
5423 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5424 break;
5425 #endif
5426 case OPC_INS:
5427 if (lsb > msb) {
5428 goto fail;
5430 gen_load_gpr(t0, rt);
5431 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5432 tcg_gen_ext32s_tl(t0, t0);
5433 break;
5434 #if defined(TARGET_MIPS64)
5435 case OPC_DINSU:
5436 lsb += 32;
5437 /* FALLTHRU */
5438 case OPC_DINSM:
5439 msb += 32;
5440 /* FALLTHRU */
5441 case OPC_DINS:
5442 if (lsb > msb) {
5443 goto fail;
5445 gen_load_gpr(t0, rt);
5446 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5447 break;
5448 #endif
5449 default:
5450 fail:
5451 MIPS_INVAL("bitops");
5452 generate_exception_end(ctx, EXCP_RI);
5453 tcg_temp_free(t0);
5454 tcg_temp_free(t1);
5455 return;
5457 gen_store_gpr(t0, rt);
5458 tcg_temp_free(t0);
5459 tcg_temp_free(t1);
5462 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
5464 TCGv t0;
5466 if (rd == 0) {
5467 /* If no destination, treat it as a NOP. */
5468 return;
5471 t0 = tcg_temp_new();
5472 gen_load_gpr(t0, rt);
5473 switch (op2) {
5474 case OPC_WSBH:
5476 TCGv t1 = tcg_temp_new();
5477 TCGv t2 = tcg_const_tl(0x00FF00FF);
5479 tcg_gen_shri_tl(t1, t0, 8);
5480 tcg_gen_and_tl(t1, t1, t2);
5481 tcg_gen_and_tl(t0, t0, t2);
5482 tcg_gen_shli_tl(t0, t0, 8);
5483 tcg_gen_or_tl(t0, t0, t1);
5484 tcg_temp_free(t2);
5485 tcg_temp_free(t1);
5486 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5488 break;
5489 case OPC_SEB:
5490 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5491 break;
5492 case OPC_SEH:
5493 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5494 break;
5495 #if defined(TARGET_MIPS64)
5496 case OPC_DSBH:
5498 TCGv t1 = tcg_temp_new();
5499 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5501 tcg_gen_shri_tl(t1, t0, 8);
5502 tcg_gen_and_tl(t1, t1, t2);
5503 tcg_gen_and_tl(t0, t0, t2);
5504 tcg_gen_shli_tl(t0, t0, 8);
5505 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5506 tcg_temp_free(t2);
5507 tcg_temp_free(t1);
5509 break;
5510 case OPC_DSHD:
5512 TCGv t1 = tcg_temp_new();
5513 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5515 tcg_gen_shri_tl(t1, t0, 16);
5516 tcg_gen_and_tl(t1, t1, t2);
5517 tcg_gen_and_tl(t0, t0, t2);
5518 tcg_gen_shli_tl(t0, t0, 16);
5519 tcg_gen_or_tl(t0, t0, t1);
5520 tcg_gen_shri_tl(t1, t0, 32);
5521 tcg_gen_shli_tl(t0, t0, 32);
5522 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5523 tcg_temp_free(t2);
5524 tcg_temp_free(t1);
5526 break;
5527 #endif
5528 default:
5529 MIPS_INVAL("bsfhl");
5530 generate_exception_end(ctx, EXCP_RI);
5531 tcg_temp_free(t0);
5532 return;
5534 tcg_temp_free(t0);
5537 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
5538 int imm2)
5540 TCGv t0;
5541 TCGv t1;
5542 if (rd == 0) {
5543 /* Treat as NOP. */
5544 return;
5546 t0 = tcg_temp_new();
5547 t1 = tcg_temp_new();
5548 gen_load_gpr(t0, rs);
5549 gen_load_gpr(t1, rt);
5550 tcg_gen_shli_tl(t0, t0, imm2 + 1);
5551 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
5552 if (opc == OPC_LSA) {
5553 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5556 tcg_temp_free(t1);
5557 tcg_temp_free(t0);
5559 return;
5562 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5563 int rt, int bits)
5565 TCGv t0;
5566 if (rd == 0) {
5567 /* Treat as NOP. */
5568 return;
5570 t0 = tcg_temp_new();
5571 if (bits == 0 || bits == wordsz) {
5572 if (bits == 0) {
5573 gen_load_gpr(t0, rt);
5574 } else {
5575 gen_load_gpr(t0, rs);
5577 switch (wordsz) {
5578 case 32:
5579 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5580 break;
5581 #if defined(TARGET_MIPS64)
5582 case 64:
5583 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5584 break;
5585 #endif
5587 } else {
5588 TCGv t1 = tcg_temp_new();
5589 gen_load_gpr(t0, rt);
5590 gen_load_gpr(t1, rs);
5591 switch (wordsz) {
5592 case 32:
5594 TCGv_i64 t2 = tcg_temp_new_i64();
5595 tcg_gen_concat_tl_i64(t2, t1, t0);
5596 tcg_gen_shri_i64(t2, t2, 32 - bits);
5597 gen_move_low32(cpu_gpr[rd], t2);
5598 tcg_temp_free_i64(t2);
5600 break;
5601 #if defined(TARGET_MIPS64)
5602 case 64:
5603 tcg_gen_shli_tl(t0, t0, bits);
5604 tcg_gen_shri_tl(t1, t1, 64 - bits);
5605 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5606 break;
5607 #endif
5609 tcg_temp_free(t1);
5612 tcg_temp_free(t0);
5615 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5616 int bp)
5618 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5621 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5622 int shift)
5624 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5627 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5629 TCGv t0;
5630 if (rd == 0) {
5631 /* Treat as NOP. */
5632 return;
5634 t0 = tcg_temp_new();
5635 gen_load_gpr(t0, rt);
5636 switch (opc) {
5637 case OPC_BITSWAP:
5638 gen_helper_bitswap(cpu_gpr[rd], t0);
5639 break;
5640 #if defined(TARGET_MIPS64)
5641 case OPC_DBITSWAP:
5642 gen_helper_dbitswap(cpu_gpr[rd], t0);
5643 break;
5644 #endif
5646 tcg_temp_free(t0);
5649 #ifndef CONFIG_USER_ONLY
5650 /* CP0 (MMU and control) */
5651 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5653 TCGv_i64 t0 = tcg_temp_new_i64();
5654 TCGv_i64 t1 = tcg_temp_new_i64();
5656 tcg_gen_ext_tl_i64(t0, arg);
5657 tcg_gen_ld_i64(t1, cpu_env, off);
5658 #if defined(TARGET_MIPS64)
5659 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5660 #else
5661 tcg_gen_concat32_i64(t1, t1, t0);
5662 #endif
5663 tcg_gen_st_i64(t1, cpu_env, off);
5664 tcg_temp_free_i64(t1);
5665 tcg_temp_free_i64(t0);
5668 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5670 TCGv_i64 t0 = tcg_temp_new_i64();
5671 TCGv_i64 t1 = tcg_temp_new_i64();
5673 tcg_gen_ext_tl_i64(t0, arg);
5674 tcg_gen_ld_i64(t1, cpu_env, off);
5675 tcg_gen_concat32_i64(t1, t1, t0);
5676 tcg_gen_st_i64(t1, cpu_env, off);
5677 tcg_temp_free_i64(t1);
5678 tcg_temp_free_i64(t0);
5681 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5683 TCGv_i64 t0 = tcg_temp_new_i64();
5685 tcg_gen_ld_i64(t0, cpu_env, off);
5686 #if defined(TARGET_MIPS64)
5687 tcg_gen_shri_i64(t0, t0, 30);
5688 #else
5689 tcg_gen_shri_i64(t0, t0, 32);
5690 #endif
5691 gen_move_low32(arg, t0);
5692 tcg_temp_free_i64(t0);
5695 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5697 TCGv_i64 t0 = tcg_temp_new_i64();
5699 tcg_gen_ld_i64(t0, cpu_env, off);
5700 tcg_gen_shri_i64(t0, t0, 32 + shift);
5701 gen_move_low32(arg, t0);
5702 tcg_temp_free_i64(t0);
5705 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5707 TCGv_i32 t0 = tcg_temp_new_i32();
5709 tcg_gen_ld_i32(t0, cpu_env, off);
5710 tcg_gen_ext_i32_tl(arg, t0);
5711 tcg_temp_free_i32(t0);
5714 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5716 tcg_gen_ld_tl(arg, cpu_env, off);
5717 tcg_gen_ext32s_tl(arg, arg);
5720 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5722 TCGv_i32 t0 = tcg_temp_new_i32();
5724 tcg_gen_trunc_tl_i32(t0, arg);
5725 tcg_gen_st_i32(t0, cpu_env, off);
5726 tcg_temp_free_i32(t0);
5729 #define CP0_CHECK(c) \
5730 do { \
5731 if (!(c)) { \
5732 goto cp0_unimplemented; \
5734 } while (0)
5736 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5738 const char *rn = "invalid";
5740 switch (reg) {
5741 case 2:
5742 switch (sel) {
5743 case 0:
5744 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5745 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5746 rn = "EntryLo0";
5747 break;
5748 default:
5749 goto cp0_unimplemented;
5751 break;
5752 case 3:
5753 switch (sel) {
5754 case 0:
5755 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5756 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5757 rn = "EntryLo1";
5758 break;
5759 default:
5760 goto cp0_unimplemented;
5762 break;
5763 case 17:
5764 switch (sel) {
5765 case 0:
5766 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5767 ctx->CP0_LLAddr_shift);
5768 rn = "LLAddr";
5769 break;
5770 case 1:
5771 CP0_CHECK(ctx->mrp);
5772 gen_helper_mfhc0_maar(arg, cpu_env);
5773 rn = "MAAR";
5774 break;
5775 default:
5776 goto cp0_unimplemented;
5778 break;
5779 case 28:
5780 switch (sel) {
5781 case 0:
5782 case 2:
5783 case 4:
5784 case 6:
5785 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5786 rn = "TagLo";
5787 break;
5788 default:
5789 goto cp0_unimplemented;
5791 break;
5792 default:
5793 goto cp0_unimplemented;
5795 trace_mips_translate_c0("mfhc0", rn, reg, sel);
5796 return;
5798 cp0_unimplemented:
5799 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5800 tcg_gen_movi_tl(arg, 0);
5803 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5805 const char *rn = "invalid";
5806 uint64_t mask = ctx->PAMask >> 36;
5808 switch (reg) {
5809 case 2:
5810 switch (sel) {
5811 case 0:
5812 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5813 tcg_gen_andi_tl(arg, arg, mask);
5814 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5815 rn = "EntryLo0";
5816 break;
5817 default:
5818 goto cp0_unimplemented;
5820 break;
5821 case 3:
5822 switch (sel) {
5823 case 0:
5824 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5825 tcg_gen_andi_tl(arg, arg, mask);
5826 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5827 rn = "EntryLo1";
5828 break;
5829 default:
5830 goto cp0_unimplemented;
5832 break;
5833 case 17:
5834 switch (sel) {
5835 case 0:
5836 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5837 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5838 relevant for modern MIPS cores supporting MTHC0, therefore
5839 treating MTHC0 to LLAddr as NOP. */
5840 rn = "LLAddr";
5841 break;
5842 case 1:
5843 CP0_CHECK(ctx->mrp);
5844 gen_helper_mthc0_maar(cpu_env, arg);
5845 rn = "MAAR";
5846 break;
5847 default:
5848 goto cp0_unimplemented;
5850 break;
5851 case 28:
5852 switch (sel) {
5853 case 0:
5854 case 2:
5855 case 4:
5856 case 6:
5857 tcg_gen_andi_tl(arg, arg, mask);
5858 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5859 rn = "TagLo";
5860 break;
5861 default:
5862 goto cp0_unimplemented;
5864 break;
5865 default:
5866 goto cp0_unimplemented;
5868 trace_mips_translate_c0("mthc0", rn, reg, sel);
5870 cp0_unimplemented:
5871 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5874 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5876 if (ctx->insn_flags & ISA_MIPS32R6) {
5877 tcg_gen_movi_tl(arg, 0);
5878 } else {
5879 tcg_gen_movi_tl(arg, ~0);
5883 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5885 const char *rn = "invalid";
5887 if (sel != 0)
5888 check_insn(ctx, ISA_MIPS32);
5890 switch (reg) {
5891 case 0:
5892 switch (sel) {
5893 case 0:
5894 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5895 rn = "Index";
5896 break;
5897 case 1:
5898 CP0_CHECK(ctx->insn_flags & ASE_MT);
5899 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5900 rn = "MVPControl";
5901 break;
5902 case 2:
5903 CP0_CHECK(ctx->insn_flags & ASE_MT);
5904 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5905 rn = "MVPConf0";
5906 break;
5907 case 3:
5908 CP0_CHECK(ctx->insn_flags & ASE_MT);
5909 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5910 rn = "MVPConf1";
5911 break;
5912 case 4:
5913 CP0_CHECK(ctx->vp);
5914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5915 rn = "VPControl";
5916 break;
5917 default:
5918 goto cp0_unimplemented;
5920 break;
5921 case 1:
5922 switch (sel) {
5923 case 0:
5924 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5925 gen_helper_mfc0_random(arg, cpu_env);
5926 rn = "Random";
5927 break;
5928 case 1:
5929 CP0_CHECK(ctx->insn_flags & ASE_MT);
5930 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5931 rn = "VPEControl";
5932 break;
5933 case 2:
5934 CP0_CHECK(ctx->insn_flags & ASE_MT);
5935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5936 rn = "VPEConf0";
5937 break;
5938 case 3:
5939 CP0_CHECK(ctx->insn_flags & ASE_MT);
5940 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5941 rn = "VPEConf1";
5942 break;
5943 case 4:
5944 CP0_CHECK(ctx->insn_flags & ASE_MT);
5945 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5946 rn = "YQMask";
5947 break;
5948 case 5:
5949 CP0_CHECK(ctx->insn_flags & ASE_MT);
5950 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5951 rn = "VPESchedule";
5952 break;
5953 case 6:
5954 CP0_CHECK(ctx->insn_flags & ASE_MT);
5955 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5956 rn = "VPEScheFBack";
5957 break;
5958 case 7:
5959 CP0_CHECK(ctx->insn_flags & ASE_MT);
5960 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5961 rn = "VPEOpt";
5962 break;
5963 default:
5964 goto cp0_unimplemented;
5966 break;
5967 case 2:
5968 switch (sel) {
5969 case 0:
5971 TCGv_i64 tmp = tcg_temp_new_i64();
5972 tcg_gen_ld_i64(tmp, cpu_env,
5973 offsetof(CPUMIPSState, CP0_EntryLo0));
5974 #if defined(TARGET_MIPS64)
5975 if (ctx->rxi) {
5976 /* Move RI/XI fields to bits 31:30 */
5977 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5978 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5980 #endif
5981 gen_move_low32(arg, tmp);
5982 tcg_temp_free_i64(tmp);
5984 rn = "EntryLo0";
5985 break;
5986 case 1:
5987 CP0_CHECK(ctx->insn_flags & ASE_MT);
5988 gen_helper_mfc0_tcstatus(arg, cpu_env);
5989 rn = "TCStatus";
5990 break;
5991 case 2:
5992 CP0_CHECK(ctx->insn_flags & ASE_MT);
5993 gen_helper_mfc0_tcbind(arg, cpu_env);
5994 rn = "TCBind";
5995 break;
5996 case 3:
5997 CP0_CHECK(ctx->insn_flags & ASE_MT);
5998 gen_helper_mfc0_tcrestart(arg, cpu_env);
5999 rn = "TCRestart";
6000 break;
6001 case 4:
6002 CP0_CHECK(ctx->insn_flags & ASE_MT);
6003 gen_helper_mfc0_tchalt(arg, cpu_env);
6004 rn = "TCHalt";
6005 break;
6006 case 5:
6007 CP0_CHECK(ctx->insn_flags & ASE_MT);
6008 gen_helper_mfc0_tccontext(arg, cpu_env);
6009 rn = "TCContext";
6010 break;
6011 case 6:
6012 CP0_CHECK(ctx->insn_flags & ASE_MT);
6013 gen_helper_mfc0_tcschedule(arg, cpu_env);
6014 rn = "TCSchedule";
6015 break;
6016 case 7:
6017 CP0_CHECK(ctx->insn_flags & ASE_MT);
6018 gen_helper_mfc0_tcschefback(arg, cpu_env);
6019 rn = "TCScheFBack";
6020 break;
6021 default:
6022 goto cp0_unimplemented;
6024 break;
6025 case 3:
6026 switch (sel) {
6027 case 0:
6029 TCGv_i64 tmp = tcg_temp_new_i64();
6030 tcg_gen_ld_i64(tmp, cpu_env,
6031 offsetof(CPUMIPSState, CP0_EntryLo1));
6032 #if defined(TARGET_MIPS64)
6033 if (ctx->rxi) {
6034 /* Move RI/XI fields to bits 31:30 */
6035 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6036 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6038 #endif
6039 gen_move_low32(arg, tmp);
6040 tcg_temp_free_i64(tmp);
6042 rn = "EntryLo1";
6043 break;
6044 case 1:
6045 CP0_CHECK(ctx->vp);
6046 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6047 rn = "GlobalNumber";
6048 break;
6049 default:
6050 goto cp0_unimplemented;
6052 break;
6053 case 4:
6054 switch (sel) {
6055 case 0:
6056 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6057 tcg_gen_ext32s_tl(arg, arg);
6058 rn = "Context";
6059 break;
6060 case 1:
6061 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6062 rn = "ContextConfig";
6063 goto cp0_unimplemented;
6064 case 2:
6065 CP0_CHECK(ctx->ulri);
6066 tcg_gen_ld_tl(arg, cpu_env,
6067 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6068 tcg_gen_ext32s_tl(arg, arg);
6069 rn = "UserLocal";
6070 break;
6071 default:
6072 goto cp0_unimplemented;
6074 break;
6075 case 5:
6076 switch (sel) {
6077 case 0:
6078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6079 rn = "PageMask";
6080 break;
6081 case 1:
6082 check_insn(ctx, ISA_MIPS32R2);
6083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6084 rn = "PageGrain";
6085 break;
6086 case 2:
6087 CP0_CHECK(ctx->sc);
6088 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6089 tcg_gen_ext32s_tl(arg, arg);
6090 rn = "SegCtl0";
6091 break;
6092 case 3:
6093 CP0_CHECK(ctx->sc);
6094 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6095 tcg_gen_ext32s_tl(arg, arg);
6096 rn = "SegCtl1";
6097 break;
6098 case 4:
6099 CP0_CHECK(ctx->sc);
6100 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6101 tcg_gen_ext32s_tl(arg, arg);
6102 rn = "SegCtl2";
6103 break;
6104 case 5:
6105 check_pw(ctx);
6106 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6107 rn = "PWBase";
6108 break;
6109 case 6:
6110 check_pw(ctx);
6111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6112 rn = "PWField";
6113 break;
6114 case 7:
6115 check_pw(ctx);
6116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6117 rn = "PWSize";
6118 break;
6119 default:
6120 goto cp0_unimplemented;
6122 break;
6123 case 6:
6124 switch (sel) {
6125 case 0:
6126 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6127 rn = "Wired";
6128 break;
6129 case 1:
6130 check_insn(ctx, ISA_MIPS32R2);
6131 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6132 rn = "SRSConf0";
6133 break;
6134 case 2:
6135 check_insn(ctx, ISA_MIPS32R2);
6136 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6137 rn = "SRSConf1";
6138 break;
6139 case 3:
6140 check_insn(ctx, ISA_MIPS32R2);
6141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6142 rn = "SRSConf2";
6143 break;
6144 case 4:
6145 check_insn(ctx, ISA_MIPS32R2);
6146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6147 rn = "SRSConf3";
6148 break;
6149 case 5:
6150 check_insn(ctx, ISA_MIPS32R2);
6151 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6152 rn = "SRSConf4";
6153 break;
6154 case 6:
6155 check_pw(ctx);
6156 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6157 rn = "PWCtl";
6158 break;
6159 default:
6160 goto cp0_unimplemented;
6162 break;
6163 case 7:
6164 switch (sel) {
6165 case 0:
6166 check_insn(ctx, ISA_MIPS32R2);
6167 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6168 rn = "HWREna";
6169 break;
6170 default:
6171 goto cp0_unimplemented;
6173 break;
6174 case 8:
6175 switch (sel) {
6176 case 0:
6177 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6178 tcg_gen_ext32s_tl(arg, arg);
6179 rn = "BadVAddr";
6180 break;
6181 case 1:
6182 CP0_CHECK(ctx->bi);
6183 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6184 rn = "BadInstr";
6185 break;
6186 case 2:
6187 CP0_CHECK(ctx->bp);
6188 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6189 rn = "BadInstrP";
6190 break;
6191 case 3:
6192 CP0_CHECK(ctx->bi);
6193 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6194 tcg_gen_andi_tl(arg, arg, ~0xffff);
6195 rn = "BadInstrX";
6196 break;
6197 default:
6198 goto cp0_unimplemented;
6200 break;
6201 case 9:
6202 switch (sel) {
6203 case 0:
6204 /* Mark as an IO operation because we read the time. */
6205 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6206 gen_io_start();
6208 gen_helper_mfc0_count(arg, cpu_env);
6209 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6210 gen_io_end();
6212 /* Break the TB to be able to take timer interrupts immediately
6213 after reading count. DISAS_STOP isn't sufficient, we need to
6214 ensure we break completely out of translated code. */
6215 gen_save_pc(ctx->base.pc_next + 4);
6216 ctx->base.is_jmp = DISAS_EXIT;
6217 rn = "Count";
6218 break;
6219 /* 6,7 are implementation dependent */
6220 default:
6221 goto cp0_unimplemented;
6223 break;
6224 case 10:
6225 switch (sel) {
6226 case 0:
6227 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6228 tcg_gen_ext32s_tl(arg, arg);
6229 rn = "EntryHi";
6230 break;
6231 default:
6232 goto cp0_unimplemented;
6234 break;
6235 case 11:
6236 switch (sel) {
6237 case 0:
6238 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6239 rn = "Compare";
6240 break;
6241 /* 6,7 are implementation dependent */
6242 default:
6243 goto cp0_unimplemented;
6245 break;
6246 case 12:
6247 switch (sel) {
6248 case 0:
6249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6250 rn = "Status";
6251 break;
6252 case 1:
6253 check_insn(ctx, ISA_MIPS32R2);
6254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6255 rn = "IntCtl";
6256 break;
6257 case 2:
6258 check_insn(ctx, ISA_MIPS32R2);
6259 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6260 rn = "SRSCtl";
6261 break;
6262 case 3:
6263 check_insn(ctx, ISA_MIPS32R2);
6264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6265 rn = "SRSMap";
6266 break;
6267 default:
6268 goto cp0_unimplemented;
6270 break;
6271 case 13:
6272 switch (sel) {
6273 case 0:
6274 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6275 rn = "Cause";
6276 break;
6277 default:
6278 goto cp0_unimplemented;
6280 break;
6281 case 14:
6282 switch (sel) {
6283 case 0:
6284 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6285 tcg_gen_ext32s_tl(arg, arg);
6286 rn = "EPC";
6287 break;
6288 default:
6289 goto cp0_unimplemented;
6291 break;
6292 case 15:
6293 switch (sel) {
6294 case 0:
6295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6296 rn = "PRid";
6297 break;
6298 case 1:
6299 check_insn(ctx, ISA_MIPS32R2);
6300 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6301 tcg_gen_ext32s_tl(arg, arg);
6302 rn = "EBase";
6303 break;
6304 case 3:
6305 check_insn(ctx, ISA_MIPS32R2);
6306 CP0_CHECK(ctx->cmgcr);
6307 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6308 tcg_gen_ext32s_tl(arg, arg);
6309 rn = "CMGCRBase";
6310 break;
6311 default:
6312 goto cp0_unimplemented;
6314 break;
6315 case 16:
6316 switch (sel) {
6317 case 0:
6318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6319 rn = "Config";
6320 break;
6321 case 1:
6322 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6323 rn = "Config1";
6324 break;
6325 case 2:
6326 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6327 rn = "Config2";
6328 break;
6329 case 3:
6330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6331 rn = "Config3";
6332 break;
6333 case 4:
6334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6335 rn = "Config4";
6336 break;
6337 case 5:
6338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6339 rn = "Config5";
6340 break;
6341 /* 6,7 are implementation dependent */
6342 case 6:
6343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6344 rn = "Config6";
6345 break;
6346 case 7:
6347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6348 rn = "Config7";
6349 break;
6350 default:
6351 goto cp0_unimplemented;
6353 break;
6354 case 17:
6355 switch (sel) {
6356 case 0:
6357 gen_helper_mfc0_lladdr(arg, cpu_env);
6358 rn = "LLAddr";
6359 break;
6360 case 1:
6361 CP0_CHECK(ctx->mrp);
6362 gen_helper_mfc0_maar(arg, cpu_env);
6363 rn = "MAAR";
6364 break;
6365 case 2:
6366 CP0_CHECK(ctx->mrp);
6367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6368 rn = "MAARI";
6369 break;
6370 default:
6371 goto cp0_unimplemented;
6373 break;
6374 case 18:
6375 switch (sel) {
6376 case 0:
6377 case 1:
6378 case 2:
6379 case 3:
6380 case 4:
6381 case 5:
6382 case 6:
6383 case 7:
6384 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6385 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6386 rn = "WatchLo";
6387 break;
6388 default:
6389 goto cp0_unimplemented;
6391 break;
6392 case 19:
6393 switch (sel) {
6394 case 0:
6395 case 1:
6396 case 2:
6397 case 3:
6398 case 4:
6399 case 5:
6400 case 6:
6401 case 7:
6402 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6403 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6404 rn = "WatchHi";
6405 break;
6406 default:
6407 goto cp0_unimplemented;
6409 break;
6410 case 20:
6411 switch (sel) {
6412 case 0:
6413 #if defined(TARGET_MIPS64)
6414 check_insn(ctx, ISA_MIPS3);
6415 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6416 tcg_gen_ext32s_tl(arg, arg);
6417 rn = "XContext";
6418 break;
6419 #endif
6420 default:
6421 goto cp0_unimplemented;
6423 break;
6424 case 21:
6425 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6426 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6427 switch (sel) {
6428 case 0:
6429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6430 rn = "Framemask";
6431 break;
6432 default:
6433 goto cp0_unimplemented;
6435 break;
6436 case 22:
6437 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6438 rn = "'Diagnostic"; /* implementation dependent */
6439 break;
6440 case 23:
6441 switch (sel) {
6442 case 0:
6443 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6444 rn = "Debug";
6445 break;
6446 case 1:
6447 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
6448 rn = "TraceControl";
6449 goto cp0_unimplemented;
6450 case 2:
6451 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
6452 rn = "TraceControl2";
6453 goto cp0_unimplemented;
6454 case 3:
6455 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
6456 rn = "UserTraceData";
6457 goto cp0_unimplemented;
6458 case 4:
6459 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
6460 rn = "TraceBPC";
6461 goto cp0_unimplemented;
6462 default:
6463 goto cp0_unimplemented;
6465 break;
6466 case 24:
6467 switch (sel) {
6468 case 0:
6469 /* EJTAG support */
6470 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6471 tcg_gen_ext32s_tl(arg, arg);
6472 rn = "DEPC";
6473 break;
6474 default:
6475 goto cp0_unimplemented;
6477 break;
6478 case 25:
6479 switch (sel) {
6480 case 0:
6481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6482 rn = "Performance0";
6483 break;
6484 case 1:
6485 // gen_helper_mfc0_performance1(arg);
6486 rn = "Performance1";
6487 goto cp0_unimplemented;
6488 case 2:
6489 // gen_helper_mfc0_performance2(arg);
6490 rn = "Performance2";
6491 goto cp0_unimplemented;
6492 case 3:
6493 // gen_helper_mfc0_performance3(arg);
6494 rn = "Performance3";
6495 goto cp0_unimplemented;
6496 case 4:
6497 // gen_helper_mfc0_performance4(arg);
6498 rn = "Performance4";
6499 goto cp0_unimplemented;
6500 case 5:
6501 // gen_helper_mfc0_performance5(arg);
6502 rn = "Performance5";
6503 goto cp0_unimplemented;
6504 case 6:
6505 // gen_helper_mfc0_performance6(arg);
6506 rn = "Performance6";
6507 goto cp0_unimplemented;
6508 case 7:
6509 // gen_helper_mfc0_performance7(arg);
6510 rn = "Performance7";
6511 goto cp0_unimplemented;
6512 default:
6513 goto cp0_unimplemented;
6515 break;
6516 case 26:
6517 switch (sel) {
6518 case 0:
6519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6520 rn = "ErrCtl";
6521 break;
6522 default:
6523 goto cp0_unimplemented;
6525 break;
6526 case 27:
6527 switch (sel) {
6528 case 0:
6529 case 1:
6530 case 2:
6531 case 3:
6532 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6533 rn = "CacheErr";
6534 break;
6535 default:
6536 goto cp0_unimplemented;
6538 break;
6539 case 28:
6540 switch (sel) {
6541 case 0:
6542 case 2:
6543 case 4:
6544 case 6:
6546 TCGv_i64 tmp = tcg_temp_new_i64();
6547 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6548 gen_move_low32(arg, tmp);
6549 tcg_temp_free_i64(tmp);
6551 rn = "TagLo";
6552 break;
6553 case 1:
6554 case 3:
6555 case 5:
6556 case 7:
6557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6558 rn = "DataLo";
6559 break;
6560 default:
6561 goto cp0_unimplemented;
6563 break;
6564 case 29:
6565 switch (sel) {
6566 case 0:
6567 case 2:
6568 case 4:
6569 case 6:
6570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6571 rn = "TagHi";
6572 break;
6573 case 1:
6574 case 3:
6575 case 5:
6576 case 7:
6577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6578 rn = "DataHi";
6579 break;
6580 default:
6581 goto cp0_unimplemented;
6583 break;
6584 case 30:
6585 switch (sel) {
6586 case 0:
6587 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6588 tcg_gen_ext32s_tl(arg, arg);
6589 rn = "ErrorEPC";
6590 break;
6591 default:
6592 goto cp0_unimplemented;
6594 break;
6595 case 31:
6596 switch (sel) {
6597 case 0:
6598 /* EJTAG support */
6599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6600 rn = "DESAVE";
6601 break;
6602 case 2:
6603 case 3:
6604 case 4:
6605 case 5:
6606 case 6:
6607 case 7:
6608 CP0_CHECK(ctx->kscrexist & (1 << sel));
6609 tcg_gen_ld_tl(arg, cpu_env,
6610 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6611 tcg_gen_ext32s_tl(arg, arg);
6612 rn = "KScratch";
6613 break;
6614 default:
6615 goto cp0_unimplemented;
6617 break;
6618 default:
6619 goto cp0_unimplemented;
6621 trace_mips_translate_c0("mfc0", rn, reg, sel);
6622 return;
6624 cp0_unimplemented:
6625 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6626 gen_mfc0_unimplemented(ctx, arg);
6629 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6631 const char *rn = "invalid";
6633 if (sel != 0)
6634 check_insn(ctx, ISA_MIPS32);
6636 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6637 gen_io_start();
6640 switch (reg) {
6641 case 0:
6642 switch (sel) {
6643 case 0:
6644 gen_helper_mtc0_index(cpu_env, arg);
6645 rn = "Index";
6646 break;
6647 case 1:
6648 CP0_CHECK(ctx->insn_flags & ASE_MT);
6649 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6650 rn = "MVPControl";
6651 break;
6652 case 2:
6653 CP0_CHECK(ctx->insn_flags & ASE_MT);
6654 /* ignored */
6655 rn = "MVPConf0";
6656 break;
6657 case 3:
6658 CP0_CHECK(ctx->insn_flags & ASE_MT);
6659 /* ignored */
6660 rn = "MVPConf1";
6661 break;
6662 case 4:
6663 CP0_CHECK(ctx->vp);
6664 /* ignored */
6665 rn = "VPControl";
6666 break;
6667 default:
6668 goto cp0_unimplemented;
6670 break;
6671 case 1:
6672 switch (sel) {
6673 case 0:
6674 /* ignored */
6675 rn = "Random";
6676 break;
6677 case 1:
6678 CP0_CHECK(ctx->insn_flags & ASE_MT);
6679 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6680 rn = "VPEControl";
6681 break;
6682 case 2:
6683 CP0_CHECK(ctx->insn_flags & ASE_MT);
6684 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6685 rn = "VPEConf0";
6686 break;
6687 case 3:
6688 CP0_CHECK(ctx->insn_flags & ASE_MT);
6689 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6690 rn = "VPEConf1";
6691 break;
6692 case 4:
6693 CP0_CHECK(ctx->insn_flags & ASE_MT);
6694 gen_helper_mtc0_yqmask(cpu_env, arg);
6695 rn = "YQMask";
6696 break;
6697 case 5:
6698 CP0_CHECK(ctx->insn_flags & ASE_MT);
6699 tcg_gen_st_tl(arg, cpu_env,
6700 offsetof(CPUMIPSState, CP0_VPESchedule));
6701 rn = "VPESchedule";
6702 break;
6703 case 6:
6704 CP0_CHECK(ctx->insn_flags & ASE_MT);
6705 tcg_gen_st_tl(arg, cpu_env,
6706 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6707 rn = "VPEScheFBack";
6708 break;
6709 case 7:
6710 CP0_CHECK(ctx->insn_flags & ASE_MT);
6711 gen_helper_mtc0_vpeopt(cpu_env, arg);
6712 rn = "VPEOpt";
6713 break;
6714 default:
6715 goto cp0_unimplemented;
6717 break;
6718 case 2:
6719 switch (sel) {
6720 case 0:
6721 gen_helper_mtc0_entrylo0(cpu_env, arg);
6722 rn = "EntryLo0";
6723 break;
6724 case 1:
6725 CP0_CHECK(ctx->insn_flags & ASE_MT);
6726 gen_helper_mtc0_tcstatus(cpu_env, arg);
6727 rn = "TCStatus";
6728 break;
6729 case 2:
6730 CP0_CHECK(ctx->insn_flags & ASE_MT);
6731 gen_helper_mtc0_tcbind(cpu_env, arg);
6732 rn = "TCBind";
6733 break;
6734 case 3:
6735 CP0_CHECK(ctx->insn_flags & ASE_MT);
6736 gen_helper_mtc0_tcrestart(cpu_env, arg);
6737 rn = "TCRestart";
6738 break;
6739 case 4:
6740 CP0_CHECK(ctx->insn_flags & ASE_MT);
6741 gen_helper_mtc0_tchalt(cpu_env, arg);
6742 rn = "TCHalt";
6743 break;
6744 case 5:
6745 CP0_CHECK(ctx->insn_flags & ASE_MT);
6746 gen_helper_mtc0_tccontext(cpu_env, arg);
6747 rn = "TCContext";
6748 break;
6749 case 6:
6750 CP0_CHECK(ctx->insn_flags & ASE_MT);
6751 gen_helper_mtc0_tcschedule(cpu_env, arg);
6752 rn = "TCSchedule";
6753 break;
6754 case 7:
6755 CP0_CHECK(ctx->insn_flags & ASE_MT);
6756 gen_helper_mtc0_tcschefback(cpu_env, arg);
6757 rn = "TCScheFBack";
6758 break;
6759 default:
6760 goto cp0_unimplemented;
6762 break;
6763 case 3:
6764 switch (sel) {
6765 case 0:
6766 gen_helper_mtc0_entrylo1(cpu_env, arg);
6767 rn = "EntryLo1";
6768 break;
6769 case 1:
6770 CP0_CHECK(ctx->vp);
6771 /* ignored */
6772 rn = "GlobalNumber";
6773 break;
6774 default:
6775 goto cp0_unimplemented;
6777 break;
6778 case 4:
6779 switch (sel) {
6780 case 0:
6781 gen_helper_mtc0_context(cpu_env, arg);
6782 rn = "Context";
6783 break;
6784 case 1:
6785 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6786 rn = "ContextConfig";
6787 goto cp0_unimplemented;
6788 case 2:
6789 CP0_CHECK(ctx->ulri);
6790 tcg_gen_st_tl(arg, cpu_env,
6791 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6792 rn = "UserLocal";
6793 break;
6794 default:
6795 goto cp0_unimplemented;
6797 break;
6798 case 5:
6799 switch (sel) {
6800 case 0:
6801 gen_helper_mtc0_pagemask(cpu_env, arg);
6802 rn = "PageMask";
6803 break;
6804 case 1:
6805 check_insn(ctx, ISA_MIPS32R2);
6806 gen_helper_mtc0_pagegrain(cpu_env, arg);
6807 rn = "PageGrain";
6808 ctx->base.is_jmp = DISAS_STOP;
6809 break;
6810 case 2:
6811 CP0_CHECK(ctx->sc);
6812 gen_helper_mtc0_segctl0(cpu_env, arg);
6813 rn = "SegCtl0";
6814 break;
6815 case 3:
6816 CP0_CHECK(ctx->sc);
6817 gen_helper_mtc0_segctl1(cpu_env, arg);
6818 rn = "SegCtl1";
6819 break;
6820 case 4:
6821 CP0_CHECK(ctx->sc);
6822 gen_helper_mtc0_segctl2(cpu_env, arg);
6823 rn = "SegCtl2";
6824 break;
6825 case 5:
6826 check_pw(ctx);
6827 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6828 rn = "PWBase";
6829 break;
6830 case 6:
6831 check_pw(ctx);
6832 gen_helper_mtc0_pwfield(cpu_env, arg);
6833 rn = "PWField";
6834 break;
6835 case 7:
6836 check_pw(ctx);
6837 gen_helper_mtc0_pwsize(cpu_env, arg);
6838 rn = "PWSize";
6839 break;
6840 default:
6841 goto cp0_unimplemented;
6843 break;
6844 case 6:
6845 switch (sel) {
6846 case 0:
6847 gen_helper_mtc0_wired(cpu_env, arg);
6848 rn = "Wired";
6849 break;
6850 case 1:
6851 check_insn(ctx, ISA_MIPS32R2);
6852 gen_helper_mtc0_srsconf0(cpu_env, arg);
6853 rn = "SRSConf0";
6854 break;
6855 case 2:
6856 check_insn(ctx, ISA_MIPS32R2);
6857 gen_helper_mtc0_srsconf1(cpu_env, arg);
6858 rn = "SRSConf1";
6859 break;
6860 case 3:
6861 check_insn(ctx, ISA_MIPS32R2);
6862 gen_helper_mtc0_srsconf2(cpu_env, arg);
6863 rn = "SRSConf2";
6864 break;
6865 case 4:
6866 check_insn(ctx, ISA_MIPS32R2);
6867 gen_helper_mtc0_srsconf3(cpu_env, arg);
6868 rn = "SRSConf3";
6869 break;
6870 case 5:
6871 check_insn(ctx, ISA_MIPS32R2);
6872 gen_helper_mtc0_srsconf4(cpu_env, arg);
6873 rn = "SRSConf4";
6874 break;
6875 case 6:
6876 check_pw(ctx);
6877 gen_helper_mtc0_pwctl(cpu_env, arg);
6878 rn = "PWCtl";
6879 break;
6880 default:
6881 goto cp0_unimplemented;
6883 break;
6884 case 7:
6885 switch (sel) {
6886 case 0:
6887 check_insn(ctx, ISA_MIPS32R2);
6888 gen_helper_mtc0_hwrena(cpu_env, arg);
6889 ctx->base.is_jmp = DISAS_STOP;
6890 rn = "HWREna";
6891 break;
6892 default:
6893 goto cp0_unimplemented;
6895 break;
6896 case 8:
6897 switch (sel) {
6898 case 0:
6899 /* ignored */
6900 rn = "BadVAddr";
6901 break;
6902 case 1:
6903 /* ignored */
6904 rn = "BadInstr";
6905 break;
6906 case 2:
6907 /* ignored */
6908 rn = "BadInstrP";
6909 break;
6910 case 3:
6911 /* ignored */
6912 rn = "BadInstrX";
6913 break;
6914 default:
6915 goto cp0_unimplemented;
6917 break;
6918 case 9:
6919 switch (sel) {
6920 case 0:
6921 gen_helper_mtc0_count(cpu_env, arg);
6922 rn = "Count";
6923 break;
6924 /* 6,7 are implementation dependent */
6925 default:
6926 goto cp0_unimplemented;
6928 break;
6929 case 10:
6930 switch (sel) {
6931 case 0:
6932 gen_helper_mtc0_entryhi(cpu_env, arg);
6933 rn = "EntryHi";
6934 break;
6935 default:
6936 goto cp0_unimplemented;
6938 break;
6939 case 11:
6940 switch (sel) {
6941 case 0:
6942 gen_helper_mtc0_compare(cpu_env, arg);
6943 rn = "Compare";
6944 break;
6945 /* 6,7 are implementation dependent */
6946 default:
6947 goto cp0_unimplemented;
6949 break;
6950 case 12:
6951 switch (sel) {
6952 case 0:
6953 save_cpu_state(ctx, 1);
6954 gen_helper_mtc0_status(cpu_env, arg);
6955 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6956 gen_save_pc(ctx->base.pc_next + 4);
6957 ctx->base.is_jmp = DISAS_EXIT;
6958 rn = "Status";
6959 break;
6960 case 1:
6961 check_insn(ctx, ISA_MIPS32R2);
6962 gen_helper_mtc0_intctl(cpu_env, arg);
6963 /* Stop translation as we may have switched the execution mode */
6964 ctx->base.is_jmp = DISAS_STOP;
6965 rn = "IntCtl";
6966 break;
6967 case 2:
6968 check_insn(ctx, ISA_MIPS32R2);
6969 gen_helper_mtc0_srsctl(cpu_env, arg);
6970 /* Stop translation as we may have switched the execution mode */
6971 ctx->base.is_jmp = DISAS_STOP;
6972 rn = "SRSCtl";
6973 break;
6974 case 3:
6975 check_insn(ctx, ISA_MIPS32R2);
6976 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6977 /* Stop translation as we may have switched the execution mode */
6978 ctx->base.is_jmp = DISAS_STOP;
6979 rn = "SRSMap";
6980 break;
6981 default:
6982 goto cp0_unimplemented;
6984 break;
6985 case 13:
6986 switch (sel) {
6987 case 0:
6988 save_cpu_state(ctx, 1);
6989 gen_helper_mtc0_cause(cpu_env, arg);
6990 /* Stop translation as we may have triggered an interrupt.
6991 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6992 * translated code to check for pending interrupts. */
6993 gen_save_pc(ctx->base.pc_next + 4);
6994 ctx->base.is_jmp = DISAS_EXIT;
6995 rn = "Cause";
6996 break;
6997 default:
6998 goto cp0_unimplemented;
7000 break;
7001 case 14:
7002 switch (sel) {
7003 case 0:
7004 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7005 rn = "EPC";
7006 break;
7007 default:
7008 goto cp0_unimplemented;
7010 break;
7011 case 15:
7012 switch (sel) {
7013 case 0:
7014 /* ignored */
7015 rn = "PRid";
7016 break;
7017 case 1:
7018 check_insn(ctx, ISA_MIPS32R2);
7019 gen_helper_mtc0_ebase(cpu_env, arg);
7020 rn = "EBase";
7021 break;
7022 default:
7023 goto cp0_unimplemented;
7025 break;
7026 case 16:
7027 switch (sel) {
7028 case 0:
7029 gen_helper_mtc0_config0(cpu_env, arg);
7030 rn = "Config";
7031 /* Stop translation as we may have switched the execution mode */
7032 ctx->base.is_jmp = DISAS_STOP;
7033 break;
7034 case 1:
7035 /* ignored, read only */
7036 rn = "Config1";
7037 break;
7038 case 2:
7039 gen_helper_mtc0_config2(cpu_env, arg);
7040 rn = "Config2";
7041 /* Stop translation as we may have switched the execution mode */
7042 ctx->base.is_jmp = DISAS_STOP;
7043 break;
7044 case 3:
7045 gen_helper_mtc0_config3(cpu_env, arg);
7046 rn = "Config3";
7047 /* Stop translation as we may have switched the execution mode */
7048 ctx->base.is_jmp = DISAS_STOP;
7049 break;
7050 case 4:
7051 gen_helper_mtc0_config4(cpu_env, arg);
7052 rn = "Config4";
7053 ctx->base.is_jmp = DISAS_STOP;
7054 break;
7055 case 5:
7056 gen_helper_mtc0_config5(cpu_env, arg);
7057 rn = "Config5";
7058 /* Stop translation as we may have switched the execution mode */
7059 ctx->base.is_jmp = DISAS_STOP;
7060 break;
7061 /* 6,7 are implementation dependent */
7062 case 6:
7063 /* ignored */
7064 rn = "Config6";
7065 break;
7066 case 7:
7067 /* ignored */
7068 rn = "Config7";
7069 break;
7070 default:
7071 rn = "Invalid config selector";
7072 goto cp0_unimplemented;
7074 break;
7075 case 17:
7076 switch (sel) {
7077 case 0:
7078 gen_helper_mtc0_lladdr(cpu_env, arg);
7079 rn = "LLAddr";
7080 break;
7081 case 1:
7082 CP0_CHECK(ctx->mrp);
7083 gen_helper_mtc0_maar(cpu_env, arg);
7084 rn = "MAAR";
7085 break;
7086 case 2:
7087 CP0_CHECK(ctx->mrp);
7088 gen_helper_mtc0_maari(cpu_env, arg);
7089 rn = "MAARI";
7090 break;
7091 default:
7092 goto cp0_unimplemented;
7094 break;
7095 case 18:
7096 switch (sel) {
7097 case 0:
7098 case 1:
7099 case 2:
7100 case 3:
7101 case 4:
7102 case 5:
7103 case 6:
7104 case 7:
7105 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7106 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7107 rn = "WatchLo";
7108 break;
7109 default:
7110 goto cp0_unimplemented;
7112 break;
7113 case 19:
7114 switch (sel) {
7115 case 0:
7116 case 1:
7117 case 2:
7118 case 3:
7119 case 4:
7120 case 5:
7121 case 6:
7122 case 7:
7123 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7124 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7125 rn = "WatchHi";
7126 break;
7127 default:
7128 goto cp0_unimplemented;
7130 break;
7131 case 20:
7132 switch (sel) {
7133 case 0:
7134 #if defined(TARGET_MIPS64)
7135 check_insn(ctx, ISA_MIPS3);
7136 gen_helper_mtc0_xcontext(cpu_env, arg);
7137 rn = "XContext";
7138 break;
7139 #endif
7140 default:
7141 goto cp0_unimplemented;
7143 break;
7144 case 21:
7145 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7146 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7147 switch (sel) {
7148 case 0:
7149 gen_helper_mtc0_framemask(cpu_env, arg);
7150 rn = "Framemask";
7151 break;
7152 default:
7153 goto cp0_unimplemented;
7155 break;
7156 case 22:
7157 /* ignored */
7158 rn = "Diagnostic"; /* implementation dependent */
7159 break;
7160 case 23:
7161 switch (sel) {
7162 case 0:
7163 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7164 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7165 gen_save_pc(ctx->base.pc_next + 4);
7166 ctx->base.is_jmp = DISAS_EXIT;
7167 rn = "Debug";
7168 break;
7169 case 1:
7170 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7171 rn = "TraceControl";
7172 /* Stop translation as we may have switched the execution mode */
7173 ctx->base.is_jmp = DISAS_STOP;
7174 goto cp0_unimplemented;
7175 case 2:
7176 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7177 rn = "TraceControl2";
7178 /* Stop translation as we may have switched the execution mode */
7179 ctx->base.is_jmp = DISAS_STOP;
7180 goto cp0_unimplemented;
7181 case 3:
7182 /* Stop translation as we may have switched the execution mode */
7183 ctx->base.is_jmp = DISAS_STOP;
7184 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7185 rn = "UserTraceData";
7186 /* Stop translation as we may have switched the execution mode */
7187 ctx->base.is_jmp = DISAS_STOP;
7188 goto cp0_unimplemented;
7189 case 4:
7190 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7191 /* Stop translation as we may have switched the execution mode */
7192 ctx->base.is_jmp = DISAS_STOP;
7193 rn = "TraceBPC";
7194 goto cp0_unimplemented;
7195 default:
7196 goto cp0_unimplemented;
7198 break;
7199 case 24:
7200 switch (sel) {
7201 case 0:
7202 /* EJTAG support */
7203 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7204 rn = "DEPC";
7205 break;
7206 default:
7207 goto cp0_unimplemented;
7209 break;
7210 case 25:
7211 switch (sel) {
7212 case 0:
7213 gen_helper_mtc0_performance0(cpu_env, arg);
7214 rn = "Performance0";
7215 break;
7216 case 1:
7217 // gen_helper_mtc0_performance1(arg);
7218 rn = "Performance1";
7219 goto cp0_unimplemented;
7220 case 2:
7221 // gen_helper_mtc0_performance2(arg);
7222 rn = "Performance2";
7223 goto cp0_unimplemented;
7224 case 3:
7225 // gen_helper_mtc0_performance3(arg);
7226 rn = "Performance3";
7227 goto cp0_unimplemented;
7228 case 4:
7229 // gen_helper_mtc0_performance4(arg);
7230 rn = "Performance4";
7231 goto cp0_unimplemented;
7232 case 5:
7233 // gen_helper_mtc0_performance5(arg);
7234 rn = "Performance5";
7235 goto cp0_unimplemented;
7236 case 6:
7237 // gen_helper_mtc0_performance6(arg);
7238 rn = "Performance6";
7239 goto cp0_unimplemented;
7240 case 7:
7241 // gen_helper_mtc0_performance7(arg);
7242 rn = "Performance7";
7243 goto cp0_unimplemented;
7244 default:
7245 goto cp0_unimplemented;
7247 break;
7248 case 26:
7249 switch (sel) {
7250 case 0:
7251 gen_helper_mtc0_errctl(cpu_env, arg);
7252 ctx->base.is_jmp = DISAS_STOP;
7253 rn = "ErrCtl";
7254 break;
7255 default:
7256 goto cp0_unimplemented;
7258 break;
7259 case 27:
7260 switch (sel) {
7261 case 0:
7262 case 1:
7263 case 2:
7264 case 3:
7265 /* ignored */
7266 rn = "CacheErr";
7267 break;
7268 default:
7269 goto cp0_unimplemented;
7271 break;
7272 case 28:
7273 switch (sel) {
7274 case 0:
7275 case 2:
7276 case 4:
7277 case 6:
7278 gen_helper_mtc0_taglo(cpu_env, arg);
7279 rn = "TagLo";
7280 break;
7281 case 1:
7282 case 3:
7283 case 5:
7284 case 7:
7285 gen_helper_mtc0_datalo(cpu_env, arg);
7286 rn = "DataLo";
7287 break;
7288 default:
7289 goto cp0_unimplemented;
7291 break;
7292 case 29:
7293 switch (sel) {
7294 case 0:
7295 case 2:
7296 case 4:
7297 case 6:
7298 gen_helper_mtc0_taghi(cpu_env, arg);
7299 rn = "TagHi";
7300 break;
7301 case 1:
7302 case 3:
7303 case 5:
7304 case 7:
7305 gen_helper_mtc0_datahi(cpu_env, arg);
7306 rn = "DataHi";
7307 break;
7308 default:
7309 rn = "invalid sel";
7310 goto cp0_unimplemented;
7312 break;
7313 case 30:
7314 switch (sel) {
7315 case 0:
7316 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7317 rn = "ErrorEPC";
7318 break;
7319 default:
7320 goto cp0_unimplemented;
7322 break;
7323 case 31:
7324 switch (sel) {
7325 case 0:
7326 /* EJTAG support */
7327 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7328 rn = "DESAVE";
7329 break;
7330 case 2:
7331 case 3:
7332 case 4:
7333 case 5:
7334 case 6:
7335 case 7:
7336 CP0_CHECK(ctx->kscrexist & (1 << sel));
7337 tcg_gen_st_tl(arg, cpu_env,
7338 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7339 rn = "KScratch";
7340 break;
7341 default:
7342 goto cp0_unimplemented;
7344 break;
7345 default:
7346 goto cp0_unimplemented;
7348 trace_mips_translate_c0("mtc0", rn, reg, sel);
7350 /* For simplicity assume that all writes can cause interrupts. */
7351 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7352 gen_io_end();
7353 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7354 * translated code to check for pending interrupts. */
7355 gen_save_pc(ctx->base.pc_next + 4);
7356 ctx->base.is_jmp = DISAS_EXIT;
7358 return;
7360 cp0_unimplemented:
7361 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7364 #if defined(TARGET_MIPS64)
7365 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7367 const char *rn = "invalid";
7369 if (sel != 0)
7370 check_insn(ctx, ISA_MIPS64);
7372 switch (reg) {
7373 case 0:
7374 switch (sel) {
7375 case 0:
7376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7377 rn = "Index";
7378 break;
7379 case 1:
7380 CP0_CHECK(ctx->insn_flags & ASE_MT);
7381 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7382 rn = "MVPControl";
7383 break;
7384 case 2:
7385 CP0_CHECK(ctx->insn_flags & ASE_MT);
7386 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7387 rn = "MVPConf0";
7388 break;
7389 case 3:
7390 CP0_CHECK(ctx->insn_flags & ASE_MT);
7391 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7392 rn = "MVPConf1";
7393 break;
7394 case 4:
7395 CP0_CHECK(ctx->vp);
7396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7397 rn = "VPControl";
7398 break;
7399 default:
7400 goto cp0_unimplemented;
7402 break;
7403 case 1:
7404 switch (sel) {
7405 case 0:
7406 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7407 gen_helper_mfc0_random(arg, cpu_env);
7408 rn = "Random";
7409 break;
7410 case 1:
7411 CP0_CHECK(ctx->insn_flags & ASE_MT);
7412 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7413 rn = "VPEControl";
7414 break;
7415 case 2:
7416 CP0_CHECK(ctx->insn_flags & ASE_MT);
7417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7418 rn = "VPEConf0";
7419 break;
7420 case 3:
7421 CP0_CHECK(ctx->insn_flags & ASE_MT);
7422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7423 rn = "VPEConf1";
7424 break;
7425 case 4:
7426 CP0_CHECK(ctx->insn_flags & ASE_MT);
7427 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
7428 rn = "YQMask";
7429 break;
7430 case 5:
7431 CP0_CHECK(ctx->insn_flags & ASE_MT);
7432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7433 rn = "VPESchedule";
7434 break;
7435 case 6:
7436 CP0_CHECK(ctx->insn_flags & ASE_MT);
7437 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7438 rn = "VPEScheFBack";
7439 break;
7440 case 7:
7441 CP0_CHECK(ctx->insn_flags & ASE_MT);
7442 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7443 rn = "VPEOpt";
7444 break;
7445 default:
7446 goto cp0_unimplemented;
7448 break;
7449 case 2:
7450 switch (sel) {
7451 case 0:
7452 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
7453 rn = "EntryLo0";
7454 break;
7455 case 1:
7456 CP0_CHECK(ctx->insn_flags & ASE_MT);
7457 gen_helper_mfc0_tcstatus(arg, cpu_env);
7458 rn = "TCStatus";
7459 break;
7460 case 2:
7461 CP0_CHECK(ctx->insn_flags & ASE_MT);
7462 gen_helper_mfc0_tcbind(arg, cpu_env);
7463 rn = "TCBind";
7464 break;
7465 case 3:
7466 CP0_CHECK(ctx->insn_flags & ASE_MT);
7467 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7468 rn = "TCRestart";
7469 break;
7470 case 4:
7471 CP0_CHECK(ctx->insn_flags & ASE_MT);
7472 gen_helper_dmfc0_tchalt(arg, cpu_env);
7473 rn = "TCHalt";
7474 break;
7475 case 5:
7476 CP0_CHECK(ctx->insn_flags & ASE_MT);
7477 gen_helper_dmfc0_tccontext(arg, cpu_env);
7478 rn = "TCContext";
7479 break;
7480 case 6:
7481 CP0_CHECK(ctx->insn_flags & ASE_MT);
7482 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7483 rn = "TCSchedule";
7484 break;
7485 case 7:
7486 CP0_CHECK(ctx->insn_flags & ASE_MT);
7487 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7488 rn = "TCScheFBack";
7489 break;
7490 default:
7491 goto cp0_unimplemented;
7493 break;
7494 case 3:
7495 switch (sel) {
7496 case 0:
7497 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7498 rn = "EntryLo1";
7499 break;
7500 case 1:
7501 CP0_CHECK(ctx->vp);
7502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7503 rn = "GlobalNumber";
7504 break;
7505 default:
7506 goto cp0_unimplemented;
7508 break;
7509 case 4:
7510 switch (sel) {
7511 case 0:
7512 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7513 rn = "Context";
7514 break;
7515 case 1:
7516 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
7517 rn = "ContextConfig";
7518 goto cp0_unimplemented;
7519 case 2:
7520 CP0_CHECK(ctx->ulri);
7521 tcg_gen_ld_tl(arg, cpu_env,
7522 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7523 rn = "UserLocal";
7524 break;
7525 default:
7526 goto cp0_unimplemented;
7528 break;
7529 case 5:
7530 switch (sel) {
7531 case 0:
7532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7533 rn = "PageMask";
7534 break;
7535 case 1:
7536 check_insn(ctx, ISA_MIPS32R2);
7537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7538 rn = "PageGrain";
7539 break;
7540 case 2:
7541 CP0_CHECK(ctx->sc);
7542 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7543 rn = "SegCtl0";
7544 break;
7545 case 3:
7546 CP0_CHECK(ctx->sc);
7547 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7548 rn = "SegCtl1";
7549 break;
7550 case 4:
7551 CP0_CHECK(ctx->sc);
7552 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7553 rn = "SegCtl2";
7554 break;
7555 case 5:
7556 check_pw(ctx);
7557 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7558 rn = "PWBase";
7559 break;
7560 case 6:
7561 check_pw(ctx);
7562 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7563 rn = "PWField";
7564 break;
7565 case 7:
7566 check_pw(ctx);
7567 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7568 rn = "PWSize";
7569 break;
7570 default:
7571 goto cp0_unimplemented;
7573 break;
7574 case 6:
7575 switch (sel) {
7576 case 0:
7577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7578 rn = "Wired";
7579 break;
7580 case 1:
7581 check_insn(ctx, ISA_MIPS32R2);
7582 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7583 rn = "SRSConf0";
7584 break;
7585 case 2:
7586 check_insn(ctx, ISA_MIPS32R2);
7587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7588 rn = "SRSConf1";
7589 break;
7590 case 3:
7591 check_insn(ctx, ISA_MIPS32R2);
7592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7593 rn = "SRSConf2";
7594 break;
7595 case 4:
7596 check_insn(ctx, ISA_MIPS32R2);
7597 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7598 rn = "SRSConf3";
7599 break;
7600 case 5:
7601 check_insn(ctx, ISA_MIPS32R2);
7602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7603 rn = "SRSConf4";
7604 break;
7605 case 6:
7606 check_pw(ctx);
7607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7608 rn = "PWCtl";
7609 break;
7610 default:
7611 goto cp0_unimplemented;
7613 break;
7614 case 7:
7615 switch (sel) {
7616 case 0:
7617 check_insn(ctx, ISA_MIPS32R2);
7618 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7619 rn = "HWREna";
7620 break;
7621 default:
7622 goto cp0_unimplemented;
7624 break;
7625 case 8:
7626 switch (sel) {
7627 case 0:
7628 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7629 rn = "BadVAddr";
7630 break;
7631 case 1:
7632 CP0_CHECK(ctx->bi);
7633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7634 rn = "BadInstr";
7635 break;
7636 case 2:
7637 CP0_CHECK(ctx->bp);
7638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7639 rn = "BadInstrP";
7640 break;
7641 case 3:
7642 CP0_CHECK(ctx->bi);
7643 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7644 tcg_gen_andi_tl(arg, arg, ~0xffff);
7645 rn = "BadInstrX";
7646 break;
7647 default:
7648 goto cp0_unimplemented;
7650 break;
7651 case 9:
7652 switch (sel) {
7653 case 0:
7654 /* Mark as an IO operation because we read the time. */
7655 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7656 gen_io_start();
7658 gen_helper_mfc0_count(arg, cpu_env);
7659 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7660 gen_io_end();
7662 /* Break the TB to be able to take timer interrupts immediately
7663 after reading count. DISAS_STOP isn't sufficient, we need to
7664 ensure we break completely out of translated code. */
7665 gen_save_pc(ctx->base.pc_next + 4);
7666 ctx->base.is_jmp = DISAS_EXIT;
7667 rn = "Count";
7668 break;
7669 /* 6,7 are implementation dependent */
7670 default:
7671 goto cp0_unimplemented;
7673 break;
7674 case 10:
7675 switch (sel) {
7676 case 0:
7677 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7678 rn = "EntryHi";
7679 break;
7680 default:
7681 goto cp0_unimplemented;
7683 break;
7684 case 11:
7685 switch (sel) {
7686 case 0:
7687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7688 rn = "Compare";
7689 break;
7690 /* 6,7 are implementation dependent */
7691 default:
7692 goto cp0_unimplemented;
7694 break;
7695 case 12:
7696 switch (sel) {
7697 case 0:
7698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7699 rn = "Status";
7700 break;
7701 case 1:
7702 check_insn(ctx, ISA_MIPS32R2);
7703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7704 rn = "IntCtl";
7705 break;
7706 case 2:
7707 check_insn(ctx, ISA_MIPS32R2);
7708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7709 rn = "SRSCtl";
7710 break;
7711 case 3:
7712 check_insn(ctx, ISA_MIPS32R2);
7713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7714 rn = "SRSMap";
7715 break;
7716 default:
7717 goto cp0_unimplemented;
7719 break;
7720 case 13:
7721 switch (sel) {
7722 case 0:
7723 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7724 rn = "Cause";
7725 break;
7726 default:
7727 goto cp0_unimplemented;
7729 break;
7730 case 14:
7731 switch (sel) {
7732 case 0:
7733 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7734 rn = "EPC";
7735 break;
7736 default:
7737 goto cp0_unimplemented;
7739 break;
7740 case 15:
7741 switch (sel) {
7742 case 0:
7743 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7744 rn = "PRid";
7745 break;
7746 case 1:
7747 check_insn(ctx, ISA_MIPS32R2);
7748 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7749 rn = "EBase";
7750 break;
7751 case 3:
7752 check_insn(ctx, ISA_MIPS32R2);
7753 CP0_CHECK(ctx->cmgcr);
7754 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7755 rn = "CMGCRBase";
7756 break;
7757 default:
7758 goto cp0_unimplemented;
7760 break;
7761 case 16:
7762 switch (sel) {
7763 case 0:
7764 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7765 rn = "Config";
7766 break;
7767 case 1:
7768 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7769 rn = "Config1";
7770 break;
7771 case 2:
7772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7773 rn = "Config2";
7774 break;
7775 case 3:
7776 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7777 rn = "Config3";
7778 break;
7779 case 4:
7780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7781 rn = "Config4";
7782 break;
7783 case 5:
7784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7785 rn = "Config5";
7786 break;
7787 /* 6,7 are implementation dependent */
7788 case 6:
7789 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7790 rn = "Config6";
7791 break;
7792 case 7:
7793 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7794 rn = "Config7";
7795 break;
7796 default:
7797 goto cp0_unimplemented;
7799 break;
7800 case 17:
7801 switch (sel) {
7802 case 0:
7803 gen_helper_dmfc0_lladdr(arg, cpu_env);
7804 rn = "LLAddr";
7805 break;
7806 case 1:
7807 CP0_CHECK(ctx->mrp);
7808 gen_helper_dmfc0_maar(arg, cpu_env);
7809 rn = "MAAR";
7810 break;
7811 case 2:
7812 CP0_CHECK(ctx->mrp);
7813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7814 rn = "MAARI";
7815 break;
7816 default:
7817 goto cp0_unimplemented;
7819 break;
7820 case 18:
7821 switch (sel) {
7822 case 0:
7823 case 1:
7824 case 2:
7825 case 3:
7826 case 4:
7827 case 5:
7828 case 6:
7829 case 7:
7830 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7831 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7832 rn = "WatchLo";
7833 break;
7834 default:
7835 goto cp0_unimplemented;
7837 break;
7838 case 19:
7839 switch (sel) {
7840 case 0:
7841 case 1:
7842 case 2:
7843 case 3:
7844 case 4:
7845 case 5:
7846 case 6:
7847 case 7:
7848 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7849 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7850 rn = "WatchHi";
7851 break;
7852 default:
7853 goto cp0_unimplemented;
7855 break;
7856 case 20:
7857 switch (sel) {
7858 case 0:
7859 check_insn(ctx, ISA_MIPS3);
7860 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7861 rn = "XContext";
7862 break;
7863 default:
7864 goto cp0_unimplemented;
7866 break;
7867 case 21:
7868 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7869 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7870 switch (sel) {
7871 case 0:
7872 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7873 rn = "Framemask";
7874 break;
7875 default:
7876 goto cp0_unimplemented;
7878 break;
7879 case 22:
7880 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7881 rn = "'Diagnostic"; /* implementation dependent */
7882 break;
7883 case 23:
7884 switch (sel) {
7885 case 0:
7886 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7887 rn = "Debug";
7888 break;
7889 case 1:
7890 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
7891 rn = "TraceControl";
7892 goto cp0_unimplemented;
7893 case 2:
7894 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
7895 rn = "TraceControl2";
7896 goto cp0_unimplemented;
7897 case 3:
7898 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
7899 rn = "UserTraceData";
7900 goto cp0_unimplemented;
7901 case 4:
7902 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
7903 rn = "TraceBPC";
7904 goto cp0_unimplemented;
7905 default:
7906 goto cp0_unimplemented;
7908 break;
7909 case 24:
7910 switch (sel) {
7911 case 0:
7912 /* EJTAG support */
7913 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7914 rn = "DEPC";
7915 break;
7916 default:
7917 goto cp0_unimplemented;
7919 break;
7920 case 25:
7921 switch (sel) {
7922 case 0:
7923 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7924 rn = "Performance0";
7925 break;
7926 case 1:
7927 // gen_helper_dmfc0_performance1(arg);
7928 rn = "Performance1";
7929 goto cp0_unimplemented;
7930 case 2:
7931 // gen_helper_dmfc0_performance2(arg);
7932 rn = "Performance2";
7933 goto cp0_unimplemented;
7934 case 3:
7935 // gen_helper_dmfc0_performance3(arg);
7936 rn = "Performance3";
7937 goto cp0_unimplemented;
7938 case 4:
7939 // gen_helper_dmfc0_performance4(arg);
7940 rn = "Performance4";
7941 goto cp0_unimplemented;
7942 case 5:
7943 // gen_helper_dmfc0_performance5(arg);
7944 rn = "Performance5";
7945 goto cp0_unimplemented;
7946 case 6:
7947 // gen_helper_dmfc0_performance6(arg);
7948 rn = "Performance6";
7949 goto cp0_unimplemented;
7950 case 7:
7951 // gen_helper_dmfc0_performance7(arg);
7952 rn = "Performance7";
7953 goto cp0_unimplemented;
7954 default:
7955 goto cp0_unimplemented;
7957 break;
7958 case 26:
7959 switch (sel) {
7960 case 0:
7961 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7962 rn = "ErrCtl";
7963 break;
7964 default:
7965 goto cp0_unimplemented;
7967 break;
7968 case 27:
7969 switch (sel) {
7970 /* ignored */
7971 case 0:
7972 case 1:
7973 case 2:
7974 case 3:
7975 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7976 rn = "CacheErr";
7977 break;
7978 default:
7979 goto cp0_unimplemented;
7981 break;
7982 case 28:
7983 switch (sel) {
7984 case 0:
7985 case 2:
7986 case 4:
7987 case 6:
7988 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7989 rn = "TagLo";
7990 break;
7991 case 1:
7992 case 3:
7993 case 5:
7994 case 7:
7995 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7996 rn = "DataLo";
7997 break;
7998 default:
7999 goto cp0_unimplemented;
8001 break;
8002 case 29:
8003 switch (sel) {
8004 case 0:
8005 case 2:
8006 case 4:
8007 case 6:
8008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8009 rn = "TagHi";
8010 break;
8011 case 1:
8012 case 3:
8013 case 5:
8014 case 7:
8015 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8016 rn = "DataHi";
8017 break;
8018 default:
8019 goto cp0_unimplemented;
8021 break;
8022 case 30:
8023 switch (sel) {
8024 case 0:
8025 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8026 rn = "ErrorEPC";
8027 break;
8028 default:
8029 goto cp0_unimplemented;
8031 break;
8032 case 31:
8033 switch (sel) {
8034 case 0:
8035 /* EJTAG support */
8036 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8037 rn = "DESAVE";
8038 break;
8039 case 2:
8040 case 3:
8041 case 4:
8042 case 5:
8043 case 6:
8044 case 7:
8045 CP0_CHECK(ctx->kscrexist & (1 << sel));
8046 tcg_gen_ld_tl(arg, cpu_env,
8047 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8048 rn = "KScratch";
8049 break;
8050 default:
8051 goto cp0_unimplemented;
8053 break;
8054 default:
8055 goto cp0_unimplemented;
8057 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8058 return;
8060 cp0_unimplemented:
8061 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8062 gen_mfc0_unimplemented(ctx, arg);
8065 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8067 const char *rn = "invalid";
8069 if (sel != 0)
8070 check_insn(ctx, ISA_MIPS64);
8072 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8073 gen_io_start();
8076 switch (reg) {
8077 case 0:
8078 switch (sel) {
8079 case 0:
8080 gen_helper_mtc0_index(cpu_env, arg);
8081 rn = "Index";
8082 break;
8083 case 1:
8084 CP0_CHECK(ctx->insn_flags & ASE_MT);
8085 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8086 rn = "MVPControl";
8087 break;
8088 case 2:
8089 CP0_CHECK(ctx->insn_flags & ASE_MT);
8090 /* ignored */
8091 rn = "MVPConf0";
8092 break;
8093 case 3:
8094 CP0_CHECK(ctx->insn_flags & ASE_MT);
8095 /* ignored */
8096 rn = "MVPConf1";
8097 break;
8098 case 4:
8099 CP0_CHECK(ctx->vp);
8100 /* ignored */
8101 rn = "VPControl";
8102 break;
8103 default:
8104 goto cp0_unimplemented;
8106 break;
8107 case 1:
8108 switch (sel) {
8109 case 0:
8110 /* ignored */
8111 rn = "Random";
8112 break;
8113 case 1:
8114 CP0_CHECK(ctx->insn_flags & ASE_MT);
8115 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8116 rn = "VPEControl";
8117 break;
8118 case 2:
8119 CP0_CHECK(ctx->insn_flags & ASE_MT);
8120 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8121 rn = "VPEConf0";
8122 break;
8123 case 3:
8124 CP0_CHECK(ctx->insn_flags & ASE_MT);
8125 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8126 rn = "VPEConf1";
8127 break;
8128 case 4:
8129 CP0_CHECK(ctx->insn_flags & ASE_MT);
8130 gen_helper_mtc0_yqmask(cpu_env, arg);
8131 rn = "YQMask";
8132 break;
8133 case 5:
8134 CP0_CHECK(ctx->insn_flags & ASE_MT);
8135 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8136 rn = "VPESchedule";
8137 break;
8138 case 6:
8139 CP0_CHECK(ctx->insn_flags & ASE_MT);
8140 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8141 rn = "VPEScheFBack";
8142 break;
8143 case 7:
8144 CP0_CHECK(ctx->insn_flags & ASE_MT);
8145 gen_helper_mtc0_vpeopt(cpu_env, arg);
8146 rn = "VPEOpt";
8147 break;
8148 default:
8149 goto cp0_unimplemented;
8151 break;
8152 case 2:
8153 switch (sel) {
8154 case 0:
8155 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8156 rn = "EntryLo0";
8157 break;
8158 case 1:
8159 CP0_CHECK(ctx->insn_flags & ASE_MT);
8160 gen_helper_mtc0_tcstatus(cpu_env, arg);
8161 rn = "TCStatus";
8162 break;
8163 case 2:
8164 CP0_CHECK(ctx->insn_flags & ASE_MT);
8165 gen_helper_mtc0_tcbind(cpu_env, arg);
8166 rn = "TCBind";
8167 break;
8168 case 3:
8169 CP0_CHECK(ctx->insn_flags & ASE_MT);
8170 gen_helper_mtc0_tcrestart(cpu_env, arg);
8171 rn = "TCRestart";
8172 break;
8173 case 4:
8174 CP0_CHECK(ctx->insn_flags & ASE_MT);
8175 gen_helper_mtc0_tchalt(cpu_env, arg);
8176 rn = "TCHalt";
8177 break;
8178 case 5:
8179 CP0_CHECK(ctx->insn_flags & ASE_MT);
8180 gen_helper_mtc0_tccontext(cpu_env, arg);
8181 rn = "TCContext";
8182 break;
8183 case 6:
8184 CP0_CHECK(ctx->insn_flags & ASE_MT);
8185 gen_helper_mtc0_tcschedule(cpu_env, arg);
8186 rn = "TCSchedule";
8187 break;
8188 case 7:
8189 CP0_CHECK(ctx->insn_flags & ASE_MT);
8190 gen_helper_mtc0_tcschefback(cpu_env, arg);
8191 rn = "TCScheFBack";
8192 break;
8193 default:
8194 goto cp0_unimplemented;
8196 break;
8197 case 3:
8198 switch (sel) {
8199 case 0:
8200 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8201 rn = "EntryLo1";
8202 break;
8203 case 1:
8204 CP0_CHECK(ctx->vp);
8205 /* ignored */
8206 rn = "GlobalNumber";
8207 break;
8208 default:
8209 goto cp0_unimplemented;
8211 break;
8212 case 4:
8213 switch (sel) {
8214 case 0:
8215 gen_helper_mtc0_context(cpu_env, arg);
8216 rn = "Context";
8217 break;
8218 case 1:
8219 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8220 rn = "ContextConfig";
8221 goto cp0_unimplemented;
8222 case 2:
8223 CP0_CHECK(ctx->ulri);
8224 tcg_gen_st_tl(arg, cpu_env,
8225 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8226 rn = "UserLocal";
8227 break;
8228 default:
8229 goto cp0_unimplemented;
8231 break;
8232 case 5:
8233 switch (sel) {
8234 case 0:
8235 gen_helper_mtc0_pagemask(cpu_env, arg);
8236 rn = "PageMask";
8237 break;
8238 case 1:
8239 check_insn(ctx, ISA_MIPS32R2);
8240 gen_helper_mtc0_pagegrain(cpu_env, arg);
8241 rn = "PageGrain";
8242 break;
8243 case 2:
8244 CP0_CHECK(ctx->sc);
8245 gen_helper_mtc0_segctl0(cpu_env, arg);
8246 rn = "SegCtl0";
8247 break;
8248 case 3:
8249 CP0_CHECK(ctx->sc);
8250 gen_helper_mtc0_segctl1(cpu_env, arg);
8251 rn = "SegCtl1";
8252 break;
8253 case 4:
8254 CP0_CHECK(ctx->sc);
8255 gen_helper_mtc0_segctl2(cpu_env, arg);
8256 rn = "SegCtl2";
8257 break;
8258 case 5:
8259 check_pw(ctx);
8260 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8261 rn = "PWBase";
8262 break;
8263 case 6:
8264 check_pw(ctx);
8265 gen_helper_mtc0_pwfield(cpu_env, arg);
8266 rn = "PWField";
8267 break;
8268 case 7:
8269 check_pw(ctx);
8270 gen_helper_mtc0_pwsize(cpu_env, arg);
8271 rn = "PWSize";
8272 break;
8273 default:
8274 goto cp0_unimplemented;
8276 break;
8277 case 6:
8278 switch (sel) {
8279 case 0:
8280 gen_helper_mtc0_wired(cpu_env, arg);
8281 rn = "Wired";
8282 break;
8283 case 1:
8284 check_insn(ctx, ISA_MIPS32R2);
8285 gen_helper_mtc0_srsconf0(cpu_env, arg);
8286 rn = "SRSConf0";
8287 break;
8288 case 2:
8289 check_insn(ctx, ISA_MIPS32R2);
8290 gen_helper_mtc0_srsconf1(cpu_env, arg);
8291 rn = "SRSConf1";
8292 break;
8293 case 3:
8294 check_insn(ctx, ISA_MIPS32R2);
8295 gen_helper_mtc0_srsconf2(cpu_env, arg);
8296 rn = "SRSConf2";
8297 break;
8298 case 4:
8299 check_insn(ctx, ISA_MIPS32R2);
8300 gen_helper_mtc0_srsconf3(cpu_env, arg);
8301 rn = "SRSConf3";
8302 break;
8303 case 5:
8304 check_insn(ctx, ISA_MIPS32R2);
8305 gen_helper_mtc0_srsconf4(cpu_env, arg);
8306 rn = "SRSConf4";
8307 break;
8308 case 6:
8309 check_pw(ctx);
8310 gen_helper_mtc0_pwctl(cpu_env, arg);
8311 rn = "PWCtl";
8312 break;
8313 default:
8314 goto cp0_unimplemented;
8316 break;
8317 case 7:
8318 switch (sel) {
8319 case 0:
8320 check_insn(ctx, ISA_MIPS32R2);
8321 gen_helper_mtc0_hwrena(cpu_env, arg);
8322 ctx->base.is_jmp = DISAS_STOP;
8323 rn = "HWREna";
8324 break;
8325 default:
8326 goto cp0_unimplemented;
8328 break;
8329 case 8:
8330 switch (sel) {
8331 case 0:
8332 /* ignored */
8333 rn = "BadVAddr";
8334 break;
8335 case 1:
8336 /* ignored */
8337 rn = "BadInstr";
8338 break;
8339 case 2:
8340 /* ignored */
8341 rn = "BadInstrP";
8342 break;
8343 case 3:
8344 /* ignored */
8345 rn = "BadInstrX";
8346 break;
8347 default:
8348 goto cp0_unimplemented;
8350 break;
8351 case 9:
8352 switch (sel) {
8353 case 0:
8354 gen_helper_mtc0_count(cpu_env, arg);
8355 rn = "Count";
8356 break;
8357 /* 6,7 are implementation dependent */
8358 default:
8359 goto cp0_unimplemented;
8361 /* Stop translation as we may have switched the execution mode */
8362 ctx->base.is_jmp = DISAS_STOP;
8363 break;
8364 case 10:
8365 switch (sel) {
8366 case 0:
8367 gen_helper_mtc0_entryhi(cpu_env, arg);
8368 rn = "EntryHi";
8369 break;
8370 default:
8371 goto cp0_unimplemented;
8373 break;
8374 case 11:
8375 switch (sel) {
8376 case 0:
8377 gen_helper_mtc0_compare(cpu_env, arg);
8378 rn = "Compare";
8379 break;
8380 /* 6,7 are implementation dependent */
8381 default:
8382 goto cp0_unimplemented;
8384 /* Stop translation as we may have switched the execution mode */
8385 ctx->base.is_jmp = DISAS_STOP;
8386 break;
8387 case 12:
8388 switch (sel) {
8389 case 0:
8390 save_cpu_state(ctx, 1);
8391 gen_helper_mtc0_status(cpu_env, arg);
8392 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8393 gen_save_pc(ctx->base.pc_next + 4);
8394 ctx->base.is_jmp = DISAS_EXIT;
8395 rn = "Status";
8396 break;
8397 case 1:
8398 check_insn(ctx, ISA_MIPS32R2);
8399 gen_helper_mtc0_intctl(cpu_env, arg);
8400 /* Stop translation as we may have switched the execution mode */
8401 ctx->base.is_jmp = DISAS_STOP;
8402 rn = "IntCtl";
8403 break;
8404 case 2:
8405 check_insn(ctx, ISA_MIPS32R2);
8406 gen_helper_mtc0_srsctl(cpu_env, arg);
8407 /* Stop translation as we may have switched the execution mode */
8408 ctx->base.is_jmp = DISAS_STOP;
8409 rn = "SRSCtl";
8410 break;
8411 case 3:
8412 check_insn(ctx, ISA_MIPS32R2);
8413 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8414 /* Stop translation as we may have switched the execution mode */
8415 ctx->base.is_jmp = DISAS_STOP;
8416 rn = "SRSMap";
8417 break;
8418 default:
8419 goto cp0_unimplemented;
8421 break;
8422 case 13:
8423 switch (sel) {
8424 case 0:
8425 save_cpu_state(ctx, 1);
8426 gen_helper_mtc0_cause(cpu_env, arg);
8427 /* Stop translation as we may have triggered an interrupt.
8428 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8429 * translated code to check for pending interrupts. */
8430 gen_save_pc(ctx->base.pc_next + 4);
8431 ctx->base.is_jmp = DISAS_EXIT;
8432 rn = "Cause";
8433 break;
8434 default:
8435 goto cp0_unimplemented;
8437 break;
8438 case 14:
8439 switch (sel) {
8440 case 0:
8441 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8442 rn = "EPC";
8443 break;
8444 default:
8445 goto cp0_unimplemented;
8447 break;
8448 case 15:
8449 switch (sel) {
8450 case 0:
8451 /* ignored */
8452 rn = "PRid";
8453 break;
8454 case 1:
8455 check_insn(ctx, ISA_MIPS32R2);
8456 gen_helper_mtc0_ebase(cpu_env, arg);
8457 rn = "EBase";
8458 break;
8459 default:
8460 goto cp0_unimplemented;
8462 break;
8463 case 16:
8464 switch (sel) {
8465 case 0:
8466 gen_helper_mtc0_config0(cpu_env, arg);
8467 rn = "Config";
8468 /* Stop translation as we may have switched the execution mode */
8469 ctx->base.is_jmp = DISAS_STOP;
8470 break;
8471 case 1:
8472 /* ignored, read only */
8473 rn = "Config1";
8474 break;
8475 case 2:
8476 gen_helper_mtc0_config2(cpu_env, arg);
8477 rn = "Config2";
8478 /* Stop translation as we may have switched the execution mode */
8479 ctx->base.is_jmp = DISAS_STOP;
8480 break;
8481 case 3:
8482 gen_helper_mtc0_config3(cpu_env, arg);
8483 rn = "Config3";
8484 /* Stop translation as we may have switched the execution mode */
8485 ctx->base.is_jmp = DISAS_STOP;
8486 break;
8487 case 4:
8488 /* currently ignored */
8489 rn = "Config4";
8490 break;
8491 case 5:
8492 gen_helper_mtc0_config5(cpu_env, arg);
8493 rn = "Config5";
8494 /* Stop translation as we may have switched the execution mode */
8495 ctx->base.is_jmp = DISAS_STOP;
8496 break;
8497 /* 6,7 are implementation dependent */
8498 default:
8499 rn = "Invalid config selector";
8500 goto cp0_unimplemented;
8502 break;
8503 case 17:
8504 switch (sel) {
8505 case 0:
8506 gen_helper_mtc0_lladdr(cpu_env, arg);
8507 rn = "LLAddr";
8508 break;
8509 case 1:
8510 CP0_CHECK(ctx->mrp);
8511 gen_helper_mtc0_maar(cpu_env, arg);
8512 rn = "MAAR";
8513 break;
8514 case 2:
8515 CP0_CHECK(ctx->mrp);
8516 gen_helper_mtc0_maari(cpu_env, arg);
8517 rn = "MAARI";
8518 break;
8519 default:
8520 goto cp0_unimplemented;
8522 break;
8523 case 18:
8524 switch (sel) {
8525 case 0:
8526 case 1:
8527 case 2:
8528 case 3:
8529 case 4:
8530 case 5:
8531 case 6:
8532 case 7:
8533 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8534 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8535 rn = "WatchLo";
8536 break;
8537 default:
8538 goto cp0_unimplemented;
8540 break;
8541 case 19:
8542 switch (sel) {
8543 case 0:
8544 case 1:
8545 case 2:
8546 case 3:
8547 case 4:
8548 case 5:
8549 case 6:
8550 case 7:
8551 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8552 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8553 rn = "WatchHi";
8554 break;
8555 default:
8556 goto cp0_unimplemented;
8558 break;
8559 case 20:
8560 switch (sel) {
8561 case 0:
8562 check_insn(ctx, ISA_MIPS3);
8563 gen_helper_mtc0_xcontext(cpu_env, arg);
8564 rn = "XContext";
8565 break;
8566 default:
8567 goto cp0_unimplemented;
8569 break;
8570 case 21:
8571 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8572 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8573 switch (sel) {
8574 case 0:
8575 gen_helper_mtc0_framemask(cpu_env, arg);
8576 rn = "Framemask";
8577 break;
8578 default:
8579 goto cp0_unimplemented;
8581 break;
8582 case 22:
8583 /* ignored */
8584 rn = "Diagnostic"; /* implementation dependent */
8585 break;
8586 case 23:
8587 switch (sel) {
8588 case 0:
8589 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8590 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8591 gen_save_pc(ctx->base.pc_next + 4);
8592 ctx->base.is_jmp = DISAS_EXIT;
8593 rn = "Debug";
8594 break;
8595 case 1:
8596 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8597 /* Stop translation as we may have switched the execution mode */
8598 ctx->base.is_jmp = DISAS_STOP;
8599 rn = "TraceControl";
8600 goto cp0_unimplemented;
8601 case 2:
8602 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8603 /* Stop translation as we may have switched the execution mode */
8604 ctx->base.is_jmp = DISAS_STOP;
8605 rn = "TraceControl2";
8606 goto cp0_unimplemented;
8607 case 3:
8608 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8609 /* Stop translation as we may have switched the execution mode */
8610 ctx->base.is_jmp = DISAS_STOP;
8611 rn = "UserTraceData";
8612 goto cp0_unimplemented;
8613 case 4:
8614 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8615 /* Stop translation as we may have switched the execution mode */
8616 ctx->base.is_jmp = DISAS_STOP;
8617 rn = "TraceBPC";
8618 goto cp0_unimplemented;
8619 default:
8620 goto cp0_unimplemented;
8622 break;
8623 case 24:
8624 switch (sel) {
8625 case 0:
8626 /* EJTAG support */
8627 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8628 rn = "DEPC";
8629 break;
8630 default:
8631 goto cp0_unimplemented;
8633 break;
8634 case 25:
8635 switch (sel) {
8636 case 0:
8637 gen_helper_mtc0_performance0(cpu_env, arg);
8638 rn = "Performance0";
8639 break;
8640 case 1:
8641 // gen_helper_mtc0_performance1(cpu_env, arg);
8642 rn = "Performance1";
8643 goto cp0_unimplemented;
8644 case 2:
8645 // gen_helper_mtc0_performance2(cpu_env, arg);
8646 rn = "Performance2";
8647 goto cp0_unimplemented;
8648 case 3:
8649 // gen_helper_mtc0_performance3(cpu_env, arg);
8650 rn = "Performance3";
8651 goto cp0_unimplemented;
8652 case 4:
8653 // gen_helper_mtc0_performance4(cpu_env, arg);
8654 rn = "Performance4";
8655 goto cp0_unimplemented;
8656 case 5:
8657 // gen_helper_mtc0_performance5(cpu_env, arg);
8658 rn = "Performance5";
8659 goto cp0_unimplemented;
8660 case 6:
8661 // gen_helper_mtc0_performance6(cpu_env, arg);
8662 rn = "Performance6";
8663 goto cp0_unimplemented;
8664 case 7:
8665 // gen_helper_mtc0_performance7(cpu_env, arg);
8666 rn = "Performance7";
8667 goto cp0_unimplemented;
8668 default:
8669 goto cp0_unimplemented;
8671 break;
8672 case 26:
8673 switch (sel) {
8674 case 0:
8675 gen_helper_mtc0_errctl(cpu_env, arg);
8676 ctx->base.is_jmp = DISAS_STOP;
8677 rn = "ErrCtl";
8678 break;
8679 default:
8680 goto cp0_unimplemented;
8682 break;
8683 case 27:
8684 switch (sel) {
8685 case 0:
8686 case 1:
8687 case 2:
8688 case 3:
8689 /* ignored */
8690 rn = "CacheErr";
8691 break;
8692 default:
8693 goto cp0_unimplemented;
8695 break;
8696 case 28:
8697 switch (sel) {
8698 case 0:
8699 case 2:
8700 case 4:
8701 case 6:
8702 gen_helper_mtc0_taglo(cpu_env, arg);
8703 rn = "TagLo";
8704 break;
8705 case 1:
8706 case 3:
8707 case 5:
8708 case 7:
8709 gen_helper_mtc0_datalo(cpu_env, arg);
8710 rn = "DataLo";
8711 break;
8712 default:
8713 goto cp0_unimplemented;
8715 break;
8716 case 29:
8717 switch (sel) {
8718 case 0:
8719 case 2:
8720 case 4:
8721 case 6:
8722 gen_helper_mtc0_taghi(cpu_env, arg);
8723 rn = "TagHi";
8724 break;
8725 case 1:
8726 case 3:
8727 case 5:
8728 case 7:
8729 gen_helper_mtc0_datahi(cpu_env, arg);
8730 rn = "DataHi";
8731 break;
8732 default:
8733 rn = "invalid sel";
8734 goto cp0_unimplemented;
8736 break;
8737 case 30:
8738 switch (sel) {
8739 case 0:
8740 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8741 rn = "ErrorEPC";
8742 break;
8743 default:
8744 goto cp0_unimplemented;
8746 break;
8747 case 31:
8748 switch (sel) {
8749 case 0:
8750 /* EJTAG support */
8751 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8752 rn = "DESAVE";
8753 break;
8754 case 2:
8755 case 3:
8756 case 4:
8757 case 5:
8758 case 6:
8759 case 7:
8760 CP0_CHECK(ctx->kscrexist & (1 << sel));
8761 tcg_gen_st_tl(arg, cpu_env,
8762 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8763 rn = "KScratch";
8764 break;
8765 default:
8766 goto cp0_unimplemented;
8768 break;
8769 default:
8770 goto cp0_unimplemented;
8772 trace_mips_translate_c0("dmtc0", rn, reg, sel);
8774 /* For simplicity assume that all writes can cause interrupts. */
8775 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8776 gen_io_end();
8777 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8778 * translated code to check for pending interrupts. */
8779 gen_save_pc(ctx->base.pc_next + 4);
8780 ctx->base.is_jmp = DISAS_EXIT;
8782 return;
8784 cp0_unimplemented:
8785 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8787 #endif /* TARGET_MIPS64 */
8789 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8790 int u, int sel, int h)
8792 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8793 TCGv t0 = tcg_temp_local_new();
8795 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8796 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8797 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
8798 tcg_gen_movi_tl(t0, -1);
8799 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8800 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
8801 tcg_gen_movi_tl(t0, -1);
8802 else if (u == 0) {
8803 switch (rt) {
8804 case 1:
8805 switch (sel) {
8806 case 1:
8807 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8808 break;
8809 case 2:
8810 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8811 break;
8812 default:
8813 goto die;
8814 break;
8816 break;
8817 case 2:
8818 switch (sel) {
8819 case 1:
8820 gen_helper_mftc0_tcstatus(t0, cpu_env);
8821 break;
8822 case 2:
8823 gen_helper_mftc0_tcbind(t0, cpu_env);
8824 break;
8825 case 3:
8826 gen_helper_mftc0_tcrestart(t0, cpu_env);
8827 break;
8828 case 4:
8829 gen_helper_mftc0_tchalt(t0, cpu_env);
8830 break;
8831 case 5:
8832 gen_helper_mftc0_tccontext(t0, cpu_env);
8833 break;
8834 case 6:
8835 gen_helper_mftc0_tcschedule(t0, cpu_env);
8836 break;
8837 case 7:
8838 gen_helper_mftc0_tcschefback(t0, cpu_env);
8839 break;
8840 default:
8841 gen_mfc0(ctx, t0, rt, sel);
8842 break;
8844 break;
8845 case 10:
8846 switch (sel) {
8847 case 0:
8848 gen_helper_mftc0_entryhi(t0, cpu_env);
8849 break;
8850 default:
8851 gen_mfc0(ctx, t0, rt, sel);
8852 break;
8854 case 12:
8855 switch (sel) {
8856 case 0:
8857 gen_helper_mftc0_status(t0, cpu_env);
8858 break;
8859 default:
8860 gen_mfc0(ctx, t0, rt, sel);
8861 break;
8863 case 13:
8864 switch (sel) {
8865 case 0:
8866 gen_helper_mftc0_cause(t0, cpu_env);
8867 break;
8868 default:
8869 goto die;
8870 break;
8872 break;
8873 case 14:
8874 switch (sel) {
8875 case 0:
8876 gen_helper_mftc0_epc(t0, cpu_env);
8877 break;
8878 default:
8879 goto die;
8880 break;
8882 break;
8883 case 15:
8884 switch (sel) {
8885 case 1:
8886 gen_helper_mftc0_ebase(t0, cpu_env);
8887 break;
8888 default:
8889 goto die;
8890 break;
8892 break;
8893 case 16:
8894 switch (sel) {
8895 case 0:
8896 case 1:
8897 case 2:
8898 case 3:
8899 case 4:
8900 case 5:
8901 case 6:
8902 case 7:
8903 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
8904 break;
8905 default:
8906 goto die;
8907 break;
8909 break;
8910 case 23:
8911 switch (sel) {
8912 case 0:
8913 gen_helper_mftc0_debug(t0, cpu_env);
8914 break;
8915 default:
8916 gen_mfc0(ctx, t0, rt, sel);
8917 break;
8919 break;
8920 default:
8921 gen_mfc0(ctx, t0, rt, sel);
8923 } else switch (sel) {
8924 /* GPR registers. */
8925 case 0:
8926 gen_helper_1e0i(mftgpr, t0, rt);
8927 break;
8928 /* Auxiliary CPU registers */
8929 case 1:
8930 switch (rt) {
8931 case 0:
8932 gen_helper_1e0i(mftlo, t0, 0);
8933 break;
8934 case 1:
8935 gen_helper_1e0i(mfthi, t0, 0);
8936 break;
8937 case 2:
8938 gen_helper_1e0i(mftacx, t0, 0);
8939 break;
8940 case 4:
8941 gen_helper_1e0i(mftlo, t0, 1);
8942 break;
8943 case 5:
8944 gen_helper_1e0i(mfthi, t0, 1);
8945 break;
8946 case 6:
8947 gen_helper_1e0i(mftacx, t0, 1);
8948 break;
8949 case 8:
8950 gen_helper_1e0i(mftlo, t0, 2);
8951 break;
8952 case 9:
8953 gen_helper_1e0i(mfthi, t0, 2);
8954 break;
8955 case 10:
8956 gen_helper_1e0i(mftacx, t0, 2);
8957 break;
8958 case 12:
8959 gen_helper_1e0i(mftlo, t0, 3);
8960 break;
8961 case 13:
8962 gen_helper_1e0i(mfthi, t0, 3);
8963 break;
8964 case 14:
8965 gen_helper_1e0i(mftacx, t0, 3);
8966 break;
8967 case 16:
8968 gen_helper_mftdsp(t0, cpu_env);
8969 break;
8970 default:
8971 goto die;
8973 break;
8974 /* Floating point (COP1). */
8975 case 2:
8976 /* XXX: For now we support only a single FPU context. */
8977 if (h == 0) {
8978 TCGv_i32 fp0 = tcg_temp_new_i32();
8980 gen_load_fpr32(ctx, fp0, rt);
8981 tcg_gen_ext_i32_tl(t0, fp0);
8982 tcg_temp_free_i32(fp0);
8983 } else {
8984 TCGv_i32 fp0 = tcg_temp_new_i32();
8986 gen_load_fpr32h(ctx, fp0, rt);
8987 tcg_gen_ext_i32_tl(t0, fp0);
8988 tcg_temp_free_i32(fp0);
8990 break;
8991 case 3:
8992 /* XXX: For now we support only a single FPU context. */
8993 gen_helper_1e0i(cfc1, t0, rt);
8994 break;
8995 /* COP2: Not implemented. */
8996 case 4:
8997 case 5:
8998 /* fall through */
8999 default:
9000 goto die;
9002 trace_mips_translate_tr("mftr", rt, u, sel, h);
9003 gen_store_gpr(t0, rd);
9004 tcg_temp_free(t0);
9005 return;
9007 die:
9008 tcg_temp_free(t0);
9009 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9010 generate_exception_end(ctx, EXCP_RI);
9013 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9014 int u, int sel, int h)
9016 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9017 TCGv t0 = tcg_temp_local_new();
9019 gen_load_gpr(t0, rt);
9020 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9021 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9022 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9023 /* NOP */ ;
9024 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9025 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9026 /* NOP */ ;
9027 else if (u == 0) {
9028 switch (rd) {
9029 case 1:
9030 switch (sel) {
9031 case 1:
9032 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9033 break;
9034 case 2:
9035 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9036 break;
9037 default:
9038 goto die;
9039 break;
9041 break;
9042 case 2:
9043 switch (sel) {
9044 case 1:
9045 gen_helper_mttc0_tcstatus(cpu_env, t0);
9046 break;
9047 case 2:
9048 gen_helper_mttc0_tcbind(cpu_env, t0);
9049 break;
9050 case 3:
9051 gen_helper_mttc0_tcrestart(cpu_env, t0);
9052 break;
9053 case 4:
9054 gen_helper_mttc0_tchalt(cpu_env, t0);
9055 break;
9056 case 5:
9057 gen_helper_mttc0_tccontext(cpu_env, t0);
9058 break;
9059 case 6:
9060 gen_helper_mttc0_tcschedule(cpu_env, t0);
9061 break;
9062 case 7:
9063 gen_helper_mttc0_tcschefback(cpu_env, t0);
9064 break;
9065 default:
9066 gen_mtc0(ctx, t0, rd, sel);
9067 break;
9069 break;
9070 case 10:
9071 switch (sel) {
9072 case 0:
9073 gen_helper_mttc0_entryhi(cpu_env, t0);
9074 break;
9075 default:
9076 gen_mtc0(ctx, t0, rd, sel);
9077 break;
9079 case 12:
9080 switch (sel) {
9081 case 0:
9082 gen_helper_mttc0_status(cpu_env, t0);
9083 break;
9084 default:
9085 gen_mtc0(ctx, t0, rd, sel);
9086 break;
9088 case 13:
9089 switch (sel) {
9090 case 0:
9091 gen_helper_mttc0_cause(cpu_env, t0);
9092 break;
9093 default:
9094 goto die;
9095 break;
9097 break;
9098 case 15:
9099 switch (sel) {
9100 case 1:
9101 gen_helper_mttc0_ebase(cpu_env, t0);
9102 break;
9103 default:
9104 goto die;
9105 break;
9107 break;
9108 case 23:
9109 switch (sel) {
9110 case 0:
9111 gen_helper_mttc0_debug(cpu_env, t0);
9112 break;
9113 default:
9114 gen_mtc0(ctx, t0, rd, sel);
9115 break;
9117 break;
9118 default:
9119 gen_mtc0(ctx, t0, rd, sel);
9121 } else switch (sel) {
9122 /* GPR registers. */
9123 case 0:
9124 gen_helper_0e1i(mttgpr, t0, rd);
9125 break;
9126 /* Auxiliary CPU registers */
9127 case 1:
9128 switch (rd) {
9129 case 0:
9130 gen_helper_0e1i(mttlo, t0, 0);
9131 break;
9132 case 1:
9133 gen_helper_0e1i(mtthi, t0, 0);
9134 break;
9135 case 2:
9136 gen_helper_0e1i(mttacx, t0, 0);
9137 break;
9138 case 4:
9139 gen_helper_0e1i(mttlo, t0, 1);
9140 break;
9141 case 5:
9142 gen_helper_0e1i(mtthi, t0, 1);
9143 break;
9144 case 6:
9145 gen_helper_0e1i(mttacx, t0, 1);
9146 break;
9147 case 8:
9148 gen_helper_0e1i(mttlo, t0, 2);
9149 break;
9150 case 9:
9151 gen_helper_0e1i(mtthi, t0, 2);
9152 break;
9153 case 10:
9154 gen_helper_0e1i(mttacx, t0, 2);
9155 break;
9156 case 12:
9157 gen_helper_0e1i(mttlo, t0, 3);
9158 break;
9159 case 13:
9160 gen_helper_0e1i(mtthi, t0, 3);
9161 break;
9162 case 14:
9163 gen_helper_0e1i(mttacx, t0, 3);
9164 break;
9165 case 16:
9166 gen_helper_mttdsp(cpu_env, t0);
9167 break;
9168 default:
9169 goto die;
9171 break;
9172 /* Floating point (COP1). */
9173 case 2:
9174 /* XXX: For now we support only a single FPU context. */
9175 if (h == 0) {
9176 TCGv_i32 fp0 = tcg_temp_new_i32();
9178 tcg_gen_trunc_tl_i32(fp0, t0);
9179 gen_store_fpr32(ctx, fp0, rd);
9180 tcg_temp_free_i32(fp0);
9181 } else {
9182 TCGv_i32 fp0 = tcg_temp_new_i32();
9184 tcg_gen_trunc_tl_i32(fp0, t0);
9185 gen_store_fpr32h(ctx, fp0, rd);
9186 tcg_temp_free_i32(fp0);
9188 break;
9189 case 3:
9190 /* XXX: For now we support only a single FPU context. */
9192 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9194 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9195 tcg_temp_free_i32(fs_tmp);
9197 /* Stop translation as we may have changed hflags */
9198 ctx->base.is_jmp = DISAS_STOP;
9199 break;
9200 /* COP2: Not implemented. */
9201 case 4:
9202 case 5:
9203 /* fall through */
9204 default:
9205 goto die;
9207 trace_mips_translate_tr("mttr", rd, u, sel, h);
9208 tcg_temp_free(t0);
9209 return;
9211 die:
9212 tcg_temp_free(t0);
9213 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9214 generate_exception_end(ctx, EXCP_RI);
9217 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9219 const char *opn = "ldst";
9221 check_cp0_enabled(ctx);
9222 switch (opc) {
9223 case OPC_MFC0:
9224 if (rt == 0) {
9225 /* Treat as NOP. */
9226 return;
9228 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9229 opn = "mfc0";
9230 break;
9231 case OPC_MTC0:
9233 TCGv t0 = tcg_temp_new();
9235 gen_load_gpr(t0, rt);
9236 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9237 tcg_temp_free(t0);
9239 opn = "mtc0";
9240 break;
9241 #if defined(TARGET_MIPS64)
9242 case OPC_DMFC0:
9243 check_insn(ctx, ISA_MIPS3);
9244 if (rt == 0) {
9245 /* Treat as NOP. */
9246 return;
9248 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9249 opn = "dmfc0";
9250 break;
9251 case OPC_DMTC0:
9252 check_insn(ctx, ISA_MIPS3);
9254 TCGv t0 = tcg_temp_new();
9256 gen_load_gpr(t0, rt);
9257 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9258 tcg_temp_free(t0);
9260 opn = "dmtc0";
9261 break;
9262 #endif
9263 case OPC_MFHC0:
9264 check_mvh(ctx);
9265 if (rt == 0) {
9266 /* Treat as NOP. */
9267 return;
9269 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9270 opn = "mfhc0";
9271 break;
9272 case OPC_MTHC0:
9273 check_mvh(ctx);
9275 TCGv t0 = tcg_temp_new();
9276 gen_load_gpr(t0, rt);
9277 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9278 tcg_temp_free(t0);
9280 opn = "mthc0";
9281 break;
9282 case OPC_MFTR:
9283 check_cp0_enabled(ctx);
9284 if (rd == 0) {
9285 /* Treat as NOP. */
9286 return;
9288 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9289 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9290 opn = "mftr";
9291 break;
9292 case OPC_MTTR:
9293 check_cp0_enabled(ctx);
9294 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9295 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9296 opn = "mttr";
9297 break;
9298 case OPC_TLBWI:
9299 opn = "tlbwi";
9300 if (!env->tlb->helper_tlbwi)
9301 goto die;
9302 gen_helper_tlbwi(cpu_env);
9303 break;
9304 case OPC_TLBINV:
9305 opn = "tlbinv";
9306 if (ctx->ie >= 2) {
9307 if (!env->tlb->helper_tlbinv) {
9308 goto die;
9310 gen_helper_tlbinv(cpu_env);
9311 } /* treat as nop if TLBINV not supported */
9312 break;
9313 case OPC_TLBINVF:
9314 opn = "tlbinvf";
9315 if (ctx->ie >= 2) {
9316 if (!env->tlb->helper_tlbinvf) {
9317 goto die;
9319 gen_helper_tlbinvf(cpu_env);
9320 } /* treat as nop if TLBINV not supported */
9321 break;
9322 case OPC_TLBWR:
9323 opn = "tlbwr";
9324 if (!env->tlb->helper_tlbwr)
9325 goto die;
9326 gen_helper_tlbwr(cpu_env);
9327 break;
9328 case OPC_TLBP:
9329 opn = "tlbp";
9330 if (!env->tlb->helper_tlbp)
9331 goto die;
9332 gen_helper_tlbp(cpu_env);
9333 break;
9334 case OPC_TLBR:
9335 opn = "tlbr";
9336 if (!env->tlb->helper_tlbr)
9337 goto die;
9338 gen_helper_tlbr(cpu_env);
9339 break;
9340 case OPC_ERET: /* OPC_ERETNC */
9341 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9342 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9343 goto die;
9344 } else {
9345 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9346 if (ctx->opcode & (1 << bit_shift)) {
9347 /* OPC_ERETNC */
9348 opn = "eretnc";
9349 check_insn(ctx, ISA_MIPS32R5);
9350 gen_helper_eretnc(cpu_env);
9351 } else {
9352 /* OPC_ERET */
9353 opn = "eret";
9354 check_insn(ctx, ISA_MIPS2);
9355 gen_helper_eret(cpu_env);
9357 ctx->base.is_jmp = DISAS_EXIT;
9359 break;
9360 case OPC_DERET:
9361 opn = "deret";
9362 check_insn(ctx, ISA_MIPS32);
9363 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9364 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9365 goto die;
9367 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9368 MIPS_INVAL(opn);
9369 generate_exception_end(ctx, EXCP_RI);
9370 } else {
9371 gen_helper_deret(cpu_env);
9372 ctx->base.is_jmp = DISAS_EXIT;
9374 break;
9375 case OPC_WAIT:
9376 opn = "wait";
9377 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9378 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9379 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9380 goto die;
9382 /* If we get an exception, we want to restart at next instruction */
9383 ctx->base.pc_next += 4;
9384 save_cpu_state(ctx, 1);
9385 ctx->base.pc_next -= 4;
9386 gen_helper_wait(cpu_env);
9387 ctx->base.is_jmp = DISAS_NORETURN;
9388 break;
9389 default:
9390 die:
9391 MIPS_INVAL(opn);
9392 generate_exception_end(ctx, EXCP_RI);
9393 return;
9395 (void)opn; /* avoid a compiler warning */
9397 #endif /* !CONFIG_USER_ONLY */
9399 /* CP1 Branches (before delay slot) */
9400 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9401 int32_t cc, int32_t offset)
9403 target_ulong btarget;
9404 TCGv_i32 t0 = tcg_temp_new_i32();
9406 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9407 generate_exception_end(ctx, EXCP_RI);
9408 goto out;
9411 if (cc != 0)
9412 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9414 btarget = ctx->base.pc_next + 4 + offset;
9416 switch (op) {
9417 case OPC_BC1F:
9418 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9419 tcg_gen_not_i32(t0, t0);
9420 tcg_gen_andi_i32(t0, t0, 1);
9421 tcg_gen_extu_i32_tl(bcond, t0);
9422 goto not_likely;
9423 case OPC_BC1FL:
9424 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9425 tcg_gen_not_i32(t0, t0);
9426 tcg_gen_andi_i32(t0, t0, 1);
9427 tcg_gen_extu_i32_tl(bcond, t0);
9428 goto likely;
9429 case OPC_BC1T:
9430 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9431 tcg_gen_andi_i32(t0, t0, 1);
9432 tcg_gen_extu_i32_tl(bcond, t0);
9433 goto not_likely;
9434 case OPC_BC1TL:
9435 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9436 tcg_gen_andi_i32(t0, t0, 1);
9437 tcg_gen_extu_i32_tl(bcond, t0);
9438 likely:
9439 ctx->hflags |= MIPS_HFLAG_BL;
9440 break;
9441 case OPC_BC1FANY2:
9443 TCGv_i32 t1 = tcg_temp_new_i32();
9444 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9445 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9446 tcg_gen_nand_i32(t0, t0, t1);
9447 tcg_temp_free_i32(t1);
9448 tcg_gen_andi_i32(t0, t0, 1);
9449 tcg_gen_extu_i32_tl(bcond, t0);
9451 goto not_likely;
9452 case OPC_BC1TANY2:
9454 TCGv_i32 t1 = tcg_temp_new_i32();
9455 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9456 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9457 tcg_gen_or_i32(t0, t0, t1);
9458 tcg_temp_free_i32(t1);
9459 tcg_gen_andi_i32(t0, t0, 1);
9460 tcg_gen_extu_i32_tl(bcond, t0);
9462 goto not_likely;
9463 case OPC_BC1FANY4:
9465 TCGv_i32 t1 = tcg_temp_new_i32();
9466 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9467 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9468 tcg_gen_and_i32(t0, t0, t1);
9469 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9470 tcg_gen_and_i32(t0, t0, t1);
9471 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9472 tcg_gen_nand_i32(t0, t0, t1);
9473 tcg_temp_free_i32(t1);
9474 tcg_gen_andi_i32(t0, t0, 1);
9475 tcg_gen_extu_i32_tl(bcond, t0);
9477 goto not_likely;
9478 case OPC_BC1TANY4:
9480 TCGv_i32 t1 = tcg_temp_new_i32();
9481 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9482 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9483 tcg_gen_or_i32(t0, t0, t1);
9484 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9485 tcg_gen_or_i32(t0, t0, t1);
9486 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9487 tcg_gen_or_i32(t0, t0, t1);
9488 tcg_temp_free_i32(t1);
9489 tcg_gen_andi_i32(t0, t0, 1);
9490 tcg_gen_extu_i32_tl(bcond, t0);
9492 not_likely:
9493 ctx->hflags |= MIPS_HFLAG_BC;
9494 break;
9495 default:
9496 MIPS_INVAL("cp1 cond branch");
9497 generate_exception_end(ctx, EXCP_RI);
9498 goto out;
9500 ctx->btarget = btarget;
9501 ctx->hflags |= MIPS_HFLAG_BDS32;
9502 out:
9503 tcg_temp_free_i32(t0);
9506 /* R6 CP1 Branches */
9507 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9508 int32_t ft, int32_t offset,
9509 int delayslot_size)
9511 target_ulong btarget;
9512 TCGv_i64 t0 = tcg_temp_new_i64();
9514 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9515 #ifdef MIPS_DEBUG_DISAS
9516 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9517 "\n", ctx->base.pc_next);
9518 #endif
9519 generate_exception_end(ctx, EXCP_RI);
9520 goto out;
9523 gen_load_fpr64(ctx, t0, ft);
9524 tcg_gen_andi_i64(t0, t0, 1);
9526 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9528 switch (op) {
9529 case OPC_BC1EQZ:
9530 tcg_gen_xori_i64(t0, t0, 1);
9531 ctx->hflags |= MIPS_HFLAG_BC;
9532 break;
9533 case OPC_BC1NEZ:
9534 /* t0 already set */
9535 ctx->hflags |= MIPS_HFLAG_BC;
9536 break;
9537 default:
9538 MIPS_INVAL("cp1 cond branch");
9539 generate_exception_end(ctx, EXCP_RI);
9540 goto out;
9543 tcg_gen_trunc_i64_tl(bcond, t0);
9545 ctx->btarget = btarget;
9547 switch (delayslot_size) {
9548 case 2:
9549 ctx->hflags |= MIPS_HFLAG_BDS16;
9550 break;
9551 case 4:
9552 ctx->hflags |= MIPS_HFLAG_BDS32;
9553 break;
9556 out:
9557 tcg_temp_free_i64(t0);
9560 /* Coprocessor 1 (FPU) */
9562 #define FOP(func, fmt) (((fmt) << 21) | (func))
9564 enum fopcode {
9565 OPC_ADD_S = FOP(0, FMT_S),
9566 OPC_SUB_S = FOP(1, FMT_S),
9567 OPC_MUL_S = FOP(2, FMT_S),
9568 OPC_DIV_S = FOP(3, FMT_S),
9569 OPC_SQRT_S = FOP(4, FMT_S),
9570 OPC_ABS_S = FOP(5, FMT_S),
9571 OPC_MOV_S = FOP(6, FMT_S),
9572 OPC_NEG_S = FOP(7, FMT_S),
9573 OPC_ROUND_L_S = FOP(8, FMT_S),
9574 OPC_TRUNC_L_S = FOP(9, FMT_S),
9575 OPC_CEIL_L_S = FOP(10, FMT_S),
9576 OPC_FLOOR_L_S = FOP(11, FMT_S),
9577 OPC_ROUND_W_S = FOP(12, FMT_S),
9578 OPC_TRUNC_W_S = FOP(13, FMT_S),
9579 OPC_CEIL_W_S = FOP(14, FMT_S),
9580 OPC_FLOOR_W_S = FOP(15, FMT_S),
9581 OPC_SEL_S = FOP(16, FMT_S),
9582 OPC_MOVCF_S = FOP(17, FMT_S),
9583 OPC_MOVZ_S = FOP(18, FMT_S),
9584 OPC_MOVN_S = FOP(19, FMT_S),
9585 OPC_SELEQZ_S = FOP(20, FMT_S),
9586 OPC_RECIP_S = FOP(21, FMT_S),
9587 OPC_RSQRT_S = FOP(22, FMT_S),
9588 OPC_SELNEZ_S = FOP(23, FMT_S),
9589 OPC_MADDF_S = FOP(24, FMT_S),
9590 OPC_MSUBF_S = FOP(25, FMT_S),
9591 OPC_RINT_S = FOP(26, FMT_S),
9592 OPC_CLASS_S = FOP(27, FMT_S),
9593 OPC_MIN_S = FOP(28, FMT_S),
9594 OPC_RECIP2_S = FOP(28, FMT_S),
9595 OPC_MINA_S = FOP(29, FMT_S),
9596 OPC_RECIP1_S = FOP(29, FMT_S),
9597 OPC_MAX_S = FOP(30, FMT_S),
9598 OPC_RSQRT1_S = FOP(30, FMT_S),
9599 OPC_MAXA_S = FOP(31, FMT_S),
9600 OPC_RSQRT2_S = FOP(31, FMT_S),
9601 OPC_CVT_D_S = FOP(33, FMT_S),
9602 OPC_CVT_W_S = FOP(36, FMT_S),
9603 OPC_CVT_L_S = FOP(37, FMT_S),
9604 OPC_CVT_PS_S = FOP(38, FMT_S),
9605 OPC_CMP_F_S = FOP (48, FMT_S),
9606 OPC_CMP_UN_S = FOP (49, FMT_S),
9607 OPC_CMP_EQ_S = FOP (50, FMT_S),
9608 OPC_CMP_UEQ_S = FOP (51, FMT_S),
9609 OPC_CMP_OLT_S = FOP (52, FMT_S),
9610 OPC_CMP_ULT_S = FOP (53, FMT_S),
9611 OPC_CMP_OLE_S = FOP (54, FMT_S),
9612 OPC_CMP_ULE_S = FOP (55, FMT_S),
9613 OPC_CMP_SF_S = FOP (56, FMT_S),
9614 OPC_CMP_NGLE_S = FOP (57, FMT_S),
9615 OPC_CMP_SEQ_S = FOP (58, FMT_S),
9616 OPC_CMP_NGL_S = FOP (59, FMT_S),
9617 OPC_CMP_LT_S = FOP (60, FMT_S),
9618 OPC_CMP_NGE_S = FOP (61, FMT_S),
9619 OPC_CMP_LE_S = FOP (62, FMT_S),
9620 OPC_CMP_NGT_S = FOP (63, FMT_S),
9622 OPC_ADD_D = FOP(0, FMT_D),
9623 OPC_SUB_D = FOP(1, FMT_D),
9624 OPC_MUL_D = FOP(2, FMT_D),
9625 OPC_DIV_D = FOP(3, FMT_D),
9626 OPC_SQRT_D = FOP(4, FMT_D),
9627 OPC_ABS_D = FOP(5, FMT_D),
9628 OPC_MOV_D = FOP(6, FMT_D),
9629 OPC_NEG_D = FOP(7, FMT_D),
9630 OPC_ROUND_L_D = FOP(8, FMT_D),
9631 OPC_TRUNC_L_D = FOP(9, FMT_D),
9632 OPC_CEIL_L_D = FOP(10, FMT_D),
9633 OPC_FLOOR_L_D = FOP(11, FMT_D),
9634 OPC_ROUND_W_D = FOP(12, FMT_D),
9635 OPC_TRUNC_W_D = FOP(13, FMT_D),
9636 OPC_CEIL_W_D = FOP(14, FMT_D),
9637 OPC_FLOOR_W_D = FOP(15, FMT_D),
9638 OPC_SEL_D = FOP(16, FMT_D),
9639 OPC_MOVCF_D = FOP(17, FMT_D),
9640 OPC_MOVZ_D = FOP(18, FMT_D),
9641 OPC_MOVN_D = FOP(19, FMT_D),
9642 OPC_SELEQZ_D = FOP(20, FMT_D),
9643 OPC_RECIP_D = FOP(21, FMT_D),
9644 OPC_RSQRT_D = FOP(22, FMT_D),
9645 OPC_SELNEZ_D = FOP(23, FMT_D),
9646 OPC_MADDF_D = FOP(24, FMT_D),
9647 OPC_MSUBF_D = FOP(25, FMT_D),
9648 OPC_RINT_D = FOP(26, FMT_D),
9649 OPC_CLASS_D = FOP(27, FMT_D),
9650 OPC_MIN_D = FOP(28, FMT_D),
9651 OPC_RECIP2_D = FOP(28, FMT_D),
9652 OPC_MINA_D = FOP(29, FMT_D),
9653 OPC_RECIP1_D = FOP(29, FMT_D),
9654 OPC_MAX_D = FOP(30, FMT_D),
9655 OPC_RSQRT1_D = FOP(30, FMT_D),
9656 OPC_MAXA_D = FOP(31, FMT_D),
9657 OPC_RSQRT2_D = FOP(31, FMT_D),
9658 OPC_CVT_S_D = FOP(32, FMT_D),
9659 OPC_CVT_W_D = FOP(36, FMT_D),
9660 OPC_CVT_L_D = FOP(37, FMT_D),
9661 OPC_CMP_F_D = FOP (48, FMT_D),
9662 OPC_CMP_UN_D = FOP (49, FMT_D),
9663 OPC_CMP_EQ_D = FOP (50, FMT_D),
9664 OPC_CMP_UEQ_D = FOP (51, FMT_D),
9665 OPC_CMP_OLT_D = FOP (52, FMT_D),
9666 OPC_CMP_ULT_D = FOP (53, FMT_D),
9667 OPC_CMP_OLE_D = FOP (54, FMT_D),
9668 OPC_CMP_ULE_D = FOP (55, FMT_D),
9669 OPC_CMP_SF_D = FOP (56, FMT_D),
9670 OPC_CMP_NGLE_D = FOP (57, FMT_D),
9671 OPC_CMP_SEQ_D = FOP (58, FMT_D),
9672 OPC_CMP_NGL_D = FOP (59, FMT_D),
9673 OPC_CMP_LT_D = FOP (60, FMT_D),
9674 OPC_CMP_NGE_D = FOP (61, FMT_D),
9675 OPC_CMP_LE_D = FOP (62, FMT_D),
9676 OPC_CMP_NGT_D = FOP (63, FMT_D),
9678 OPC_CVT_S_W = FOP(32, FMT_W),
9679 OPC_CVT_D_W = FOP(33, FMT_W),
9680 OPC_CVT_S_L = FOP(32, FMT_L),
9681 OPC_CVT_D_L = FOP(33, FMT_L),
9682 OPC_CVT_PS_PW = FOP(38, FMT_W),
9684 OPC_ADD_PS = FOP(0, FMT_PS),
9685 OPC_SUB_PS = FOP(1, FMT_PS),
9686 OPC_MUL_PS = FOP(2, FMT_PS),
9687 OPC_DIV_PS = FOP(3, FMT_PS),
9688 OPC_ABS_PS = FOP(5, FMT_PS),
9689 OPC_MOV_PS = FOP(6, FMT_PS),
9690 OPC_NEG_PS = FOP(7, FMT_PS),
9691 OPC_MOVCF_PS = FOP(17, FMT_PS),
9692 OPC_MOVZ_PS = FOP(18, FMT_PS),
9693 OPC_MOVN_PS = FOP(19, FMT_PS),
9694 OPC_ADDR_PS = FOP(24, FMT_PS),
9695 OPC_MULR_PS = FOP(26, FMT_PS),
9696 OPC_RECIP2_PS = FOP(28, FMT_PS),
9697 OPC_RECIP1_PS = FOP(29, FMT_PS),
9698 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9699 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9701 OPC_CVT_S_PU = FOP(32, FMT_PS),
9702 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9703 OPC_CVT_S_PL = FOP(40, FMT_PS),
9704 OPC_PLL_PS = FOP(44, FMT_PS),
9705 OPC_PLU_PS = FOP(45, FMT_PS),
9706 OPC_PUL_PS = FOP(46, FMT_PS),
9707 OPC_PUU_PS = FOP(47, FMT_PS),
9708 OPC_CMP_F_PS = FOP (48, FMT_PS),
9709 OPC_CMP_UN_PS = FOP (49, FMT_PS),
9710 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
9711 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
9712 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
9713 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
9714 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
9715 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
9716 OPC_CMP_SF_PS = FOP (56, FMT_PS),
9717 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
9718 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
9719 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
9720 OPC_CMP_LT_PS = FOP (60, FMT_PS),
9721 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
9722 OPC_CMP_LE_PS = FOP (62, FMT_PS),
9723 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
9726 enum r6_f_cmp_op {
9727 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9728 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9729 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9730 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9731 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9732 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9733 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9734 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9735 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9736 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9737 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9738 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9739 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9740 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9741 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9742 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9743 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9744 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9745 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9746 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9747 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9748 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9750 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9751 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9752 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9753 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9754 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9755 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9756 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9757 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9758 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9759 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9760 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9761 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9762 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9763 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9764 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9765 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9766 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9767 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9768 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9769 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9770 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9771 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9773 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
9775 TCGv t0 = tcg_temp_new();
9777 switch (opc) {
9778 case OPC_MFC1:
9780 TCGv_i32 fp0 = tcg_temp_new_i32();
9782 gen_load_fpr32(ctx, fp0, fs);
9783 tcg_gen_ext_i32_tl(t0, fp0);
9784 tcg_temp_free_i32(fp0);
9786 gen_store_gpr(t0, rt);
9787 break;
9788 case OPC_MTC1:
9789 gen_load_gpr(t0, rt);
9791 TCGv_i32 fp0 = tcg_temp_new_i32();
9793 tcg_gen_trunc_tl_i32(fp0, t0);
9794 gen_store_fpr32(ctx, fp0, fs);
9795 tcg_temp_free_i32(fp0);
9797 break;
9798 case OPC_CFC1:
9799 gen_helper_1e0i(cfc1, t0, fs);
9800 gen_store_gpr(t0, rt);
9801 break;
9802 case OPC_CTC1:
9803 gen_load_gpr(t0, rt);
9804 save_cpu_state(ctx, 0);
9806 TCGv_i32 fs_tmp = tcg_const_i32(fs);
9808 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9809 tcg_temp_free_i32(fs_tmp);
9811 /* Stop translation as we may have changed hflags */
9812 ctx->base.is_jmp = DISAS_STOP;
9813 break;
9814 #if defined(TARGET_MIPS64)
9815 case OPC_DMFC1:
9816 gen_load_fpr64(ctx, t0, fs);
9817 gen_store_gpr(t0, rt);
9818 break;
9819 case OPC_DMTC1:
9820 gen_load_gpr(t0, rt);
9821 gen_store_fpr64(ctx, t0, fs);
9822 break;
9823 #endif
9824 case OPC_MFHC1:
9826 TCGv_i32 fp0 = tcg_temp_new_i32();
9828 gen_load_fpr32h(ctx, fp0, fs);
9829 tcg_gen_ext_i32_tl(t0, fp0);
9830 tcg_temp_free_i32(fp0);
9832 gen_store_gpr(t0, rt);
9833 break;
9834 case OPC_MTHC1:
9835 gen_load_gpr(t0, rt);
9837 TCGv_i32 fp0 = tcg_temp_new_i32();
9839 tcg_gen_trunc_tl_i32(fp0, t0);
9840 gen_store_fpr32h(ctx, fp0, fs);
9841 tcg_temp_free_i32(fp0);
9843 break;
9844 default:
9845 MIPS_INVAL("cp1 move");
9846 generate_exception_end(ctx, EXCP_RI);
9847 goto out;
9850 out:
9851 tcg_temp_free(t0);
9854 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
9856 TCGLabel *l1;
9857 TCGCond cond;
9858 TCGv_i32 t0;
9860 if (rd == 0) {
9861 /* Treat as NOP. */
9862 return;
9865 if (tf)
9866 cond = TCG_COND_EQ;
9867 else
9868 cond = TCG_COND_NE;
9870 l1 = gen_new_label();
9871 t0 = tcg_temp_new_i32();
9872 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9873 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9874 tcg_temp_free_i32(t0);
9875 if (rs == 0) {
9876 tcg_gen_movi_tl(cpu_gpr[rd], 0);
9877 } else {
9878 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
9880 gen_set_label(l1);
9883 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9884 int tf)
9886 int cond;
9887 TCGv_i32 t0 = tcg_temp_new_i32();
9888 TCGLabel *l1 = gen_new_label();
9890 if (tf)
9891 cond = TCG_COND_EQ;
9892 else
9893 cond = TCG_COND_NE;
9895 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9896 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9897 gen_load_fpr32(ctx, t0, fs);
9898 gen_store_fpr32(ctx, t0, fd);
9899 gen_set_label(l1);
9900 tcg_temp_free_i32(t0);
9903 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
9905 int cond;
9906 TCGv_i32 t0 = tcg_temp_new_i32();
9907 TCGv_i64 fp0;
9908 TCGLabel *l1 = gen_new_label();
9910 if (tf)
9911 cond = TCG_COND_EQ;
9912 else
9913 cond = TCG_COND_NE;
9915 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9916 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9917 tcg_temp_free_i32(t0);
9918 fp0 = tcg_temp_new_i64();
9919 gen_load_fpr64(ctx, fp0, fs);
9920 gen_store_fpr64(ctx, fp0, fd);
9921 tcg_temp_free_i64(fp0);
9922 gen_set_label(l1);
9925 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9926 int cc, int tf)
9928 int cond;
9929 TCGv_i32 t0 = tcg_temp_new_i32();
9930 TCGLabel *l1 = gen_new_label();
9931 TCGLabel *l2 = gen_new_label();
9933 if (tf)
9934 cond = TCG_COND_EQ;
9935 else
9936 cond = TCG_COND_NE;
9938 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9939 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9940 gen_load_fpr32(ctx, t0, fs);
9941 gen_store_fpr32(ctx, t0, fd);
9942 gen_set_label(l1);
9944 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
9945 tcg_gen_brcondi_i32(cond, t0, 0, l2);
9946 gen_load_fpr32h(ctx, t0, fs);
9947 gen_store_fpr32h(ctx, t0, fd);
9948 tcg_temp_free_i32(t0);
9949 gen_set_label(l2);
9952 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9953 int fs)
9955 TCGv_i32 t1 = tcg_const_i32(0);
9956 TCGv_i32 fp0 = tcg_temp_new_i32();
9957 TCGv_i32 fp1 = tcg_temp_new_i32();
9958 TCGv_i32 fp2 = tcg_temp_new_i32();
9959 gen_load_fpr32(ctx, fp0, fd);
9960 gen_load_fpr32(ctx, fp1, ft);
9961 gen_load_fpr32(ctx, fp2, fs);
9963 switch (op1) {
9964 case OPC_SEL_S:
9965 tcg_gen_andi_i32(fp0, fp0, 1);
9966 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9967 break;
9968 case OPC_SELEQZ_S:
9969 tcg_gen_andi_i32(fp1, fp1, 1);
9970 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9971 break;
9972 case OPC_SELNEZ_S:
9973 tcg_gen_andi_i32(fp1, fp1, 1);
9974 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9975 break;
9976 default:
9977 MIPS_INVAL("gen_sel_s");
9978 generate_exception_end(ctx, EXCP_RI);
9979 break;
9982 gen_store_fpr32(ctx, fp0, fd);
9983 tcg_temp_free_i32(fp2);
9984 tcg_temp_free_i32(fp1);
9985 tcg_temp_free_i32(fp0);
9986 tcg_temp_free_i32(t1);
9989 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9990 int fs)
9992 TCGv_i64 t1 = tcg_const_i64(0);
9993 TCGv_i64 fp0 = tcg_temp_new_i64();
9994 TCGv_i64 fp1 = tcg_temp_new_i64();
9995 TCGv_i64 fp2 = tcg_temp_new_i64();
9996 gen_load_fpr64(ctx, fp0, fd);
9997 gen_load_fpr64(ctx, fp1, ft);
9998 gen_load_fpr64(ctx, fp2, fs);
10000 switch (op1) {
10001 case OPC_SEL_D:
10002 tcg_gen_andi_i64(fp0, fp0, 1);
10003 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10004 break;
10005 case OPC_SELEQZ_D:
10006 tcg_gen_andi_i64(fp1, fp1, 1);
10007 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10008 break;
10009 case OPC_SELNEZ_D:
10010 tcg_gen_andi_i64(fp1, fp1, 1);
10011 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10012 break;
10013 default:
10014 MIPS_INVAL("gen_sel_d");
10015 generate_exception_end(ctx, EXCP_RI);
10016 break;
10019 gen_store_fpr64(ctx, fp0, fd);
10020 tcg_temp_free_i64(fp2);
10021 tcg_temp_free_i64(fp1);
10022 tcg_temp_free_i64(fp0);
10023 tcg_temp_free_i64(t1);
10026 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10027 int ft, int fs, int fd, int cc)
10029 uint32_t func = ctx->opcode & 0x3f;
10030 switch (op1) {
10031 case OPC_ADD_S:
10033 TCGv_i32 fp0 = tcg_temp_new_i32();
10034 TCGv_i32 fp1 = tcg_temp_new_i32();
10036 gen_load_fpr32(ctx, fp0, fs);
10037 gen_load_fpr32(ctx, fp1, ft);
10038 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10039 tcg_temp_free_i32(fp1);
10040 gen_store_fpr32(ctx, fp0, fd);
10041 tcg_temp_free_i32(fp0);
10043 break;
10044 case OPC_SUB_S:
10046 TCGv_i32 fp0 = tcg_temp_new_i32();
10047 TCGv_i32 fp1 = tcg_temp_new_i32();
10049 gen_load_fpr32(ctx, fp0, fs);
10050 gen_load_fpr32(ctx, fp1, ft);
10051 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10052 tcg_temp_free_i32(fp1);
10053 gen_store_fpr32(ctx, fp0, fd);
10054 tcg_temp_free_i32(fp0);
10056 break;
10057 case OPC_MUL_S:
10059 TCGv_i32 fp0 = tcg_temp_new_i32();
10060 TCGv_i32 fp1 = tcg_temp_new_i32();
10062 gen_load_fpr32(ctx, fp0, fs);
10063 gen_load_fpr32(ctx, fp1, ft);
10064 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10065 tcg_temp_free_i32(fp1);
10066 gen_store_fpr32(ctx, fp0, fd);
10067 tcg_temp_free_i32(fp0);
10069 break;
10070 case OPC_DIV_S:
10072 TCGv_i32 fp0 = tcg_temp_new_i32();
10073 TCGv_i32 fp1 = tcg_temp_new_i32();
10075 gen_load_fpr32(ctx, fp0, fs);
10076 gen_load_fpr32(ctx, fp1, ft);
10077 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10078 tcg_temp_free_i32(fp1);
10079 gen_store_fpr32(ctx, fp0, fd);
10080 tcg_temp_free_i32(fp0);
10082 break;
10083 case OPC_SQRT_S:
10085 TCGv_i32 fp0 = tcg_temp_new_i32();
10087 gen_load_fpr32(ctx, fp0, fs);
10088 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10089 gen_store_fpr32(ctx, fp0, fd);
10090 tcg_temp_free_i32(fp0);
10092 break;
10093 case OPC_ABS_S:
10095 TCGv_i32 fp0 = tcg_temp_new_i32();
10097 gen_load_fpr32(ctx, fp0, fs);
10098 if (ctx->abs2008) {
10099 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10100 } else {
10101 gen_helper_float_abs_s(fp0, fp0);
10103 gen_store_fpr32(ctx, fp0, fd);
10104 tcg_temp_free_i32(fp0);
10106 break;
10107 case OPC_MOV_S:
10109 TCGv_i32 fp0 = tcg_temp_new_i32();
10111 gen_load_fpr32(ctx, fp0, fs);
10112 gen_store_fpr32(ctx, fp0, fd);
10113 tcg_temp_free_i32(fp0);
10115 break;
10116 case OPC_NEG_S:
10118 TCGv_i32 fp0 = tcg_temp_new_i32();
10120 gen_load_fpr32(ctx, fp0, fs);
10121 if (ctx->abs2008) {
10122 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10123 } else {
10124 gen_helper_float_chs_s(fp0, fp0);
10126 gen_store_fpr32(ctx, fp0, fd);
10127 tcg_temp_free_i32(fp0);
10129 break;
10130 case OPC_ROUND_L_S:
10131 check_cp1_64bitmode(ctx);
10133 TCGv_i32 fp32 = tcg_temp_new_i32();
10134 TCGv_i64 fp64 = tcg_temp_new_i64();
10136 gen_load_fpr32(ctx, fp32, fs);
10137 if (ctx->nan2008) {
10138 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10139 } else {
10140 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10142 tcg_temp_free_i32(fp32);
10143 gen_store_fpr64(ctx, fp64, fd);
10144 tcg_temp_free_i64(fp64);
10146 break;
10147 case OPC_TRUNC_L_S:
10148 check_cp1_64bitmode(ctx);
10150 TCGv_i32 fp32 = tcg_temp_new_i32();
10151 TCGv_i64 fp64 = tcg_temp_new_i64();
10153 gen_load_fpr32(ctx, fp32, fs);
10154 if (ctx->nan2008) {
10155 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10156 } else {
10157 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10159 tcg_temp_free_i32(fp32);
10160 gen_store_fpr64(ctx, fp64, fd);
10161 tcg_temp_free_i64(fp64);
10163 break;
10164 case OPC_CEIL_L_S:
10165 check_cp1_64bitmode(ctx);
10167 TCGv_i32 fp32 = tcg_temp_new_i32();
10168 TCGv_i64 fp64 = tcg_temp_new_i64();
10170 gen_load_fpr32(ctx, fp32, fs);
10171 if (ctx->nan2008) {
10172 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10173 } else {
10174 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10176 tcg_temp_free_i32(fp32);
10177 gen_store_fpr64(ctx, fp64, fd);
10178 tcg_temp_free_i64(fp64);
10180 break;
10181 case OPC_FLOOR_L_S:
10182 check_cp1_64bitmode(ctx);
10184 TCGv_i32 fp32 = tcg_temp_new_i32();
10185 TCGv_i64 fp64 = tcg_temp_new_i64();
10187 gen_load_fpr32(ctx, fp32, fs);
10188 if (ctx->nan2008) {
10189 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10190 } else {
10191 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10193 tcg_temp_free_i32(fp32);
10194 gen_store_fpr64(ctx, fp64, fd);
10195 tcg_temp_free_i64(fp64);
10197 break;
10198 case OPC_ROUND_W_S:
10200 TCGv_i32 fp0 = tcg_temp_new_i32();
10202 gen_load_fpr32(ctx, fp0, fs);
10203 if (ctx->nan2008) {
10204 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10205 } else {
10206 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10208 gen_store_fpr32(ctx, fp0, fd);
10209 tcg_temp_free_i32(fp0);
10211 break;
10212 case OPC_TRUNC_W_S:
10214 TCGv_i32 fp0 = tcg_temp_new_i32();
10216 gen_load_fpr32(ctx, fp0, fs);
10217 if (ctx->nan2008) {
10218 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10219 } else {
10220 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10222 gen_store_fpr32(ctx, fp0, fd);
10223 tcg_temp_free_i32(fp0);
10225 break;
10226 case OPC_CEIL_W_S:
10228 TCGv_i32 fp0 = tcg_temp_new_i32();
10230 gen_load_fpr32(ctx, fp0, fs);
10231 if (ctx->nan2008) {
10232 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10233 } else {
10234 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10236 gen_store_fpr32(ctx, fp0, fd);
10237 tcg_temp_free_i32(fp0);
10239 break;
10240 case OPC_FLOOR_W_S:
10242 TCGv_i32 fp0 = tcg_temp_new_i32();
10244 gen_load_fpr32(ctx, fp0, fs);
10245 if (ctx->nan2008) {
10246 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10247 } else {
10248 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10250 gen_store_fpr32(ctx, fp0, fd);
10251 tcg_temp_free_i32(fp0);
10253 break;
10254 case OPC_SEL_S:
10255 check_insn(ctx, ISA_MIPS32R6);
10256 gen_sel_s(ctx, op1, fd, ft, fs);
10257 break;
10258 case OPC_SELEQZ_S:
10259 check_insn(ctx, ISA_MIPS32R6);
10260 gen_sel_s(ctx, op1, fd, ft, fs);
10261 break;
10262 case OPC_SELNEZ_S:
10263 check_insn(ctx, ISA_MIPS32R6);
10264 gen_sel_s(ctx, op1, fd, ft, fs);
10265 break;
10266 case OPC_MOVCF_S:
10267 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10268 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10269 break;
10270 case OPC_MOVZ_S:
10271 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10273 TCGLabel *l1 = gen_new_label();
10274 TCGv_i32 fp0;
10276 if (ft != 0) {
10277 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10279 fp0 = tcg_temp_new_i32();
10280 gen_load_fpr32(ctx, fp0, fs);
10281 gen_store_fpr32(ctx, fp0, fd);
10282 tcg_temp_free_i32(fp0);
10283 gen_set_label(l1);
10285 break;
10286 case OPC_MOVN_S:
10287 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10289 TCGLabel *l1 = gen_new_label();
10290 TCGv_i32 fp0;
10292 if (ft != 0) {
10293 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10294 fp0 = tcg_temp_new_i32();
10295 gen_load_fpr32(ctx, fp0, fs);
10296 gen_store_fpr32(ctx, fp0, fd);
10297 tcg_temp_free_i32(fp0);
10298 gen_set_label(l1);
10301 break;
10302 case OPC_RECIP_S:
10304 TCGv_i32 fp0 = tcg_temp_new_i32();
10306 gen_load_fpr32(ctx, fp0, fs);
10307 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10308 gen_store_fpr32(ctx, fp0, fd);
10309 tcg_temp_free_i32(fp0);
10311 break;
10312 case OPC_RSQRT_S:
10314 TCGv_i32 fp0 = tcg_temp_new_i32();
10316 gen_load_fpr32(ctx, fp0, fs);
10317 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10318 gen_store_fpr32(ctx, fp0, fd);
10319 tcg_temp_free_i32(fp0);
10321 break;
10322 case OPC_MADDF_S:
10323 check_insn(ctx, ISA_MIPS32R6);
10325 TCGv_i32 fp0 = tcg_temp_new_i32();
10326 TCGv_i32 fp1 = tcg_temp_new_i32();
10327 TCGv_i32 fp2 = tcg_temp_new_i32();
10328 gen_load_fpr32(ctx, fp0, fs);
10329 gen_load_fpr32(ctx, fp1, ft);
10330 gen_load_fpr32(ctx, fp2, fd);
10331 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10332 gen_store_fpr32(ctx, fp2, fd);
10333 tcg_temp_free_i32(fp2);
10334 tcg_temp_free_i32(fp1);
10335 tcg_temp_free_i32(fp0);
10337 break;
10338 case OPC_MSUBF_S:
10339 check_insn(ctx, ISA_MIPS32R6);
10341 TCGv_i32 fp0 = tcg_temp_new_i32();
10342 TCGv_i32 fp1 = tcg_temp_new_i32();
10343 TCGv_i32 fp2 = tcg_temp_new_i32();
10344 gen_load_fpr32(ctx, fp0, fs);
10345 gen_load_fpr32(ctx, fp1, ft);
10346 gen_load_fpr32(ctx, fp2, fd);
10347 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10348 gen_store_fpr32(ctx, fp2, fd);
10349 tcg_temp_free_i32(fp2);
10350 tcg_temp_free_i32(fp1);
10351 tcg_temp_free_i32(fp0);
10353 break;
10354 case OPC_RINT_S:
10355 check_insn(ctx, ISA_MIPS32R6);
10357 TCGv_i32 fp0 = tcg_temp_new_i32();
10358 gen_load_fpr32(ctx, fp0, fs);
10359 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10360 gen_store_fpr32(ctx, fp0, fd);
10361 tcg_temp_free_i32(fp0);
10363 break;
10364 case OPC_CLASS_S:
10365 check_insn(ctx, ISA_MIPS32R6);
10367 TCGv_i32 fp0 = tcg_temp_new_i32();
10368 gen_load_fpr32(ctx, fp0, fs);
10369 gen_helper_float_class_s(fp0, cpu_env, fp0);
10370 gen_store_fpr32(ctx, fp0, fd);
10371 tcg_temp_free_i32(fp0);
10373 break;
10374 case OPC_MIN_S: /* OPC_RECIP2_S */
10375 if (ctx->insn_flags & ISA_MIPS32R6) {
10376 /* OPC_MIN_S */
10377 TCGv_i32 fp0 = tcg_temp_new_i32();
10378 TCGv_i32 fp1 = tcg_temp_new_i32();
10379 TCGv_i32 fp2 = tcg_temp_new_i32();
10380 gen_load_fpr32(ctx, fp0, fs);
10381 gen_load_fpr32(ctx, fp1, ft);
10382 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10383 gen_store_fpr32(ctx, fp2, fd);
10384 tcg_temp_free_i32(fp2);
10385 tcg_temp_free_i32(fp1);
10386 tcg_temp_free_i32(fp0);
10387 } else {
10388 /* OPC_RECIP2_S */
10389 check_cp1_64bitmode(ctx);
10391 TCGv_i32 fp0 = tcg_temp_new_i32();
10392 TCGv_i32 fp1 = tcg_temp_new_i32();
10394 gen_load_fpr32(ctx, fp0, fs);
10395 gen_load_fpr32(ctx, fp1, ft);
10396 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10397 tcg_temp_free_i32(fp1);
10398 gen_store_fpr32(ctx, fp0, fd);
10399 tcg_temp_free_i32(fp0);
10402 break;
10403 case OPC_MINA_S: /* OPC_RECIP1_S */
10404 if (ctx->insn_flags & ISA_MIPS32R6) {
10405 /* OPC_MINA_S */
10406 TCGv_i32 fp0 = tcg_temp_new_i32();
10407 TCGv_i32 fp1 = tcg_temp_new_i32();
10408 TCGv_i32 fp2 = tcg_temp_new_i32();
10409 gen_load_fpr32(ctx, fp0, fs);
10410 gen_load_fpr32(ctx, fp1, ft);
10411 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10412 gen_store_fpr32(ctx, fp2, fd);
10413 tcg_temp_free_i32(fp2);
10414 tcg_temp_free_i32(fp1);
10415 tcg_temp_free_i32(fp0);
10416 } else {
10417 /* OPC_RECIP1_S */
10418 check_cp1_64bitmode(ctx);
10420 TCGv_i32 fp0 = tcg_temp_new_i32();
10422 gen_load_fpr32(ctx, fp0, fs);
10423 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10424 gen_store_fpr32(ctx, fp0, fd);
10425 tcg_temp_free_i32(fp0);
10428 break;
10429 case OPC_MAX_S: /* OPC_RSQRT1_S */
10430 if (ctx->insn_flags & ISA_MIPS32R6) {
10431 /* OPC_MAX_S */
10432 TCGv_i32 fp0 = tcg_temp_new_i32();
10433 TCGv_i32 fp1 = tcg_temp_new_i32();
10434 gen_load_fpr32(ctx, fp0, fs);
10435 gen_load_fpr32(ctx, fp1, ft);
10436 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10437 gen_store_fpr32(ctx, fp1, fd);
10438 tcg_temp_free_i32(fp1);
10439 tcg_temp_free_i32(fp0);
10440 } else {
10441 /* OPC_RSQRT1_S */
10442 check_cp1_64bitmode(ctx);
10444 TCGv_i32 fp0 = tcg_temp_new_i32();
10446 gen_load_fpr32(ctx, fp0, fs);
10447 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10448 gen_store_fpr32(ctx, fp0, fd);
10449 tcg_temp_free_i32(fp0);
10452 break;
10453 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10454 if (ctx->insn_flags & ISA_MIPS32R6) {
10455 /* OPC_MAXA_S */
10456 TCGv_i32 fp0 = tcg_temp_new_i32();
10457 TCGv_i32 fp1 = tcg_temp_new_i32();
10458 gen_load_fpr32(ctx, fp0, fs);
10459 gen_load_fpr32(ctx, fp1, ft);
10460 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10461 gen_store_fpr32(ctx, fp1, fd);
10462 tcg_temp_free_i32(fp1);
10463 tcg_temp_free_i32(fp0);
10464 } else {
10465 /* OPC_RSQRT2_S */
10466 check_cp1_64bitmode(ctx);
10468 TCGv_i32 fp0 = tcg_temp_new_i32();
10469 TCGv_i32 fp1 = tcg_temp_new_i32();
10471 gen_load_fpr32(ctx, fp0, fs);
10472 gen_load_fpr32(ctx, fp1, ft);
10473 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10474 tcg_temp_free_i32(fp1);
10475 gen_store_fpr32(ctx, fp0, fd);
10476 tcg_temp_free_i32(fp0);
10479 break;
10480 case OPC_CVT_D_S:
10481 check_cp1_registers(ctx, fd);
10483 TCGv_i32 fp32 = tcg_temp_new_i32();
10484 TCGv_i64 fp64 = tcg_temp_new_i64();
10486 gen_load_fpr32(ctx, fp32, fs);
10487 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10488 tcg_temp_free_i32(fp32);
10489 gen_store_fpr64(ctx, fp64, fd);
10490 tcg_temp_free_i64(fp64);
10492 break;
10493 case OPC_CVT_W_S:
10495 TCGv_i32 fp0 = tcg_temp_new_i32();
10497 gen_load_fpr32(ctx, fp0, fs);
10498 if (ctx->nan2008) {
10499 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10500 } else {
10501 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10503 gen_store_fpr32(ctx, fp0, fd);
10504 tcg_temp_free_i32(fp0);
10506 break;
10507 case OPC_CVT_L_S:
10508 check_cp1_64bitmode(ctx);
10510 TCGv_i32 fp32 = tcg_temp_new_i32();
10511 TCGv_i64 fp64 = tcg_temp_new_i64();
10513 gen_load_fpr32(ctx, fp32, fs);
10514 if (ctx->nan2008) {
10515 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10516 } else {
10517 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10519 tcg_temp_free_i32(fp32);
10520 gen_store_fpr64(ctx, fp64, fd);
10521 tcg_temp_free_i64(fp64);
10523 break;
10524 case OPC_CVT_PS_S:
10525 check_ps(ctx);
10527 TCGv_i64 fp64 = tcg_temp_new_i64();
10528 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10529 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10531 gen_load_fpr32(ctx, fp32_0, fs);
10532 gen_load_fpr32(ctx, fp32_1, ft);
10533 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10534 tcg_temp_free_i32(fp32_1);
10535 tcg_temp_free_i32(fp32_0);
10536 gen_store_fpr64(ctx, fp64, fd);
10537 tcg_temp_free_i64(fp64);
10539 break;
10540 case OPC_CMP_F_S:
10541 case OPC_CMP_UN_S:
10542 case OPC_CMP_EQ_S:
10543 case OPC_CMP_UEQ_S:
10544 case OPC_CMP_OLT_S:
10545 case OPC_CMP_ULT_S:
10546 case OPC_CMP_OLE_S:
10547 case OPC_CMP_ULE_S:
10548 case OPC_CMP_SF_S:
10549 case OPC_CMP_NGLE_S:
10550 case OPC_CMP_SEQ_S:
10551 case OPC_CMP_NGL_S:
10552 case OPC_CMP_LT_S:
10553 case OPC_CMP_NGE_S:
10554 case OPC_CMP_LE_S:
10555 case OPC_CMP_NGT_S:
10556 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10557 if (ctx->opcode & (1 << 6)) {
10558 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
10559 } else {
10560 gen_cmp_s(ctx, func-48, ft, fs, cc);
10562 break;
10563 case OPC_ADD_D:
10564 check_cp1_registers(ctx, fs | ft | fd);
10566 TCGv_i64 fp0 = tcg_temp_new_i64();
10567 TCGv_i64 fp1 = tcg_temp_new_i64();
10569 gen_load_fpr64(ctx, fp0, fs);
10570 gen_load_fpr64(ctx, fp1, ft);
10571 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10572 tcg_temp_free_i64(fp1);
10573 gen_store_fpr64(ctx, fp0, fd);
10574 tcg_temp_free_i64(fp0);
10576 break;
10577 case OPC_SUB_D:
10578 check_cp1_registers(ctx, fs | ft | fd);
10580 TCGv_i64 fp0 = tcg_temp_new_i64();
10581 TCGv_i64 fp1 = tcg_temp_new_i64();
10583 gen_load_fpr64(ctx, fp0, fs);
10584 gen_load_fpr64(ctx, fp1, ft);
10585 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10586 tcg_temp_free_i64(fp1);
10587 gen_store_fpr64(ctx, fp0, fd);
10588 tcg_temp_free_i64(fp0);
10590 break;
10591 case OPC_MUL_D:
10592 check_cp1_registers(ctx, fs | ft | fd);
10594 TCGv_i64 fp0 = tcg_temp_new_i64();
10595 TCGv_i64 fp1 = tcg_temp_new_i64();
10597 gen_load_fpr64(ctx, fp0, fs);
10598 gen_load_fpr64(ctx, fp1, ft);
10599 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10600 tcg_temp_free_i64(fp1);
10601 gen_store_fpr64(ctx, fp0, fd);
10602 tcg_temp_free_i64(fp0);
10604 break;
10605 case OPC_DIV_D:
10606 check_cp1_registers(ctx, fs | ft | fd);
10608 TCGv_i64 fp0 = tcg_temp_new_i64();
10609 TCGv_i64 fp1 = tcg_temp_new_i64();
10611 gen_load_fpr64(ctx, fp0, fs);
10612 gen_load_fpr64(ctx, fp1, ft);
10613 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10614 tcg_temp_free_i64(fp1);
10615 gen_store_fpr64(ctx, fp0, fd);
10616 tcg_temp_free_i64(fp0);
10618 break;
10619 case OPC_SQRT_D:
10620 check_cp1_registers(ctx, fs | fd);
10622 TCGv_i64 fp0 = tcg_temp_new_i64();
10624 gen_load_fpr64(ctx, fp0, fs);
10625 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10626 gen_store_fpr64(ctx, fp0, fd);
10627 tcg_temp_free_i64(fp0);
10629 break;
10630 case OPC_ABS_D:
10631 check_cp1_registers(ctx, fs | fd);
10633 TCGv_i64 fp0 = tcg_temp_new_i64();
10635 gen_load_fpr64(ctx, fp0, fs);
10636 if (ctx->abs2008) {
10637 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10638 } else {
10639 gen_helper_float_abs_d(fp0, fp0);
10641 gen_store_fpr64(ctx, fp0, fd);
10642 tcg_temp_free_i64(fp0);
10644 break;
10645 case OPC_MOV_D:
10646 check_cp1_registers(ctx, fs | fd);
10648 TCGv_i64 fp0 = tcg_temp_new_i64();
10650 gen_load_fpr64(ctx, fp0, fs);
10651 gen_store_fpr64(ctx, fp0, fd);
10652 tcg_temp_free_i64(fp0);
10654 break;
10655 case OPC_NEG_D:
10656 check_cp1_registers(ctx, fs | fd);
10658 TCGv_i64 fp0 = tcg_temp_new_i64();
10660 gen_load_fpr64(ctx, fp0, fs);
10661 if (ctx->abs2008) {
10662 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10663 } else {
10664 gen_helper_float_chs_d(fp0, fp0);
10666 gen_store_fpr64(ctx, fp0, fd);
10667 tcg_temp_free_i64(fp0);
10669 break;
10670 case OPC_ROUND_L_D:
10671 check_cp1_64bitmode(ctx);
10673 TCGv_i64 fp0 = tcg_temp_new_i64();
10675 gen_load_fpr64(ctx, fp0, fs);
10676 if (ctx->nan2008) {
10677 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10678 } else {
10679 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10681 gen_store_fpr64(ctx, fp0, fd);
10682 tcg_temp_free_i64(fp0);
10684 break;
10685 case OPC_TRUNC_L_D:
10686 check_cp1_64bitmode(ctx);
10688 TCGv_i64 fp0 = tcg_temp_new_i64();
10690 gen_load_fpr64(ctx, fp0, fs);
10691 if (ctx->nan2008) {
10692 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10693 } else {
10694 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10696 gen_store_fpr64(ctx, fp0, fd);
10697 tcg_temp_free_i64(fp0);
10699 break;
10700 case OPC_CEIL_L_D:
10701 check_cp1_64bitmode(ctx);
10703 TCGv_i64 fp0 = tcg_temp_new_i64();
10705 gen_load_fpr64(ctx, fp0, fs);
10706 if (ctx->nan2008) {
10707 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10708 } else {
10709 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10711 gen_store_fpr64(ctx, fp0, fd);
10712 tcg_temp_free_i64(fp0);
10714 break;
10715 case OPC_FLOOR_L_D:
10716 check_cp1_64bitmode(ctx);
10718 TCGv_i64 fp0 = tcg_temp_new_i64();
10720 gen_load_fpr64(ctx, fp0, fs);
10721 if (ctx->nan2008) {
10722 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10723 } else {
10724 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10726 gen_store_fpr64(ctx, fp0, fd);
10727 tcg_temp_free_i64(fp0);
10729 break;
10730 case OPC_ROUND_W_D:
10731 check_cp1_registers(ctx, fs);
10733 TCGv_i32 fp32 = tcg_temp_new_i32();
10734 TCGv_i64 fp64 = tcg_temp_new_i64();
10736 gen_load_fpr64(ctx, fp64, fs);
10737 if (ctx->nan2008) {
10738 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10739 } else {
10740 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10742 tcg_temp_free_i64(fp64);
10743 gen_store_fpr32(ctx, fp32, fd);
10744 tcg_temp_free_i32(fp32);
10746 break;
10747 case OPC_TRUNC_W_D:
10748 check_cp1_registers(ctx, fs);
10750 TCGv_i32 fp32 = tcg_temp_new_i32();
10751 TCGv_i64 fp64 = tcg_temp_new_i64();
10753 gen_load_fpr64(ctx, fp64, fs);
10754 if (ctx->nan2008) {
10755 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10756 } else {
10757 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10759 tcg_temp_free_i64(fp64);
10760 gen_store_fpr32(ctx, fp32, fd);
10761 tcg_temp_free_i32(fp32);
10763 break;
10764 case OPC_CEIL_W_D:
10765 check_cp1_registers(ctx, fs);
10767 TCGv_i32 fp32 = tcg_temp_new_i32();
10768 TCGv_i64 fp64 = tcg_temp_new_i64();
10770 gen_load_fpr64(ctx, fp64, fs);
10771 if (ctx->nan2008) {
10772 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10773 } else {
10774 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10776 tcg_temp_free_i64(fp64);
10777 gen_store_fpr32(ctx, fp32, fd);
10778 tcg_temp_free_i32(fp32);
10780 break;
10781 case OPC_FLOOR_W_D:
10782 check_cp1_registers(ctx, fs);
10784 TCGv_i32 fp32 = tcg_temp_new_i32();
10785 TCGv_i64 fp64 = tcg_temp_new_i64();
10787 gen_load_fpr64(ctx, fp64, fs);
10788 if (ctx->nan2008) {
10789 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10790 } else {
10791 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10793 tcg_temp_free_i64(fp64);
10794 gen_store_fpr32(ctx, fp32, fd);
10795 tcg_temp_free_i32(fp32);
10797 break;
10798 case OPC_SEL_D:
10799 check_insn(ctx, ISA_MIPS32R6);
10800 gen_sel_d(ctx, op1, fd, ft, fs);
10801 break;
10802 case OPC_SELEQZ_D:
10803 check_insn(ctx, ISA_MIPS32R6);
10804 gen_sel_d(ctx, op1, fd, ft, fs);
10805 break;
10806 case OPC_SELNEZ_D:
10807 check_insn(ctx, ISA_MIPS32R6);
10808 gen_sel_d(ctx, op1, fd, ft, fs);
10809 break;
10810 case OPC_MOVCF_D:
10811 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10812 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10813 break;
10814 case OPC_MOVZ_D:
10815 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10817 TCGLabel *l1 = gen_new_label();
10818 TCGv_i64 fp0;
10820 if (ft != 0) {
10821 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10823 fp0 = tcg_temp_new_i64();
10824 gen_load_fpr64(ctx, fp0, fs);
10825 gen_store_fpr64(ctx, fp0, fd);
10826 tcg_temp_free_i64(fp0);
10827 gen_set_label(l1);
10829 break;
10830 case OPC_MOVN_D:
10831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10833 TCGLabel *l1 = gen_new_label();
10834 TCGv_i64 fp0;
10836 if (ft != 0) {
10837 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10838 fp0 = tcg_temp_new_i64();
10839 gen_load_fpr64(ctx, fp0, fs);
10840 gen_store_fpr64(ctx, fp0, fd);
10841 tcg_temp_free_i64(fp0);
10842 gen_set_label(l1);
10845 break;
10846 case OPC_RECIP_D:
10847 check_cp1_registers(ctx, fs | fd);
10849 TCGv_i64 fp0 = tcg_temp_new_i64();
10851 gen_load_fpr64(ctx, fp0, fs);
10852 gen_helper_float_recip_d(fp0, cpu_env, fp0);
10853 gen_store_fpr64(ctx, fp0, fd);
10854 tcg_temp_free_i64(fp0);
10856 break;
10857 case OPC_RSQRT_D:
10858 check_cp1_registers(ctx, fs | fd);
10860 TCGv_i64 fp0 = tcg_temp_new_i64();
10862 gen_load_fpr64(ctx, fp0, fs);
10863 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
10864 gen_store_fpr64(ctx, fp0, fd);
10865 tcg_temp_free_i64(fp0);
10867 break;
10868 case OPC_MADDF_D:
10869 check_insn(ctx, ISA_MIPS32R6);
10871 TCGv_i64 fp0 = tcg_temp_new_i64();
10872 TCGv_i64 fp1 = tcg_temp_new_i64();
10873 TCGv_i64 fp2 = tcg_temp_new_i64();
10874 gen_load_fpr64(ctx, fp0, fs);
10875 gen_load_fpr64(ctx, fp1, ft);
10876 gen_load_fpr64(ctx, fp2, fd);
10877 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
10878 gen_store_fpr64(ctx, fp2, fd);
10879 tcg_temp_free_i64(fp2);
10880 tcg_temp_free_i64(fp1);
10881 tcg_temp_free_i64(fp0);
10883 break;
10884 case OPC_MSUBF_D:
10885 check_insn(ctx, ISA_MIPS32R6);
10887 TCGv_i64 fp0 = tcg_temp_new_i64();
10888 TCGv_i64 fp1 = tcg_temp_new_i64();
10889 TCGv_i64 fp2 = tcg_temp_new_i64();
10890 gen_load_fpr64(ctx, fp0, fs);
10891 gen_load_fpr64(ctx, fp1, ft);
10892 gen_load_fpr64(ctx, fp2, fd);
10893 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
10894 gen_store_fpr64(ctx, fp2, fd);
10895 tcg_temp_free_i64(fp2);
10896 tcg_temp_free_i64(fp1);
10897 tcg_temp_free_i64(fp0);
10899 break;
10900 case OPC_RINT_D:
10901 check_insn(ctx, ISA_MIPS32R6);
10903 TCGv_i64 fp0 = tcg_temp_new_i64();
10904 gen_load_fpr64(ctx, fp0, fs);
10905 gen_helper_float_rint_d(fp0, cpu_env, fp0);
10906 gen_store_fpr64(ctx, fp0, fd);
10907 tcg_temp_free_i64(fp0);
10909 break;
10910 case OPC_CLASS_D:
10911 check_insn(ctx, ISA_MIPS32R6);
10913 TCGv_i64 fp0 = tcg_temp_new_i64();
10914 gen_load_fpr64(ctx, fp0, fs);
10915 gen_helper_float_class_d(fp0, cpu_env, fp0);
10916 gen_store_fpr64(ctx, fp0, fd);
10917 tcg_temp_free_i64(fp0);
10919 break;
10920 case OPC_MIN_D: /* OPC_RECIP2_D */
10921 if (ctx->insn_flags & ISA_MIPS32R6) {
10922 /* OPC_MIN_D */
10923 TCGv_i64 fp0 = tcg_temp_new_i64();
10924 TCGv_i64 fp1 = tcg_temp_new_i64();
10925 gen_load_fpr64(ctx, fp0, fs);
10926 gen_load_fpr64(ctx, fp1, ft);
10927 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
10928 gen_store_fpr64(ctx, fp1, fd);
10929 tcg_temp_free_i64(fp1);
10930 tcg_temp_free_i64(fp0);
10931 } else {
10932 /* OPC_RECIP2_D */
10933 check_cp1_64bitmode(ctx);
10935 TCGv_i64 fp0 = tcg_temp_new_i64();
10936 TCGv_i64 fp1 = tcg_temp_new_i64();
10938 gen_load_fpr64(ctx, fp0, fs);
10939 gen_load_fpr64(ctx, fp1, ft);
10940 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
10941 tcg_temp_free_i64(fp1);
10942 gen_store_fpr64(ctx, fp0, fd);
10943 tcg_temp_free_i64(fp0);
10946 break;
10947 case OPC_MINA_D: /* OPC_RECIP1_D */
10948 if (ctx->insn_flags & ISA_MIPS32R6) {
10949 /* OPC_MINA_D */
10950 TCGv_i64 fp0 = tcg_temp_new_i64();
10951 TCGv_i64 fp1 = tcg_temp_new_i64();
10952 gen_load_fpr64(ctx, fp0, fs);
10953 gen_load_fpr64(ctx, fp1, ft);
10954 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
10955 gen_store_fpr64(ctx, fp1, fd);
10956 tcg_temp_free_i64(fp1);
10957 tcg_temp_free_i64(fp0);
10958 } else {
10959 /* OPC_RECIP1_D */
10960 check_cp1_64bitmode(ctx);
10962 TCGv_i64 fp0 = tcg_temp_new_i64();
10964 gen_load_fpr64(ctx, fp0, fs);
10965 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
10966 gen_store_fpr64(ctx, fp0, fd);
10967 tcg_temp_free_i64(fp0);
10970 break;
10971 case OPC_MAX_D: /* OPC_RSQRT1_D */
10972 if (ctx->insn_flags & ISA_MIPS32R6) {
10973 /* OPC_MAX_D */
10974 TCGv_i64 fp0 = tcg_temp_new_i64();
10975 TCGv_i64 fp1 = tcg_temp_new_i64();
10976 gen_load_fpr64(ctx, fp0, fs);
10977 gen_load_fpr64(ctx, fp1, ft);
10978 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
10979 gen_store_fpr64(ctx, fp1, fd);
10980 tcg_temp_free_i64(fp1);
10981 tcg_temp_free_i64(fp0);
10982 } else {
10983 /* OPC_RSQRT1_D */
10984 check_cp1_64bitmode(ctx);
10986 TCGv_i64 fp0 = tcg_temp_new_i64();
10988 gen_load_fpr64(ctx, fp0, fs);
10989 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
10990 gen_store_fpr64(ctx, fp0, fd);
10991 tcg_temp_free_i64(fp0);
10994 break;
10995 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10996 if (ctx->insn_flags & ISA_MIPS32R6) {
10997 /* OPC_MAXA_D */
10998 TCGv_i64 fp0 = tcg_temp_new_i64();
10999 TCGv_i64 fp1 = tcg_temp_new_i64();
11000 gen_load_fpr64(ctx, fp0, fs);
11001 gen_load_fpr64(ctx, fp1, ft);
11002 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11003 gen_store_fpr64(ctx, fp1, fd);
11004 tcg_temp_free_i64(fp1);
11005 tcg_temp_free_i64(fp0);
11006 } else {
11007 /* OPC_RSQRT2_D */
11008 check_cp1_64bitmode(ctx);
11010 TCGv_i64 fp0 = tcg_temp_new_i64();
11011 TCGv_i64 fp1 = tcg_temp_new_i64();
11013 gen_load_fpr64(ctx, fp0, fs);
11014 gen_load_fpr64(ctx, fp1, ft);
11015 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11016 tcg_temp_free_i64(fp1);
11017 gen_store_fpr64(ctx, fp0, fd);
11018 tcg_temp_free_i64(fp0);
11021 break;
11022 case OPC_CMP_F_D:
11023 case OPC_CMP_UN_D:
11024 case OPC_CMP_EQ_D:
11025 case OPC_CMP_UEQ_D:
11026 case OPC_CMP_OLT_D:
11027 case OPC_CMP_ULT_D:
11028 case OPC_CMP_OLE_D:
11029 case OPC_CMP_ULE_D:
11030 case OPC_CMP_SF_D:
11031 case OPC_CMP_NGLE_D:
11032 case OPC_CMP_SEQ_D:
11033 case OPC_CMP_NGL_D:
11034 case OPC_CMP_LT_D:
11035 case OPC_CMP_NGE_D:
11036 case OPC_CMP_LE_D:
11037 case OPC_CMP_NGT_D:
11038 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11039 if (ctx->opcode & (1 << 6)) {
11040 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11041 } else {
11042 gen_cmp_d(ctx, func-48, ft, fs, cc);
11044 break;
11045 case OPC_CVT_S_D:
11046 check_cp1_registers(ctx, fs);
11048 TCGv_i32 fp32 = tcg_temp_new_i32();
11049 TCGv_i64 fp64 = tcg_temp_new_i64();
11051 gen_load_fpr64(ctx, fp64, fs);
11052 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11053 tcg_temp_free_i64(fp64);
11054 gen_store_fpr32(ctx, fp32, fd);
11055 tcg_temp_free_i32(fp32);
11057 break;
11058 case OPC_CVT_W_D:
11059 check_cp1_registers(ctx, fs);
11061 TCGv_i32 fp32 = tcg_temp_new_i32();
11062 TCGv_i64 fp64 = tcg_temp_new_i64();
11064 gen_load_fpr64(ctx, fp64, fs);
11065 if (ctx->nan2008) {
11066 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11067 } else {
11068 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11070 tcg_temp_free_i64(fp64);
11071 gen_store_fpr32(ctx, fp32, fd);
11072 tcg_temp_free_i32(fp32);
11074 break;
11075 case OPC_CVT_L_D:
11076 check_cp1_64bitmode(ctx);
11078 TCGv_i64 fp0 = tcg_temp_new_i64();
11080 gen_load_fpr64(ctx, fp0, fs);
11081 if (ctx->nan2008) {
11082 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11083 } else {
11084 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11086 gen_store_fpr64(ctx, fp0, fd);
11087 tcg_temp_free_i64(fp0);
11089 break;
11090 case OPC_CVT_S_W:
11092 TCGv_i32 fp0 = tcg_temp_new_i32();
11094 gen_load_fpr32(ctx, fp0, fs);
11095 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11096 gen_store_fpr32(ctx, fp0, fd);
11097 tcg_temp_free_i32(fp0);
11099 break;
11100 case OPC_CVT_D_W:
11101 check_cp1_registers(ctx, fd);
11103 TCGv_i32 fp32 = tcg_temp_new_i32();
11104 TCGv_i64 fp64 = tcg_temp_new_i64();
11106 gen_load_fpr32(ctx, fp32, fs);
11107 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11108 tcg_temp_free_i32(fp32);
11109 gen_store_fpr64(ctx, fp64, fd);
11110 tcg_temp_free_i64(fp64);
11112 break;
11113 case OPC_CVT_S_L:
11114 check_cp1_64bitmode(ctx);
11116 TCGv_i32 fp32 = tcg_temp_new_i32();
11117 TCGv_i64 fp64 = tcg_temp_new_i64();
11119 gen_load_fpr64(ctx, fp64, fs);
11120 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11121 tcg_temp_free_i64(fp64);
11122 gen_store_fpr32(ctx, fp32, fd);
11123 tcg_temp_free_i32(fp32);
11125 break;
11126 case OPC_CVT_D_L:
11127 check_cp1_64bitmode(ctx);
11129 TCGv_i64 fp0 = tcg_temp_new_i64();
11131 gen_load_fpr64(ctx, fp0, fs);
11132 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11133 gen_store_fpr64(ctx, fp0, fd);
11134 tcg_temp_free_i64(fp0);
11136 break;
11137 case OPC_CVT_PS_PW:
11138 check_ps(ctx);
11140 TCGv_i64 fp0 = tcg_temp_new_i64();
11142 gen_load_fpr64(ctx, fp0, fs);
11143 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11144 gen_store_fpr64(ctx, fp0, fd);
11145 tcg_temp_free_i64(fp0);
11147 break;
11148 case OPC_ADD_PS:
11149 check_ps(ctx);
11151 TCGv_i64 fp0 = tcg_temp_new_i64();
11152 TCGv_i64 fp1 = tcg_temp_new_i64();
11154 gen_load_fpr64(ctx, fp0, fs);
11155 gen_load_fpr64(ctx, fp1, ft);
11156 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11157 tcg_temp_free_i64(fp1);
11158 gen_store_fpr64(ctx, fp0, fd);
11159 tcg_temp_free_i64(fp0);
11161 break;
11162 case OPC_SUB_PS:
11163 check_ps(ctx);
11165 TCGv_i64 fp0 = tcg_temp_new_i64();
11166 TCGv_i64 fp1 = tcg_temp_new_i64();
11168 gen_load_fpr64(ctx, fp0, fs);
11169 gen_load_fpr64(ctx, fp1, ft);
11170 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11171 tcg_temp_free_i64(fp1);
11172 gen_store_fpr64(ctx, fp0, fd);
11173 tcg_temp_free_i64(fp0);
11175 break;
11176 case OPC_MUL_PS:
11177 check_ps(ctx);
11179 TCGv_i64 fp0 = tcg_temp_new_i64();
11180 TCGv_i64 fp1 = tcg_temp_new_i64();
11182 gen_load_fpr64(ctx, fp0, fs);
11183 gen_load_fpr64(ctx, fp1, ft);
11184 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11185 tcg_temp_free_i64(fp1);
11186 gen_store_fpr64(ctx, fp0, fd);
11187 tcg_temp_free_i64(fp0);
11189 break;
11190 case OPC_ABS_PS:
11191 check_ps(ctx);
11193 TCGv_i64 fp0 = tcg_temp_new_i64();
11195 gen_load_fpr64(ctx, fp0, fs);
11196 gen_helper_float_abs_ps(fp0, fp0);
11197 gen_store_fpr64(ctx, fp0, fd);
11198 tcg_temp_free_i64(fp0);
11200 break;
11201 case OPC_MOV_PS:
11202 check_ps(ctx);
11204 TCGv_i64 fp0 = tcg_temp_new_i64();
11206 gen_load_fpr64(ctx, fp0, fs);
11207 gen_store_fpr64(ctx, fp0, fd);
11208 tcg_temp_free_i64(fp0);
11210 break;
11211 case OPC_NEG_PS:
11212 check_ps(ctx);
11214 TCGv_i64 fp0 = tcg_temp_new_i64();
11216 gen_load_fpr64(ctx, fp0, fs);
11217 gen_helper_float_chs_ps(fp0, fp0);
11218 gen_store_fpr64(ctx, fp0, fd);
11219 tcg_temp_free_i64(fp0);
11221 break;
11222 case OPC_MOVCF_PS:
11223 check_ps(ctx);
11224 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11225 break;
11226 case OPC_MOVZ_PS:
11227 check_ps(ctx);
11229 TCGLabel *l1 = gen_new_label();
11230 TCGv_i64 fp0;
11232 if (ft != 0)
11233 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11234 fp0 = tcg_temp_new_i64();
11235 gen_load_fpr64(ctx, fp0, fs);
11236 gen_store_fpr64(ctx, fp0, fd);
11237 tcg_temp_free_i64(fp0);
11238 gen_set_label(l1);
11240 break;
11241 case OPC_MOVN_PS:
11242 check_ps(ctx);
11244 TCGLabel *l1 = gen_new_label();
11245 TCGv_i64 fp0;
11247 if (ft != 0) {
11248 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11249 fp0 = tcg_temp_new_i64();
11250 gen_load_fpr64(ctx, fp0, fs);
11251 gen_store_fpr64(ctx, fp0, fd);
11252 tcg_temp_free_i64(fp0);
11253 gen_set_label(l1);
11256 break;
11257 case OPC_ADDR_PS:
11258 check_ps(ctx);
11260 TCGv_i64 fp0 = tcg_temp_new_i64();
11261 TCGv_i64 fp1 = tcg_temp_new_i64();
11263 gen_load_fpr64(ctx, fp0, ft);
11264 gen_load_fpr64(ctx, fp1, fs);
11265 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11266 tcg_temp_free_i64(fp1);
11267 gen_store_fpr64(ctx, fp0, fd);
11268 tcg_temp_free_i64(fp0);
11270 break;
11271 case OPC_MULR_PS:
11272 check_ps(ctx);
11274 TCGv_i64 fp0 = tcg_temp_new_i64();
11275 TCGv_i64 fp1 = tcg_temp_new_i64();
11277 gen_load_fpr64(ctx, fp0, ft);
11278 gen_load_fpr64(ctx, fp1, fs);
11279 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11280 tcg_temp_free_i64(fp1);
11281 gen_store_fpr64(ctx, fp0, fd);
11282 tcg_temp_free_i64(fp0);
11284 break;
11285 case OPC_RECIP2_PS:
11286 check_ps(ctx);
11288 TCGv_i64 fp0 = tcg_temp_new_i64();
11289 TCGv_i64 fp1 = tcg_temp_new_i64();
11291 gen_load_fpr64(ctx, fp0, fs);
11292 gen_load_fpr64(ctx, fp1, ft);
11293 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11294 tcg_temp_free_i64(fp1);
11295 gen_store_fpr64(ctx, fp0, fd);
11296 tcg_temp_free_i64(fp0);
11298 break;
11299 case OPC_RECIP1_PS:
11300 check_ps(ctx);
11302 TCGv_i64 fp0 = tcg_temp_new_i64();
11304 gen_load_fpr64(ctx, fp0, fs);
11305 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11306 gen_store_fpr64(ctx, fp0, fd);
11307 tcg_temp_free_i64(fp0);
11309 break;
11310 case OPC_RSQRT1_PS:
11311 check_ps(ctx);
11313 TCGv_i64 fp0 = tcg_temp_new_i64();
11315 gen_load_fpr64(ctx, fp0, fs);
11316 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11317 gen_store_fpr64(ctx, fp0, fd);
11318 tcg_temp_free_i64(fp0);
11320 break;
11321 case OPC_RSQRT2_PS:
11322 check_ps(ctx);
11324 TCGv_i64 fp0 = tcg_temp_new_i64();
11325 TCGv_i64 fp1 = tcg_temp_new_i64();
11327 gen_load_fpr64(ctx, fp0, fs);
11328 gen_load_fpr64(ctx, fp1, ft);
11329 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11330 tcg_temp_free_i64(fp1);
11331 gen_store_fpr64(ctx, fp0, fd);
11332 tcg_temp_free_i64(fp0);
11334 break;
11335 case OPC_CVT_S_PU:
11336 check_cp1_64bitmode(ctx);
11338 TCGv_i32 fp0 = tcg_temp_new_i32();
11340 gen_load_fpr32h(ctx, fp0, fs);
11341 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11342 gen_store_fpr32(ctx, fp0, fd);
11343 tcg_temp_free_i32(fp0);
11345 break;
11346 case OPC_CVT_PW_PS:
11347 check_ps(ctx);
11349 TCGv_i64 fp0 = tcg_temp_new_i64();
11351 gen_load_fpr64(ctx, fp0, fs);
11352 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11353 gen_store_fpr64(ctx, fp0, fd);
11354 tcg_temp_free_i64(fp0);
11356 break;
11357 case OPC_CVT_S_PL:
11358 check_cp1_64bitmode(ctx);
11360 TCGv_i32 fp0 = tcg_temp_new_i32();
11362 gen_load_fpr32(ctx, fp0, fs);
11363 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11364 gen_store_fpr32(ctx, fp0, fd);
11365 tcg_temp_free_i32(fp0);
11367 break;
11368 case OPC_PLL_PS:
11369 check_ps(ctx);
11371 TCGv_i32 fp0 = tcg_temp_new_i32();
11372 TCGv_i32 fp1 = tcg_temp_new_i32();
11374 gen_load_fpr32(ctx, fp0, fs);
11375 gen_load_fpr32(ctx, fp1, ft);
11376 gen_store_fpr32h(ctx, fp0, fd);
11377 gen_store_fpr32(ctx, fp1, fd);
11378 tcg_temp_free_i32(fp0);
11379 tcg_temp_free_i32(fp1);
11381 break;
11382 case OPC_PLU_PS:
11383 check_ps(ctx);
11385 TCGv_i32 fp0 = tcg_temp_new_i32();
11386 TCGv_i32 fp1 = tcg_temp_new_i32();
11388 gen_load_fpr32(ctx, fp0, fs);
11389 gen_load_fpr32h(ctx, fp1, ft);
11390 gen_store_fpr32(ctx, fp1, fd);
11391 gen_store_fpr32h(ctx, fp0, fd);
11392 tcg_temp_free_i32(fp0);
11393 tcg_temp_free_i32(fp1);
11395 break;
11396 case OPC_PUL_PS:
11397 check_ps(ctx);
11399 TCGv_i32 fp0 = tcg_temp_new_i32();
11400 TCGv_i32 fp1 = tcg_temp_new_i32();
11402 gen_load_fpr32h(ctx, fp0, fs);
11403 gen_load_fpr32(ctx, fp1, ft);
11404 gen_store_fpr32(ctx, fp1, fd);
11405 gen_store_fpr32h(ctx, fp0, fd);
11406 tcg_temp_free_i32(fp0);
11407 tcg_temp_free_i32(fp1);
11409 break;
11410 case OPC_PUU_PS:
11411 check_ps(ctx);
11413 TCGv_i32 fp0 = tcg_temp_new_i32();
11414 TCGv_i32 fp1 = tcg_temp_new_i32();
11416 gen_load_fpr32h(ctx, fp0, fs);
11417 gen_load_fpr32h(ctx, fp1, ft);
11418 gen_store_fpr32(ctx, fp1, fd);
11419 gen_store_fpr32h(ctx, fp0, fd);
11420 tcg_temp_free_i32(fp0);
11421 tcg_temp_free_i32(fp1);
11423 break;
11424 case OPC_CMP_F_PS:
11425 case OPC_CMP_UN_PS:
11426 case OPC_CMP_EQ_PS:
11427 case OPC_CMP_UEQ_PS:
11428 case OPC_CMP_OLT_PS:
11429 case OPC_CMP_ULT_PS:
11430 case OPC_CMP_OLE_PS:
11431 case OPC_CMP_ULE_PS:
11432 case OPC_CMP_SF_PS:
11433 case OPC_CMP_NGLE_PS:
11434 case OPC_CMP_SEQ_PS:
11435 case OPC_CMP_NGL_PS:
11436 case OPC_CMP_LT_PS:
11437 case OPC_CMP_NGE_PS:
11438 case OPC_CMP_LE_PS:
11439 case OPC_CMP_NGT_PS:
11440 if (ctx->opcode & (1 << 6)) {
11441 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
11442 } else {
11443 gen_cmp_ps(ctx, func-48, ft, fs, cc);
11445 break;
11446 default:
11447 MIPS_INVAL("farith");
11448 generate_exception_end(ctx, EXCP_RI);
11449 return;
11453 /* Coprocessor 3 (FPU) */
11454 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
11455 int fd, int fs, int base, int index)
11457 TCGv t0 = tcg_temp_new();
11459 if (base == 0) {
11460 gen_load_gpr(t0, index);
11461 } else if (index == 0) {
11462 gen_load_gpr(t0, base);
11463 } else {
11464 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11466 /* Don't do NOP if destination is zero: we must perform the actual
11467 memory access. */
11468 switch (opc) {
11469 case OPC_LWXC1:
11470 check_cop1x(ctx);
11472 TCGv_i32 fp0 = tcg_temp_new_i32();
11474 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11475 tcg_gen_trunc_tl_i32(fp0, t0);
11476 gen_store_fpr32(ctx, fp0, fd);
11477 tcg_temp_free_i32(fp0);
11479 break;
11480 case OPC_LDXC1:
11481 check_cop1x(ctx);
11482 check_cp1_registers(ctx, fd);
11484 TCGv_i64 fp0 = tcg_temp_new_i64();
11485 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11486 gen_store_fpr64(ctx, fp0, fd);
11487 tcg_temp_free_i64(fp0);
11489 break;
11490 case OPC_LUXC1:
11491 check_cp1_64bitmode(ctx);
11492 tcg_gen_andi_tl(t0, t0, ~0x7);
11494 TCGv_i64 fp0 = tcg_temp_new_i64();
11496 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11497 gen_store_fpr64(ctx, fp0, fd);
11498 tcg_temp_free_i64(fp0);
11500 break;
11501 case OPC_SWXC1:
11502 check_cop1x(ctx);
11504 TCGv_i32 fp0 = tcg_temp_new_i32();
11505 gen_load_fpr32(ctx, fp0, fs);
11506 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11507 tcg_temp_free_i32(fp0);
11509 break;
11510 case OPC_SDXC1:
11511 check_cop1x(ctx);
11512 check_cp1_registers(ctx, fs);
11514 TCGv_i64 fp0 = tcg_temp_new_i64();
11515 gen_load_fpr64(ctx, fp0, fs);
11516 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11517 tcg_temp_free_i64(fp0);
11519 break;
11520 case OPC_SUXC1:
11521 check_cp1_64bitmode(ctx);
11522 tcg_gen_andi_tl(t0, t0, ~0x7);
11524 TCGv_i64 fp0 = tcg_temp_new_i64();
11525 gen_load_fpr64(ctx, fp0, fs);
11526 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11527 tcg_temp_free_i64(fp0);
11529 break;
11531 tcg_temp_free(t0);
11534 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
11535 int fd, int fr, int fs, int ft)
11537 switch (opc) {
11538 case OPC_ALNV_PS:
11539 check_ps(ctx);
11541 TCGv t0 = tcg_temp_local_new();
11542 TCGv_i32 fp = tcg_temp_new_i32();
11543 TCGv_i32 fph = tcg_temp_new_i32();
11544 TCGLabel *l1 = gen_new_label();
11545 TCGLabel *l2 = gen_new_label();
11547 gen_load_gpr(t0, fr);
11548 tcg_gen_andi_tl(t0, t0, 0x7);
11550 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11551 gen_load_fpr32(ctx, fp, fs);
11552 gen_load_fpr32h(ctx, fph, fs);
11553 gen_store_fpr32(ctx, fp, fd);
11554 gen_store_fpr32h(ctx, fph, fd);
11555 tcg_gen_br(l2);
11556 gen_set_label(l1);
11557 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11558 tcg_temp_free(t0);
11559 #ifdef TARGET_WORDS_BIGENDIAN
11560 gen_load_fpr32(ctx, fp, fs);
11561 gen_load_fpr32h(ctx, fph, ft);
11562 gen_store_fpr32h(ctx, fp, fd);
11563 gen_store_fpr32(ctx, fph, fd);
11564 #else
11565 gen_load_fpr32h(ctx, fph, fs);
11566 gen_load_fpr32(ctx, fp, ft);
11567 gen_store_fpr32(ctx, fph, fd);
11568 gen_store_fpr32h(ctx, fp, fd);
11569 #endif
11570 gen_set_label(l2);
11571 tcg_temp_free_i32(fp);
11572 tcg_temp_free_i32(fph);
11574 break;
11575 case OPC_MADD_S:
11576 check_cop1x(ctx);
11578 TCGv_i32 fp0 = tcg_temp_new_i32();
11579 TCGv_i32 fp1 = tcg_temp_new_i32();
11580 TCGv_i32 fp2 = tcg_temp_new_i32();
11582 gen_load_fpr32(ctx, fp0, fs);
11583 gen_load_fpr32(ctx, fp1, ft);
11584 gen_load_fpr32(ctx, fp2, fr);
11585 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11586 tcg_temp_free_i32(fp0);
11587 tcg_temp_free_i32(fp1);
11588 gen_store_fpr32(ctx, fp2, fd);
11589 tcg_temp_free_i32(fp2);
11591 break;
11592 case OPC_MADD_D:
11593 check_cop1x(ctx);
11594 check_cp1_registers(ctx, fd | fs | ft | fr);
11596 TCGv_i64 fp0 = tcg_temp_new_i64();
11597 TCGv_i64 fp1 = tcg_temp_new_i64();
11598 TCGv_i64 fp2 = tcg_temp_new_i64();
11600 gen_load_fpr64(ctx, fp0, fs);
11601 gen_load_fpr64(ctx, fp1, ft);
11602 gen_load_fpr64(ctx, fp2, fr);
11603 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11604 tcg_temp_free_i64(fp0);
11605 tcg_temp_free_i64(fp1);
11606 gen_store_fpr64(ctx, fp2, fd);
11607 tcg_temp_free_i64(fp2);
11609 break;
11610 case OPC_MADD_PS:
11611 check_ps(ctx);
11613 TCGv_i64 fp0 = tcg_temp_new_i64();
11614 TCGv_i64 fp1 = tcg_temp_new_i64();
11615 TCGv_i64 fp2 = tcg_temp_new_i64();
11617 gen_load_fpr64(ctx, fp0, fs);
11618 gen_load_fpr64(ctx, fp1, ft);
11619 gen_load_fpr64(ctx, fp2, fr);
11620 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11621 tcg_temp_free_i64(fp0);
11622 tcg_temp_free_i64(fp1);
11623 gen_store_fpr64(ctx, fp2, fd);
11624 tcg_temp_free_i64(fp2);
11626 break;
11627 case OPC_MSUB_S:
11628 check_cop1x(ctx);
11630 TCGv_i32 fp0 = tcg_temp_new_i32();
11631 TCGv_i32 fp1 = tcg_temp_new_i32();
11632 TCGv_i32 fp2 = tcg_temp_new_i32();
11634 gen_load_fpr32(ctx, fp0, fs);
11635 gen_load_fpr32(ctx, fp1, ft);
11636 gen_load_fpr32(ctx, fp2, fr);
11637 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11638 tcg_temp_free_i32(fp0);
11639 tcg_temp_free_i32(fp1);
11640 gen_store_fpr32(ctx, fp2, fd);
11641 tcg_temp_free_i32(fp2);
11643 break;
11644 case OPC_MSUB_D:
11645 check_cop1x(ctx);
11646 check_cp1_registers(ctx, fd | fs | ft | fr);
11648 TCGv_i64 fp0 = tcg_temp_new_i64();
11649 TCGv_i64 fp1 = tcg_temp_new_i64();
11650 TCGv_i64 fp2 = tcg_temp_new_i64();
11652 gen_load_fpr64(ctx, fp0, fs);
11653 gen_load_fpr64(ctx, fp1, ft);
11654 gen_load_fpr64(ctx, fp2, fr);
11655 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11656 tcg_temp_free_i64(fp0);
11657 tcg_temp_free_i64(fp1);
11658 gen_store_fpr64(ctx, fp2, fd);
11659 tcg_temp_free_i64(fp2);
11661 break;
11662 case OPC_MSUB_PS:
11663 check_ps(ctx);
11665 TCGv_i64 fp0 = tcg_temp_new_i64();
11666 TCGv_i64 fp1 = tcg_temp_new_i64();
11667 TCGv_i64 fp2 = tcg_temp_new_i64();
11669 gen_load_fpr64(ctx, fp0, fs);
11670 gen_load_fpr64(ctx, fp1, ft);
11671 gen_load_fpr64(ctx, fp2, fr);
11672 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11673 tcg_temp_free_i64(fp0);
11674 tcg_temp_free_i64(fp1);
11675 gen_store_fpr64(ctx, fp2, fd);
11676 tcg_temp_free_i64(fp2);
11678 break;
11679 case OPC_NMADD_S:
11680 check_cop1x(ctx);
11682 TCGv_i32 fp0 = tcg_temp_new_i32();
11683 TCGv_i32 fp1 = tcg_temp_new_i32();
11684 TCGv_i32 fp2 = tcg_temp_new_i32();
11686 gen_load_fpr32(ctx, fp0, fs);
11687 gen_load_fpr32(ctx, fp1, ft);
11688 gen_load_fpr32(ctx, fp2, fr);
11689 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11690 tcg_temp_free_i32(fp0);
11691 tcg_temp_free_i32(fp1);
11692 gen_store_fpr32(ctx, fp2, fd);
11693 tcg_temp_free_i32(fp2);
11695 break;
11696 case OPC_NMADD_D:
11697 check_cop1x(ctx);
11698 check_cp1_registers(ctx, fd | fs | ft | fr);
11700 TCGv_i64 fp0 = tcg_temp_new_i64();
11701 TCGv_i64 fp1 = tcg_temp_new_i64();
11702 TCGv_i64 fp2 = tcg_temp_new_i64();
11704 gen_load_fpr64(ctx, fp0, fs);
11705 gen_load_fpr64(ctx, fp1, ft);
11706 gen_load_fpr64(ctx, fp2, fr);
11707 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11708 tcg_temp_free_i64(fp0);
11709 tcg_temp_free_i64(fp1);
11710 gen_store_fpr64(ctx, fp2, fd);
11711 tcg_temp_free_i64(fp2);
11713 break;
11714 case OPC_NMADD_PS:
11715 check_ps(ctx);
11717 TCGv_i64 fp0 = tcg_temp_new_i64();
11718 TCGv_i64 fp1 = tcg_temp_new_i64();
11719 TCGv_i64 fp2 = tcg_temp_new_i64();
11721 gen_load_fpr64(ctx, fp0, fs);
11722 gen_load_fpr64(ctx, fp1, ft);
11723 gen_load_fpr64(ctx, fp2, fr);
11724 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11725 tcg_temp_free_i64(fp0);
11726 tcg_temp_free_i64(fp1);
11727 gen_store_fpr64(ctx, fp2, fd);
11728 tcg_temp_free_i64(fp2);
11730 break;
11731 case OPC_NMSUB_S:
11732 check_cop1x(ctx);
11734 TCGv_i32 fp0 = tcg_temp_new_i32();
11735 TCGv_i32 fp1 = tcg_temp_new_i32();
11736 TCGv_i32 fp2 = tcg_temp_new_i32();
11738 gen_load_fpr32(ctx, fp0, fs);
11739 gen_load_fpr32(ctx, fp1, ft);
11740 gen_load_fpr32(ctx, fp2, fr);
11741 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11742 tcg_temp_free_i32(fp0);
11743 tcg_temp_free_i32(fp1);
11744 gen_store_fpr32(ctx, fp2, fd);
11745 tcg_temp_free_i32(fp2);
11747 break;
11748 case OPC_NMSUB_D:
11749 check_cop1x(ctx);
11750 check_cp1_registers(ctx, fd | fs | ft | fr);
11752 TCGv_i64 fp0 = tcg_temp_new_i64();
11753 TCGv_i64 fp1 = tcg_temp_new_i64();
11754 TCGv_i64 fp2 = tcg_temp_new_i64();
11756 gen_load_fpr64(ctx, fp0, fs);
11757 gen_load_fpr64(ctx, fp1, ft);
11758 gen_load_fpr64(ctx, fp2, fr);
11759 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11760 tcg_temp_free_i64(fp0);
11761 tcg_temp_free_i64(fp1);
11762 gen_store_fpr64(ctx, fp2, fd);
11763 tcg_temp_free_i64(fp2);
11765 break;
11766 case OPC_NMSUB_PS:
11767 check_ps(ctx);
11769 TCGv_i64 fp0 = tcg_temp_new_i64();
11770 TCGv_i64 fp1 = tcg_temp_new_i64();
11771 TCGv_i64 fp2 = tcg_temp_new_i64();
11773 gen_load_fpr64(ctx, fp0, fs);
11774 gen_load_fpr64(ctx, fp1, ft);
11775 gen_load_fpr64(ctx, fp2, fr);
11776 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11777 tcg_temp_free_i64(fp0);
11778 tcg_temp_free_i64(fp1);
11779 gen_store_fpr64(ctx, fp2, fd);
11780 tcg_temp_free_i64(fp2);
11782 break;
11783 default:
11784 MIPS_INVAL("flt3_arith");
11785 generate_exception_end(ctx, EXCP_RI);
11786 return;
11790 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11792 TCGv t0;
11794 #if !defined(CONFIG_USER_ONLY)
11795 /* The Linux kernel will emulate rdhwr if it's not supported natively.
11796 Therefore only check the ISA in system mode. */
11797 check_insn(ctx, ISA_MIPS32R2);
11798 #endif
11799 t0 = tcg_temp_new();
11801 switch (rd) {
11802 case 0:
11803 gen_helper_rdhwr_cpunum(t0, cpu_env);
11804 gen_store_gpr(t0, rt);
11805 break;
11806 case 1:
11807 gen_helper_rdhwr_synci_step(t0, cpu_env);
11808 gen_store_gpr(t0, rt);
11809 break;
11810 case 2:
11811 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11812 gen_io_start();
11814 gen_helper_rdhwr_cc(t0, cpu_env);
11815 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11816 gen_io_end();
11818 gen_store_gpr(t0, rt);
11819 /* Break the TB to be able to take timer interrupts immediately
11820 after reading count. DISAS_STOP isn't sufficient, we need to ensure
11821 we break completely out of translated code. */
11822 gen_save_pc(ctx->base.pc_next + 4);
11823 ctx->base.is_jmp = DISAS_EXIT;
11824 break;
11825 case 3:
11826 gen_helper_rdhwr_ccres(t0, cpu_env);
11827 gen_store_gpr(t0, rt);
11828 break;
11829 case 4:
11830 check_insn(ctx, ISA_MIPS32R6);
11831 if (sel != 0) {
11832 /* Performance counter registers are not implemented other than
11833 * control register 0.
11835 generate_exception(ctx, EXCP_RI);
11837 gen_helper_rdhwr_performance(t0, cpu_env);
11838 gen_store_gpr(t0, rt);
11839 break;
11840 case 5:
11841 check_insn(ctx, ISA_MIPS32R6);
11842 gen_helper_rdhwr_xnp(t0, cpu_env);
11843 gen_store_gpr(t0, rt);
11844 break;
11845 case 29:
11846 #if defined(CONFIG_USER_ONLY)
11847 tcg_gen_ld_tl(t0, cpu_env,
11848 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11849 gen_store_gpr(t0, rt);
11850 break;
11851 #else
11852 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11853 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
11854 tcg_gen_ld_tl(t0, cpu_env,
11855 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11856 gen_store_gpr(t0, rt);
11857 } else {
11858 generate_exception_end(ctx, EXCP_RI);
11860 break;
11861 #endif
11862 default: /* Invalid */
11863 MIPS_INVAL("rdhwr");
11864 generate_exception_end(ctx, EXCP_RI);
11865 break;
11867 tcg_temp_free(t0);
11870 static inline void clear_branch_hflags(DisasContext *ctx)
11872 ctx->hflags &= ~MIPS_HFLAG_BMASK;
11873 if (ctx->base.is_jmp == DISAS_NEXT) {
11874 save_cpu_state(ctx, 0);
11875 } else {
11876 /* it is not safe to save ctx->hflags as hflags may be changed
11877 in execution time by the instruction in delay / forbidden slot. */
11878 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11882 static void gen_branch(DisasContext *ctx, int insn_bytes)
11884 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11885 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
11886 /* Branches completion */
11887 clear_branch_hflags(ctx);
11888 ctx->base.is_jmp = DISAS_NORETURN;
11889 /* FIXME: Need to clear can_do_io. */
11890 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
11891 case MIPS_HFLAG_FBNSLOT:
11892 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
11893 break;
11894 case MIPS_HFLAG_B:
11895 /* unconditional branch */
11896 if (proc_hflags & MIPS_HFLAG_BX) {
11897 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11899 gen_goto_tb(ctx, 0, ctx->btarget);
11900 break;
11901 case MIPS_HFLAG_BL:
11902 /* blikely taken case */
11903 gen_goto_tb(ctx, 0, ctx->btarget);
11904 break;
11905 case MIPS_HFLAG_BC:
11906 /* Conditional branch */
11908 TCGLabel *l1 = gen_new_label();
11910 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11911 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
11912 gen_set_label(l1);
11913 gen_goto_tb(ctx, 0, ctx->btarget);
11915 break;
11916 case MIPS_HFLAG_BR:
11917 /* unconditional branch to register */
11918 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
11919 TCGv t0 = tcg_temp_new();
11920 TCGv_i32 t1 = tcg_temp_new_i32();
11922 tcg_gen_andi_tl(t0, btarget, 0x1);
11923 tcg_gen_trunc_tl_i32(t1, t0);
11924 tcg_temp_free(t0);
11925 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11926 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11927 tcg_gen_or_i32(hflags, hflags, t1);
11928 tcg_temp_free_i32(t1);
11930 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11931 } else {
11932 tcg_gen_mov_tl(cpu_PC, btarget);
11934 if (ctx->base.singlestep_enabled) {
11935 save_cpu_state(ctx, 0);
11936 gen_helper_raise_exception_debug(cpu_env);
11938 tcg_gen_lookup_and_goto_ptr();
11939 break;
11940 default:
11941 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11942 abort();
11947 /* Compact Branches */
11948 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11949 int rs, int rt, int32_t offset)
11951 int bcond_compute = 0;
11952 TCGv t0 = tcg_temp_new();
11953 TCGv t1 = tcg_temp_new();
11954 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11956 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11957 #ifdef MIPS_DEBUG_DISAS
11958 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11959 "\n", ctx->base.pc_next);
11960 #endif
11961 generate_exception_end(ctx, EXCP_RI);
11962 goto out;
11965 /* Load needed operands and calculate btarget */
11966 switch (opc) {
11967 /* compact branch */
11968 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11969 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11970 gen_load_gpr(t0, rs);
11971 gen_load_gpr(t1, rt);
11972 bcond_compute = 1;
11973 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11974 if (rs <= rt && rs == 0) {
11975 /* OPC_BEQZALC, OPC_BNEZALC */
11976 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11978 break;
11979 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11980 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11981 gen_load_gpr(t0, rs);
11982 gen_load_gpr(t1, rt);
11983 bcond_compute = 1;
11984 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11985 break;
11986 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11987 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11988 if (rs == 0 || rs == rt) {
11989 /* OPC_BLEZALC, OPC_BGEZALC */
11990 /* OPC_BGTZALC, OPC_BLTZALC */
11991 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11993 gen_load_gpr(t0, rs);
11994 gen_load_gpr(t1, rt);
11995 bcond_compute = 1;
11996 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11997 break;
11998 case OPC_BC:
11999 case OPC_BALC:
12000 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12001 break;
12002 case OPC_BEQZC:
12003 case OPC_BNEZC:
12004 if (rs != 0) {
12005 /* OPC_BEQZC, OPC_BNEZC */
12006 gen_load_gpr(t0, rs);
12007 bcond_compute = 1;
12008 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12009 } else {
12010 /* OPC_JIC, OPC_JIALC */
12011 TCGv tbase = tcg_temp_new();
12012 TCGv toffset = tcg_temp_new();
12014 gen_load_gpr(tbase, rt);
12015 tcg_gen_movi_tl(toffset, offset);
12016 gen_op_addr_add(ctx, btarget, tbase, toffset);
12017 tcg_temp_free(tbase);
12018 tcg_temp_free(toffset);
12020 break;
12021 default:
12022 MIPS_INVAL("Compact branch/jump");
12023 generate_exception_end(ctx, EXCP_RI);
12024 goto out;
12027 if (bcond_compute == 0) {
12028 /* Uncoditional compact branch */
12029 switch (opc) {
12030 case OPC_JIALC:
12031 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12032 /* Fallthrough */
12033 case OPC_JIC:
12034 ctx->hflags |= MIPS_HFLAG_BR;
12035 break;
12036 case OPC_BALC:
12037 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12038 /* Fallthrough */
12039 case OPC_BC:
12040 ctx->hflags |= MIPS_HFLAG_B;
12041 break;
12042 default:
12043 MIPS_INVAL("Compact branch/jump");
12044 generate_exception_end(ctx, EXCP_RI);
12045 goto out;
12048 /* Generating branch here as compact branches don't have delay slot */
12049 gen_branch(ctx, 4);
12050 } else {
12051 /* Conditional compact branch */
12052 TCGLabel *fs = gen_new_label();
12053 save_cpu_state(ctx, 0);
12055 switch (opc) {
12056 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12057 if (rs == 0 && rt != 0) {
12058 /* OPC_BLEZALC */
12059 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12060 } else if (rs != 0 && rt != 0 && rs == rt) {
12061 /* OPC_BGEZALC */
12062 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12063 } else {
12064 /* OPC_BGEUC */
12065 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12067 break;
12068 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12069 if (rs == 0 && rt != 0) {
12070 /* OPC_BGTZALC */
12071 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12072 } else if (rs != 0 && rt != 0 && rs == rt) {
12073 /* OPC_BLTZALC */
12074 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12075 } else {
12076 /* OPC_BLTUC */
12077 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12079 break;
12080 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12081 if (rs == 0 && rt != 0) {
12082 /* OPC_BLEZC */
12083 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12084 } else if (rs != 0 && rt != 0 && rs == rt) {
12085 /* OPC_BGEZC */
12086 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12087 } else {
12088 /* OPC_BGEC */
12089 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12091 break;
12092 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12093 if (rs == 0 && rt != 0) {
12094 /* OPC_BGTZC */
12095 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12096 } else if (rs != 0 && rt != 0 && rs == rt) {
12097 /* OPC_BLTZC */
12098 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12099 } else {
12100 /* OPC_BLTC */
12101 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12103 break;
12104 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12105 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12106 if (rs >= rt) {
12107 /* OPC_BOVC, OPC_BNVC */
12108 TCGv t2 = tcg_temp_new();
12109 TCGv t3 = tcg_temp_new();
12110 TCGv t4 = tcg_temp_new();
12111 TCGv input_overflow = tcg_temp_new();
12113 gen_load_gpr(t0, rs);
12114 gen_load_gpr(t1, rt);
12115 tcg_gen_ext32s_tl(t2, t0);
12116 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12117 tcg_gen_ext32s_tl(t3, t1);
12118 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12119 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12121 tcg_gen_add_tl(t4, t2, t3);
12122 tcg_gen_ext32s_tl(t4, t4);
12123 tcg_gen_xor_tl(t2, t2, t3);
12124 tcg_gen_xor_tl(t3, t4, t3);
12125 tcg_gen_andc_tl(t2, t3, t2);
12126 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12127 tcg_gen_or_tl(t4, t4, input_overflow);
12128 if (opc == OPC_BOVC) {
12129 /* OPC_BOVC */
12130 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12131 } else {
12132 /* OPC_BNVC */
12133 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12135 tcg_temp_free(input_overflow);
12136 tcg_temp_free(t4);
12137 tcg_temp_free(t3);
12138 tcg_temp_free(t2);
12139 } else if (rs < rt && rs == 0) {
12140 /* OPC_BEQZALC, OPC_BNEZALC */
12141 if (opc == OPC_BEQZALC) {
12142 /* OPC_BEQZALC */
12143 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12144 } else {
12145 /* OPC_BNEZALC */
12146 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12148 } else {
12149 /* OPC_BEQC, OPC_BNEC */
12150 if (opc == OPC_BEQC) {
12151 /* OPC_BEQC */
12152 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12153 } else {
12154 /* OPC_BNEC */
12155 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12158 break;
12159 case OPC_BEQZC:
12160 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12161 break;
12162 case OPC_BNEZC:
12163 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12164 break;
12165 default:
12166 MIPS_INVAL("Compact conditional branch/jump");
12167 generate_exception_end(ctx, EXCP_RI);
12168 goto out;
12171 /* Generating branch here as compact branches don't have delay slot */
12172 gen_goto_tb(ctx, 1, ctx->btarget);
12173 gen_set_label(fs);
12175 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12178 out:
12179 tcg_temp_free(t0);
12180 tcg_temp_free(t1);
12183 /* ISA extensions (ASEs) */
12184 /* MIPS16 extension to MIPS32 */
12186 /* MIPS16 major opcodes */
12187 enum {
12188 M16_OPC_ADDIUSP = 0x00,
12189 M16_OPC_ADDIUPC = 0x01,
12190 M16_OPC_B = 0x02,
12191 M16_OPC_JAL = 0x03,
12192 M16_OPC_BEQZ = 0x04,
12193 M16_OPC_BNEQZ = 0x05,
12194 M16_OPC_SHIFT = 0x06,
12195 M16_OPC_LD = 0x07,
12196 M16_OPC_RRIA = 0x08,
12197 M16_OPC_ADDIU8 = 0x09,
12198 M16_OPC_SLTI = 0x0a,
12199 M16_OPC_SLTIU = 0x0b,
12200 M16_OPC_I8 = 0x0c,
12201 M16_OPC_LI = 0x0d,
12202 M16_OPC_CMPI = 0x0e,
12203 M16_OPC_SD = 0x0f,
12204 M16_OPC_LB = 0x10,
12205 M16_OPC_LH = 0x11,
12206 M16_OPC_LWSP = 0x12,
12207 M16_OPC_LW = 0x13,
12208 M16_OPC_LBU = 0x14,
12209 M16_OPC_LHU = 0x15,
12210 M16_OPC_LWPC = 0x16,
12211 M16_OPC_LWU = 0x17,
12212 M16_OPC_SB = 0x18,
12213 M16_OPC_SH = 0x19,
12214 M16_OPC_SWSP = 0x1a,
12215 M16_OPC_SW = 0x1b,
12216 M16_OPC_RRR = 0x1c,
12217 M16_OPC_RR = 0x1d,
12218 M16_OPC_EXTEND = 0x1e,
12219 M16_OPC_I64 = 0x1f
12222 /* I8 funct field */
12223 enum {
12224 I8_BTEQZ = 0x0,
12225 I8_BTNEZ = 0x1,
12226 I8_SWRASP = 0x2,
12227 I8_ADJSP = 0x3,
12228 I8_SVRS = 0x4,
12229 I8_MOV32R = 0x5,
12230 I8_MOVR32 = 0x7
12233 /* RRR f field */
12234 enum {
12235 RRR_DADDU = 0x0,
12236 RRR_ADDU = 0x1,
12237 RRR_DSUBU = 0x2,
12238 RRR_SUBU = 0x3
12241 /* RR funct field */
12242 enum {
12243 RR_JR = 0x00,
12244 RR_SDBBP = 0x01,
12245 RR_SLT = 0x02,
12246 RR_SLTU = 0x03,
12247 RR_SLLV = 0x04,
12248 RR_BREAK = 0x05,
12249 RR_SRLV = 0x06,
12250 RR_SRAV = 0x07,
12251 RR_DSRL = 0x08,
12252 RR_CMP = 0x0a,
12253 RR_NEG = 0x0b,
12254 RR_AND = 0x0c,
12255 RR_OR = 0x0d,
12256 RR_XOR = 0x0e,
12257 RR_NOT = 0x0f,
12258 RR_MFHI = 0x10,
12259 RR_CNVT = 0x11,
12260 RR_MFLO = 0x12,
12261 RR_DSRA = 0x13,
12262 RR_DSLLV = 0x14,
12263 RR_DSRLV = 0x16,
12264 RR_DSRAV = 0x17,
12265 RR_MULT = 0x18,
12266 RR_MULTU = 0x19,
12267 RR_DIV = 0x1a,
12268 RR_DIVU = 0x1b,
12269 RR_DMULT = 0x1c,
12270 RR_DMULTU = 0x1d,
12271 RR_DDIV = 0x1e,
12272 RR_DDIVU = 0x1f
12275 /* I64 funct field */
12276 enum {
12277 I64_LDSP = 0x0,
12278 I64_SDSP = 0x1,
12279 I64_SDRASP = 0x2,
12280 I64_DADJSP = 0x3,
12281 I64_LDPC = 0x4,
12282 I64_DADDIU5 = 0x5,
12283 I64_DADDIUPC = 0x6,
12284 I64_DADDIUSP = 0x7
12287 /* RR ry field for CNVT */
12288 enum {
12289 RR_RY_CNVT_ZEB = 0x0,
12290 RR_RY_CNVT_ZEH = 0x1,
12291 RR_RY_CNVT_ZEW = 0x2,
12292 RR_RY_CNVT_SEB = 0x4,
12293 RR_RY_CNVT_SEH = 0x5,
12294 RR_RY_CNVT_SEW = 0x6,
12297 static int xlat (int r)
12299 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12301 return map[r];
12304 static void gen_mips16_save (DisasContext *ctx,
12305 int xsregs, int aregs,
12306 int do_ra, int do_s0, int do_s1,
12307 int framesize)
12309 TCGv t0 = tcg_temp_new();
12310 TCGv t1 = tcg_temp_new();
12311 TCGv t2 = tcg_temp_new();
12312 int args, astatic;
12314 switch (aregs) {
12315 case 0:
12316 case 1:
12317 case 2:
12318 case 3:
12319 case 11:
12320 args = 0;
12321 break;
12322 case 4:
12323 case 5:
12324 case 6:
12325 case 7:
12326 args = 1;
12327 break;
12328 case 8:
12329 case 9:
12330 case 10:
12331 args = 2;
12332 break;
12333 case 12:
12334 case 13:
12335 args = 3;
12336 break;
12337 case 14:
12338 args = 4;
12339 break;
12340 default:
12341 generate_exception_end(ctx, EXCP_RI);
12342 return;
12345 switch (args) {
12346 case 4:
12347 gen_base_offset_addr(ctx, t0, 29, 12);
12348 gen_load_gpr(t1, 7);
12349 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12350 /* Fall through */
12351 case 3:
12352 gen_base_offset_addr(ctx, t0, 29, 8);
12353 gen_load_gpr(t1, 6);
12354 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12355 /* Fall through */
12356 case 2:
12357 gen_base_offset_addr(ctx, t0, 29, 4);
12358 gen_load_gpr(t1, 5);
12359 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12360 /* Fall through */
12361 case 1:
12362 gen_base_offset_addr(ctx, t0, 29, 0);
12363 gen_load_gpr(t1, 4);
12364 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12367 gen_load_gpr(t0, 29);
12369 #define DECR_AND_STORE(reg) do { \
12370 tcg_gen_movi_tl(t2, -4); \
12371 gen_op_addr_add(ctx, t0, t0, t2); \
12372 gen_load_gpr(t1, reg); \
12373 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12374 } while (0)
12376 if (do_ra) {
12377 DECR_AND_STORE(31);
12380 switch (xsregs) {
12381 case 7:
12382 DECR_AND_STORE(30);
12383 /* Fall through */
12384 case 6:
12385 DECR_AND_STORE(23);
12386 /* Fall through */
12387 case 5:
12388 DECR_AND_STORE(22);
12389 /* Fall through */
12390 case 4:
12391 DECR_AND_STORE(21);
12392 /* Fall through */
12393 case 3:
12394 DECR_AND_STORE(20);
12395 /* Fall through */
12396 case 2:
12397 DECR_AND_STORE(19);
12398 /* Fall through */
12399 case 1:
12400 DECR_AND_STORE(18);
12403 if (do_s1) {
12404 DECR_AND_STORE(17);
12406 if (do_s0) {
12407 DECR_AND_STORE(16);
12410 switch (aregs) {
12411 case 0:
12412 case 4:
12413 case 8:
12414 case 12:
12415 case 14:
12416 astatic = 0;
12417 break;
12418 case 1:
12419 case 5:
12420 case 9:
12421 case 13:
12422 astatic = 1;
12423 break;
12424 case 2:
12425 case 6:
12426 case 10:
12427 astatic = 2;
12428 break;
12429 case 3:
12430 case 7:
12431 astatic = 3;
12432 break;
12433 case 11:
12434 astatic = 4;
12435 break;
12436 default:
12437 generate_exception_end(ctx, EXCP_RI);
12438 return;
12441 if (astatic > 0) {
12442 DECR_AND_STORE(7);
12443 if (astatic > 1) {
12444 DECR_AND_STORE(6);
12445 if (astatic > 2) {
12446 DECR_AND_STORE(5);
12447 if (astatic > 3) {
12448 DECR_AND_STORE(4);
12453 #undef DECR_AND_STORE
12455 tcg_gen_movi_tl(t2, -framesize);
12456 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12457 tcg_temp_free(t0);
12458 tcg_temp_free(t1);
12459 tcg_temp_free(t2);
12462 static void gen_mips16_restore (DisasContext *ctx,
12463 int xsregs, int aregs,
12464 int do_ra, int do_s0, int do_s1,
12465 int framesize)
12467 int astatic;
12468 TCGv t0 = tcg_temp_new();
12469 TCGv t1 = tcg_temp_new();
12470 TCGv t2 = tcg_temp_new();
12472 tcg_gen_movi_tl(t2, framesize);
12473 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12475 #define DECR_AND_LOAD(reg) do { \
12476 tcg_gen_movi_tl(t2, -4); \
12477 gen_op_addr_add(ctx, t0, t0, t2); \
12478 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12479 gen_store_gpr(t1, reg); \
12480 } while (0)
12482 if (do_ra) {
12483 DECR_AND_LOAD(31);
12486 switch (xsregs) {
12487 case 7:
12488 DECR_AND_LOAD(30);
12489 /* Fall through */
12490 case 6:
12491 DECR_AND_LOAD(23);
12492 /* Fall through */
12493 case 5:
12494 DECR_AND_LOAD(22);
12495 /* Fall through */
12496 case 4:
12497 DECR_AND_LOAD(21);
12498 /* Fall through */
12499 case 3:
12500 DECR_AND_LOAD(20);
12501 /* Fall through */
12502 case 2:
12503 DECR_AND_LOAD(19);
12504 /* Fall through */
12505 case 1:
12506 DECR_AND_LOAD(18);
12509 if (do_s1) {
12510 DECR_AND_LOAD(17);
12512 if (do_s0) {
12513 DECR_AND_LOAD(16);
12516 switch (aregs) {
12517 case 0:
12518 case 4:
12519 case 8:
12520 case 12:
12521 case 14:
12522 astatic = 0;
12523 break;
12524 case 1:
12525 case 5:
12526 case 9:
12527 case 13:
12528 astatic = 1;
12529 break;
12530 case 2:
12531 case 6:
12532 case 10:
12533 astatic = 2;
12534 break;
12535 case 3:
12536 case 7:
12537 astatic = 3;
12538 break;
12539 case 11:
12540 astatic = 4;
12541 break;
12542 default:
12543 generate_exception_end(ctx, EXCP_RI);
12544 return;
12547 if (astatic > 0) {
12548 DECR_AND_LOAD(7);
12549 if (astatic > 1) {
12550 DECR_AND_LOAD(6);
12551 if (astatic > 2) {
12552 DECR_AND_LOAD(5);
12553 if (astatic > 3) {
12554 DECR_AND_LOAD(4);
12559 #undef DECR_AND_LOAD
12561 tcg_gen_movi_tl(t2, framesize);
12562 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12563 tcg_temp_free(t0);
12564 tcg_temp_free(t1);
12565 tcg_temp_free(t2);
12568 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
12569 int is_64_bit, int extended)
12571 TCGv t0;
12573 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12574 generate_exception_end(ctx, EXCP_RI);
12575 return;
12578 t0 = tcg_temp_new();
12580 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12581 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12582 if (!is_64_bit) {
12583 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12586 tcg_temp_free(t0);
12589 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12590 int16_t offset)
12592 TCGv_i32 t0 = tcg_const_i32(op);
12593 TCGv t1 = tcg_temp_new();
12594 gen_base_offset_addr(ctx, t1, base, offset);
12595 gen_helper_cache(cpu_env, t1, t0);
12598 #if defined(TARGET_MIPS64)
12599 static void decode_i64_mips16 (DisasContext *ctx,
12600 int ry, int funct, int16_t offset,
12601 int extended)
12603 switch (funct) {
12604 case I64_LDSP:
12605 check_insn(ctx, ISA_MIPS3);
12606 check_mips_64(ctx);
12607 offset = extended ? offset : offset << 3;
12608 gen_ld(ctx, OPC_LD, ry, 29, offset);
12609 break;
12610 case I64_SDSP:
12611 check_insn(ctx, ISA_MIPS3);
12612 check_mips_64(ctx);
12613 offset = extended ? offset : offset << 3;
12614 gen_st(ctx, OPC_SD, ry, 29, offset);
12615 break;
12616 case I64_SDRASP:
12617 check_insn(ctx, ISA_MIPS3);
12618 check_mips_64(ctx);
12619 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
12620 gen_st(ctx, OPC_SD, 31, 29, offset);
12621 break;
12622 case I64_DADJSP:
12623 check_insn(ctx, ISA_MIPS3);
12624 check_mips_64(ctx);
12625 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
12626 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
12627 break;
12628 case I64_LDPC:
12629 check_insn(ctx, ISA_MIPS3);
12630 check_mips_64(ctx);
12631 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12632 generate_exception_end(ctx, EXCP_RI);
12633 } else {
12634 offset = extended ? offset : offset << 3;
12635 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
12637 break;
12638 case I64_DADDIU5:
12639 check_insn(ctx, ISA_MIPS3);
12640 check_mips_64(ctx);
12641 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
12642 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
12643 break;
12644 case I64_DADDIUPC:
12645 check_insn(ctx, ISA_MIPS3);
12646 check_mips_64(ctx);
12647 offset = extended ? offset : offset << 2;
12648 gen_addiupc(ctx, ry, offset, 1, extended);
12649 break;
12650 case I64_DADDIUSP:
12651 check_insn(ctx, ISA_MIPS3);
12652 check_mips_64(ctx);
12653 offset = extended ? offset : offset << 2;
12654 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12655 break;
12658 #endif
12660 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12662 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
12663 int op, rx, ry, funct, sa;
12664 int16_t imm, offset;
12666 ctx->opcode = (ctx->opcode << 16) | extend;
12667 op = (ctx->opcode >> 11) & 0x1f;
12668 sa = (ctx->opcode >> 22) & 0x1f;
12669 funct = (ctx->opcode >> 8) & 0x7;
12670 rx = xlat((ctx->opcode >> 8) & 0x7);
12671 ry = xlat((ctx->opcode >> 5) & 0x7);
12672 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12673 | ((ctx->opcode >> 21) & 0x3f) << 5
12674 | (ctx->opcode & 0x1f));
12676 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
12677 counterparts. */
12678 switch (op) {
12679 case M16_OPC_ADDIUSP:
12680 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12681 break;
12682 case M16_OPC_ADDIUPC:
12683 gen_addiupc(ctx, rx, imm, 0, 1);
12684 break;
12685 case M16_OPC_B:
12686 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12687 /* No delay slot, so just process as a normal instruction */
12688 break;
12689 case M16_OPC_BEQZ:
12690 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12691 /* No delay slot, so just process as a normal instruction */
12692 break;
12693 case M16_OPC_BNEQZ:
12694 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12695 /* No delay slot, so just process as a normal instruction */
12696 break;
12697 case M16_OPC_SHIFT:
12698 switch (ctx->opcode & 0x3) {
12699 case 0x0:
12700 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12701 break;
12702 case 0x1:
12703 #if defined(TARGET_MIPS64)
12704 check_mips_64(ctx);
12705 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12706 #else
12707 generate_exception_end(ctx, EXCP_RI);
12708 #endif
12709 break;
12710 case 0x2:
12711 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12712 break;
12713 case 0x3:
12714 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12715 break;
12717 break;
12718 #if defined(TARGET_MIPS64)
12719 case M16_OPC_LD:
12720 check_insn(ctx, ISA_MIPS3);
12721 check_mips_64(ctx);
12722 gen_ld(ctx, OPC_LD, ry, rx, offset);
12723 break;
12724 #endif
12725 case M16_OPC_RRIA:
12726 imm = ctx->opcode & 0xf;
12727 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12728 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12729 imm = (int16_t) (imm << 1) >> 1;
12730 if ((ctx->opcode >> 4) & 0x1) {
12731 #if defined(TARGET_MIPS64)
12732 check_mips_64(ctx);
12733 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12734 #else
12735 generate_exception_end(ctx, EXCP_RI);
12736 #endif
12737 } else {
12738 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12740 break;
12741 case M16_OPC_ADDIU8:
12742 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12743 break;
12744 case M16_OPC_SLTI:
12745 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12746 break;
12747 case M16_OPC_SLTIU:
12748 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12749 break;
12750 case M16_OPC_I8:
12751 switch (funct) {
12752 case I8_BTEQZ:
12753 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
12754 break;
12755 case I8_BTNEZ:
12756 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
12757 break;
12758 case I8_SWRASP:
12759 gen_st(ctx, OPC_SW, 31, 29, imm);
12760 break;
12761 case I8_ADJSP:
12762 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
12763 break;
12764 case I8_SVRS:
12765 check_insn(ctx, ISA_MIPS32);
12767 int xsregs = (ctx->opcode >> 24) & 0x7;
12768 int aregs = (ctx->opcode >> 16) & 0xf;
12769 int do_ra = (ctx->opcode >> 6) & 0x1;
12770 int do_s0 = (ctx->opcode >> 5) & 0x1;
12771 int do_s1 = (ctx->opcode >> 4) & 0x1;
12772 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12773 | (ctx->opcode & 0xf)) << 3;
12775 if (ctx->opcode & (1 << 7)) {
12776 gen_mips16_save(ctx, xsregs, aregs,
12777 do_ra, do_s0, do_s1,
12778 framesize);
12779 } else {
12780 gen_mips16_restore(ctx, xsregs, aregs,
12781 do_ra, do_s0, do_s1,
12782 framesize);
12785 break;
12786 default:
12787 generate_exception_end(ctx, EXCP_RI);
12788 break;
12790 break;
12791 case M16_OPC_LI:
12792 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
12793 break;
12794 case M16_OPC_CMPI:
12795 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
12796 break;
12797 #if defined(TARGET_MIPS64)
12798 case M16_OPC_SD:
12799 check_insn(ctx, ISA_MIPS3);
12800 check_mips_64(ctx);
12801 gen_st(ctx, OPC_SD, ry, rx, offset);
12802 break;
12803 #endif
12804 case M16_OPC_LB:
12805 gen_ld(ctx, OPC_LB, ry, rx, offset);
12806 break;
12807 case M16_OPC_LH:
12808 gen_ld(ctx, OPC_LH, ry, rx, offset);
12809 break;
12810 case M16_OPC_LWSP:
12811 gen_ld(ctx, OPC_LW, rx, 29, offset);
12812 break;
12813 case M16_OPC_LW:
12814 gen_ld(ctx, OPC_LW, ry, rx, offset);
12815 break;
12816 case M16_OPC_LBU:
12817 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12818 break;
12819 case M16_OPC_LHU:
12820 gen_ld(ctx, OPC_LHU, ry, rx, offset);
12821 break;
12822 case M16_OPC_LWPC:
12823 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
12824 break;
12825 #if defined(TARGET_MIPS64)
12826 case M16_OPC_LWU:
12827 check_insn(ctx, ISA_MIPS3);
12828 check_mips_64(ctx);
12829 gen_ld(ctx, OPC_LWU, ry, rx, offset);
12830 break;
12831 #endif
12832 case M16_OPC_SB:
12833 gen_st(ctx, OPC_SB, ry, rx, offset);
12834 break;
12835 case M16_OPC_SH:
12836 gen_st(ctx, OPC_SH, ry, rx, offset);
12837 break;
12838 case M16_OPC_SWSP:
12839 gen_st(ctx, OPC_SW, rx, 29, offset);
12840 break;
12841 case M16_OPC_SW:
12842 gen_st(ctx, OPC_SW, ry, rx, offset);
12843 break;
12844 #if defined(TARGET_MIPS64)
12845 case M16_OPC_I64:
12846 decode_i64_mips16(ctx, ry, funct, offset, 1);
12847 break;
12848 #endif
12849 default:
12850 generate_exception_end(ctx, EXCP_RI);
12851 break;
12854 return 4;
12857 static inline bool is_uhi(int sdbbp_code)
12859 #ifdef CONFIG_USER_ONLY
12860 return false;
12861 #else
12862 return semihosting_enabled() && sdbbp_code == 1;
12863 #endif
12866 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12868 int rx, ry;
12869 int sa;
12870 int op, cnvt_op, op1, offset;
12871 int funct;
12872 int n_bytes;
12874 op = (ctx->opcode >> 11) & 0x1f;
12875 sa = (ctx->opcode >> 2) & 0x7;
12876 sa = sa == 0 ? 8 : sa;
12877 rx = xlat((ctx->opcode >> 8) & 0x7);
12878 cnvt_op = (ctx->opcode >> 5) & 0x7;
12879 ry = xlat((ctx->opcode >> 5) & 0x7);
12880 op1 = offset = ctx->opcode & 0x1f;
12882 n_bytes = 2;
12884 switch (op) {
12885 case M16_OPC_ADDIUSP:
12887 int16_t imm = ((uint8_t) ctx->opcode) << 2;
12889 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12891 break;
12892 case M16_OPC_ADDIUPC:
12893 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
12894 break;
12895 case M16_OPC_B:
12896 offset = (ctx->opcode & 0x7ff) << 1;
12897 offset = (int16_t)(offset << 4) >> 4;
12898 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
12899 /* No delay slot, so just process as a normal instruction */
12900 break;
12901 case M16_OPC_JAL:
12902 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
12903 offset = (((ctx->opcode & 0x1f) << 21)
12904 | ((ctx->opcode >> 5) & 0x1f) << 16
12905 | offset) << 2;
12906 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
12907 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
12908 n_bytes = 4;
12909 break;
12910 case M16_OPC_BEQZ:
12911 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
12912 ((int8_t)ctx->opcode) << 1, 0);
12913 /* No delay slot, so just process as a normal instruction */
12914 break;
12915 case M16_OPC_BNEQZ:
12916 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
12917 ((int8_t)ctx->opcode) << 1, 0);
12918 /* No delay slot, so just process as a normal instruction */
12919 break;
12920 case M16_OPC_SHIFT:
12921 switch (ctx->opcode & 0x3) {
12922 case 0x0:
12923 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12924 break;
12925 case 0x1:
12926 #if defined(TARGET_MIPS64)
12927 check_insn(ctx, ISA_MIPS3);
12928 check_mips_64(ctx);
12929 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12930 #else
12931 generate_exception_end(ctx, EXCP_RI);
12932 #endif
12933 break;
12934 case 0x2:
12935 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12936 break;
12937 case 0x3:
12938 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12939 break;
12941 break;
12942 #if defined(TARGET_MIPS64)
12943 case M16_OPC_LD:
12944 check_insn(ctx, ISA_MIPS3);
12945 check_mips_64(ctx);
12946 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
12947 break;
12948 #endif
12949 case M16_OPC_RRIA:
12951 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12953 if ((ctx->opcode >> 4) & 1) {
12954 #if defined(TARGET_MIPS64)
12955 check_insn(ctx, ISA_MIPS3);
12956 check_mips_64(ctx);
12957 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12958 #else
12959 generate_exception_end(ctx, EXCP_RI);
12960 #endif
12961 } else {
12962 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12965 break;
12966 case M16_OPC_ADDIU8:
12968 int16_t imm = (int8_t) ctx->opcode;
12970 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12972 break;
12973 case M16_OPC_SLTI:
12975 int16_t imm = (uint8_t) ctx->opcode;
12976 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12978 break;
12979 case M16_OPC_SLTIU:
12981 int16_t imm = (uint8_t) ctx->opcode;
12982 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12984 break;
12985 case M16_OPC_I8:
12987 int reg32;
12989 funct = (ctx->opcode >> 8) & 0x7;
12990 switch (funct) {
12991 case I8_BTEQZ:
12992 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
12993 ((int8_t)ctx->opcode) << 1, 0);
12994 break;
12995 case I8_BTNEZ:
12996 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
12997 ((int8_t)ctx->opcode) << 1, 0);
12998 break;
12999 case I8_SWRASP:
13000 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13001 break;
13002 case I8_ADJSP:
13003 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13004 ((int8_t)ctx->opcode) << 3);
13005 break;
13006 case I8_SVRS:
13007 check_insn(ctx, ISA_MIPS32);
13009 int do_ra = ctx->opcode & (1 << 6);
13010 int do_s0 = ctx->opcode & (1 << 5);
13011 int do_s1 = ctx->opcode & (1 << 4);
13012 int framesize = ctx->opcode & 0xf;
13014 if (framesize == 0) {
13015 framesize = 128;
13016 } else {
13017 framesize = framesize << 3;
13020 if (ctx->opcode & (1 << 7)) {
13021 gen_mips16_save(ctx, 0, 0,
13022 do_ra, do_s0, do_s1, framesize);
13023 } else {
13024 gen_mips16_restore(ctx, 0, 0,
13025 do_ra, do_s0, do_s1, framesize);
13028 break;
13029 case I8_MOV32R:
13031 int rz = xlat(ctx->opcode & 0x7);
13033 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13034 ((ctx->opcode >> 5) & 0x7);
13035 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13037 break;
13038 case I8_MOVR32:
13039 reg32 = ctx->opcode & 0x1f;
13040 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13041 break;
13042 default:
13043 generate_exception_end(ctx, EXCP_RI);
13044 break;
13047 break;
13048 case M16_OPC_LI:
13050 int16_t imm = (uint8_t) ctx->opcode;
13052 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13054 break;
13055 case M16_OPC_CMPI:
13057 int16_t imm = (uint8_t) ctx->opcode;
13058 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13060 break;
13061 #if defined(TARGET_MIPS64)
13062 case M16_OPC_SD:
13063 check_insn(ctx, ISA_MIPS3);
13064 check_mips_64(ctx);
13065 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13066 break;
13067 #endif
13068 case M16_OPC_LB:
13069 gen_ld(ctx, OPC_LB, ry, rx, offset);
13070 break;
13071 case M16_OPC_LH:
13072 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13073 break;
13074 case M16_OPC_LWSP:
13075 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13076 break;
13077 case M16_OPC_LW:
13078 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13079 break;
13080 case M16_OPC_LBU:
13081 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13082 break;
13083 case M16_OPC_LHU:
13084 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13085 break;
13086 case M16_OPC_LWPC:
13087 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13088 break;
13089 #if defined (TARGET_MIPS64)
13090 case M16_OPC_LWU:
13091 check_insn(ctx, ISA_MIPS3);
13092 check_mips_64(ctx);
13093 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13094 break;
13095 #endif
13096 case M16_OPC_SB:
13097 gen_st(ctx, OPC_SB, ry, rx, offset);
13098 break;
13099 case M16_OPC_SH:
13100 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13101 break;
13102 case M16_OPC_SWSP:
13103 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13104 break;
13105 case M16_OPC_SW:
13106 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13107 break;
13108 case M16_OPC_RRR:
13110 int rz = xlat((ctx->opcode >> 2) & 0x7);
13111 int mips32_op;
13113 switch (ctx->opcode & 0x3) {
13114 case RRR_ADDU:
13115 mips32_op = OPC_ADDU;
13116 break;
13117 case RRR_SUBU:
13118 mips32_op = OPC_SUBU;
13119 break;
13120 #if defined(TARGET_MIPS64)
13121 case RRR_DADDU:
13122 mips32_op = OPC_DADDU;
13123 check_insn(ctx, ISA_MIPS3);
13124 check_mips_64(ctx);
13125 break;
13126 case RRR_DSUBU:
13127 mips32_op = OPC_DSUBU;
13128 check_insn(ctx, ISA_MIPS3);
13129 check_mips_64(ctx);
13130 break;
13131 #endif
13132 default:
13133 generate_exception_end(ctx, EXCP_RI);
13134 goto done;
13137 gen_arith(ctx, mips32_op, rz, rx, ry);
13138 done:
13141 break;
13142 case M16_OPC_RR:
13143 switch (op1) {
13144 case RR_JR:
13146 int nd = (ctx->opcode >> 7) & 0x1;
13147 int link = (ctx->opcode >> 6) & 0x1;
13148 int ra = (ctx->opcode >> 5) & 0x1;
13150 if (nd) {
13151 check_insn(ctx, ISA_MIPS32);
13154 if (link) {
13155 op = OPC_JALR;
13156 } else {
13157 op = OPC_JR;
13160 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13161 (nd ? 0 : 2));
13163 break;
13164 case RR_SDBBP:
13165 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13166 gen_helper_do_semihosting(cpu_env);
13167 } else {
13168 /* XXX: not clear which exception should be raised
13169 * when in debug mode...
13171 check_insn(ctx, ISA_MIPS32);
13172 generate_exception_end(ctx, EXCP_DBp);
13174 break;
13175 case RR_SLT:
13176 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13177 break;
13178 case RR_SLTU:
13179 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13180 break;
13181 case RR_BREAK:
13182 generate_exception_end(ctx, EXCP_BREAK);
13183 break;
13184 case RR_SLLV:
13185 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13186 break;
13187 case RR_SRLV:
13188 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13189 break;
13190 case RR_SRAV:
13191 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13192 break;
13193 #if defined (TARGET_MIPS64)
13194 case RR_DSRL:
13195 check_insn(ctx, ISA_MIPS3);
13196 check_mips_64(ctx);
13197 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13198 break;
13199 #endif
13200 case RR_CMP:
13201 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13202 break;
13203 case RR_NEG:
13204 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13205 break;
13206 case RR_AND:
13207 gen_logic(ctx, OPC_AND, rx, rx, ry);
13208 break;
13209 case RR_OR:
13210 gen_logic(ctx, OPC_OR, rx, rx, ry);
13211 break;
13212 case RR_XOR:
13213 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13214 break;
13215 case RR_NOT:
13216 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13217 break;
13218 case RR_MFHI:
13219 gen_HILO(ctx, OPC_MFHI, 0, rx);
13220 break;
13221 case RR_CNVT:
13222 check_insn(ctx, ISA_MIPS32);
13223 switch (cnvt_op) {
13224 case RR_RY_CNVT_ZEB:
13225 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13226 break;
13227 case RR_RY_CNVT_ZEH:
13228 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13229 break;
13230 case RR_RY_CNVT_SEB:
13231 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13232 break;
13233 case RR_RY_CNVT_SEH:
13234 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13235 break;
13236 #if defined (TARGET_MIPS64)
13237 case RR_RY_CNVT_ZEW:
13238 check_insn(ctx, ISA_MIPS64);
13239 check_mips_64(ctx);
13240 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13241 break;
13242 case RR_RY_CNVT_SEW:
13243 check_insn(ctx, ISA_MIPS64);
13244 check_mips_64(ctx);
13245 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13246 break;
13247 #endif
13248 default:
13249 generate_exception_end(ctx, EXCP_RI);
13250 break;
13252 break;
13253 case RR_MFLO:
13254 gen_HILO(ctx, OPC_MFLO, 0, rx);
13255 break;
13256 #if defined (TARGET_MIPS64)
13257 case RR_DSRA:
13258 check_insn(ctx, ISA_MIPS3);
13259 check_mips_64(ctx);
13260 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13261 break;
13262 case RR_DSLLV:
13263 check_insn(ctx, ISA_MIPS3);
13264 check_mips_64(ctx);
13265 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13266 break;
13267 case RR_DSRLV:
13268 check_insn(ctx, ISA_MIPS3);
13269 check_mips_64(ctx);
13270 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13271 break;
13272 case RR_DSRAV:
13273 check_insn(ctx, ISA_MIPS3);
13274 check_mips_64(ctx);
13275 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13276 break;
13277 #endif
13278 case RR_MULT:
13279 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13280 break;
13281 case RR_MULTU:
13282 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13283 break;
13284 case RR_DIV:
13285 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13286 break;
13287 case RR_DIVU:
13288 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13289 break;
13290 #if defined (TARGET_MIPS64)
13291 case RR_DMULT:
13292 check_insn(ctx, ISA_MIPS3);
13293 check_mips_64(ctx);
13294 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13295 break;
13296 case RR_DMULTU:
13297 check_insn(ctx, ISA_MIPS3);
13298 check_mips_64(ctx);
13299 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13300 break;
13301 case RR_DDIV:
13302 check_insn(ctx, ISA_MIPS3);
13303 check_mips_64(ctx);
13304 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13305 break;
13306 case RR_DDIVU:
13307 check_insn(ctx, ISA_MIPS3);
13308 check_mips_64(ctx);
13309 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13310 break;
13311 #endif
13312 default:
13313 generate_exception_end(ctx, EXCP_RI);
13314 break;
13316 break;
13317 case M16_OPC_EXTEND:
13318 decode_extended_mips16_opc(env, ctx);
13319 n_bytes = 4;
13320 break;
13321 #if defined(TARGET_MIPS64)
13322 case M16_OPC_I64:
13323 funct = (ctx->opcode >> 8) & 0x7;
13324 decode_i64_mips16(ctx, ry, funct, offset, 0);
13325 break;
13326 #endif
13327 default:
13328 generate_exception_end(ctx, EXCP_RI);
13329 break;
13332 return n_bytes;
13335 /* microMIPS extension to MIPS32/MIPS64 */
13338 * microMIPS32/microMIPS64 major opcodes
13340 * 1. MIPS Architecture for Programmers Volume II-B:
13341 * The microMIPS32 Instruction Set (Revision 3.05)
13343 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13345 * 2. MIPS Architecture For Programmers Volume II-A:
13346 * The MIPS64 Instruction Set (Revision 3.51)
13349 enum {
13350 POOL32A = 0x00,
13351 POOL16A = 0x01,
13352 LBU16 = 0x02,
13353 MOVE16 = 0x03,
13354 ADDI32 = 0x04,
13355 R6_LUI = 0x04,
13356 AUI = 0x04,
13357 LBU32 = 0x05,
13358 SB32 = 0x06,
13359 LB32 = 0x07,
13361 POOL32B = 0x08,
13362 POOL16B = 0x09,
13363 LHU16 = 0x0a,
13364 ANDI16 = 0x0b,
13365 ADDIU32 = 0x0c,
13366 LHU32 = 0x0d,
13367 SH32 = 0x0e,
13368 LH32 = 0x0f,
13370 POOL32I = 0x10,
13371 POOL16C = 0x11,
13372 LWSP16 = 0x12,
13373 POOL16D = 0x13,
13374 ORI32 = 0x14,
13375 POOL32F = 0x15,
13376 POOL32S = 0x16, /* MIPS64 */
13377 DADDIU32 = 0x17, /* MIPS64 */
13379 POOL32C = 0x18,
13380 LWGP16 = 0x19,
13381 LW16 = 0x1a,
13382 POOL16E = 0x1b,
13383 XORI32 = 0x1c,
13384 JALS32 = 0x1d,
13385 BOVC = 0x1d,
13386 BEQC = 0x1d,
13387 BEQZALC = 0x1d,
13388 ADDIUPC = 0x1e,
13389 PCREL = 0x1e,
13390 BNVC = 0x1f,
13391 BNEC = 0x1f,
13392 BNEZALC = 0x1f,
13394 R6_BEQZC = 0x20,
13395 JIC = 0x20,
13396 POOL16F = 0x21,
13397 SB16 = 0x22,
13398 BEQZ16 = 0x23,
13399 BEQZC16 = 0x23,
13400 SLTI32 = 0x24,
13401 BEQ32 = 0x25,
13402 BC = 0x25,
13403 SWC132 = 0x26,
13404 LWC132 = 0x27,
13406 /* 0x29 is reserved */
13407 RES_29 = 0x29,
13408 R6_BNEZC = 0x28,
13409 JIALC = 0x28,
13410 SH16 = 0x2a,
13411 BNEZ16 = 0x2b,
13412 BNEZC16 = 0x2b,
13413 SLTIU32 = 0x2c,
13414 BNE32 = 0x2d,
13415 BALC = 0x2d,
13416 SDC132 = 0x2e,
13417 LDC132 = 0x2f,
13419 /* 0x31 is reserved */
13420 RES_31 = 0x31,
13421 BLEZALC = 0x30,
13422 BGEZALC = 0x30,
13423 BGEUC = 0x30,
13424 SWSP16 = 0x32,
13425 B16 = 0x33,
13426 BC16 = 0x33,
13427 ANDI32 = 0x34,
13428 J32 = 0x35,
13429 BGTZC = 0x35,
13430 BLTZC = 0x35,
13431 BLTC = 0x35,
13432 SD32 = 0x36, /* MIPS64 */
13433 LD32 = 0x37, /* MIPS64 */
13435 /* 0x39 is reserved */
13436 RES_39 = 0x39,
13437 BGTZALC = 0x38,
13438 BLTZALC = 0x38,
13439 BLTUC = 0x38,
13440 SW16 = 0x3a,
13441 LI16 = 0x3b,
13442 JALX32 = 0x3c,
13443 JAL32 = 0x3d,
13444 BLEZC = 0x3d,
13445 BGEZC = 0x3d,
13446 BGEC = 0x3d,
13447 SW32 = 0x3e,
13448 LW32 = 0x3f
13451 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13452 enum {
13453 ADDIUPC_00 = 0x00,
13454 ADDIUPC_01 = 0x01,
13455 ADDIUPC_02 = 0x02,
13456 ADDIUPC_03 = 0x03,
13457 ADDIUPC_04 = 0x04,
13458 ADDIUPC_05 = 0x05,
13459 ADDIUPC_06 = 0x06,
13460 ADDIUPC_07 = 0x07,
13461 AUIPC = 0x1e,
13462 ALUIPC = 0x1f,
13463 LWPC_08 = 0x08,
13464 LWPC_09 = 0x09,
13465 LWPC_0A = 0x0A,
13466 LWPC_0B = 0x0B,
13467 LWPC_0C = 0x0C,
13468 LWPC_0D = 0x0D,
13469 LWPC_0E = 0x0E,
13470 LWPC_0F = 0x0F,
13473 /* POOL32A encoding of minor opcode field */
13475 enum {
13476 /* These opcodes are distinguished only by bits 9..6; those bits are
13477 * what are recorded below. */
13478 SLL32 = 0x0,
13479 SRL32 = 0x1,
13480 SRA = 0x2,
13481 ROTR = 0x3,
13482 SELEQZ = 0x5,
13483 SELNEZ = 0x6,
13484 R6_RDHWR = 0x7,
13486 SLLV = 0x0,
13487 SRLV = 0x1,
13488 SRAV = 0x2,
13489 ROTRV = 0x3,
13490 ADD = 0x4,
13491 ADDU32 = 0x5,
13492 SUB = 0x6,
13493 SUBU32 = 0x7,
13494 MUL = 0x8,
13495 AND = 0x9,
13496 OR32 = 0xa,
13497 NOR = 0xb,
13498 XOR32 = 0xc,
13499 SLT = 0xd,
13500 SLTU = 0xe,
13502 MOVN = 0x0,
13503 R6_MUL = 0x0,
13504 MOVZ = 0x1,
13505 MUH = 0x1,
13506 MULU = 0x2,
13507 MUHU = 0x3,
13508 LWXS = 0x4,
13509 R6_DIV = 0x4,
13510 MOD = 0x5,
13511 R6_DIVU = 0x6,
13512 MODU = 0x7,
13514 /* The following can be distinguished by their lower 6 bits. */
13515 BREAK32 = 0x07,
13516 INS = 0x0c,
13517 LSA = 0x0f,
13518 ALIGN = 0x1f,
13519 EXT = 0x2c,
13520 POOL32AXF = 0x3c,
13521 SIGRIE = 0x3f
13524 /* POOL32AXF encoding of minor opcode field extension */
13527 * 1. MIPS Architecture for Programmers Volume II-B:
13528 * The microMIPS32 Instruction Set (Revision 3.05)
13530 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13532 * 2. MIPS Architecture for Programmers VolumeIV-e:
13533 * The MIPS DSP Application-Specific Extension
13534 * to the microMIPS32 Architecture (Revision 2.34)
13536 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13539 enum {
13540 /* bits 11..6 */
13541 TEQ = 0x00,
13542 TGE = 0x08,
13543 TGEU = 0x10,
13544 TLT = 0x20,
13545 TLTU = 0x28,
13546 TNE = 0x30,
13548 MFC0 = 0x03,
13549 MTC0 = 0x0b,
13551 /* begin of microMIPS32 DSP */
13553 /* bits 13..12 for 0x01 */
13554 MFHI_ACC = 0x0,
13555 MFLO_ACC = 0x1,
13556 MTHI_ACC = 0x2,
13557 MTLO_ACC = 0x3,
13559 /* bits 13..12 for 0x2a */
13560 MADD_ACC = 0x0,
13561 MADDU_ACC = 0x1,
13562 MSUB_ACC = 0x2,
13563 MSUBU_ACC = 0x3,
13565 /* bits 13..12 for 0x32 */
13566 MULT_ACC = 0x0,
13567 MULTU_ACC = 0x1,
13569 /* end of microMIPS32 DSP */
13571 /* bits 15..12 for 0x2c */
13572 BITSWAP = 0x0,
13573 SEB = 0x2,
13574 SEH = 0x3,
13575 CLO = 0x4,
13576 CLZ = 0x5,
13577 RDHWR = 0x6,
13578 WSBH = 0x7,
13579 MULT = 0x8,
13580 MULTU = 0x9,
13581 DIV = 0xa,
13582 DIVU = 0xb,
13583 MADD = 0xc,
13584 MADDU = 0xd,
13585 MSUB = 0xe,
13586 MSUBU = 0xf,
13588 /* bits 15..12 for 0x34 */
13589 MFC2 = 0x4,
13590 MTC2 = 0x5,
13591 MFHC2 = 0x8,
13592 MTHC2 = 0x9,
13593 CFC2 = 0xc,
13594 CTC2 = 0xd,
13596 /* bits 15..12 for 0x3c */
13597 JALR = 0x0,
13598 JR = 0x0, /* alias */
13599 JALRC = 0x0,
13600 JRC = 0x0,
13601 JALR_HB = 0x1,
13602 JALRC_HB = 0x1,
13603 JALRS = 0x4,
13604 JALRS_HB = 0x5,
13606 /* bits 15..12 for 0x05 */
13607 RDPGPR = 0xe,
13608 WRPGPR = 0xf,
13610 /* bits 15..12 for 0x0d */
13611 TLBP = 0x0,
13612 TLBR = 0x1,
13613 TLBWI = 0x2,
13614 TLBWR = 0x3,
13615 TLBINV = 0x4,
13616 TLBINVF = 0x5,
13617 WAIT = 0x9,
13618 IRET = 0xd,
13619 DERET = 0xe,
13620 ERET = 0xf,
13622 /* bits 15..12 for 0x15 */
13623 DMT = 0x0,
13624 DVPE = 0x1,
13625 EMT = 0x2,
13626 EVPE = 0x3,
13628 /* bits 15..12 for 0x1d */
13629 DI = 0x4,
13630 EI = 0x5,
13632 /* bits 15..12 for 0x2d */
13633 SYNC = 0x6,
13634 SYSCALL = 0x8,
13635 SDBBP = 0xd,
13637 /* bits 15..12 for 0x35 */
13638 MFHI32 = 0x0,
13639 MFLO32 = 0x1,
13640 MTHI32 = 0x2,
13641 MTLO32 = 0x3,
13644 /* POOL32B encoding of minor opcode field (bits 15..12) */
13646 enum {
13647 LWC2 = 0x0,
13648 LWP = 0x1,
13649 LDP = 0x4,
13650 LWM32 = 0x5,
13651 CACHE = 0x6,
13652 LDM = 0x7,
13653 SWC2 = 0x8,
13654 SWP = 0x9,
13655 SDP = 0xc,
13656 SWM32 = 0xd,
13657 SDM = 0xf
13660 /* POOL32C encoding of minor opcode field (bits 15..12) */
13662 enum {
13663 LWL = 0x0,
13664 SWL = 0x8,
13665 LWR = 0x1,
13666 SWR = 0x9,
13667 PREF = 0x2,
13668 ST_EVA = 0xa,
13669 LL = 0x3,
13670 SC = 0xb,
13671 LDL = 0x4,
13672 SDL = 0xc,
13673 LDR = 0x5,
13674 SDR = 0xd,
13675 LD_EVA = 0x6,
13676 LWU = 0xe,
13677 LLD = 0x7,
13678 SCD = 0xf
13681 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13683 enum {
13684 LBUE = 0x0,
13685 LHUE = 0x1,
13686 LWLE = 0x2,
13687 LWRE = 0x3,
13688 LBE = 0x4,
13689 LHE = 0x5,
13690 LLE = 0x6,
13691 LWE = 0x7,
13694 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13696 enum {
13697 SWLE = 0x0,
13698 SWRE = 0x1,
13699 PREFE = 0x2,
13700 CACHEE = 0x3,
13701 SBE = 0x4,
13702 SHE = 0x5,
13703 SCE = 0x6,
13704 SWE = 0x7,
13707 /* POOL32F encoding of minor opcode field (bits 5..0) */
13709 enum {
13710 /* These are the bit 7..6 values */
13711 ADD_FMT = 0x0,
13713 SUB_FMT = 0x1,
13715 MUL_FMT = 0x2,
13717 DIV_FMT = 0x3,
13719 /* These are the bit 8..6 values */
13720 MOVN_FMT = 0x0,
13721 RSQRT2_FMT = 0x0,
13722 MOVF_FMT = 0x0,
13723 RINT_FMT = 0x0,
13724 SELNEZ_FMT = 0x0,
13726 MOVZ_FMT = 0x1,
13727 LWXC1 = 0x1,
13728 MOVT_FMT = 0x1,
13729 CLASS_FMT = 0x1,
13730 SELEQZ_FMT = 0x1,
13732 PLL_PS = 0x2,
13733 SWXC1 = 0x2,
13734 SEL_FMT = 0x2,
13736 PLU_PS = 0x3,
13737 LDXC1 = 0x3,
13739 MOVN_FMT_04 = 0x4,
13740 PUL_PS = 0x4,
13741 SDXC1 = 0x4,
13742 RECIP2_FMT = 0x4,
13744 MOVZ_FMT_05 = 0x05,
13745 PUU_PS = 0x5,
13746 LUXC1 = 0x5,
13748 CVT_PS_S = 0x6,
13749 SUXC1 = 0x6,
13750 ADDR_PS = 0x6,
13751 PREFX = 0x6,
13752 MADDF_FMT = 0x6,
13754 MULR_PS = 0x7,
13755 MSUBF_FMT = 0x7,
13757 MADD_S = 0x01,
13758 MADD_D = 0x09,
13759 MADD_PS = 0x11,
13760 ALNV_PS = 0x19,
13761 MSUB_S = 0x21,
13762 MSUB_D = 0x29,
13763 MSUB_PS = 0x31,
13765 NMADD_S = 0x02,
13766 NMADD_D = 0x0a,
13767 NMADD_PS = 0x12,
13768 NMSUB_S = 0x22,
13769 NMSUB_D = 0x2a,
13770 NMSUB_PS = 0x32,
13772 MIN_FMT = 0x3,
13773 MAX_FMT = 0xb,
13774 MINA_FMT = 0x23,
13775 MAXA_FMT = 0x2b,
13776 POOL32FXF = 0x3b,
13778 CABS_COND_FMT = 0x1c, /* MIPS3D */
13779 C_COND_FMT = 0x3c,
13781 CMP_CONDN_S = 0x5,
13782 CMP_CONDN_D = 0x15
13785 /* POOL32Fxf encoding of minor opcode extension field */
13787 enum {
13788 CVT_L = 0x04,
13789 RSQRT_FMT = 0x08,
13790 FLOOR_L = 0x0c,
13791 CVT_PW_PS = 0x1c,
13792 CVT_W = 0x24,
13793 SQRT_FMT = 0x28,
13794 FLOOR_W = 0x2c,
13795 CVT_PS_PW = 0x3c,
13796 CFC1 = 0x40,
13797 RECIP_FMT = 0x48,
13798 CEIL_L = 0x4c,
13799 CTC1 = 0x60,
13800 CEIL_W = 0x6c,
13801 MFC1 = 0x80,
13802 CVT_S_PL = 0x84,
13803 TRUNC_L = 0x8c,
13804 MTC1 = 0xa0,
13805 CVT_S_PU = 0xa4,
13806 TRUNC_W = 0xac,
13807 MFHC1 = 0xc0,
13808 ROUND_L = 0xcc,
13809 MTHC1 = 0xe0,
13810 ROUND_W = 0xec,
13812 MOV_FMT = 0x01,
13813 MOVF = 0x05,
13814 ABS_FMT = 0x0d,
13815 RSQRT1_FMT = 0x1d,
13816 MOVT = 0x25,
13817 NEG_FMT = 0x2d,
13818 CVT_D = 0x4d,
13819 RECIP1_FMT = 0x5d,
13820 CVT_S = 0x6d
13823 /* POOL32I encoding of minor opcode field (bits 25..21) */
13825 enum {
13826 BLTZ = 0x00,
13827 BLTZAL = 0x01,
13828 BGEZ = 0x02,
13829 BGEZAL = 0x03,
13830 BLEZ = 0x04,
13831 BNEZC = 0x05,
13832 BGTZ = 0x06,
13833 BEQZC = 0x07,
13834 TLTI = 0x08,
13835 BC1EQZC = 0x08,
13836 TGEI = 0x09,
13837 BC1NEZC = 0x09,
13838 TLTIU = 0x0a,
13839 BC2EQZC = 0x0a,
13840 TGEIU = 0x0b,
13841 BC2NEZC = 0x0a,
13842 TNEI = 0x0c,
13843 R6_SYNCI = 0x0c,
13844 LUI = 0x0d,
13845 TEQI = 0x0e,
13846 SYNCI = 0x10,
13847 BLTZALS = 0x11,
13848 BGEZALS = 0x13,
13849 BC2F = 0x14,
13850 BC2T = 0x15,
13851 BPOSGE64 = 0x1a,
13852 BPOSGE32 = 0x1b,
13853 /* These overlap and are distinguished by bit16 of the instruction */
13854 BC1F = 0x1c,
13855 BC1T = 0x1d,
13856 BC1ANY2F = 0x1c,
13857 BC1ANY2T = 0x1d,
13858 BC1ANY4F = 0x1e,
13859 BC1ANY4T = 0x1f
13862 /* POOL16A encoding of minor opcode field */
13864 enum {
13865 ADDU16 = 0x0,
13866 SUBU16 = 0x1
13869 /* POOL16B encoding of minor opcode field */
13871 enum {
13872 SLL16 = 0x0,
13873 SRL16 = 0x1
13876 /* POOL16C encoding of minor opcode field */
13878 enum {
13879 NOT16 = 0x00,
13880 XOR16 = 0x04,
13881 AND16 = 0x08,
13882 OR16 = 0x0c,
13883 LWM16 = 0x10,
13884 SWM16 = 0x14,
13885 JR16 = 0x18,
13886 JRC16 = 0x1a,
13887 JALR16 = 0x1c,
13888 JALR16S = 0x1e,
13889 MFHI16 = 0x20,
13890 MFLO16 = 0x24,
13891 BREAK16 = 0x28,
13892 SDBBP16 = 0x2c,
13893 JRADDIUSP = 0x30
13896 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
13898 enum {
13899 R6_NOT16 = 0x00,
13900 R6_AND16 = 0x01,
13901 R6_LWM16 = 0x02,
13902 R6_JRC16 = 0x03,
13903 MOVEP = 0x04,
13904 MOVEP_05 = 0x05,
13905 MOVEP_06 = 0x06,
13906 MOVEP_07 = 0x07,
13907 R6_XOR16 = 0x08,
13908 R6_OR16 = 0x09,
13909 R6_SWM16 = 0x0a,
13910 JALRC16 = 0x0b,
13911 MOVEP_0C = 0x0c,
13912 MOVEP_0D = 0x0d,
13913 MOVEP_0E = 0x0e,
13914 MOVEP_0F = 0x0f,
13915 JRCADDIUSP = 0x13,
13916 R6_BREAK16 = 0x1b,
13917 R6_SDBBP16 = 0x3b
13920 /* POOL16D encoding of minor opcode field */
13922 enum {
13923 ADDIUS5 = 0x0,
13924 ADDIUSP = 0x1
13927 /* POOL16E encoding of minor opcode field */
13929 enum {
13930 ADDIUR2 = 0x0,
13931 ADDIUR1SP = 0x1
13934 static int mmreg (int r)
13936 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13938 return map[r];
13941 /* Used for 16-bit store instructions. */
13942 static int mmreg2 (int r)
13944 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
13946 return map[r];
13949 #define uMIPS_RD(op) ((op >> 7) & 0x7)
13950 #define uMIPS_RS(op) ((op >> 4) & 0x7)
13951 #define uMIPS_RS2(op) uMIPS_RS(op)
13952 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
13953 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
13954 #define uMIPS_RS5(op) (op & 0x1f)
13956 /* Signed immediate */
13957 #define SIMM(op, start, width) \
13958 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
13959 << (32-width)) \
13960 >> (32-width))
13961 /* Zero-extended immediate */
13962 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
13964 static void gen_addiur1sp(DisasContext *ctx)
13966 int rd = mmreg(uMIPS_RD(ctx->opcode));
13968 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
13971 static void gen_addiur2(DisasContext *ctx)
13973 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
13974 int rd = mmreg(uMIPS_RD(ctx->opcode));
13975 int rs = mmreg(uMIPS_RS(ctx->opcode));
13977 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
13980 static void gen_addiusp(DisasContext *ctx)
13982 int encoded = ZIMM(ctx->opcode, 1, 9);
13983 int decoded;
13985 if (encoded <= 1) {
13986 decoded = 256 + encoded;
13987 } else if (encoded <= 255) {
13988 decoded = encoded;
13989 } else if (encoded <= 509) {
13990 decoded = encoded - 512;
13991 } else {
13992 decoded = encoded - 768;
13995 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
13998 static void gen_addius5(DisasContext *ctx)
14000 int imm = SIMM(ctx->opcode, 1, 4);
14001 int rd = (ctx->opcode >> 5) & 0x1f;
14003 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14006 static void gen_andi16(DisasContext *ctx)
14008 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14009 31, 32, 63, 64, 255, 32768, 65535 };
14010 int rd = mmreg(uMIPS_RD(ctx->opcode));
14011 int rs = mmreg(uMIPS_RS(ctx->opcode));
14012 int encoded = ZIMM(ctx->opcode, 0, 4);
14014 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14017 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14018 int base, int16_t offset)
14020 TCGv t0, t1;
14021 TCGv_i32 t2;
14023 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14024 generate_exception_end(ctx, EXCP_RI);
14025 return;
14028 t0 = tcg_temp_new();
14030 gen_base_offset_addr(ctx, t0, base, offset);
14032 t1 = tcg_const_tl(reglist);
14033 t2 = tcg_const_i32(ctx->mem_idx);
14035 save_cpu_state(ctx, 1);
14036 switch (opc) {
14037 case LWM32:
14038 gen_helper_lwm(cpu_env, t0, t1, t2);
14039 break;
14040 case SWM32:
14041 gen_helper_swm(cpu_env, t0, t1, t2);
14042 break;
14043 #ifdef TARGET_MIPS64
14044 case LDM:
14045 gen_helper_ldm(cpu_env, t0, t1, t2);
14046 break;
14047 case SDM:
14048 gen_helper_sdm(cpu_env, t0, t1, t2);
14049 break;
14050 #endif
14052 tcg_temp_free(t0);
14053 tcg_temp_free(t1);
14054 tcg_temp_free_i32(t2);
14058 static void gen_pool16c_insn(DisasContext *ctx)
14060 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14061 int rs = mmreg(ctx->opcode & 0x7);
14063 switch (((ctx->opcode) >> 4) & 0x3f) {
14064 case NOT16 + 0:
14065 case NOT16 + 1:
14066 case NOT16 + 2:
14067 case NOT16 + 3:
14068 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14069 break;
14070 case XOR16 + 0:
14071 case XOR16 + 1:
14072 case XOR16 + 2:
14073 case XOR16 + 3:
14074 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14075 break;
14076 case AND16 + 0:
14077 case AND16 + 1:
14078 case AND16 + 2:
14079 case AND16 + 3:
14080 gen_logic(ctx, OPC_AND, rd, rd, rs);
14081 break;
14082 case OR16 + 0:
14083 case OR16 + 1:
14084 case OR16 + 2:
14085 case OR16 + 3:
14086 gen_logic(ctx, OPC_OR, rd, rd, rs);
14087 break;
14088 case LWM16 + 0:
14089 case LWM16 + 1:
14090 case LWM16 + 2:
14091 case LWM16 + 3:
14093 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14094 int offset = ZIMM(ctx->opcode, 0, 4);
14096 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14097 29, offset << 2);
14099 break;
14100 case SWM16 + 0:
14101 case SWM16 + 1:
14102 case SWM16 + 2:
14103 case SWM16 + 3:
14105 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14106 int offset = ZIMM(ctx->opcode, 0, 4);
14108 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14109 29, offset << 2);
14111 break;
14112 case JR16 + 0:
14113 case JR16 + 1:
14115 int reg = ctx->opcode & 0x1f;
14117 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14119 break;
14120 case JRC16 + 0:
14121 case JRC16 + 1:
14123 int reg = ctx->opcode & 0x1f;
14124 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14125 /* Let normal delay slot handling in our caller take us
14126 to the branch target. */
14128 break;
14129 case JALR16 + 0:
14130 case JALR16 + 1:
14131 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14132 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14133 break;
14134 case JALR16S + 0:
14135 case JALR16S + 1:
14136 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14137 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14138 break;
14139 case MFHI16 + 0:
14140 case MFHI16 + 1:
14141 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14142 break;
14143 case MFLO16 + 0:
14144 case MFLO16 + 1:
14145 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14146 break;
14147 case BREAK16:
14148 generate_exception_end(ctx, EXCP_BREAK);
14149 break;
14150 case SDBBP16:
14151 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14152 gen_helper_do_semihosting(cpu_env);
14153 } else {
14154 /* XXX: not clear which exception should be raised
14155 * when in debug mode...
14157 check_insn(ctx, ISA_MIPS32);
14158 generate_exception_end(ctx, EXCP_DBp);
14160 break;
14161 case JRADDIUSP + 0:
14162 case JRADDIUSP + 1:
14164 int imm = ZIMM(ctx->opcode, 0, 5);
14165 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14166 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14167 /* Let normal delay slot handling in our caller take us
14168 to the branch target. */
14170 break;
14171 default:
14172 generate_exception_end(ctx, EXCP_RI);
14173 break;
14177 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14178 int enc_rs)
14180 int rd, rs, re, rt;
14181 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14182 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14183 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14184 rd = rd_enc[enc_dest];
14185 re = re_enc[enc_dest];
14186 rs = rs_rt_enc[enc_rs];
14187 rt = rs_rt_enc[enc_rt];
14188 if (rs) {
14189 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14190 } else {
14191 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14193 if (rt) {
14194 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14195 } else {
14196 tcg_gen_movi_tl(cpu_gpr[re], 0);
14200 static void gen_pool16c_r6_insn(DisasContext *ctx)
14202 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14203 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14205 switch (ctx->opcode & 0xf) {
14206 case R6_NOT16:
14207 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14208 break;
14209 case R6_AND16:
14210 gen_logic(ctx, OPC_AND, rt, rt, rs);
14211 break;
14212 case R6_LWM16:
14214 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14215 int offset = extract32(ctx->opcode, 4, 4);
14216 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14218 break;
14219 case R6_JRC16: /* JRCADDIUSP */
14220 if ((ctx->opcode >> 4) & 1) {
14221 /* JRCADDIUSP */
14222 int imm = extract32(ctx->opcode, 5, 5);
14223 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14224 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14225 } else {
14226 /* JRC16 */
14227 rs = extract32(ctx->opcode, 5, 5);
14228 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14230 break;
14231 case MOVEP:
14232 case MOVEP_05:
14233 case MOVEP_06:
14234 case MOVEP_07:
14235 case MOVEP_0C:
14236 case MOVEP_0D:
14237 case MOVEP_0E:
14238 case MOVEP_0F:
14240 int enc_dest = uMIPS_RD(ctx->opcode);
14241 int enc_rt = uMIPS_RS2(ctx->opcode);
14242 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14243 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14245 break;
14246 case R6_XOR16:
14247 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14248 break;
14249 case R6_OR16:
14250 gen_logic(ctx, OPC_OR, rt, rt, rs);
14251 break;
14252 case R6_SWM16:
14254 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14255 int offset = extract32(ctx->opcode, 4, 4);
14256 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14258 break;
14259 case JALRC16: /* BREAK16, SDBBP16 */
14260 switch (ctx->opcode & 0x3f) {
14261 case JALRC16:
14262 case JALRC16 + 0x20:
14263 /* JALRC16 */
14264 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14265 31, 0, 0);
14266 break;
14267 case R6_BREAK16:
14268 /* BREAK16 */
14269 generate_exception(ctx, EXCP_BREAK);
14270 break;
14271 case R6_SDBBP16:
14272 /* SDBBP16 */
14273 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14274 gen_helper_do_semihosting(cpu_env);
14275 } else {
14276 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14277 generate_exception(ctx, EXCP_RI);
14278 } else {
14279 generate_exception(ctx, EXCP_DBp);
14282 break;
14284 break;
14285 default:
14286 generate_exception(ctx, EXCP_RI);
14287 break;
14291 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14293 TCGv t0 = tcg_temp_new();
14294 TCGv t1 = tcg_temp_new();
14296 gen_load_gpr(t0, base);
14298 if (index != 0) {
14299 gen_load_gpr(t1, index);
14300 tcg_gen_shli_tl(t1, t1, 2);
14301 gen_op_addr_add(ctx, t0, t1, t0);
14304 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14305 gen_store_gpr(t1, rd);
14307 tcg_temp_free(t0);
14308 tcg_temp_free(t1);
14311 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14312 int base, int16_t offset)
14314 TCGv t0, t1;
14316 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14317 generate_exception_end(ctx, EXCP_RI);
14318 return;
14321 t0 = tcg_temp_new();
14322 t1 = tcg_temp_new();
14324 gen_base_offset_addr(ctx, t0, base, offset);
14326 switch (opc) {
14327 case LWP:
14328 if (rd == base) {
14329 generate_exception_end(ctx, EXCP_RI);
14330 return;
14332 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14333 gen_store_gpr(t1, rd);
14334 tcg_gen_movi_tl(t1, 4);
14335 gen_op_addr_add(ctx, t0, t0, t1);
14336 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14337 gen_store_gpr(t1, rd+1);
14338 break;
14339 case SWP:
14340 gen_load_gpr(t1, rd);
14341 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14342 tcg_gen_movi_tl(t1, 4);
14343 gen_op_addr_add(ctx, t0, t0, t1);
14344 gen_load_gpr(t1, rd+1);
14345 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14346 break;
14347 #ifdef TARGET_MIPS64
14348 case LDP:
14349 if (rd == base) {
14350 generate_exception_end(ctx, EXCP_RI);
14351 return;
14353 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14354 gen_store_gpr(t1, rd);
14355 tcg_gen_movi_tl(t1, 8);
14356 gen_op_addr_add(ctx, t0, t0, t1);
14357 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14358 gen_store_gpr(t1, rd+1);
14359 break;
14360 case SDP:
14361 gen_load_gpr(t1, rd);
14362 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14363 tcg_gen_movi_tl(t1, 8);
14364 gen_op_addr_add(ctx, t0, t0, t1);
14365 gen_load_gpr(t1, rd+1);
14366 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14367 break;
14368 #endif
14370 tcg_temp_free(t0);
14371 tcg_temp_free(t1);
14374 static void gen_sync(int stype)
14376 TCGBar tcg_mo = TCG_BAR_SC;
14378 switch (stype) {
14379 case 0x4: /* SYNC_WMB */
14380 tcg_mo |= TCG_MO_ST_ST;
14381 break;
14382 case 0x10: /* SYNC_MB */
14383 tcg_mo |= TCG_MO_ALL;
14384 break;
14385 case 0x11: /* SYNC_ACQUIRE */
14386 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14387 break;
14388 case 0x12: /* SYNC_RELEASE */
14389 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14390 break;
14391 case 0x13: /* SYNC_RMB */
14392 tcg_mo |= TCG_MO_LD_LD;
14393 break;
14394 default:
14395 tcg_mo |= TCG_MO_ALL;
14396 break;
14399 tcg_gen_mb(tcg_mo);
14402 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14404 int extension = (ctx->opcode >> 6) & 0x3f;
14405 int minor = (ctx->opcode >> 12) & 0xf;
14406 uint32_t mips32_op;
14408 switch (extension) {
14409 case TEQ:
14410 mips32_op = OPC_TEQ;
14411 goto do_trap;
14412 case TGE:
14413 mips32_op = OPC_TGE;
14414 goto do_trap;
14415 case TGEU:
14416 mips32_op = OPC_TGEU;
14417 goto do_trap;
14418 case TLT:
14419 mips32_op = OPC_TLT;
14420 goto do_trap;
14421 case TLTU:
14422 mips32_op = OPC_TLTU;
14423 goto do_trap;
14424 case TNE:
14425 mips32_op = OPC_TNE;
14426 do_trap:
14427 gen_trap(ctx, mips32_op, rs, rt, -1);
14428 break;
14429 #ifndef CONFIG_USER_ONLY
14430 case MFC0:
14431 case MFC0 + 32:
14432 check_cp0_enabled(ctx);
14433 if (rt == 0) {
14434 /* Treat as NOP. */
14435 break;
14437 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14438 break;
14439 case MTC0:
14440 case MTC0 + 32:
14441 check_cp0_enabled(ctx);
14443 TCGv t0 = tcg_temp_new();
14445 gen_load_gpr(t0, rt);
14446 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14447 tcg_temp_free(t0);
14449 break;
14450 #endif
14451 case 0x2a:
14452 switch (minor & 3) {
14453 case MADD_ACC:
14454 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14455 break;
14456 case MADDU_ACC:
14457 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14458 break;
14459 case MSUB_ACC:
14460 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14461 break;
14462 case MSUBU_ACC:
14463 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14464 break;
14465 default:
14466 goto pool32axf_invalid;
14468 break;
14469 case 0x32:
14470 switch (minor & 3) {
14471 case MULT_ACC:
14472 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14473 break;
14474 case MULTU_ACC:
14475 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14476 break;
14477 default:
14478 goto pool32axf_invalid;
14480 break;
14481 case 0x2c:
14482 switch (minor) {
14483 case BITSWAP:
14484 check_insn(ctx, ISA_MIPS32R6);
14485 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14486 break;
14487 case SEB:
14488 gen_bshfl(ctx, OPC_SEB, rs, rt);
14489 break;
14490 case SEH:
14491 gen_bshfl(ctx, OPC_SEH, rs, rt);
14492 break;
14493 case CLO:
14494 mips32_op = OPC_CLO;
14495 goto do_cl;
14496 case CLZ:
14497 mips32_op = OPC_CLZ;
14498 do_cl:
14499 check_insn(ctx, ISA_MIPS32);
14500 gen_cl(ctx, mips32_op, rt, rs);
14501 break;
14502 case RDHWR:
14503 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14504 gen_rdhwr(ctx, rt, rs, 0);
14505 break;
14506 case WSBH:
14507 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14508 break;
14509 case MULT:
14510 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14511 mips32_op = OPC_MULT;
14512 goto do_mul;
14513 case MULTU:
14514 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14515 mips32_op = OPC_MULTU;
14516 goto do_mul;
14517 case DIV:
14518 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14519 mips32_op = OPC_DIV;
14520 goto do_div;
14521 case DIVU:
14522 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14523 mips32_op = OPC_DIVU;
14524 goto do_div;
14525 do_div:
14526 check_insn(ctx, ISA_MIPS32);
14527 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14528 break;
14529 case MADD:
14530 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14531 mips32_op = OPC_MADD;
14532 goto do_mul;
14533 case MADDU:
14534 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14535 mips32_op = OPC_MADDU;
14536 goto do_mul;
14537 case MSUB:
14538 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14539 mips32_op = OPC_MSUB;
14540 goto do_mul;
14541 case MSUBU:
14542 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14543 mips32_op = OPC_MSUBU;
14544 do_mul:
14545 check_insn(ctx, ISA_MIPS32);
14546 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14547 break;
14548 default:
14549 goto pool32axf_invalid;
14551 break;
14552 case 0x34:
14553 switch (minor) {
14554 case MFC2:
14555 case MTC2:
14556 case MFHC2:
14557 case MTHC2:
14558 case CFC2:
14559 case CTC2:
14560 generate_exception_err(ctx, EXCP_CpU, 2);
14561 break;
14562 default:
14563 goto pool32axf_invalid;
14565 break;
14566 case 0x3c:
14567 switch (minor) {
14568 case JALR: /* JALRC */
14569 case JALR_HB: /* JALRC_HB */
14570 if (ctx->insn_flags & ISA_MIPS32R6) {
14571 /* JALRC, JALRC_HB */
14572 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14573 } else {
14574 /* JALR, JALR_HB */
14575 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14576 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14578 break;
14579 case JALRS:
14580 case JALRS_HB:
14581 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14582 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14583 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14584 break;
14585 default:
14586 goto pool32axf_invalid;
14588 break;
14589 case 0x05:
14590 switch (minor) {
14591 case RDPGPR:
14592 check_cp0_enabled(ctx);
14593 check_insn(ctx, ISA_MIPS32R2);
14594 gen_load_srsgpr(rs, rt);
14595 break;
14596 case WRPGPR:
14597 check_cp0_enabled(ctx);
14598 check_insn(ctx, ISA_MIPS32R2);
14599 gen_store_srsgpr(rs, rt);
14600 break;
14601 default:
14602 goto pool32axf_invalid;
14604 break;
14605 #ifndef CONFIG_USER_ONLY
14606 case 0x0d:
14607 switch (minor) {
14608 case TLBP:
14609 mips32_op = OPC_TLBP;
14610 goto do_cp0;
14611 case TLBR:
14612 mips32_op = OPC_TLBR;
14613 goto do_cp0;
14614 case TLBWI:
14615 mips32_op = OPC_TLBWI;
14616 goto do_cp0;
14617 case TLBWR:
14618 mips32_op = OPC_TLBWR;
14619 goto do_cp0;
14620 case TLBINV:
14621 mips32_op = OPC_TLBINV;
14622 goto do_cp0;
14623 case TLBINVF:
14624 mips32_op = OPC_TLBINVF;
14625 goto do_cp0;
14626 case WAIT:
14627 mips32_op = OPC_WAIT;
14628 goto do_cp0;
14629 case DERET:
14630 mips32_op = OPC_DERET;
14631 goto do_cp0;
14632 case ERET:
14633 mips32_op = OPC_ERET;
14634 do_cp0:
14635 gen_cp0(env, ctx, mips32_op, rt, rs);
14636 break;
14637 default:
14638 goto pool32axf_invalid;
14640 break;
14641 case 0x1d:
14642 switch (minor) {
14643 case DI:
14644 check_cp0_enabled(ctx);
14646 TCGv t0 = tcg_temp_new();
14648 save_cpu_state(ctx, 1);
14649 gen_helper_di(t0, cpu_env);
14650 gen_store_gpr(t0, rs);
14651 /* Stop translation as we may have switched the execution mode */
14652 ctx->base.is_jmp = DISAS_STOP;
14653 tcg_temp_free(t0);
14655 break;
14656 case EI:
14657 check_cp0_enabled(ctx);
14659 TCGv t0 = tcg_temp_new();
14661 save_cpu_state(ctx, 1);
14662 gen_helper_ei(t0, cpu_env);
14663 gen_store_gpr(t0, rs);
14664 /* DISAS_STOP isn't sufficient, we need to ensure we break out
14665 of translated code to check for pending interrupts. */
14666 gen_save_pc(ctx->base.pc_next + 4);
14667 ctx->base.is_jmp = DISAS_EXIT;
14668 tcg_temp_free(t0);
14670 break;
14671 default:
14672 goto pool32axf_invalid;
14674 break;
14675 #endif
14676 case 0x2d:
14677 switch (minor) {
14678 case SYNC:
14679 gen_sync(extract32(ctx->opcode, 16, 5));
14680 break;
14681 case SYSCALL:
14682 generate_exception_end(ctx, EXCP_SYSCALL);
14683 break;
14684 case SDBBP:
14685 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14686 gen_helper_do_semihosting(cpu_env);
14687 } else {
14688 check_insn(ctx, ISA_MIPS32);
14689 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14690 generate_exception_end(ctx, EXCP_RI);
14691 } else {
14692 generate_exception_end(ctx, EXCP_DBp);
14695 break;
14696 default:
14697 goto pool32axf_invalid;
14699 break;
14700 case 0x01:
14701 switch (minor & 3) {
14702 case MFHI_ACC:
14703 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14704 break;
14705 case MFLO_ACC:
14706 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14707 break;
14708 case MTHI_ACC:
14709 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14710 break;
14711 case MTLO_ACC:
14712 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14713 break;
14714 default:
14715 goto pool32axf_invalid;
14717 break;
14718 case 0x35:
14719 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14720 switch (minor) {
14721 case MFHI32:
14722 gen_HILO(ctx, OPC_MFHI, 0, rs);
14723 break;
14724 case MFLO32:
14725 gen_HILO(ctx, OPC_MFLO, 0, rs);
14726 break;
14727 case MTHI32:
14728 gen_HILO(ctx, OPC_MTHI, 0, rs);
14729 break;
14730 case MTLO32:
14731 gen_HILO(ctx, OPC_MTLO, 0, rs);
14732 break;
14733 default:
14734 goto pool32axf_invalid;
14736 break;
14737 default:
14738 pool32axf_invalid:
14739 MIPS_INVAL("pool32axf");
14740 generate_exception_end(ctx, EXCP_RI);
14741 break;
14745 /* Values for microMIPS fmt field. Variable-width, depending on which
14746 formats the instruction supports. */
14748 enum {
14749 FMT_SD_S = 0,
14750 FMT_SD_D = 1,
14752 FMT_SDPS_S = 0,
14753 FMT_SDPS_D = 1,
14754 FMT_SDPS_PS = 2,
14756 FMT_SWL_S = 0,
14757 FMT_SWL_W = 1,
14758 FMT_SWL_L = 2,
14760 FMT_DWL_D = 0,
14761 FMT_DWL_W = 1,
14762 FMT_DWL_L = 2
14765 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
14767 int extension = (ctx->opcode >> 6) & 0x3ff;
14768 uint32_t mips32_op;
14770 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
14771 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
14772 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
14774 switch (extension) {
14775 case FLOAT_1BIT_FMT(CFC1, 0):
14776 mips32_op = OPC_CFC1;
14777 goto do_cp1;
14778 case FLOAT_1BIT_FMT(CTC1, 0):
14779 mips32_op = OPC_CTC1;
14780 goto do_cp1;
14781 case FLOAT_1BIT_FMT(MFC1, 0):
14782 mips32_op = OPC_MFC1;
14783 goto do_cp1;
14784 case FLOAT_1BIT_FMT(MTC1, 0):
14785 mips32_op = OPC_MTC1;
14786 goto do_cp1;
14787 case FLOAT_1BIT_FMT(MFHC1, 0):
14788 mips32_op = OPC_MFHC1;
14789 goto do_cp1;
14790 case FLOAT_1BIT_FMT(MTHC1, 0):
14791 mips32_op = OPC_MTHC1;
14792 do_cp1:
14793 gen_cp1(ctx, mips32_op, rt, rs);
14794 break;
14796 /* Reciprocal square root */
14797 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
14798 mips32_op = OPC_RSQRT_S;
14799 goto do_unaryfp;
14800 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
14801 mips32_op = OPC_RSQRT_D;
14802 goto do_unaryfp;
14804 /* Square root */
14805 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
14806 mips32_op = OPC_SQRT_S;
14807 goto do_unaryfp;
14808 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
14809 mips32_op = OPC_SQRT_D;
14810 goto do_unaryfp;
14812 /* Reciprocal */
14813 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
14814 mips32_op = OPC_RECIP_S;
14815 goto do_unaryfp;
14816 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
14817 mips32_op = OPC_RECIP_D;
14818 goto do_unaryfp;
14820 /* Floor */
14821 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
14822 mips32_op = OPC_FLOOR_L_S;
14823 goto do_unaryfp;
14824 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
14825 mips32_op = OPC_FLOOR_L_D;
14826 goto do_unaryfp;
14827 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
14828 mips32_op = OPC_FLOOR_W_S;
14829 goto do_unaryfp;
14830 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
14831 mips32_op = OPC_FLOOR_W_D;
14832 goto do_unaryfp;
14834 /* Ceiling */
14835 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
14836 mips32_op = OPC_CEIL_L_S;
14837 goto do_unaryfp;
14838 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
14839 mips32_op = OPC_CEIL_L_D;
14840 goto do_unaryfp;
14841 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
14842 mips32_op = OPC_CEIL_W_S;
14843 goto do_unaryfp;
14844 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
14845 mips32_op = OPC_CEIL_W_D;
14846 goto do_unaryfp;
14848 /* Truncation */
14849 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
14850 mips32_op = OPC_TRUNC_L_S;
14851 goto do_unaryfp;
14852 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
14853 mips32_op = OPC_TRUNC_L_D;
14854 goto do_unaryfp;
14855 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
14856 mips32_op = OPC_TRUNC_W_S;
14857 goto do_unaryfp;
14858 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
14859 mips32_op = OPC_TRUNC_W_D;
14860 goto do_unaryfp;
14862 /* Round */
14863 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
14864 mips32_op = OPC_ROUND_L_S;
14865 goto do_unaryfp;
14866 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
14867 mips32_op = OPC_ROUND_L_D;
14868 goto do_unaryfp;
14869 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
14870 mips32_op = OPC_ROUND_W_S;
14871 goto do_unaryfp;
14872 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
14873 mips32_op = OPC_ROUND_W_D;
14874 goto do_unaryfp;
14876 /* Integer to floating-point conversion */
14877 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
14878 mips32_op = OPC_CVT_L_S;
14879 goto do_unaryfp;
14880 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
14881 mips32_op = OPC_CVT_L_D;
14882 goto do_unaryfp;
14883 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
14884 mips32_op = OPC_CVT_W_S;
14885 goto do_unaryfp;
14886 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
14887 mips32_op = OPC_CVT_W_D;
14888 goto do_unaryfp;
14890 /* Paired-foo conversions */
14891 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
14892 mips32_op = OPC_CVT_S_PL;
14893 goto do_unaryfp;
14894 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
14895 mips32_op = OPC_CVT_S_PU;
14896 goto do_unaryfp;
14897 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
14898 mips32_op = OPC_CVT_PW_PS;
14899 goto do_unaryfp;
14900 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
14901 mips32_op = OPC_CVT_PS_PW;
14902 goto do_unaryfp;
14904 /* Floating-point moves */
14905 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
14906 mips32_op = OPC_MOV_S;
14907 goto do_unaryfp;
14908 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
14909 mips32_op = OPC_MOV_D;
14910 goto do_unaryfp;
14911 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
14912 mips32_op = OPC_MOV_PS;
14913 goto do_unaryfp;
14915 /* Absolute value */
14916 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
14917 mips32_op = OPC_ABS_S;
14918 goto do_unaryfp;
14919 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
14920 mips32_op = OPC_ABS_D;
14921 goto do_unaryfp;
14922 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
14923 mips32_op = OPC_ABS_PS;
14924 goto do_unaryfp;
14926 /* Negation */
14927 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
14928 mips32_op = OPC_NEG_S;
14929 goto do_unaryfp;
14930 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
14931 mips32_op = OPC_NEG_D;
14932 goto do_unaryfp;
14933 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
14934 mips32_op = OPC_NEG_PS;
14935 goto do_unaryfp;
14937 /* Reciprocal square root step */
14938 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
14939 mips32_op = OPC_RSQRT1_S;
14940 goto do_unaryfp;
14941 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
14942 mips32_op = OPC_RSQRT1_D;
14943 goto do_unaryfp;
14944 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
14945 mips32_op = OPC_RSQRT1_PS;
14946 goto do_unaryfp;
14948 /* Reciprocal step */
14949 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
14950 mips32_op = OPC_RECIP1_S;
14951 goto do_unaryfp;
14952 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
14953 mips32_op = OPC_RECIP1_S;
14954 goto do_unaryfp;
14955 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
14956 mips32_op = OPC_RECIP1_PS;
14957 goto do_unaryfp;
14959 /* Conversions from double */
14960 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
14961 mips32_op = OPC_CVT_D_S;
14962 goto do_unaryfp;
14963 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
14964 mips32_op = OPC_CVT_D_W;
14965 goto do_unaryfp;
14966 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
14967 mips32_op = OPC_CVT_D_L;
14968 goto do_unaryfp;
14970 /* Conversions from single */
14971 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
14972 mips32_op = OPC_CVT_S_D;
14973 goto do_unaryfp;
14974 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
14975 mips32_op = OPC_CVT_S_W;
14976 goto do_unaryfp;
14977 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
14978 mips32_op = OPC_CVT_S_L;
14979 do_unaryfp:
14980 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
14981 break;
14983 /* Conditional moves on floating-point codes */
14984 case COND_FLOAT_MOV(MOVT, 0):
14985 case COND_FLOAT_MOV(MOVT, 1):
14986 case COND_FLOAT_MOV(MOVT, 2):
14987 case COND_FLOAT_MOV(MOVT, 3):
14988 case COND_FLOAT_MOV(MOVT, 4):
14989 case COND_FLOAT_MOV(MOVT, 5):
14990 case COND_FLOAT_MOV(MOVT, 6):
14991 case COND_FLOAT_MOV(MOVT, 7):
14992 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14993 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
14994 break;
14995 case COND_FLOAT_MOV(MOVF, 0):
14996 case COND_FLOAT_MOV(MOVF, 1):
14997 case COND_FLOAT_MOV(MOVF, 2):
14998 case COND_FLOAT_MOV(MOVF, 3):
14999 case COND_FLOAT_MOV(MOVF, 4):
15000 case COND_FLOAT_MOV(MOVF, 5):
15001 case COND_FLOAT_MOV(MOVF, 6):
15002 case COND_FLOAT_MOV(MOVF, 7):
15003 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15004 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15005 break;
15006 default:
15007 MIPS_INVAL("pool32fxf");
15008 generate_exception_end(ctx, EXCP_RI);
15009 break;
15013 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15015 int32_t offset;
15016 uint16_t insn;
15017 int rt, rs, rd, rr;
15018 int16_t imm;
15019 uint32_t op, minor, minor2, mips32_op;
15020 uint32_t cond, fmt, cc;
15022 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15023 ctx->opcode = (ctx->opcode << 16) | insn;
15025 rt = (ctx->opcode >> 21) & 0x1f;
15026 rs = (ctx->opcode >> 16) & 0x1f;
15027 rd = (ctx->opcode >> 11) & 0x1f;
15028 rr = (ctx->opcode >> 6) & 0x1f;
15029 imm = (int16_t) ctx->opcode;
15031 op = (ctx->opcode >> 26) & 0x3f;
15032 switch (op) {
15033 case POOL32A:
15034 minor = ctx->opcode & 0x3f;
15035 switch (minor) {
15036 case 0x00:
15037 minor = (ctx->opcode >> 6) & 0xf;
15038 switch (minor) {
15039 case SLL32:
15040 mips32_op = OPC_SLL;
15041 goto do_shifti;
15042 case SRA:
15043 mips32_op = OPC_SRA;
15044 goto do_shifti;
15045 case SRL32:
15046 mips32_op = OPC_SRL;
15047 goto do_shifti;
15048 case ROTR:
15049 mips32_op = OPC_ROTR;
15050 do_shifti:
15051 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15052 break;
15053 case SELEQZ:
15054 check_insn(ctx, ISA_MIPS32R6);
15055 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15056 break;
15057 case SELNEZ:
15058 check_insn(ctx, ISA_MIPS32R6);
15059 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15060 break;
15061 case R6_RDHWR:
15062 check_insn(ctx, ISA_MIPS32R6);
15063 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15064 break;
15065 default:
15066 goto pool32a_invalid;
15068 break;
15069 case 0x10:
15070 minor = (ctx->opcode >> 6) & 0xf;
15071 switch (minor) {
15072 /* Arithmetic */
15073 case ADD:
15074 mips32_op = OPC_ADD;
15075 goto do_arith;
15076 case ADDU32:
15077 mips32_op = OPC_ADDU;
15078 goto do_arith;
15079 case SUB:
15080 mips32_op = OPC_SUB;
15081 goto do_arith;
15082 case SUBU32:
15083 mips32_op = OPC_SUBU;
15084 goto do_arith;
15085 case MUL:
15086 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15087 mips32_op = OPC_MUL;
15088 do_arith:
15089 gen_arith(ctx, mips32_op, rd, rs, rt);
15090 break;
15091 /* Shifts */
15092 case SLLV:
15093 mips32_op = OPC_SLLV;
15094 goto do_shift;
15095 case SRLV:
15096 mips32_op = OPC_SRLV;
15097 goto do_shift;
15098 case SRAV:
15099 mips32_op = OPC_SRAV;
15100 goto do_shift;
15101 case ROTRV:
15102 mips32_op = OPC_ROTRV;
15103 do_shift:
15104 gen_shift(ctx, mips32_op, rd, rs, rt);
15105 break;
15106 /* Logical operations */
15107 case AND:
15108 mips32_op = OPC_AND;
15109 goto do_logic;
15110 case OR32:
15111 mips32_op = OPC_OR;
15112 goto do_logic;
15113 case NOR:
15114 mips32_op = OPC_NOR;
15115 goto do_logic;
15116 case XOR32:
15117 mips32_op = OPC_XOR;
15118 do_logic:
15119 gen_logic(ctx, mips32_op, rd, rs, rt);
15120 break;
15121 /* Set less than */
15122 case SLT:
15123 mips32_op = OPC_SLT;
15124 goto do_slt;
15125 case SLTU:
15126 mips32_op = OPC_SLTU;
15127 do_slt:
15128 gen_slt(ctx, mips32_op, rd, rs, rt);
15129 break;
15130 default:
15131 goto pool32a_invalid;
15133 break;
15134 case 0x18:
15135 minor = (ctx->opcode >> 6) & 0xf;
15136 switch (minor) {
15137 /* Conditional moves */
15138 case MOVN: /* MUL */
15139 if (ctx->insn_flags & ISA_MIPS32R6) {
15140 /* MUL */
15141 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15142 } else {
15143 /* MOVN */
15144 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15146 break;
15147 case MOVZ: /* MUH */
15148 if (ctx->insn_flags & ISA_MIPS32R6) {
15149 /* MUH */
15150 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15151 } else {
15152 /* MOVZ */
15153 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15155 break;
15156 case MULU:
15157 check_insn(ctx, ISA_MIPS32R6);
15158 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15159 break;
15160 case MUHU:
15161 check_insn(ctx, ISA_MIPS32R6);
15162 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15163 break;
15164 case LWXS: /* DIV */
15165 if (ctx->insn_flags & ISA_MIPS32R6) {
15166 /* DIV */
15167 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15168 } else {
15169 /* LWXS */
15170 gen_ldxs(ctx, rs, rt, rd);
15172 break;
15173 case MOD:
15174 check_insn(ctx, ISA_MIPS32R6);
15175 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15176 break;
15177 case R6_DIVU:
15178 check_insn(ctx, ISA_MIPS32R6);
15179 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15180 break;
15181 case MODU:
15182 check_insn(ctx, ISA_MIPS32R6);
15183 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15184 break;
15185 default:
15186 goto pool32a_invalid;
15188 break;
15189 case INS:
15190 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15191 return;
15192 case LSA:
15193 check_insn(ctx, ISA_MIPS32R6);
15194 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15195 extract32(ctx->opcode, 9, 2));
15196 break;
15197 case ALIGN:
15198 check_insn(ctx, ISA_MIPS32R6);
15199 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15200 break;
15201 case EXT:
15202 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15203 return;
15204 case POOL32AXF:
15205 gen_pool32axf(env, ctx, rt, rs);
15206 break;
15207 case BREAK32:
15208 generate_exception_end(ctx, EXCP_BREAK);
15209 break;
15210 case SIGRIE:
15211 check_insn(ctx, ISA_MIPS32R6);
15212 generate_exception_end(ctx, EXCP_RI);
15213 break;
15214 default:
15215 pool32a_invalid:
15216 MIPS_INVAL("pool32a");
15217 generate_exception_end(ctx, EXCP_RI);
15218 break;
15220 break;
15221 case POOL32B:
15222 minor = (ctx->opcode >> 12) & 0xf;
15223 switch (minor) {
15224 case CACHE:
15225 check_cp0_enabled(ctx);
15226 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15227 gen_cache_operation(ctx, rt, rs, imm);
15229 break;
15230 case LWC2:
15231 case SWC2:
15232 /* COP2: Not implemented. */
15233 generate_exception_err(ctx, EXCP_CpU, 2);
15234 break;
15235 #ifdef TARGET_MIPS64
15236 case LDP:
15237 case SDP:
15238 check_insn(ctx, ISA_MIPS3);
15239 check_mips_64(ctx);
15240 #endif
15241 /* fall through */
15242 case LWP:
15243 case SWP:
15244 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15245 break;
15246 #ifdef TARGET_MIPS64
15247 case LDM:
15248 case SDM:
15249 check_insn(ctx, ISA_MIPS3);
15250 check_mips_64(ctx);
15251 #endif
15252 /* fall through */
15253 case LWM32:
15254 case SWM32:
15255 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15256 break;
15257 default:
15258 MIPS_INVAL("pool32b");
15259 generate_exception_end(ctx, EXCP_RI);
15260 break;
15262 break;
15263 case POOL32F:
15264 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15265 minor = ctx->opcode & 0x3f;
15266 check_cp1_enabled(ctx);
15267 switch (minor) {
15268 case ALNV_PS:
15269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15270 mips32_op = OPC_ALNV_PS;
15271 goto do_madd;
15272 case MADD_S:
15273 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15274 mips32_op = OPC_MADD_S;
15275 goto do_madd;
15276 case MADD_D:
15277 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15278 mips32_op = OPC_MADD_D;
15279 goto do_madd;
15280 case MADD_PS:
15281 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15282 mips32_op = OPC_MADD_PS;
15283 goto do_madd;
15284 case MSUB_S:
15285 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15286 mips32_op = OPC_MSUB_S;
15287 goto do_madd;
15288 case MSUB_D:
15289 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15290 mips32_op = OPC_MSUB_D;
15291 goto do_madd;
15292 case MSUB_PS:
15293 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15294 mips32_op = OPC_MSUB_PS;
15295 goto do_madd;
15296 case NMADD_S:
15297 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15298 mips32_op = OPC_NMADD_S;
15299 goto do_madd;
15300 case NMADD_D:
15301 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15302 mips32_op = OPC_NMADD_D;
15303 goto do_madd;
15304 case NMADD_PS:
15305 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15306 mips32_op = OPC_NMADD_PS;
15307 goto do_madd;
15308 case NMSUB_S:
15309 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15310 mips32_op = OPC_NMSUB_S;
15311 goto do_madd;
15312 case NMSUB_D:
15313 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15314 mips32_op = OPC_NMSUB_D;
15315 goto do_madd;
15316 case NMSUB_PS:
15317 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15318 mips32_op = OPC_NMSUB_PS;
15319 do_madd:
15320 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15321 break;
15322 case CABS_COND_FMT:
15323 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15324 cond = (ctx->opcode >> 6) & 0xf;
15325 cc = (ctx->opcode >> 13) & 0x7;
15326 fmt = (ctx->opcode >> 10) & 0x3;
15327 switch (fmt) {
15328 case 0x0:
15329 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15330 break;
15331 case 0x1:
15332 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15333 break;
15334 case 0x2:
15335 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15336 break;
15337 default:
15338 goto pool32f_invalid;
15340 break;
15341 case C_COND_FMT:
15342 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15343 cond = (ctx->opcode >> 6) & 0xf;
15344 cc = (ctx->opcode >> 13) & 0x7;
15345 fmt = (ctx->opcode >> 10) & 0x3;
15346 switch (fmt) {
15347 case 0x0:
15348 gen_cmp_s(ctx, cond, rt, rs, cc);
15349 break;
15350 case 0x1:
15351 gen_cmp_d(ctx, cond, rt, rs, cc);
15352 break;
15353 case 0x2:
15354 gen_cmp_ps(ctx, cond, rt, rs, cc);
15355 break;
15356 default:
15357 goto pool32f_invalid;
15359 break;
15360 case CMP_CONDN_S:
15361 check_insn(ctx, ISA_MIPS32R6);
15362 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15363 break;
15364 case CMP_CONDN_D:
15365 check_insn(ctx, ISA_MIPS32R6);
15366 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15367 break;
15368 case POOL32FXF:
15369 gen_pool32fxf(ctx, rt, rs);
15370 break;
15371 case 0x00:
15372 /* PLL foo */
15373 switch ((ctx->opcode >> 6) & 0x7) {
15374 case PLL_PS:
15375 mips32_op = OPC_PLL_PS;
15376 goto do_ps;
15377 case PLU_PS:
15378 mips32_op = OPC_PLU_PS;
15379 goto do_ps;
15380 case PUL_PS:
15381 mips32_op = OPC_PUL_PS;
15382 goto do_ps;
15383 case PUU_PS:
15384 mips32_op = OPC_PUU_PS;
15385 goto do_ps;
15386 case CVT_PS_S:
15387 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15388 mips32_op = OPC_CVT_PS_S;
15389 do_ps:
15390 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15391 break;
15392 default:
15393 goto pool32f_invalid;
15395 break;
15396 case MIN_FMT:
15397 check_insn(ctx, ISA_MIPS32R6);
15398 switch ((ctx->opcode >> 9) & 0x3) {
15399 case FMT_SDPS_S:
15400 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15401 break;
15402 case FMT_SDPS_D:
15403 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15404 break;
15405 default:
15406 goto pool32f_invalid;
15408 break;
15409 case 0x08:
15410 /* [LS][WDU]XC1 */
15411 switch ((ctx->opcode >> 6) & 0x7) {
15412 case LWXC1:
15413 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15414 mips32_op = OPC_LWXC1;
15415 goto do_ldst_cp1;
15416 case SWXC1:
15417 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15418 mips32_op = OPC_SWXC1;
15419 goto do_ldst_cp1;
15420 case LDXC1:
15421 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15422 mips32_op = OPC_LDXC1;
15423 goto do_ldst_cp1;
15424 case SDXC1:
15425 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15426 mips32_op = OPC_SDXC1;
15427 goto do_ldst_cp1;
15428 case LUXC1:
15429 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15430 mips32_op = OPC_LUXC1;
15431 goto do_ldst_cp1;
15432 case SUXC1:
15433 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15434 mips32_op = OPC_SUXC1;
15435 do_ldst_cp1:
15436 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15437 break;
15438 default:
15439 goto pool32f_invalid;
15441 break;
15442 case MAX_FMT:
15443 check_insn(ctx, ISA_MIPS32R6);
15444 switch ((ctx->opcode >> 9) & 0x3) {
15445 case FMT_SDPS_S:
15446 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15447 break;
15448 case FMT_SDPS_D:
15449 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15450 break;
15451 default:
15452 goto pool32f_invalid;
15454 break;
15455 case 0x18:
15456 /* 3D insns */
15457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15458 fmt = (ctx->opcode >> 9) & 0x3;
15459 switch ((ctx->opcode >> 6) & 0x7) {
15460 case RSQRT2_FMT:
15461 switch (fmt) {
15462 case FMT_SDPS_S:
15463 mips32_op = OPC_RSQRT2_S;
15464 goto do_3d;
15465 case FMT_SDPS_D:
15466 mips32_op = OPC_RSQRT2_D;
15467 goto do_3d;
15468 case FMT_SDPS_PS:
15469 mips32_op = OPC_RSQRT2_PS;
15470 goto do_3d;
15471 default:
15472 goto pool32f_invalid;
15474 break;
15475 case RECIP2_FMT:
15476 switch (fmt) {
15477 case FMT_SDPS_S:
15478 mips32_op = OPC_RECIP2_S;
15479 goto do_3d;
15480 case FMT_SDPS_D:
15481 mips32_op = OPC_RECIP2_D;
15482 goto do_3d;
15483 case FMT_SDPS_PS:
15484 mips32_op = OPC_RECIP2_PS;
15485 goto do_3d;
15486 default:
15487 goto pool32f_invalid;
15489 break;
15490 case ADDR_PS:
15491 mips32_op = OPC_ADDR_PS;
15492 goto do_3d;
15493 case MULR_PS:
15494 mips32_op = OPC_MULR_PS;
15495 do_3d:
15496 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15497 break;
15498 default:
15499 goto pool32f_invalid;
15501 break;
15502 case 0x20:
15503 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
15504 cc = (ctx->opcode >> 13) & 0x7;
15505 fmt = (ctx->opcode >> 9) & 0x3;
15506 switch ((ctx->opcode >> 6) & 0x7) {
15507 case MOVF_FMT: /* RINT_FMT */
15508 if (ctx->insn_flags & ISA_MIPS32R6) {
15509 /* RINT_FMT */
15510 switch (fmt) {
15511 case FMT_SDPS_S:
15512 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15513 break;
15514 case FMT_SDPS_D:
15515 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15516 break;
15517 default:
15518 goto pool32f_invalid;
15520 } else {
15521 /* MOVF_FMT */
15522 switch (fmt) {
15523 case FMT_SDPS_S:
15524 gen_movcf_s(ctx, rs, rt, cc, 0);
15525 break;
15526 case FMT_SDPS_D:
15527 gen_movcf_d(ctx, rs, rt, cc, 0);
15528 break;
15529 case FMT_SDPS_PS:
15530 check_ps(ctx);
15531 gen_movcf_ps(ctx, rs, rt, cc, 0);
15532 break;
15533 default:
15534 goto pool32f_invalid;
15537 break;
15538 case MOVT_FMT: /* CLASS_FMT */
15539 if (ctx->insn_flags & ISA_MIPS32R6) {
15540 /* CLASS_FMT */
15541 switch (fmt) {
15542 case FMT_SDPS_S:
15543 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15544 break;
15545 case FMT_SDPS_D:
15546 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15547 break;
15548 default:
15549 goto pool32f_invalid;
15551 } else {
15552 /* MOVT_FMT */
15553 switch (fmt) {
15554 case FMT_SDPS_S:
15555 gen_movcf_s(ctx, rs, rt, cc, 1);
15556 break;
15557 case FMT_SDPS_D:
15558 gen_movcf_d(ctx, rs, rt, cc, 1);
15559 break;
15560 case FMT_SDPS_PS:
15561 check_ps(ctx);
15562 gen_movcf_ps(ctx, rs, rt, cc, 1);
15563 break;
15564 default:
15565 goto pool32f_invalid;
15568 break;
15569 case PREFX:
15570 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15571 break;
15572 default:
15573 goto pool32f_invalid;
15575 break;
15576 #define FINSN_3ARG_SDPS(prfx) \
15577 switch ((ctx->opcode >> 8) & 0x3) { \
15578 case FMT_SDPS_S: \
15579 mips32_op = OPC_##prfx##_S; \
15580 goto do_fpop; \
15581 case FMT_SDPS_D: \
15582 mips32_op = OPC_##prfx##_D; \
15583 goto do_fpop; \
15584 case FMT_SDPS_PS: \
15585 check_ps(ctx); \
15586 mips32_op = OPC_##prfx##_PS; \
15587 goto do_fpop; \
15588 default: \
15589 goto pool32f_invalid; \
15591 case MINA_FMT:
15592 check_insn(ctx, ISA_MIPS32R6);
15593 switch ((ctx->opcode >> 9) & 0x3) {
15594 case FMT_SDPS_S:
15595 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15596 break;
15597 case FMT_SDPS_D:
15598 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15599 break;
15600 default:
15601 goto pool32f_invalid;
15603 break;
15604 case MAXA_FMT:
15605 check_insn(ctx, ISA_MIPS32R6);
15606 switch ((ctx->opcode >> 9) & 0x3) {
15607 case FMT_SDPS_S:
15608 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15609 break;
15610 case FMT_SDPS_D:
15611 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15612 break;
15613 default:
15614 goto pool32f_invalid;
15616 break;
15617 case 0x30:
15618 /* regular FP ops */
15619 switch ((ctx->opcode >> 6) & 0x3) {
15620 case ADD_FMT:
15621 FINSN_3ARG_SDPS(ADD);
15622 break;
15623 case SUB_FMT:
15624 FINSN_3ARG_SDPS(SUB);
15625 break;
15626 case MUL_FMT:
15627 FINSN_3ARG_SDPS(MUL);
15628 break;
15629 case DIV_FMT:
15630 fmt = (ctx->opcode >> 8) & 0x3;
15631 if (fmt == 1) {
15632 mips32_op = OPC_DIV_D;
15633 } else if (fmt == 0) {
15634 mips32_op = OPC_DIV_S;
15635 } else {
15636 goto pool32f_invalid;
15638 goto do_fpop;
15639 default:
15640 goto pool32f_invalid;
15642 break;
15643 case 0x38:
15644 /* cmovs */
15645 switch ((ctx->opcode >> 6) & 0x7) {
15646 case MOVN_FMT: /* SELEQZ_FMT */
15647 if (ctx->insn_flags & ISA_MIPS32R6) {
15648 /* SELEQZ_FMT */
15649 switch ((ctx->opcode >> 9) & 0x3) {
15650 case FMT_SDPS_S:
15651 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15652 break;
15653 case FMT_SDPS_D:
15654 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15655 break;
15656 default:
15657 goto pool32f_invalid;
15659 } else {
15660 /* MOVN_FMT */
15661 FINSN_3ARG_SDPS(MOVN);
15663 break;
15664 case MOVN_FMT_04:
15665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15666 FINSN_3ARG_SDPS(MOVN);
15667 break;
15668 case MOVZ_FMT: /* SELNEZ_FMT */
15669 if (ctx->insn_flags & ISA_MIPS32R6) {
15670 /* SELNEZ_FMT */
15671 switch ((ctx->opcode >> 9) & 0x3) {
15672 case FMT_SDPS_S:
15673 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15674 break;
15675 case FMT_SDPS_D:
15676 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15677 break;
15678 default:
15679 goto pool32f_invalid;
15681 } else {
15682 /* MOVZ_FMT */
15683 FINSN_3ARG_SDPS(MOVZ);
15685 break;
15686 case MOVZ_FMT_05:
15687 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15688 FINSN_3ARG_SDPS(MOVZ);
15689 break;
15690 case SEL_FMT:
15691 check_insn(ctx, ISA_MIPS32R6);
15692 switch ((ctx->opcode >> 9) & 0x3) {
15693 case FMT_SDPS_S:
15694 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15695 break;
15696 case FMT_SDPS_D:
15697 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15698 break;
15699 default:
15700 goto pool32f_invalid;
15702 break;
15703 case MADDF_FMT:
15704 check_insn(ctx, ISA_MIPS32R6);
15705 switch ((ctx->opcode >> 9) & 0x3) {
15706 case FMT_SDPS_S:
15707 mips32_op = OPC_MADDF_S;
15708 goto do_fpop;
15709 case FMT_SDPS_D:
15710 mips32_op = OPC_MADDF_D;
15711 goto do_fpop;
15712 default:
15713 goto pool32f_invalid;
15715 break;
15716 case MSUBF_FMT:
15717 check_insn(ctx, ISA_MIPS32R6);
15718 switch ((ctx->opcode >> 9) & 0x3) {
15719 case FMT_SDPS_S:
15720 mips32_op = OPC_MSUBF_S;
15721 goto do_fpop;
15722 case FMT_SDPS_D:
15723 mips32_op = OPC_MSUBF_D;
15724 goto do_fpop;
15725 default:
15726 goto pool32f_invalid;
15728 break;
15729 default:
15730 goto pool32f_invalid;
15732 break;
15733 do_fpop:
15734 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15735 break;
15736 default:
15737 pool32f_invalid:
15738 MIPS_INVAL("pool32f");
15739 generate_exception_end(ctx, EXCP_RI);
15740 break;
15742 } else {
15743 generate_exception_err(ctx, EXCP_CpU, 1);
15745 break;
15746 case POOL32I:
15747 minor = (ctx->opcode >> 21) & 0x1f;
15748 switch (minor) {
15749 case BLTZ:
15750 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15751 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15752 break;
15753 case BLTZAL:
15754 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15755 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15756 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15757 break;
15758 case BLTZALS:
15759 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15760 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15761 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15762 break;
15763 case BGEZ:
15764 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15765 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15766 break;
15767 case BGEZAL:
15768 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15769 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15770 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15771 break;
15772 case BGEZALS:
15773 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15774 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
15775 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15776 break;
15777 case BLEZ:
15778 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15779 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
15780 break;
15781 case BGTZ:
15782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15783 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
15784 break;
15786 /* Traps */
15787 case TLTI: /* BC1EQZC */
15788 if (ctx->insn_flags & ISA_MIPS32R6) {
15789 /* BC1EQZC */
15790 check_cp1_enabled(ctx);
15791 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
15792 } else {
15793 /* TLTI */
15794 mips32_op = OPC_TLTI;
15795 goto do_trapi;
15797 break;
15798 case TGEI: /* BC1NEZC */
15799 if (ctx->insn_flags & ISA_MIPS32R6) {
15800 /* BC1NEZC */
15801 check_cp1_enabled(ctx);
15802 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
15803 } else {
15804 /* TGEI */
15805 mips32_op = OPC_TGEI;
15806 goto do_trapi;
15808 break;
15809 case TLTIU:
15810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15811 mips32_op = OPC_TLTIU;
15812 goto do_trapi;
15813 case TGEIU:
15814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15815 mips32_op = OPC_TGEIU;
15816 goto do_trapi;
15817 case TNEI: /* SYNCI */
15818 if (ctx->insn_flags & ISA_MIPS32R6) {
15819 /* SYNCI */
15820 /* Break the TB to be able to sync copied instructions
15821 immediately */
15822 ctx->base.is_jmp = DISAS_STOP;
15823 } else {
15824 /* TNEI */
15825 mips32_op = OPC_TNEI;
15826 goto do_trapi;
15828 break;
15829 case TEQI:
15830 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15831 mips32_op = OPC_TEQI;
15832 do_trapi:
15833 gen_trap(ctx, mips32_op, rs, -1, imm);
15834 break;
15836 case BNEZC:
15837 case BEQZC:
15838 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15839 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
15840 4, rs, 0, imm << 1, 0);
15841 /* Compact branches don't have a delay slot, so just let
15842 the normal delay slot handling take us to the branch
15843 target. */
15844 break;
15845 case LUI:
15846 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15847 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
15848 break;
15849 case SYNCI:
15850 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15851 /* Break the TB to be able to sync copied instructions
15852 immediately */
15853 ctx->base.is_jmp = DISAS_STOP;
15854 break;
15855 case BC2F:
15856 case BC2T:
15857 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15858 /* COP2: Not implemented. */
15859 generate_exception_err(ctx, EXCP_CpU, 2);
15860 break;
15861 case BC1F:
15862 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15863 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
15864 goto do_cp1branch;
15865 case BC1T:
15866 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15867 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
15868 goto do_cp1branch;
15869 case BC1ANY4F:
15870 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15871 mips32_op = OPC_BC1FANY4;
15872 goto do_cp1mips3d;
15873 case BC1ANY4T:
15874 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15875 mips32_op = OPC_BC1TANY4;
15876 do_cp1mips3d:
15877 check_cop1x(ctx);
15878 check_insn(ctx, ASE_MIPS3D);
15879 /* Fall through */
15880 do_cp1branch:
15881 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15882 check_cp1_enabled(ctx);
15883 gen_compute_branch1(ctx, mips32_op,
15884 (ctx->opcode >> 18) & 0x7, imm << 1);
15885 } else {
15886 generate_exception_err(ctx, EXCP_CpU, 1);
15888 break;
15889 case BPOSGE64:
15890 case BPOSGE32:
15891 /* MIPS DSP: not implemented */
15892 /* Fall through */
15893 default:
15894 MIPS_INVAL("pool32i");
15895 generate_exception_end(ctx, EXCP_RI);
15896 break;
15898 break;
15899 case POOL32C:
15900 minor = (ctx->opcode >> 12) & 0xf;
15901 offset = sextract32(ctx->opcode, 0,
15902 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
15903 switch (minor) {
15904 case LWL:
15905 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15906 mips32_op = OPC_LWL;
15907 goto do_ld_lr;
15908 case SWL:
15909 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15910 mips32_op = OPC_SWL;
15911 goto do_st_lr;
15912 case LWR:
15913 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15914 mips32_op = OPC_LWR;
15915 goto do_ld_lr;
15916 case SWR:
15917 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15918 mips32_op = OPC_SWR;
15919 goto do_st_lr;
15920 #if defined(TARGET_MIPS64)
15921 case LDL:
15922 check_insn(ctx, ISA_MIPS3);
15923 check_mips_64(ctx);
15924 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15925 mips32_op = OPC_LDL;
15926 goto do_ld_lr;
15927 case SDL:
15928 check_insn(ctx, ISA_MIPS3);
15929 check_mips_64(ctx);
15930 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15931 mips32_op = OPC_SDL;
15932 goto do_st_lr;
15933 case LDR:
15934 check_insn(ctx, ISA_MIPS3);
15935 check_mips_64(ctx);
15936 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15937 mips32_op = OPC_LDR;
15938 goto do_ld_lr;
15939 case SDR:
15940 check_insn(ctx, ISA_MIPS3);
15941 check_mips_64(ctx);
15942 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15943 mips32_op = OPC_SDR;
15944 goto do_st_lr;
15945 case LWU:
15946 check_insn(ctx, ISA_MIPS3);
15947 check_mips_64(ctx);
15948 mips32_op = OPC_LWU;
15949 goto do_ld_lr;
15950 case LLD:
15951 check_insn(ctx, ISA_MIPS3);
15952 check_mips_64(ctx);
15953 mips32_op = OPC_LLD;
15954 goto do_ld_lr;
15955 #endif
15956 case LL:
15957 mips32_op = OPC_LL;
15958 goto do_ld_lr;
15959 do_ld_lr:
15960 gen_ld(ctx, mips32_op, rt, rs, offset);
15961 break;
15962 do_st_lr:
15963 gen_st(ctx, mips32_op, rt, rs, offset);
15964 break;
15965 case SC:
15966 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
15967 break;
15968 #if defined(TARGET_MIPS64)
15969 case SCD:
15970 check_insn(ctx, ISA_MIPS3);
15971 check_mips_64(ctx);
15972 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
15973 break;
15974 #endif
15975 case LD_EVA:
15976 if (!ctx->eva) {
15977 MIPS_INVAL("pool32c ld-eva");
15978 generate_exception_end(ctx, EXCP_RI);
15979 break;
15981 check_cp0_enabled(ctx);
15983 minor2 = (ctx->opcode >> 9) & 0x7;
15984 offset = sextract32(ctx->opcode, 0, 9);
15985 switch (minor2) {
15986 case LBUE:
15987 mips32_op = OPC_LBUE;
15988 goto do_ld_lr;
15989 case LHUE:
15990 mips32_op = OPC_LHUE;
15991 goto do_ld_lr;
15992 case LWLE:
15993 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15994 mips32_op = OPC_LWLE;
15995 goto do_ld_lr;
15996 case LWRE:
15997 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15998 mips32_op = OPC_LWRE;
15999 goto do_ld_lr;
16000 case LBE:
16001 mips32_op = OPC_LBE;
16002 goto do_ld_lr;
16003 case LHE:
16004 mips32_op = OPC_LHE;
16005 goto do_ld_lr;
16006 case LLE:
16007 mips32_op = OPC_LLE;
16008 goto do_ld_lr;
16009 case LWE:
16010 mips32_op = OPC_LWE;
16011 goto do_ld_lr;
16013 break;
16014 case ST_EVA:
16015 if (!ctx->eva) {
16016 MIPS_INVAL("pool32c st-eva");
16017 generate_exception_end(ctx, EXCP_RI);
16018 break;
16020 check_cp0_enabled(ctx);
16022 minor2 = (ctx->opcode >> 9) & 0x7;
16023 offset = sextract32(ctx->opcode, 0, 9);
16024 switch (minor2) {
16025 case SWLE:
16026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16027 mips32_op = OPC_SWLE;
16028 goto do_st_lr;
16029 case SWRE:
16030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16031 mips32_op = OPC_SWRE;
16032 goto do_st_lr;
16033 case PREFE:
16034 /* Treat as no-op */
16035 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16036 /* hint codes 24-31 are reserved and signal RI */
16037 generate_exception(ctx, EXCP_RI);
16039 break;
16040 case CACHEE:
16041 /* Treat as no-op */
16042 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16043 gen_cache_operation(ctx, rt, rs, offset);
16045 break;
16046 case SBE:
16047 mips32_op = OPC_SBE;
16048 goto do_st_lr;
16049 case SHE:
16050 mips32_op = OPC_SHE;
16051 goto do_st_lr;
16052 case SCE:
16053 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16054 break;
16055 case SWE:
16056 mips32_op = OPC_SWE;
16057 goto do_st_lr;
16059 break;
16060 case PREF:
16061 /* Treat as no-op */
16062 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16063 /* hint codes 24-31 are reserved and signal RI */
16064 generate_exception(ctx, EXCP_RI);
16066 break;
16067 default:
16068 MIPS_INVAL("pool32c");
16069 generate_exception_end(ctx, EXCP_RI);
16070 break;
16072 break;
16073 case ADDI32: /* AUI, LUI */
16074 if (ctx->insn_flags & ISA_MIPS32R6) {
16075 /* AUI, LUI */
16076 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16077 } else {
16078 /* ADDI32 */
16079 mips32_op = OPC_ADDI;
16080 goto do_addi;
16082 break;
16083 case ADDIU32:
16084 mips32_op = OPC_ADDIU;
16085 do_addi:
16086 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16087 break;
16089 /* Logical operations */
16090 case ORI32:
16091 mips32_op = OPC_ORI;
16092 goto do_logici;
16093 case XORI32:
16094 mips32_op = OPC_XORI;
16095 goto do_logici;
16096 case ANDI32:
16097 mips32_op = OPC_ANDI;
16098 do_logici:
16099 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16100 break;
16102 /* Set less than immediate */
16103 case SLTI32:
16104 mips32_op = OPC_SLTI;
16105 goto do_slti;
16106 case SLTIU32:
16107 mips32_op = OPC_SLTIU;
16108 do_slti:
16109 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16110 break;
16111 case JALX32:
16112 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16113 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16114 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16115 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16116 break;
16117 case JALS32: /* BOVC, BEQC, BEQZALC */
16118 if (ctx->insn_flags & ISA_MIPS32R6) {
16119 if (rs >= rt) {
16120 /* BOVC */
16121 mips32_op = OPC_BOVC;
16122 } else if (rs < rt && rs == 0) {
16123 /* BEQZALC */
16124 mips32_op = OPC_BEQZALC;
16125 } else {
16126 /* BEQC */
16127 mips32_op = OPC_BEQC;
16129 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16130 } else {
16131 /* JALS32 */
16132 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16133 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16134 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16136 break;
16137 case BEQ32: /* BC */
16138 if (ctx->insn_flags & ISA_MIPS32R6) {
16139 /* BC */
16140 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16141 sextract32(ctx->opcode << 1, 0, 27));
16142 } else {
16143 /* BEQ32 */
16144 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16146 break;
16147 case BNE32: /* BALC */
16148 if (ctx->insn_flags & ISA_MIPS32R6) {
16149 /* BALC */
16150 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16151 sextract32(ctx->opcode << 1, 0, 27));
16152 } else {
16153 /* BNE32 */
16154 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16156 break;
16157 case J32: /* BGTZC, BLTZC, BLTC */
16158 if (ctx->insn_flags & ISA_MIPS32R6) {
16159 if (rs == 0 && rt != 0) {
16160 /* BGTZC */
16161 mips32_op = OPC_BGTZC;
16162 } else if (rs != 0 && rt != 0 && rs == rt) {
16163 /* BLTZC */
16164 mips32_op = OPC_BLTZC;
16165 } else {
16166 /* BLTC */
16167 mips32_op = OPC_BLTC;
16169 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16170 } else {
16171 /* J32 */
16172 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16173 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16175 break;
16176 case JAL32: /* BLEZC, BGEZC, BGEC */
16177 if (ctx->insn_flags & ISA_MIPS32R6) {
16178 if (rs == 0 && rt != 0) {
16179 /* BLEZC */
16180 mips32_op = OPC_BLEZC;
16181 } else if (rs != 0 && rt != 0 && rs == rt) {
16182 /* BGEZC */
16183 mips32_op = OPC_BGEZC;
16184 } else {
16185 /* BGEC */
16186 mips32_op = OPC_BGEC;
16188 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16189 } else {
16190 /* JAL32 */
16191 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16192 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16193 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16195 break;
16196 /* Floating point (COP1) */
16197 case LWC132:
16198 mips32_op = OPC_LWC1;
16199 goto do_cop1;
16200 case LDC132:
16201 mips32_op = OPC_LDC1;
16202 goto do_cop1;
16203 case SWC132:
16204 mips32_op = OPC_SWC1;
16205 goto do_cop1;
16206 case SDC132:
16207 mips32_op = OPC_SDC1;
16208 do_cop1:
16209 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16210 break;
16211 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16212 if (ctx->insn_flags & ISA_MIPS32R6) {
16213 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16214 switch ((ctx->opcode >> 16) & 0x1f) {
16215 case ADDIUPC_00:
16216 case ADDIUPC_01:
16217 case ADDIUPC_02:
16218 case ADDIUPC_03:
16219 case ADDIUPC_04:
16220 case ADDIUPC_05:
16221 case ADDIUPC_06:
16222 case ADDIUPC_07:
16223 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16224 break;
16225 case AUIPC:
16226 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16227 break;
16228 case ALUIPC:
16229 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16230 break;
16231 case LWPC_08:
16232 case LWPC_09:
16233 case LWPC_0A:
16234 case LWPC_0B:
16235 case LWPC_0C:
16236 case LWPC_0D:
16237 case LWPC_0E:
16238 case LWPC_0F:
16239 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16240 break;
16241 default:
16242 generate_exception(ctx, EXCP_RI);
16243 break;
16245 } else {
16246 /* ADDIUPC */
16247 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16248 offset = SIMM(ctx->opcode, 0, 23) << 2;
16250 gen_addiupc(ctx, reg, offset, 0, 0);
16252 break;
16253 case BNVC: /* BNEC, BNEZALC */
16254 check_insn(ctx, ISA_MIPS32R6);
16255 if (rs >= rt) {
16256 /* BNVC */
16257 mips32_op = OPC_BNVC;
16258 } else if (rs < rt && rs == 0) {
16259 /* BNEZALC */
16260 mips32_op = OPC_BNEZALC;
16261 } else {
16262 /* BNEC */
16263 mips32_op = OPC_BNEC;
16265 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16266 break;
16267 case R6_BNEZC: /* JIALC */
16268 check_insn(ctx, ISA_MIPS32R6);
16269 if (rt != 0) {
16270 /* BNEZC */
16271 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16272 sextract32(ctx->opcode << 1, 0, 22));
16273 } else {
16274 /* JIALC */
16275 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16277 break;
16278 case R6_BEQZC: /* JIC */
16279 check_insn(ctx, ISA_MIPS32R6);
16280 if (rt != 0) {
16281 /* BEQZC */
16282 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16283 sextract32(ctx->opcode << 1, 0, 22));
16284 } else {
16285 /* JIC */
16286 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16288 break;
16289 case BLEZALC: /* BGEZALC, BGEUC */
16290 check_insn(ctx, ISA_MIPS32R6);
16291 if (rs == 0 && rt != 0) {
16292 /* BLEZALC */
16293 mips32_op = OPC_BLEZALC;
16294 } else if (rs != 0 && rt != 0 && rs == rt) {
16295 /* BGEZALC */
16296 mips32_op = OPC_BGEZALC;
16297 } else {
16298 /* BGEUC */
16299 mips32_op = OPC_BGEUC;
16301 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16302 break;
16303 case BGTZALC: /* BLTZALC, BLTUC */
16304 check_insn(ctx, ISA_MIPS32R6);
16305 if (rs == 0 && rt != 0) {
16306 /* BGTZALC */
16307 mips32_op = OPC_BGTZALC;
16308 } else if (rs != 0 && rt != 0 && rs == rt) {
16309 /* BLTZALC */
16310 mips32_op = OPC_BLTZALC;
16311 } else {
16312 /* BLTUC */
16313 mips32_op = OPC_BLTUC;
16315 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16316 break;
16317 /* Loads and stores */
16318 case LB32:
16319 mips32_op = OPC_LB;
16320 goto do_ld;
16321 case LBU32:
16322 mips32_op = OPC_LBU;
16323 goto do_ld;
16324 case LH32:
16325 mips32_op = OPC_LH;
16326 goto do_ld;
16327 case LHU32:
16328 mips32_op = OPC_LHU;
16329 goto do_ld;
16330 case LW32:
16331 mips32_op = OPC_LW;
16332 goto do_ld;
16333 #ifdef TARGET_MIPS64
16334 case LD32:
16335 check_insn(ctx, ISA_MIPS3);
16336 check_mips_64(ctx);
16337 mips32_op = OPC_LD;
16338 goto do_ld;
16339 case SD32:
16340 check_insn(ctx, ISA_MIPS3);
16341 check_mips_64(ctx);
16342 mips32_op = OPC_SD;
16343 goto do_st;
16344 #endif
16345 case SB32:
16346 mips32_op = OPC_SB;
16347 goto do_st;
16348 case SH32:
16349 mips32_op = OPC_SH;
16350 goto do_st;
16351 case SW32:
16352 mips32_op = OPC_SW;
16353 goto do_st;
16354 do_ld:
16355 gen_ld(ctx, mips32_op, rt, rs, imm);
16356 break;
16357 do_st:
16358 gen_st(ctx, mips32_op, rt, rs, imm);
16359 break;
16360 default:
16361 generate_exception_end(ctx, EXCP_RI);
16362 break;
16366 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16368 uint32_t op;
16370 /* make sure instructions are on a halfword boundary */
16371 if (ctx->base.pc_next & 0x1) {
16372 env->CP0_BadVAddr = ctx->base.pc_next;
16373 generate_exception_end(ctx, EXCP_AdEL);
16374 return 2;
16377 op = (ctx->opcode >> 10) & 0x3f;
16378 /* Enforce properly-sized instructions in a delay slot */
16379 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16380 switch (op & 0x7) { /* MSB-3..MSB-5 */
16381 case 0:
16382 /* POOL32A, POOL32B, POOL32I, POOL32C */
16383 case 4:
16384 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16385 case 5:
16386 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16387 case 6:
16388 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16389 case 7:
16390 /* LB32, LH32, LWC132, LDC132, LW32 */
16391 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16392 generate_exception_end(ctx, EXCP_RI);
16393 return 2;
16395 break;
16396 case 1:
16397 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16398 case 2:
16399 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16400 case 3:
16401 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16402 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16403 generate_exception_end(ctx, EXCP_RI);
16404 return 2;
16406 break;
16410 switch (op) {
16411 case POOL16A:
16413 int rd = mmreg(uMIPS_RD(ctx->opcode));
16414 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16415 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16416 uint32_t opc = 0;
16418 switch (ctx->opcode & 0x1) {
16419 case ADDU16:
16420 opc = OPC_ADDU;
16421 break;
16422 case SUBU16:
16423 opc = OPC_SUBU;
16424 break;
16426 if (ctx->insn_flags & ISA_MIPS32R6) {
16427 /* In the Release 6 the register number location in
16428 * the instruction encoding has changed.
16430 gen_arith(ctx, opc, rs1, rd, rs2);
16431 } else {
16432 gen_arith(ctx, opc, rd, rs1, rs2);
16435 break;
16436 case POOL16B:
16438 int rd = mmreg(uMIPS_RD(ctx->opcode));
16439 int rs = mmreg(uMIPS_RS(ctx->opcode));
16440 int amount = (ctx->opcode >> 1) & 0x7;
16441 uint32_t opc = 0;
16442 amount = amount == 0 ? 8 : amount;
16444 switch (ctx->opcode & 0x1) {
16445 case SLL16:
16446 opc = OPC_SLL;
16447 break;
16448 case SRL16:
16449 opc = OPC_SRL;
16450 break;
16453 gen_shift_imm(ctx, opc, rd, rs, amount);
16455 break;
16456 case POOL16C:
16457 if (ctx->insn_flags & ISA_MIPS32R6) {
16458 gen_pool16c_r6_insn(ctx);
16459 } else {
16460 gen_pool16c_insn(ctx);
16462 break;
16463 case LWGP16:
16465 int rd = mmreg(uMIPS_RD(ctx->opcode));
16466 int rb = 28; /* GP */
16467 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16469 gen_ld(ctx, OPC_LW, rd, rb, offset);
16471 break;
16472 case POOL16F:
16473 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16474 if (ctx->opcode & 1) {
16475 generate_exception_end(ctx, EXCP_RI);
16476 } else {
16477 /* MOVEP */
16478 int enc_dest = uMIPS_RD(ctx->opcode);
16479 int enc_rt = uMIPS_RS2(ctx->opcode);
16480 int enc_rs = uMIPS_RS1(ctx->opcode);
16481 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
16483 break;
16484 case LBU16:
16486 int rd = mmreg(uMIPS_RD(ctx->opcode));
16487 int rb = mmreg(uMIPS_RS(ctx->opcode));
16488 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16489 offset = (offset == 0xf ? -1 : offset);
16491 gen_ld(ctx, OPC_LBU, rd, rb, offset);
16493 break;
16494 case LHU16:
16496 int rd = mmreg(uMIPS_RD(ctx->opcode));
16497 int rb = mmreg(uMIPS_RS(ctx->opcode));
16498 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16500 gen_ld(ctx, OPC_LHU, rd, rb, offset);
16502 break;
16503 case LWSP16:
16505 int rd = (ctx->opcode >> 5) & 0x1f;
16506 int rb = 29; /* SP */
16507 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16509 gen_ld(ctx, OPC_LW, rd, rb, offset);
16511 break;
16512 case LW16:
16514 int rd = mmreg(uMIPS_RD(ctx->opcode));
16515 int rb = mmreg(uMIPS_RS(ctx->opcode));
16516 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16518 gen_ld(ctx, OPC_LW, rd, rb, offset);
16520 break;
16521 case SB16:
16523 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16524 int rb = mmreg(uMIPS_RS(ctx->opcode));
16525 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16527 gen_st(ctx, OPC_SB, rd, rb, offset);
16529 break;
16530 case SH16:
16532 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16533 int rb = mmreg(uMIPS_RS(ctx->opcode));
16534 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16536 gen_st(ctx, OPC_SH, rd, rb, offset);
16538 break;
16539 case SWSP16:
16541 int rd = (ctx->opcode >> 5) & 0x1f;
16542 int rb = 29; /* SP */
16543 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16545 gen_st(ctx, OPC_SW, rd, rb, offset);
16547 break;
16548 case SW16:
16550 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16551 int rb = mmreg(uMIPS_RS(ctx->opcode));
16552 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16554 gen_st(ctx, OPC_SW, rd, rb, offset);
16556 break;
16557 case MOVE16:
16559 int rd = uMIPS_RD5(ctx->opcode);
16560 int rs = uMIPS_RS5(ctx->opcode);
16562 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
16564 break;
16565 case ANDI16:
16566 gen_andi16(ctx);
16567 break;
16568 case POOL16D:
16569 switch (ctx->opcode & 0x1) {
16570 case ADDIUS5:
16571 gen_addius5(ctx);
16572 break;
16573 case ADDIUSP:
16574 gen_addiusp(ctx);
16575 break;
16577 break;
16578 case POOL16E:
16579 switch (ctx->opcode & 0x1) {
16580 case ADDIUR2:
16581 gen_addiur2(ctx);
16582 break;
16583 case ADDIUR1SP:
16584 gen_addiur1sp(ctx);
16585 break;
16587 break;
16588 case B16: /* BC16 */
16589 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
16590 sextract32(ctx->opcode, 0, 10) << 1,
16591 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16592 break;
16593 case BNEZ16: /* BNEZC16 */
16594 case BEQZ16: /* BEQZC16 */
16595 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16596 mmreg(uMIPS_RD(ctx->opcode)),
16597 0, sextract32(ctx->opcode, 0, 7) << 1,
16598 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16600 break;
16601 case LI16:
16603 int reg = mmreg(uMIPS_RD(ctx->opcode));
16604 int imm = ZIMM(ctx->opcode, 0, 7);
16606 imm = (imm == 0x7f ? -1 : imm);
16607 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16609 break;
16610 case RES_29:
16611 case RES_31:
16612 case RES_39:
16613 generate_exception_end(ctx, EXCP_RI);
16614 break;
16615 default:
16616 decode_micromips32_opc(env, ctx);
16617 return 4;
16620 return 2;
16625 * nanoMIPS opcodes
16629 /* MAJOR, P16, and P32 pools opcodes */
16630 enum {
16631 NM_P_ADDIU = 0x00,
16632 NM_ADDIUPC = 0x01,
16633 NM_MOVE_BALC = 0x02,
16634 NM_P16_MV = 0x04,
16635 NM_LW16 = 0x05,
16636 NM_BC16 = 0x06,
16637 NM_P16_SR = 0x07,
16639 NM_POOL32A = 0x08,
16640 NM_P_BAL = 0x0a,
16641 NM_P16_SHIFT = 0x0c,
16642 NM_LWSP16 = 0x0d,
16643 NM_BALC16 = 0x0e,
16644 NM_P16_4X4 = 0x0f,
16646 NM_P_GP_W = 0x10,
16647 NM_P_GP_BH = 0x11,
16648 NM_P_J = 0x12,
16649 NM_P16C = 0x14,
16650 NM_LWGP16 = 0x15,
16651 NM_P16_LB = 0x17,
16653 NM_P48I = 0x18,
16654 NM_P16_A1 = 0x1c,
16655 NM_LW4X4 = 0x1d,
16656 NM_P16_LH = 0x1f,
16658 NM_P_U12 = 0x20,
16659 NM_P_LS_U12 = 0x21,
16660 NM_P_BR1 = 0x22,
16661 NM_P16_A2 = 0x24,
16662 NM_SW16 = 0x25,
16663 NM_BEQZC16 = 0x26,
16665 NM_POOL32F = 0x28,
16666 NM_P_LS_S9 = 0x29,
16667 NM_P_BR2 = 0x2a,
16669 NM_P16_ADDU = 0x2c,
16670 NM_SWSP16 = 0x2d,
16671 NM_BNEZC16 = 0x2e,
16672 NM_MOVEP = 0x2f,
16674 NM_POOL32S = 0x30,
16675 NM_P_BRI = 0x32,
16676 NM_LI16 = 0x34,
16677 NM_SWGP16 = 0x35,
16678 NM_P16_BR = 0x36,
16680 NM_P_LUI = 0x38,
16681 NM_ANDI16 = 0x3c,
16682 NM_SW4X4 = 0x3d,
16683 NM_MOVEPREV = 0x3f,
16686 /* POOL32A instruction pool */
16687 enum {
16688 NM_POOL32A0 = 0x00,
16689 NM_SPECIAL2 = 0x01,
16690 NM_COP2_1 = 0x02,
16691 NM_UDI = 0x03,
16692 NM_POOL32A5 = 0x05,
16693 NM_POOL32A7 = 0x07,
16696 /* P.GP.W instruction pool */
16697 enum {
16698 NM_ADDIUGP_W = 0x00,
16699 NM_LWGP = 0x02,
16700 NM_SWGP = 0x03,
16703 /* P48I instruction pool */
16704 enum {
16705 NM_LI48 = 0x00,
16706 NM_ADDIU48 = 0x01,
16707 NM_ADDIUGP48 = 0x02,
16708 NM_ADDIUPC48 = 0x03,
16709 NM_LWPC48 = 0x0b,
16710 NM_SWPC48 = 0x0f,
16713 /* P.U12 instruction pool */
16714 enum {
16715 NM_ORI = 0x00,
16716 NM_XORI = 0x01,
16717 NM_ANDI = 0x02,
16718 NM_P_SR = 0x03,
16719 NM_SLTI = 0x04,
16720 NM_SLTIU = 0x05,
16721 NM_SEQI = 0x06,
16722 NM_ADDIUNEG = 0x08,
16723 NM_P_SHIFT = 0x0c,
16724 NM_P_ROTX = 0x0d,
16725 NM_P_INS = 0x0e,
16726 NM_P_EXT = 0x0f,
16729 /* POOL32F instruction pool */
16730 enum {
16731 NM_POOL32F_0 = 0x00,
16732 NM_POOL32F_3 = 0x03,
16733 NM_POOL32F_5 = 0x05,
16736 /* POOL32S instruction pool */
16737 enum {
16738 NM_POOL32S_0 = 0x00,
16739 NM_POOL32S_4 = 0x04,
16742 /* P.LUI instruction pool */
16743 enum {
16744 NM_LUI = 0x00,
16745 NM_ALUIPC = 0x01,
16748 /* P.GP.BH instruction pool */
16749 enum {
16750 NM_LBGP = 0x00,
16751 NM_SBGP = 0x01,
16752 NM_LBUGP = 0x02,
16753 NM_ADDIUGP_B = 0x03,
16754 NM_P_GP_LH = 0x04,
16755 NM_P_GP_SH = 0x05,
16756 NM_P_GP_CP1 = 0x06,
16759 /* P.LS.U12 instruction pool */
16760 enum {
16761 NM_LB = 0x00,
16762 NM_SB = 0x01,
16763 NM_LBU = 0x02,
16764 NM_P_PREFU12 = 0x03,
16765 NM_LH = 0x04,
16766 NM_SH = 0x05,
16767 NM_LHU = 0x06,
16768 NM_LWU = 0x07,
16769 NM_LW = 0x08,
16770 NM_SW = 0x09,
16771 NM_LWC1 = 0x0a,
16772 NM_SWC1 = 0x0b,
16773 NM_LDC1 = 0x0e,
16774 NM_SDC1 = 0x0f,
16777 /* P.LS.S9 instruction pool */
16778 enum {
16779 NM_P_LS_S0 = 0x00,
16780 NM_P_LS_S1 = 0x01,
16781 NM_P_LS_E0 = 0x02,
16782 NM_P_LS_WM = 0x04,
16783 NM_P_LS_UAWM = 0x05,
16786 /* P.BAL instruction pool */
16787 enum {
16788 NM_BC = 0x00,
16789 NM_BALC = 0x01,
16792 /* P.J instruction pool */
16793 enum {
16794 NM_JALRC = 0x00,
16795 NM_JALRC_HB = 0x01,
16796 NM_P_BALRSC = 0x08,
16799 /* P.BR1 instruction pool */
16800 enum {
16801 NM_BEQC = 0x00,
16802 NM_P_BR3A = 0x01,
16803 NM_BGEC = 0x02,
16804 NM_BGEUC = 0x03,
16807 /* P.BR2 instruction pool */
16808 enum {
16809 NM_BNEC = 0x00,
16810 NM_BLTC = 0x02,
16811 NM_BLTUC = 0x03,
16814 /* P.BRI instruction pool */
16815 enum {
16816 NM_BEQIC = 0x00,
16817 NM_BBEQZC = 0x01,
16818 NM_BGEIC = 0x02,
16819 NM_BGEIUC = 0x03,
16820 NM_BNEIC = 0x04,
16821 NM_BBNEZC = 0x05,
16822 NM_BLTIC = 0x06,
16823 NM_BLTIUC = 0x07,
16826 /* P16.SHIFT instruction pool */
16827 enum {
16828 NM_SLL16 = 0x00,
16829 NM_SRL16 = 0x01,
16832 /* POOL16C instruction pool */
16833 enum {
16834 NM_POOL16C_0 = 0x00,
16835 NM_LWXS16 = 0x01,
16838 /* P16.A1 instruction pool */
16839 enum {
16840 NM_ADDIUR1SP = 0x01,
16843 /* P16.A2 instruction pool */
16844 enum {
16845 NM_ADDIUR2 = 0x00,
16846 NM_P_ADDIURS5 = 0x01,
16849 /* P16.ADDU instruction pool */
16850 enum {
16851 NM_ADDU16 = 0x00,
16852 NM_SUBU16 = 0x01,
16855 /* P16.SR instruction pool */
16856 enum {
16857 NM_SAVE16 = 0x00,
16858 NM_RESTORE_JRC16 = 0x01,
16861 /* P16.4X4 instruction pool */
16862 enum {
16863 NM_ADDU4X4 = 0x00,
16864 NM_MUL4X4 = 0x01,
16867 /* P16.LB instruction pool */
16868 enum {
16869 NM_LB16 = 0x00,
16870 NM_SB16 = 0x01,
16871 NM_LBU16 = 0x02,
16874 /* P16.LH instruction pool */
16875 enum {
16876 NM_LH16 = 0x00,
16877 NM_SH16 = 0x01,
16878 NM_LHU16 = 0x02,
16881 /* P.RI instruction pool */
16882 enum {
16883 NM_SIGRIE = 0x00,
16884 NM_P_SYSCALL = 0x01,
16885 NM_BREAK = 0x02,
16886 NM_SDBBP = 0x03,
16889 /* POOL32A0 instruction pool */
16890 enum {
16891 NM_P_TRAP = 0x00,
16892 NM_SEB = 0x01,
16893 NM_SLLV = 0x02,
16894 NM_MUL = 0x03,
16895 NM_MFC0 = 0x06,
16896 NM_MFHC0 = 0x07,
16897 NM_SEH = 0x09,
16898 NM_SRLV = 0x0a,
16899 NM_MUH = 0x0b,
16900 NM_MTC0 = 0x0e,
16901 NM_MTHC0 = 0x0f,
16902 NM_SRAV = 0x12,
16903 NM_MULU = 0x13,
16904 NM_ROTRV = 0x1a,
16905 NM_MUHU = 0x1b,
16906 NM_ADD = 0x22,
16907 NM_DIV = 0x23,
16908 NM_ADDU = 0x2a,
16909 NM_MOD = 0x2b,
16910 NM_SUB = 0x32,
16911 NM_DIVU = 0x33,
16912 NM_RDHWR = 0x38,
16913 NM_SUBU = 0x3a,
16914 NM_MODU = 0x3b,
16915 NM_P_CMOVE = 0x42,
16916 NM_FORK = 0x45,
16917 NM_MFTR = 0x46,
16918 NM_MFHTR = 0x47,
16919 NM_AND = 0x4a,
16920 NM_YIELD = 0x4d,
16921 NM_MTTR = 0x4e,
16922 NM_MTHTR = 0x4f,
16923 NM_OR = 0x52,
16924 NM_D_E_MT_VPE = 0x56,
16925 NM_NOR = 0x5a,
16926 NM_XOR = 0x62,
16927 NM_SLT = 0x6a,
16928 NM_P_SLTU = 0x72,
16929 NM_SOV = 0x7a,
16932 /* POOL32A5 instruction pool */
16933 enum {
16934 NM_CMP_EQ_PH = 0x00,
16935 NM_CMP_LT_PH = 0x08,
16936 NM_CMP_LE_PH = 0x10,
16937 NM_CMPGU_EQ_QB = 0x18,
16938 NM_CMPGU_LT_QB = 0x20,
16939 NM_CMPGU_LE_QB = 0x28,
16940 NM_CMPGDU_EQ_QB = 0x30,
16941 NM_CMPGDU_LT_QB = 0x38,
16942 NM_CMPGDU_LE_QB = 0x40,
16943 NM_CMPU_EQ_QB = 0x48,
16944 NM_CMPU_LT_QB = 0x50,
16945 NM_CMPU_LE_QB = 0x58,
16946 NM_ADDQ_S_W = 0x60,
16947 NM_SUBQ_S_W = 0x68,
16948 NM_ADDSC = 0x70,
16949 NM_ADDWC = 0x78,
16951 NM_ADDQ_S_PH = 0x01,
16952 NM_ADDQH_R_PH = 0x09,
16953 NM_ADDQH_R_W = 0x11,
16954 NM_ADDU_S_QB = 0x19,
16955 NM_ADDU_S_PH = 0x21,
16956 NM_ADDUH_R_QB = 0x29,
16957 NM_SHRAV_R_PH = 0x31,
16958 NM_SHRAV_R_QB = 0x39,
16959 NM_SUBQ_S_PH = 0x41,
16960 NM_SUBQH_R_PH = 0x49,
16961 NM_SUBQH_R_W = 0x51,
16962 NM_SUBU_S_QB = 0x59,
16963 NM_SUBU_S_PH = 0x61,
16964 NM_SUBUH_R_QB = 0x69,
16965 NM_SHLLV_S_PH = 0x71,
16966 NM_PRECR_SRA_R_PH_W = 0x79,
16968 NM_MULEU_S_PH_QBL = 0x12,
16969 NM_MULEU_S_PH_QBR = 0x1a,
16970 NM_MULQ_RS_PH = 0x22,
16971 NM_MULQ_S_PH = 0x2a,
16972 NM_MULQ_RS_W = 0x32,
16973 NM_MULQ_S_W = 0x3a,
16974 NM_APPEND = 0x42,
16975 NM_MODSUB = 0x52,
16976 NM_SHRAV_R_W = 0x5a,
16977 NM_SHRLV_PH = 0x62,
16978 NM_SHRLV_QB = 0x6a,
16979 NM_SHLLV_QB = 0x72,
16980 NM_SHLLV_S_W = 0x7a,
16982 NM_SHILO = 0x03,
16984 NM_MULEQ_S_W_PHL = 0x04,
16985 NM_MULEQ_S_W_PHR = 0x0c,
16987 NM_MUL_S_PH = 0x05,
16988 NM_PRECR_QB_PH = 0x0d,
16989 NM_PRECRQ_QB_PH = 0x15,
16990 NM_PRECRQ_PH_W = 0x1d,
16991 NM_PRECRQ_RS_PH_W = 0x25,
16992 NM_PRECRQU_S_QB_PH = 0x2d,
16993 NM_PACKRL_PH = 0x35,
16994 NM_PICK_QB = 0x3d,
16995 NM_PICK_PH = 0x45,
16997 NM_SHRA_R_W = 0x5e,
16998 NM_SHRA_R_PH = 0x66,
16999 NM_SHLL_S_PH = 0x76,
17000 NM_SHLL_S_W = 0x7e,
17002 NM_REPL_PH = 0x07
17005 /* POOL32A7 instruction pool */
17006 enum {
17007 NM_P_LSX = 0x00,
17008 NM_LSA = 0x01,
17009 NM_EXTW = 0x03,
17010 NM_POOL32AXF = 0x07,
17013 /* P.SR instruction pool */
17014 enum {
17015 NM_PP_SR = 0x00,
17016 NM_P_SR_F = 0x01,
17019 /* P.SHIFT instruction pool */
17020 enum {
17021 NM_P_SLL = 0x00,
17022 NM_SRL = 0x02,
17023 NM_SRA = 0x04,
17024 NM_ROTR = 0x06,
17027 /* P.ROTX instruction pool */
17028 enum {
17029 NM_ROTX = 0x00,
17032 /* P.INS instruction pool */
17033 enum {
17034 NM_INS = 0x00,
17037 /* P.EXT instruction pool */
17038 enum {
17039 NM_EXT = 0x00,
17042 /* POOL32F_0 (fmt) instruction pool */
17043 enum {
17044 NM_RINT_S = 0x04,
17045 NM_RINT_D = 0x44,
17046 NM_ADD_S = 0x06,
17047 NM_SELEQZ_S = 0x07,
17048 NM_SELEQZ_D = 0x47,
17049 NM_CLASS_S = 0x0c,
17050 NM_CLASS_D = 0x4c,
17051 NM_SUB_S = 0x0e,
17052 NM_SELNEZ_S = 0x0f,
17053 NM_SELNEZ_D = 0x4f,
17054 NM_MUL_S = 0x16,
17055 NM_SEL_S = 0x17,
17056 NM_SEL_D = 0x57,
17057 NM_DIV_S = 0x1e,
17058 NM_ADD_D = 0x26,
17059 NM_SUB_D = 0x2e,
17060 NM_MUL_D = 0x36,
17061 NM_MADDF_S = 0x37,
17062 NM_MADDF_D = 0x77,
17063 NM_DIV_D = 0x3e,
17064 NM_MSUBF_S = 0x3f,
17065 NM_MSUBF_D = 0x7f,
17068 /* POOL32F_3 instruction pool */
17069 enum {
17070 NM_MIN_FMT = 0x00,
17071 NM_MAX_FMT = 0x01,
17072 NM_MINA_FMT = 0x04,
17073 NM_MAXA_FMT = 0x05,
17074 NM_POOL32FXF = 0x07,
17077 /* POOL32F_5 instruction pool */
17078 enum {
17079 NM_CMP_CONDN_S = 0x00,
17080 NM_CMP_CONDN_D = 0x02,
17083 /* P.GP.LH instruction pool */
17084 enum {
17085 NM_LHGP = 0x00,
17086 NM_LHUGP = 0x01,
17089 /* P.GP.SH instruction pool */
17090 enum {
17091 NM_SHGP = 0x00,
17094 /* P.GP.CP1 instruction pool */
17095 enum {
17096 NM_LWC1GP = 0x00,
17097 NM_SWC1GP = 0x01,
17098 NM_LDC1GP = 0x02,
17099 NM_SDC1GP = 0x03,
17102 /* P.LS.S0 instruction pool */
17103 enum {
17104 NM_LBS9 = 0x00,
17105 NM_LHS9 = 0x04,
17106 NM_LWS9 = 0x08,
17107 NM_LDS9 = 0x0c,
17109 NM_SBS9 = 0x01,
17110 NM_SHS9 = 0x05,
17111 NM_SWS9 = 0x09,
17112 NM_SDS9 = 0x0d,
17114 NM_LBUS9 = 0x02,
17115 NM_LHUS9 = 0x06,
17116 NM_LWC1S9 = 0x0a,
17117 NM_LDC1S9 = 0x0e,
17119 NM_P_PREFS9 = 0x03,
17120 NM_LWUS9 = 0x07,
17121 NM_SWC1S9 = 0x0b,
17122 NM_SDC1S9 = 0x0f,
17125 /* P.LS.S1 instruction pool */
17126 enum {
17127 NM_ASET_ACLR = 0x02,
17128 NM_UALH = 0x04,
17129 NM_UASH = 0x05,
17130 NM_CACHE = 0x07,
17131 NM_P_LL = 0x0a,
17132 NM_P_SC = 0x0b,
17135 /* P.LS.WM instruction pool */
17136 enum {
17137 NM_LWM = 0x00,
17138 NM_SWM = 0x01,
17141 /* P.LS.UAWM instruction pool */
17142 enum {
17143 NM_UALWM = 0x00,
17144 NM_UASWM = 0x01,
17147 /* P.BR3A instruction pool */
17148 enum {
17149 NM_BC1EQZC = 0x00,
17150 NM_BC1NEZC = 0x01,
17151 NM_BC2EQZC = 0x02,
17152 NM_BC2NEZC = 0x03,
17153 NM_BPOSGE32C = 0x04,
17156 /* P16.RI instruction pool */
17157 enum {
17158 NM_P16_SYSCALL = 0x01,
17159 NM_BREAK16 = 0x02,
17160 NM_SDBBP16 = 0x03,
17163 /* POOL16C_0 instruction pool */
17164 enum {
17165 NM_POOL16C_00 = 0x00,
17168 /* P16.JRC instruction pool */
17169 enum {
17170 NM_JRC = 0x00,
17171 NM_JALRC16 = 0x01,
17174 /* P.SYSCALL instruction pool */
17175 enum {
17176 NM_SYSCALL = 0x00,
17177 NM_HYPCALL = 0x01,
17180 /* P.TRAP instruction pool */
17181 enum {
17182 NM_TEQ = 0x00,
17183 NM_TNE = 0x01,
17186 /* P.CMOVE instruction pool */
17187 enum {
17188 NM_MOVZ = 0x00,
17189 NM_MOVN = 0x01,
17192 /* POOL32Axf instruction pool */
17193 enum {
17194 NM_POOL32AXF_1 = 0x01,
17195 NM_POOL32AXF_2 = 0x02,
17196 NM_POOL32AXF_4 = 0x04,
17197 NM_POOL32AXF_5 = 0x05,
17198 NM_POOL32AXF_7 = 0x07,
17201 /* POOL32Axf_1 instruction pool */
17202 enum {
17203 NM_POOL32AXF_1_0 = 0x00,
17204 NM_POOL32AXF_1_1 = 0x01,
17205 NM_POOL32AXF_1_3 = 0x03,
17206 NM_POOL32AXF_1_4 = 0x04,
17207 NM_POOL32AXF_1_5 = 0x05,
17208 NM_POOL32AXF_1_7 = 0x07,
17211 /* POOL32Axf_2 instruction pool */
17212 enum {
17213 NM_POOL32AXF_2_0_7 = 0x00,
17214 NM_POOL32AXF_2_8_15 = 0x01,
17215 NM_POOL32AXF_2_16_23 = 0x02,
17216 NM_POOL32AXF_2_24_31 = 0x03,
17219 /* POOL32Axf_7 instruction pool */
17220 enum {
17221 NM_SHRA_R_QB = 0x0,
17222 NM_SHRL_PH = 0x1,
17223 NM_REPL_QB = 0x2,
17226 /* POOL32Axf_1_0 instruction pool */
17227 enum {
17228 NM_MFHI = 0x0,
17229 NM_MFLO = 0x1,
17230 NM_MTHI = 0x2,
17231 NM_MTLO = 0x3,
17234 /* POOL32Axf_1_1 instruction pool */
17235 enum {
17236 NM_MTHLIP = 0x0,
17237 NM_SHILOV = 0x1,
17240 /* POOL32Axf_1_3 instruction pool */
17241 enum {
17242 NM_RDDSP = 0x0,
17243 NM_WRDSP = 0x1,
17244 NM_EXTP = 0x2,
17245 NM_EXTPDP = 0x3,
17248 /* POOL32Axf_1_4 instruction pool */
17249 enum {
17250 NM_SHLL_QB = 0x0,
17251 NM_SHRL_QB = 0x1,
17254 /* POOL32Axf_1_5 instruction pool */
17255 enum {
17256 NM_MAQ_S_W_PHR = 0x0,
17257 NM_MAQ_S_W_PHL = 0x1,
17258 NM_MAQ_SA_W_PHR = 0x2,
17259 NM_MAQ_SA_W_PHL = 0x3,
17262 /* POOL32Axf_1_7 instruction pool */
17263 enum {
17264 NM_EXTR_W = 0x0,
17265 NM_EXTR_R_W = 0x1,
17266 NM_EXTR_RS_W = 0x2,
17267 NM_EXTR_S_H = 0x3,
17270 /* POOL32Axf_2_0_7 instruction pool */
17271 enum {
17272 NM_DPA_W_PH = 0x0,
17273 NM_DPAQ_S_W_PH = 0x1,
17274 NM_DPS_W_PH = 0x2,
17275 NM_DPSQ_S_W_PH = 0x3,
17276 NM_BALIGN = 0x4,
17277 NM_MADD = 0x5,
17278 NM_MULT = 0x6,
17279 NM_EXTRV_W = 0x7,
17282 /* POOL32Axf_2_8_15 instruction pool */
17283 enum {
17284 NM_DPAX_W_PH = 0x0,
17285 NM_DPAQ_SA_L_W = 0x1,
17286 NM_DPSX_W_PH = 0x2,
17287 NM_DPSQ_SA_L_W = 0x3,
17288 NM_MADDU = 0x5,
17289 NM_MULTU = 0x6,
17290 NM_EXTRV_R_W = 0x7,
17293 /* POOL32Axf_2_16_23 instruction pool */
17294 enum {
17295 NM_DPAU_H_QBL = 0x0,
17296 NM_DPAQX_S_W_PH = 0x1,
17297 NM_DPSU_H_QBL = 0x2,
17298 NM_DPSQX_S_W_PH = 0x3,
17299 NM_EXTPV = 0x4,
17300 NM_MSUB = 0x5,
17301 NM_MULSA_W_PH = 0x6,
17302 NM_EXTRV_RS_W = 0x7,
17305 /* POOL32Axf_2_24_31 instruction pool */
17306 enum {
17307 NM_DPAU_H_QBR = 0x0,
17308 NM_DPAQX_SA_W_PH = 0x1,
17309 NM_DPSU_H_QBR = 0x2,
17310 NM_DPSQX_SA_W_PH = 0x3,
17311 NM_EXTPDPV = 0x4,
17312 NM_MSUBU = 0x5,
17313 NM_MULSAQ_S_W_PH = 0x6,
17314 NM_EXTRV_S_H = 0x7,
17317 /* POOL32Axf_{4, 5} instruction pool */
17318 enum {
17319 NM_CLO = 0x25,
17320 NM_CLZ = 0x2d,
17322 NM_TLBP = 0x01,
17323 NM_TLBR = 0x09,
17324 NM_TLBWI = 0x11,
17325 NM_TLBWR = 0x19,
17326 NM_TLBINV = 0x03,
17327 NM_TLBINVF = 0x0b,
17328 NM_DI = 0x23,
17329 NM_EI = 0x2b,
17330 NM_RDPGPR = 0x70,
17331 NM_WRPGPR = 0x78,
17332 NM_WAIT = 0x61,
17333 NM_DERET = 0x71,
17334 NM_ERETX = 0x79,
17336 /* nanoMIPS DSP instructions */
17337 NM_ABSQ_S_QB = 0x00,
17338 NM_ABSQ_S_PH = 0x08,
17339 NM_ABSQ_S_W = 0x10,
17340 NM_PRECEQ_W_PHL = 0x28,
17341 NM_PRECEQ_W_PHR = 0x30,
17342 NM_PRECEQU_PH_QBL = 0x38,
17343 NM_PRECEQU_PH_QBR = 0x48,
17344 NM_PRECEU_PH_QBL = 0x58,
17345 NM_PRECEU_PH_QBR = 0x68,
17346 NM_PRECEQU_PH_QBLA = 0x39,
17347 NM_PRECEQU_PH_QBRA = 0x49,
17348 NM_PRECEU_PH_QBLA = 0x59,
17349 NM_PRECEU_PH_QBRA = 0x69,
17350 NM_REPLV_PH = 0x01,
17351 NM_REPLV_QB = 0x09,
17352 NM_BITREV = 0x18,
17353 NM_INSV = 0x20,
17354 NM_RADDU_W_QB = 0x78,
17356 NM_BITSWAP = 0x05,
17357 NM_WSBH = 0x3d,
17360 /* PP.SR instruction pool */
17361 enum {
17362 NM_SAVE = 0x00,
17363 NM_RESTORE = 0x02,
17364 NM_RESTORE_JRC = 0x03,
17367 /* P.SR.F instruction pool */
17368 enum {
17369 NM_SAVEF = 0x00,
17370 NM_RESTOREF = 0x01,
17373 /* P16.SYSCALL instruction pool */
17374 enum {
17375 NM_SYSCALL16 = 0x00,
17376 NM_HYPCALL16 = 0x01,
17379 /* POOL16C_00 instruction pool */
17380 enum {
17381 NM_NOT16 = 0x00,
17382 NM_XOR16 = 0x01,
17383 NM_AND16 = 0x02,
17384 NM_OR16 = 0x03,
17387 /* PP.LSX and PP.LSXS instruction pool */
17388 enum {
17389 NM_LBX = 0x00,
17390 NM_LHX = 0x04,
17391 NM_LWX = 0x08,
17392 NM_LDX = 0x0c,
17394 NM_SBX = 0x01,
17395 NM_SHX = 0x05,
17396 NM_SWX = 0x09,
17397 NM_SDX = 0x0d,
17399 NM_LBUX = 0x02,
17400 NM_LHUX = 0x06,
17401 NM_LWC1X = 0x0a,
17402 NM_LDC1X = 0x0e,
17404 NM_LWUX = 0x07,
17405 NM_SWC1X = 0x0b,
17406 NM_SDC1X = 0x0f,
17408 NM_LHXS = 0x04,
17409 NM_LWXS = 0x08,
17410 NM_LDXS = 0x0c,
17412 NM_SHXS = 0x05,
17413 NM_SWXS = 0x09,
17414 NM_SDXS = 0x0d,
17416 NM_LHUXS = 0x06,
17417 NM_LWC1XS = 0x0a,
17418 NM_LDC1XS = 0x0e,
17420 NM_LWUXS = 0x07,
17421 NM_SWC1XS = 0x0b,
17422 NM_SDC1XS = 0x0f,
17425 /* ERETx instruction pool */
17426 enum {
17427 NM_ERET = 0x00,
17428 NM_ERETNC = 0x01,
17431 /* POOL32FxF_{0, 1} insturction pool */
17432 enum {
17433 NM_CFC1 = 0x40,
17434 NM_CTC1 = 0x60,
17435 NM_MFC1 = 0x80,
17436 NM_MTC1 = 0xa0,
17437 NM_MFHC1 = 0xc0,
17438 NM_MTHC1 = 0xe0,
17440 NM_CVT_S_PL = 0x84,
17441 NM_CVT_S_PU = 0xa4,
17443 NM_CVT_L_S = 0x004,
17444 NM_CVT_L_D = 0x104,
17445 NM_CVT_W_S = 0x024,
17446 NM_CVT_W_D = 0x124,
17448 NM_RSQRT_S = 0x008,
17449 NM_RSQRT_D = 0x108,
17451 NM_SQRT_S = 0x028,
17452 NM_SQRT_D = 0x128,
17454 NM_RECIP_S = 0x048,
17455 NM_RECIP_D = 0x148,
17457 NM_FLOOR_L_S = 0x00c,
17458 NM_FLOOR_L_D = 0x10c,
17460 NM_FLOOR_W_S = 0x02c,
17461 NM_FLOOR_W_D = 0x12c,
17463 NM_CEIL_L_S = 0x04c,
17464 NM_CEIL_L_D = 0x14c,
17465 NM_CEIL_W_S = 0x06c,
17466 NM_CEIL_W_D = 0x16c,
17467 NM_TRUNC_L_S = 0x08c,
17468 NM_TRUNC_L_D = 0x18c,
17469 NM_TRUNC_W_S = 0x0ac,
17470 NM_TRUNC_W_D = 0x1ac,
17471 NM_ROUND_L_S = 0x0cc,
17472 NM_ROUND_L_D = 0x1cc,
17473 NM_ROUND_W_S = 0x0ec,
17474 NM_ROUND_W_D = 0x1ec,
17476 NM_MOV_S = 0x01,
17477 NM_MOV_D = 0x81,
17478 NM_ABS_S = 0x0d,
17479 NM_ABS_D = 0x8d,
17480 NM_NEG_S = 0x2d,
17481 NM_NEG_D = 0xad,
17482 NM_CVT_D_S = 0x04d,
17483 NM_CVT_D_W = 0x0cd,
17484 NM_CVT_D_L = 0x14d,
17485 NM_CVT_S_D = 0x06d,
17486 NM_CVT_S_W = 0x0ed,
17487 NM_CVT_S_L = 0x16d,
17490 /* P.LL instruction pool */
17491 enum {
17492 NM_LL = 0x00,
17493 NM_LLWP = 0x01,
17496 /* P.SC instruction pool */
17497 enum {
17498 NM_SC = 0x00,
17499 NM_SCWP = 0x01,
17502 /* P.DVP instruction pool */
17503 enum {
17504 NM_DVP = 0x00,
17505 NM_EVP = 0x01,
17511 * nanoMIPS decoding engine
17516 /* extraction utilities */
17518 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17519 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17520 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17521 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17522 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17523 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17525 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17526 static inline int decode_gpr_gpr3(int r)
17528 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17530 return map[r & 0x7];
17533 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17534 static inline int decode_gpr_gpr3_src_store(int r)
17536 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17538 return map[r & 0x7];
17541 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17542 static inline int decode_gpr_gpr4(int r)
17544 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17545 16, 17, 18, 19, 20, 21, 22, 23 };
17547 return map[r & 0xf];
17550 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17551 static inline int decode_gpr_gpr4_zero(int r)
17553 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17554 16, 17, 18, 19, 20, 21, 22, 23 };
17556 return map[r & 0xf];
17560 /* extraction utilities */
17562 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17563 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17564 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17565 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17566 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17567 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17570 static void gen_adjust_sp(DisasContext *ctx, int u)
17572 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17575 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17576 uint8_t gp, uint16_t u)
17578 int counter = 0;
17579 TCGv va = tcg_temp_new();
17580 TCGv t0 = tcg_temp_new();
17582 while (counter != count) {
17583 bool use_gp = gp && (counter == count - 1);
17584 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17585 int this_offset = -((counter + 1) << 2);
17586 gen_base_offset_addr(ctx, va, 29, this_offset);
17587 gen_load_gpr(t0, this_rt);
17588 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17589 (MO_TEUL | ctx->default_tcg_memop_mask));
17590 counter++;
17593 /* adjust stack pointer */
17594 gen_adjust_sp(ctx, -u);
17596 tcg_temp_free(t0);
17597 tcg_temp_free(va);
17600 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17601 uint8_t gp, uint16_t u)
17603 int counter = 0;
17604 TCGv va = tcg_temp_new();
17605 TCGv t0 = tcg_temp_new();
17607 while (counter != count) {
17608 bool use_gp = gp && (counter == count - 1);
17609 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17610 int this_offset = u - ((counter + 1) << 2);
17611 gen_base_offset_addr(ctx, va, 29, this_offset);
17612 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17613 ctx->default_tcg_memop_mask);
17614 tcg_gen_ext32s_tl(t0, t0);
17615 gen_store_gpr(t0, this_rt);
17616 counter++;
17619 /* adjust stack pointer */
17620 gen_adjust_sp(ctx, u);
17622 tcg_temp_free(t0);
17623 tcg_temp_free(va);
17626 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17628 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
17629 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
17631 switch (extract32(ctx->opcode, 2, 2)) {
17632 case NM_NOT16:
17633 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17634 break;
17635 case NM_AND16:
17636 gen_logic(ctx, OPC_AND, rt, rt, rs);
17637 break;
17638 case NM_XOR16:
17639 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17640 break;
17641 case NM_OR16:
17642 gen_logic(ctx, OPC_OR, rt, rt, rs);
17643 break;
17647 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17649 int rt = extract32(ctx->opcode, 21, 5);
17650 int rs = extract32(ctx->opcode, 16, 5);
17651 int rd = extract32(ctx->opcode, 11, 5);
17653 switch (extract32(ctx->opcode, 3, 7)) {
17654 case NM_P_TRAP:
17655 switch (extract32(ctx->opcode, 10, 1)) {
17656 case NM_TEQ:
17657 check_nms(ctx);
17658 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17659 break;
17660 case NM_TNE:
17661 check_nms(ctx);
17662 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17663 break;
17665 break;
17666 case NM_RDHWR:
17667 check_nms(ctx);
17668 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17669 break;
17670 case NM_SEB:
17671 check_nms(ctx);
17672 gen_bshfl(ctx, OPC_SEB, rs, rt);
17673 break;
17674 case NM_SEH:
17675 gen_bshfl(ctx, OPC_SEH, rs, rt);
17676 break;
17677 case NM_SLLV:
17678 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17679 break;
17680 case NM_SRLV:
17681 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17682 break;
17683 case NM_SRAV:
17684 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17685 break;
17686 case NM_ROTRV:
17687 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17688 break;
17689 case NM_ADD:
17690 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17691 break;
17692 case NM_ADDU:
17693 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17694 break;
17695 case NM_SUB:
17696 check_nms(ctx);
17697 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17698 break;
17699 case NM_SUBU:
17700 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17701 break;
17702 case NM_P_CMOVE:
17703 switch (extract32(ctx->opcode, 10, 1)) {
17704 case NM_MOVZ:
17705 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17706 break;
17707 case NM_MOVN:
17708 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17709 break;
17711 break;
17712 case NM_AND:
17713 gen_logic(ctx, OPC_AND, rd, rs, rt);
17714 break;
17715 case NM_OR:
17716 gen_logic(ctx, OPC_OR, rd, rs, rt);
17717 break;
17718 case NM_NOR:
17719 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17720 break;
17721 case NM_XOR:
17722 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17723 break;
17724 case NM_SLT:
17725 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17726 break;
17727 case NM_P_SLTU:
17728 if (rd == 0) {
17729 /* P_DVP */
17730 #ifndef CONFIG_USER_ONLY
17731 TCGv t0 = tcg_temp_new();
17732 switch (extract32(ctx->opcode, 10, 1)) {
17733 case NM_DVP:
17734 if (ctx->vp) {
17735 check_cp0_enabled(ctx);
17736 gen_helper_dvp(t0, cpu_env);
17737 gen_store_gpr(t0, rt);
17739 break;
17740 case NM_EVP:
17741 if (ctx->vp) {
17742 check_cp0_enabled(ctx);
17743 gen_helper_evp(t0, cpu_env);
17744 gen_store_gpr(t0, rt);
17746 break;
17748 tcg_temp_free(t0);
17749 #endif
17750 } else {
17751 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
17753 break;
17754 case NM_SOV:
17756 TCGv t0 = tcg_temp_new();
17757 TCGv t1 = tcg_temp_new();
17758 TCGv t2 = tcg_temp_new();
17760 gen_load_gpr(t1, rs);
17761 gen_load_gpr(t2, rt);
17762 tcg_gen_add_tl(t0, t1, t2);
17763 tcg_gen_ext32s_tl(t0, t0);
17764 tcg_gen_xor_tl(t1, t1, t2);
17765 tcg_gen_xor_tl(t2, t0, t2);
17766 tcg_gen_andc_tl(t1, t2, t1);
17768 /* operands of same sign, result different sign */
17769 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
17770 gen_store_gpr(t0, rd);
17772 tcg_temp_free(t0);
17773 tcg_temp_free(t1);
17774 tcg_temp_free(t2);
17776 break;
17777 case NM_MUL:
17778 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
17779 break;
17780 case NM_MUH:
17781 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
17782 break;
17783 case NM_MULU:
17784 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
17785 break;
17786 case NM_MUHU:
17787 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
17788 break;
17789 case NM_DIV:
17790 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
17791 break;
17792 case NM_MOD:
17793 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
17794 break;
17795 case NM_DIVU:
17796 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
17797 break;
17798 case NM_MODU:
17799 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
17800 break;
17801 #ifndef CONFIG_USER_ONLY
17802 case NM_MFC0:
17803 check_cp0_enabled(ctx);
17804 if (rt == 0) {
17805 /* Treat as NOP. */
17806 break;
17808 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
17809 break;
17810 case NM_MTC0:
17811 check_cp0_enabled(ctx);
17813 TCGv t0 = tcg_temp_new();
17815 gen_load_gpr(t0, rt);
17816 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
17817 tcg_temp_free(t0);
17819 break;
17820 case NM_D_E_MT_VPE:
17822 uint8_t sc = extract32(ctx->opcode, 10, 1);
17823 TCGv t0 = tcg_temp_new();
17825 switch (sc) {
17826 case 0:
17827 if (rs == 1) {
17828 /* DMT */
17829 check_cp0_mt(ctx);
17830 gen_helper_dmt(t0);
17831 gen_store_gpr(t0, rt);
17832 } else if (rs == 0) {
17833 /* DVPE */
17834 check_cp0_mt(ctx);
17835 gen_helper_dvpe(t0, cpu_env);
17836 gen_store_gpr(t0, rt);
17837 } else {
17838 generate_exception_end(ctx, EXCP_RI);
17840 break;
17841 case 1:
17842 if (rs == 1) {
17843 /* EMT */
17844 check_cp0_mt(ctx);
17845 gen_helper_emt(t0);
17846 gen_store_gpr(t0, rt);
17847 } else if (rs == 0) {
17848 /* EVPE */
17849 check_cp0_mt(ctx);
17850 gen_helper_evpe(t0, cpu_env);
17851 gen_store_gpr(t0, rt);
17852 } else {
17853 generate_exception_end(ctx, EXCP_RI);
17855 break;
17858 tcg_temp_free(t0);
17860 break;
17861 case NM_FORK:
17862 check_mt(ctx);
17864 TCGv t0 = tcg_temp_new();
17865 TCGv t1 = tcg_temp_new();
17867 gen_load_gpr(t0, rt);
17868 gen_load_gpr(t1, rs);
17869 gen_helper_fork(t0, t1);
17870 tcg_temp_free(t0);
17871 tcg_temp_free(t1);
17873 break;
17874 case NM_MFTR:
17875 case NM_MFHTR:
17876 check_cp0_enabled(ctx);
17877 if (rd == 0) {
17878 /* Treat as NOP. */
17879 return;
17881 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17882 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17883 break;
17884 case NM_MTTR:
17885 case NM_MTHTR:
17886 check_cp0_enabled(ctx);
17887 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17888 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17889 break;
17890 case NM_YIELD:
17891 check_mt(ctx);
17893 TCGv t0 = tcg_temp_new();
17895 gen_load_gpr(t0, rs);
17896 gen_helper_yield(t0, cpu_env, t0);
17897 gen_store_gpr(t0, rt);
17898 tcg_temp_free(t0);
17900 break;
17901 #endif
17902 default:
17903 generate_exception_end(ctx, EXCP_RI);
17904 break;
17908 /* dsp */
17909 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
17910 int ret, int v1, int v2)
17912 TCGv_i32 t0;
17913 TCGv v0_t;
17914 TCGv v1_t;
17916 t0 = tcg_temp_new_i32();
17918 v0_t = tcg_temp_new();
17919 v1_t = tcg_temp_new();
17921 tcg_gen_movi_i32(t0, v2 >> 3);
17923 gen_load_gpr(v0_t, ret);
17924 gen_load_gpr(v1_t, v1);
17926 switch (opc) {
17927 case NM_MAQ_S_W_PHR:
17928 check_dsp(ctx);
17929 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
17930 break;
17931 case NM_MAQ_S_W_PHL:
17932 check_dsp(ctx);
17933 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
17934 break;
17935 case NM_MAQ_SA_W_PHR:
17936 check_dsp(ctx);
17937 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
17938 break;
17939 case NM_MAQ_SA_W_PHL:
17940 check_dsp(ctx);
17941 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
17942 break;
17943 default:
17944 generate_exception_end(ctx, EXCP_RI);
17945 break;
17948 tcg_temp_free_i32(t0);
17950 tcg_temp_free(v0_t);
17951 tcg_temp_free(v1_t);
17955 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
17956 int ret, int v1, int v2)
17958 int16_t imm;
17959 TCGv t0 = tcg_temp_new();
17960 TCGv t1 = tcg_temp_new();
17961 TCGv v0_t = tcg_temp_new();
17963 gen_load_gpr(v0_t, v1);
17965 switch (opc) {
17966 case NM_POOL32AXF_1_0:
17967 check_dsp(ctx);
17968 switch (extract32(ctx->opcode, 12, 2)) {
17969 case NM_MFHI:
17970 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
17971 break;
17972 case NM_MFLO:
17973 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
17974 break;
17975 case NM_MTHI:
17976 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
17977 break;
17978 case NM_MTLO:
17979 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
17980 break;
17982 break;
17983 case NM_POOL32AXF_1_1:
17984 check_dsp(ctx);
17985 switch (extract32(ctx->opcode, 12, 2)) {
17986 case NM_MTHLIP:
17987 tcg_gen_movi_tl(t0, v2);
17988 gen_helper_mthlip(t0, v0_t, cpu_env);
17989 break;
17990 case NM_SHILOV:
17991 tcg_gen_movi_tl(t0, v2 >> 3);
17992 gen_helper_shilo(t0, v0_t, cpu_env);
17993 break;
17994 default:
17995 generate_exception_end(ctx, EXCP_RI);
17996 break;
17998 break;
17999 case NM_POOL32AXF_1_3:
18000 check_dsp(ctx);
18001 imm = extract32(ctx->opcode, 14, 7);
18002 switch (extract32(ctx->opcode, 12, 2)) {
18003 case NM_RDDSP:
18004 tcg_gen_movi_tl(t0, imm);
18005 gen_helper_rddsp(t0, t0, cpu_env);
18006 gen_store_gpr(t0, ret);
18007 break;
18008 case NM_WRDSP:
18009 gen_load_gpr(t0, ret);
18010 tcg_gen_movi_tl(t1, imm);
18011 gen_helper_wrdsp(t0, t1, cpu_env);
18012 break;
18013 case NM_EXTP:
18014 tcg_gen_movi_tl(t0, v2 >> 3);
18015 tcg_gen_movi_tl(t1, v1);
18016 gen_helper_extp(t0, t0, t1, cpu_env);
18017 gen_store_gpr(t0, ret);
18018 break;
18019 case NM_EXTPDP:
18020 tcg_gen_movi_tl(t0, v2 >> 3);
18021 tcg_gen_movi_tl(t1, v1);
18022 gen_helper_extpdp(t0, t0, t1, cpu_env);
18023 gen_store_gpr(t0, ret);
18024 break;
18026 break;
18027 case NM_POOL32AXF_1_4:
18028 check_dsp(ctx);
18029 tcg_gen_movi_tl(t0, v2 >> 2);
18030 switch (extract32(ctx->opcode, 12, 1)) {
18031 case NM_SHLL_QB:
18032 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18033 gen_store_gpr(t0, ret);
18034 break;
18035 case NM_SHRL_QB:
18036 gen_helper_shrl_qb(t0, t0, v0_t);
18037 gen_store_gpr(t0, ret);
18038 break;
18040 break;
18041 case NM_POOL32AXF_1_5:
18042 opc = extract32(ctx->opcode, 12, 2);
18043 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18044 break;
18045 case NM_POOL32AXF_1_7:
18046 check_dsp(ctx);
18047 tcg_gen_movi_tl(t0, v2 >> 3);
18048 tcg_gen_movi_tl(t1, v1);
18049 switch (extract32(ctx->opcode, 12, 2)) {
18050 case NM_EXTR_W:
18051 gen_helper_extr_w(t0, t0, t1, cpu_env);
18052 gen_store_gpr(t0, ret);
18053 break;
18054 case NM_EXTR_R_W:
18055 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18056 gen_store_gpr(t0, ret);
18057 break;
18058 case NM_EXTR_RS_W:
18059 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18060 gen_store_gpr(t0, ret);
18061 break;
18062 case NM_EXTR_S_H:
18063 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18064 gen_store_gpr(t0, ret);
18065 break;
18067 break;
18068 default:
18069 generate_exception_end(ctx, EXCP_RI);
18070 break;
18073 tcg_temp_free(t0);
18074 tcg_temp_free(t1);
18075 tcg_temp_free(v0_t);
18078 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18079 TCGv v0, TCGv v1, int rd)
18081 TCGv_i32 t0;
18083 t0 = tcg_temp_new_i32();
18085 tcg_gen_movi_i32(t0, rd >> 3);
18087 switch (opc) {
18088 case NM_POOL32AXF_2_0_7:
18089 switch (extract32(ctx->opcode, 9, 3)) {
18090 case NM_DPA_W_PH:
18091 check_dsp_r2(ctx);
18092 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18093 break;
18094 case NM_DPAQ_S_W_PH:
18095 check_dsp(ctx);
18096 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18097 break;
18098 case NM_DPS_W_PH:
18099 check_dsp_r2(ctx);
18100 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18101 break;
18102 case NM_DPSQ_S_W_PH:
18103 check_dsp(ctx);
18104 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18105 break;
18106 default:
18107 generate_exception_end(ctx, EXCP_RI);
18108 break;
18110 break;
18111 case NM_POOL32AXF_2_8_15:
18112 switch (extract32(ctx->opcode, 9, 3)) {
18113 case NM_DPAX_W_PH:
18114 check_dsp_r2(ctx);
18115 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18116 break;
18117 case NM_DPAQ_SA_L_W:
18118 check_dsp(ctx);
18119 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18120 break;
18121 case NM_DPSX_W_PH:
18122 check_dsp_r2(ctx);
18123 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18124 break;
18125 case NM_DPSQ_SA_L_W:
18126 check_dsp(ctx);
18127 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18128 break;
18129 default:
18130 generate_exception_end(ctx, EXCP_RI);
18131 break;
18133 break;
18134 case NM_POOL32AXF_2_16_23:
18135 switch (extract32(ctx->opcode, 9, 3)) {
18136 case NM_DPAU_H_QBL:
18137 check_dsp(ctx);
18138 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18139 break;
18140 case NM_DPAQX_S_W_PH:
18141 check_dsp_r2(ctx);
18142 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18143 break;
18144 case NM_DPSU_H_QBL:
18145 check_dsp(ctx);
18146 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18147 break;
18148 case NM_DPSQX_S_W_PH:
18149 check_dsp_r2(ctx);
18150 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18151 break;
18152 case NM_MULSA_W_PH:
18153 check_dsp_r2(ctx);
18154 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18155 break;
18156 default:
18157 generate_exception_end(ctx, EXCP_RI);
18158 break;
18160 break;
18161 case NM_POOL32AXF_2_24_31:
18162 switch (extract32(ctx->opcode, 9, 3)) {
18163 case NM_DPAU_H_QBR:
18164 check_dsp(ctx);
18165 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18166 break;
18167 case NM_DPAQX_SA_W_PH:
18168 check_dsp_r2(ctx);
18169 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18170 break;
18171 case NM_DPSU_H_QBR:
18172 check_dsp(ctx);
18173 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18174 break;
18175 case NM_DPSQX_SA_W_PH:
18176 check_dsp_r2(ctx);
18177 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18178 break;
18179 case NM_MULSAQ_S_W_PH:
18180 check_dsp(ctx);
18181 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18182 break;
18183 default:
18184 generate_exception_end(ctx, EXCP_RI);
18185 break;
18187 break;
18188 default:
18189 generate_exception_end(ctx, EXCP_RI);
18190 break;
18193 tcg_temp_free_i32(t0);
18196 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18197 int rt, int rs, int rd)
18199 int ret = rt;
18200 TCGv t0 = tcg_temp_new();
18201 TCGv t1 = tcg_temp_new();
18202 TCGv v0_t = tcg_temp_new();
18203 TCGv v1_t = tcg_temp_new();
18205 gen_load_gpr(v0_t, rt);
18206 gen_load_gpr(v1_t, rs);
18208 switch (opc) {
18209 case NM_POOL32AXF_2_0_7:
18210 switch (extract32(ctx->opcode, 9, 3)) {
18211 case NM_DPA_W_PH:
18212 case NM_DPAQ_S_W_PH:
18213 case NM_DPS_W_PH:
18214 case NM_DPSQ_S_W_PH:
18215 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18216 break;
18217 case NM_BALIGN:
18218 check_dsp_r2(ctx);
18219 if (rt != 0) {
18220 gen_load_gpr(t0, rs);
18221 rd &= 3;
18222 if (rd != 0 && rd != 2) {
18223 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18224 tcg_gen_ext32u_tl(t0, t0);
18225 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18226 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18228 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18230 break;
18231 case NM_MADD:
18232 check_dsp(ctx);
18234 int acc = extract32(ctx->opcode, 14, 2);
18235 TCGv_i64 t2 = tcg_temp_new_i64();
18236 TCGv_i64 t3 = tcg_temp_new_i64();
18238 gen_load_gpr(t0, rt);
18239 gen_load_gpr(t1, rs);
18240 tcg_gen_ext_tl_i64(t2, t0);
18241 tcg_gen_ext_tl_i64(t3, t1);
18242 tcg_gen_mul_i64(t2, t2, t3);
18243 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18244 tcg_gen_add_i64(t2, t2, t3);
18245 tcg_temp_free_i64(t3);
18246 gen_move_low32(cpu_LO[acc], t2);
18247 gen_move_high32(cpu_HI[acc], t2);
18248 tcg_temp_free_i64(t2);
18250 break;
18251 case NM_MULT:
18252 check_dsp(ctx);
18254 int acc = extract32(ctx->opcode, 14, 2);
18255 TCGv_i32 t2 = tcg_temp_new_i32();
18256 TCGv_i32 t3 = tcg_temp_new_i32();
18258 gen_load_gpr(t0, rs);
18259 gen_load_gpr(t1, rt);
18260 tcg_gen_trunc_tl_i32(t2, t0);
18261 tcg_gen_trunc_tl_i32(t3, t1);
18262 tcg_gen_muls2_i32(t2, t3, t2, t3);
18263 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18264 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18265 tcg_temp_free_i32(t2);
18266 tcg_temp_free_i32(t3);
18268 break;
18269 case NM_EXTRV_W:
18270 check_dsp(ctx);
18271 gen_load_gpr(v1_t, rs);
18272 tcg_gen_movi_tl(t0, rd >> 3);
18273 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18274 gen_store_gpr(t0, ret);
18275 break;
18277 break;
18278 case NM_POOL32AXF_2_8_15:
18279 switch (extract32(ctx->opcode, 9, 3)) {
18280 case NM_DPAX_W_PH:
18281 case NM_DPAQ_SA_L_W:
18282 case NM_DPSX_W_PH:
18283 case NM_DPSQ_SA_L_W:
18284 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18285 break;
18286 case NM_MADDU:
18287 check_dsp(ctx);
18289 int acc = extract32(ctx->opcode, 14, 2);
18290 TCGv_i64 t2 = tcg_temp_new_i64();
18291 TCGv_i64 t3 = tcg_temp_new_i64();
18293 gen_load_gpr(t0, rs);
18294 gen_load_gpr(t1, rt);
18295 tcg_gen_ext32u_tl(t0, t0);
18296 tcg_gen_ext32u_tl(t1, t1);
18297 tcg_gen_extu_tl_i64(t2, t0);
18298 tcg_gen_extu_tl_i64(t3, t1);
18299 tcg_gen_mul_i64(t2, t2, t3);
18300 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18301 tcg_gen_add_i64(t2, t2, t3);
18302 tcg_temp_free_i64(t3);
18303 gen_move_low32(cpu_LO[acc], t2);
18304 gen_move_high32(cpu_HI[acc], t2);
18305 tcg_temp_free_i64(t2);
18307 break;
18308 case NM_MULTU:
18309 check_dsp(ctx);
18311 int acc = extract32(ctx->opcode, 14, 2);
18312 TCGv_i32 t2 = tcg_temp_new_i32();
18313 TCGv_i32 t3 = tcg_temp_new_i32();
18315 gen_load_gpr(t0, rs);
18316 gen_load_gpr(t1, rt);
18317 tcg_gen_trunc_tl_i32(t2, t0);
18318 tcg_gen_trunc_tl_i32(t3, t1);
18319 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18320 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18321 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18322 tcg_temp_free_i32(t2);
18323 tcg_temp_free_i32(t3);
18325 break;
18326 case NM_EXTRV_R_W:
18327 check_dsp(ctx);
18328 tcg_gen_movi_tl(t0, rd >> 3);
18329 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18330 gen_store_gpr(t0, ret);
18331 break;
18332 default:
18333 generate_exception_end(ctx, EXCP_RI);
18334 break;
18336 break;
18337 case NM_POOL32AXF_2_16_23:
18338 switch (extract32(ctx->opcode, 9, 3)) {
18339 case NM_DPAU_H_QBL:
18340 case NM_DPAQX_S_W_PH:
18341 case NM_DPSU_H_QBL:
18342 case NM_DPSQX_S_W_PH:
18343 case NM_MULSA_W_PH:
18344 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18345 break;
18346 case NM_EXTPV:
18347 check_dsp(ctx);
18348 tcg_gen_movi_tl(t0, rd >> 3);
18349 gen_helper_extp(t0, t0, v1_t, cpu_env);
18350 gen_store_gpr(t0, ret);
18351 break;
18352 case NM_MSUB:
18353 check_dsp(ctx);
18355 int acc = extract32(ctx->opcode, 14, 2);
18356 TCGv_i64 t2 = tcg_temp_new_i64();
18357 TCGv_i64 t3 = tcg_temp_new_i64();
18359 gen_load_gpr(t0, rs);
18360 gen_load_gpr(t1, rt);
18361 tcg_gen_ext_tl_i64(t2, t0);
18362 tcg_gen_ext_tl_i64(t3, t1);
18363 tcg_gen_mul_i64(t2, t2, t3);
18364 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18365 tcg_gen_sub_i64(t2, t3, t2);
18366 tcg_temp_free_i64(t3);
18367 gen_move_low32(cpu_LO[acc], t2);
18368 gen_move_high32(cpu_HI[acc], t2);
18369 tcg_temp_free_i64(t2);
18371 break;
18372 case NM_EXTRV_RS_W:
18373 check_dsp(ctx);
18374 tcg_gen_movi_tl(t0, rd >> 3);
18375 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18376 gen_store_gpr(t0, ret);
18377 break;
18379 break;
18380 case NM_POOL32AXF_2_24_31:
18381 switch (extract32(ctx->opcode, 9, 3)) {
18382 case NM_DPAU_H_QBR:
18383 case NM_DPAQX_SA_W_PH:
18384 case NM_DPSU_H_QBR:
18385 case NM_DPSQX_SA_W_PH:
18386 case NM_MULSAQ_S_W_PH:
18387 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18388 break;
18389 case NM_EXTPDPV:
18390 check_dsp(ctx);
18391 tcg_gen_movi_tl(t0, rd >> 3);
18392 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18393 gen_store_gpr(t0, ret);
18394 break;
18395 case NM_MSUBU:
18396 check_dsp(ctx);
18398 int acc = extract32(ctx->opcode, 14, 2);
18399 TCGv_i64 t2 = tcg_temp_new_i64();
18400 TCGv_i64 t3 = tcg_temp_new_i64();
18402 gen_load_gpr(t0, rs);
18403 gen_load_gpr(t1, rt);
18404 tcg_gen_ext32u_tl(t0, t0);
18405 tcg_gen_ext32u_tl(t1, t1);
18406 tcg_gen_extu_tl_i64(t2, t0);
18407 tcg_gen_extu_tl_i64(t3, t1);
18408 tcg_gen_mul_i64(t2, t2, t3);
18409 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18410 tcg_gen_sub_i64(t2, t3, t2);
18411 tcg_temp_free_i64(t3);
18412 gen_move_low32(cpu_LO[acc], t2);
18413 gen_move_high32(cpu_HI[acc], t2);
18414 tcg_temp_free_i64(t2);
18416 break;
18417 case NM_EXTRV_S_H:
18418 check_dsp(ctx);
18419 tcg_gen_movi_tl(t0, rd >> 3);
18420 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18421 gen_store_gpr(t0, ret);
18422 break;
18424 break;
18425 default:
18426 generate_exception_end(ctx, EXCP_RI);
18427 break;
18430 tcg_temp_free(t0);
18431 tcg_temp_free(t1);
18433 tcg_temp_free(v0_t);
18434 tcg_temp_free(v1_t);
18437 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18438 int rt, int rs)
18440 int ret = rt;
18441 TCGv t0 = tcg_temp_new();
18442 TCGv v0_t = tcg_temp_new();
18444 gen_load_gpr(v0_t, rs);
18446 switch (opc) {
18447 case NM_ABSQ_S_QB:
18448 check_dsp_r2(ctx);
18449 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18450 gen_store_gpr(v0_t, ret);
18451 break;
18452 case NM_ABSQ_S_PH:
18453 check_dsp(ctx);
18454 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18455 gen_store_gpr(v0_t, ret);
18456 break;
18457 case NM_ABSQ_S_W:
18458 check_dsp(ctx);
18459 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18460 gen_store_gpr(v0_t, ret);
18461 break;
18462 case NM_PRECEQ_W_PHL:
18463 check_dsp(ctx);
18464 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18465 tcg_gen_ext32s_tl(v0_t, v0_t);
18466 gen_store_gpr(v0_t, ret);
18467 break;
18468 case NM_PRECEQ_W_PHR:
18469 check_dsp(ctx);
18470 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18471 tcg_gen_shli_tl(v0_t, v0_t, 16);
18472 tcg_gen_ext32s_tl(v0_t, v0_t);
18473 gen_store_gpr(v0_t, ret);
18474 break;
18475 case NM_PRECEQU_PH_QBL:
18476 check_dsp(ctx);
18477 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18478 gen_store_gpr(v0_t, ret);
18479 break;
18480 case NM_PRECEQU_PH_QBR:
18481 check_dsp(ctx);
18482 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18483 gen_store_gpr(v0_t, ret);
18484 break;
18485 case NM_PRECEQU_PH_QBLA:
18486 check_dsp(ctx);
18487 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18488 gen_store_gpr(v0_t, ret);
18489 break;
18490 case NM_PRECEQU_PH_QBRA:
18491 check_dsp(ctx);
18492 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18493 gen_store_gpr(v0_t, ret);
18494 break;
18495 case NM_PRECEU_PH_QBL:
18496 check_dsp(ctx);
18497 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18498 gen_store_gpr(v0_t, ret);
18499 break;
18500 case NM_PRECEU_PH_QBR:
18501 check_dsp(ctx);
18502 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18503 gen_store_gpr(v0_t, ret);
18504 break;
18505 case NM_PRECEU_PH_QBLA:
18506 check_dsp(ctx);
18507 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18508 gen_store_gpr(v0_t, ret);
18509 break;
18510 case NM_PRECEU_PH_QBRA:
18511 check_dsp(ctx);
18512 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18513 gen_store_gpr(v0_t, ret);
18514 break;
18515 case NM_REPLV_PH:
18516 check_dsp(ctx);
18517 tcg_gen_ext16u_tl(v0_t, v0_t);
18518 tcg_gen_shli_tl(t0, v0_t, 16);
18519 tcg_gen_or_tl(v0_t, v0_t, t0);
18520 tcg_gen_ext32s_tl(v0_t, v0_t);
18521 gen_store_gpr(v0_t, ret);
18522 break;
18523 case NM_REPLV_QB:
18524 check_dsp(ctx);
18525 tcg_gen_ext8u_tl(v0_t, v0_t);
18526 tcg_gen_shli_tl(t0, v0_t, 8);
18527 tcg_gen_or_tl(v0_t, v0_t, t0);
18528 tcg_gen_shli_tl(t0, v0_t, 16);
18529 tcg_gen_or_tl(v0_t, v0_t, t0);
18530 tcg_gen_ext32s_tl(v0_t, v0_t);
18531 gen_store_gpr(v0_t, ret);
18532 break;
18533 case NM_BITREV:
18534 check_dsp(ctx);
18535 gen_helper_bitrev(v0_t, v0_t);
18536 gen_store_gpr(v0_t, ret);
18537 break;
18538 case NM_INSV:
18539 check_dsp(ctx);
18541 TCGv tv0 = tcg_temp_new();
18543 gen_load_gpr(tv0, rt);
18544 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18545 gen_store_gpr(v0_t, ret);
18546 tcg_temp_free(tv0);
18548 break;
18549 case NM_RADDU_W_QB:
18550 check_dsp(ctx);
18551 gen_helper_raddu_w_qb(v0_t, v0_t);
18552 gen_store_gpr(v0_t, ret);
18553 break;
18554 case NM_BITSWAP:
18555 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18556 break;
18557 case NM_CLO:
18558 check_nms(ctx);
18559 gen_cl(ctx, OPC_CLO, ret, rs);
18560 break;
18561 case NM_CLZ:
18562 check_nms(ctx);
18563 gen_cl(ctx, OPC_CLZ, ret, rs);
18564 break;
18565 case NM_WSBH:
18566 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18567 break;
18568 default:
18569 generate_exception_end(ctx, EXCP_RI);
18570 break;
18573 tcg_temp_free(v0_t);
18574 tcg_temp_free(t0);
18577 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18578 int rt, int rs, int rd)
18580 TCGv t0 = tcg_temp_new();
18581 TCGv rs_t = tcg_temp_new();
18583 gen_load_gpr(rs_t, rs);
18585 switch (opc) {
18586 case NM_SHRA_R_QB:
18587 check_dsp_r2(ctx);
18588 tcg_gen_movi_tl(t0, rd >> 2);
18589 switch (extract32(ctx->opcode, 12, 1)) {
18590 case 0:
18591 /* NM_SHRA_QB */
18592 gen_helper_shra_qb(t0, t0, rs_t);
18593 gen_store_gpr(t0, rt);
18594 break;
18595 case 1:
18596 /* NM_SHRA_R_QB */
18597 gen_helper_shra_r_qb(t0, t0, rs_t);
18598 gen_store_gpr(t0, rt);
18599 break;
18601 break;
18602 case NM_SHRL_PH:
18603 check_dsp_r2(ctx);
18604 tcg_gen_movi_tl(t0, rd >> 1);
18605 gen_helper_shrl_ph(t0, t0, rs_t);
18606 gen_store_gpr(t0, rt);
18607 break;
18608 case NM_REPL_QB:
18609 check_dsp(ctx);
18611 int16_t imm;
18612 target_long result;
18613 imm = extract32(ctx->opcode, 13, 8);
18614 result = (uint32_t)imm << 24 |
18615 (uint32_t)imm << 16 |
18616 (uint32_t)imm << 8 |
18617 (uint32_t)imm;
18618 result = (int32_t)result;
18619 tcg_gen_movi_tl(t0, result);
18620 gen_store_gpr(t0, rt);
18622 break;
18623 default:
18624 generate_exception_end(ctx, EXCP_RI);
18625 break;
18627 tcg_temp_free(t0);
18628 tcg_temp_free(rs_t);
18632 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18634 int rt = extract32(ctx->opcode, 21, 5);
18635 int rs = extract32(ctx->opcode, 16, 5);
18636 int rd = extract32(ctx->opcode, 11, 5);
18638 switch (extract32(ctx->opcode, 6, 3)) {
18639 case NM_POOL32AXF_1:
18641 int32_t op1 = extract32(ctx->opcode, 9, 3);
18642 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18644 break;
18645 case NM_POOL32AXF_2:
18647 int32_t op1 = extract32(ctx->opcode, 12, 2);
18648 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18650 break;
18651 case NM_POOL32AXF_4:
18653 int32_t op1 = extract32(ctx->opcode, 9, 7);
18654 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18656 break;
18657 case NM_POOL32AXF_5:
18658 switch (extract32(ctx->opcode, 9, 7)) {
18659 #ifndef CONFIG_USER_ONLY
18660 case NM_TLBP:
18661 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18662 break;
18663 case NM_TLBR:
18664 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18665 break;
18666 case NM_TLBWI:
18667 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18668 break;
18669 case NM_TLBWR:
18670 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18671 break;
18672 case NM_TLBINV:
18673 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18674 break;
18675 case NM_TLBINVF:
18676 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18677 break;
18678 case NM_DI:
18679 check_cp0_enabled(ctx);
18681 TCGv t0 = tcg_temp_new();
18683 save_cpu_state(ctx, 1);
18684 gen_helper_di(t0, cpu_env);
18685 gen_store_gpr(t0, rt);
18686 /* Stop translation as we may have switched the execution mode */
18687 ctx->base.is_jmp = DISAS_STOP;
18688 tcg_temp_free(t0);
18690 break;
18691 case NM_EI:
18692 check_cp0_enabled(ctx);
18694 TCGv t0 = tcg_temp_new();
18696 save_cpu_state(ctx, 1);
18697 gen_helper_ei(t0, cpu_env);
18698 gen_store_gpr(t0, rt);
18699 /* Stop translation as we may have switched the execution mode */
18700 ctx->base.is_jmp = DISAS_STOP;
18701 tcg_temp_free(t0);
18703 break;
18704 case NM_RDPGPR:
18705 gen_load_srsgpr(rs, rt);
18706 break;
18707 case NM_WRPGPR:
18708 gen_store_srsgpr(rs, rt);
18709 break;
18710 case NM_WAIT:
18711 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18712 break;
18713 case NM_DERET:
18714 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18715 break;
18716 case NM_ERETX:
18717 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18718 break;
18719 #endif
18720 default:
18721 generate_exception_end(ctx, EXCP_RI);
18722 break;
18724 break;
18725 case NM_POOL32AXF_7:
18727 int32_t op1 = extract32(ctx->opcode, 9, 3);
18728 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18730 break;
18731 default:
18732 generate_exception_end(ctx, EXCP_RI);
18733 break;
18737 /* Immediate Value Compact Branches */
18738 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
18739 int rt, int32_t imm, int32_t offset)
18741 TCGCond cond;
18742 int bcond_compute = 0;
18743 TCGv t0 = tcg_temp_new();
18744 TCGv t1 = tcg_temp_new();
18746 gen_load_gpr(t0, rt);
18747 tcg_gen_movi_tl(t1, imm);
18748 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18750 /* Load needed operands and calculate btarget */
18751 switch (opc) {
18752 case NM_BEQIC:
18753 if (rt == 0 && imm == 0) {
18754 /* Unconditional branch */
18755 } else if (rt == 0 && imm != 0) {
18756 /* Treat as NOP */
18757 goto out;
18758 } else {
18759 bcond_compute = 1;
18760 cond = TCG_COND_EQ;
18762 break;
18763 case NM_BBEQZC:
18764 case NM_BBNEZC:
18765 check_nms(ctx);
18766 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
18767 generate_exception_end(ctx, EXCP_RI);
18768 goto out;
18769 } else if (rt == 0 && opc == NM_BBEQZC) {
18770 /* Unconditional branch */
18771 } else if (rt == 0 && opc == NM_BBNEZC) {
18772 /* Treat as NOP */
18773 goto out;
18774 } else {
18775 tcg_gen_shri_tl(t0, t0, imm);
18776 tcg_gen_andi_tl(t0, t0, 1);
18777 tcg_gen_movi_tl(t1, 0);
18778 bcond_compute = 1;
18779 if (opc == NM_BBEQZC) {
18780 cond = TCG_COND_EQ;
18781 } else {
18782 cond = TCG_COND_NE;
18785 break;
18786 case NM_BNEIC:
18787 if (rt == 0 && imm == 0) {
18788 /* Treat as NOP */
18789 goto out;
18790 } else if (rt == 0 && imm != 0) {
18791 /* Unconditional branch */
18792 } else {
18793 bcond_compute = 1;
18794 cond = TCG_COND_NE;
18796 break;
18797 case NM_BGEIC:
18798 if (rt == 0 && imm == 0) {
18799 /* Unconditional branch */
18800 } else {
18801 bcond_compute = 1;
18802 cond = TCG_COND_GE;
18804 break;
18805 case NM_BLTIC:
18806 bcond_compute = 1;
18807 cond = TCG_COND_LT;
18808 break;
18809 case NM_BGEIUC:
18810 if (rt == 0 && imm == 0) {
18811 /* Unconditional branch */
18812 } else {
18813 bcond_compute = 1;
18814 cond = TCG_COND_GEU;
18816 break;
18817 case NM_BLTIUC:
18818 bcond_compute = 1;
18819 cond = TCG_COND_LTU;
18820 break;
18821 default:
18822 MIPS_INVAL("Immediate Value Compact branch");
18823 generate_exception_end(ctx, EXCP_RI);
18824 goto out;
18827 if (bcond_compute == 0) {
18828 /* Uncoditional compact branch */
18829 gen_goto_tb(ctx, 0, ctx->btarget);
18830 } else {
18831 /* Conditional compact branch */
18832 TCGLabel *fs = gen_new_label();
18834 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
18836 gen_goto_tb(ctx, 1, ctx->btarget);
18837 gen_set_label(fs);
18839 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
18842 out:
18843 tcg_temp_free(t0);
18844 tcg_temp_free(t1);
18847 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
18848 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
18849 int rt)
18851 TCGv t0 = tcg_temp_new();
18852 TCGv t1 = tcg_temp_new();
18854 /* load rs */
18855 gen_load_gpr(t0, rs);
18857 /* link */
18858 if (rt != 0) {
18859 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
18862 /* calculate btarget */
18863 tcg_gen_shli_tl(t0, t0, 1);
18864 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
18865 gen_op_addr_add(ctx, btarget, t1, t0);
18867 /* unconditional branch to register */
18868 tcg_gen_mov_tl(cpu_PC, btarget);
18869 tcg_gen_lookup_and_goto_ptr();
18871 tcg_temp_free(t0);
18872 tcg_temp_free(t1);
18875 /* nanoMIPS Branches */
18876 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
18877 int rs, int rt, int32_t offset)
18879 int bcond_compute = 0;
18880 TCGv t0 = tcg_temp_new();
18881 TCGv t1 = tcg_temp_new();
18883 /* Load needed operands and calculate btarget */
18884 switch (opc) {
18885 /* compact branch */
18886 case OPC_BGEC:
18887 case OPC_BLTC:
18888 gen_load_gpr(t0, rs);
18889 gen_load_gpr(t1, rt);
18890 bcond_compute = 1;
18891 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18892 break;
18893 case OPC_BGEUC:
18894 case OPC_BLTUC:
18895 if (rs == 0 || rs == rt) {
18896 /* OPC_BLEZALC, OPC_BGEZALC */
18897 /* OPC_BGTZALC, OPC_BLTZALC */
18898 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
18900 gen_load_gpr(t0, rs);
18901 gen_load_gpr(t1, rt);
18902 bcond_compute = 1;
18903 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18904 break;
18905 case OPC_BC:
18906 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18907 break;
18908 case OPC_BEQZC:
18909 if (rs != 0) {
18910 /* OPC_BEQZC, OPC_BNEZC */
18911 gen_load_gpr(t0, rs);
18912 bcond_compute = 1;
18913 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18914 } else {
18915 /* OPC_JIC, OPC_JIALC */
18916 TCGv tbase = tcg_temp_new();
18917 TCGv toffset = tcg_temp_new();
18919 gen_load_gpr(tbase, rt);
18920 tcg_gen_movi_tl(toffset, offset);
18921 gen_op_addr_add(ctx, btarget, tbase, toffset);
18922 tcg_temp_free(tbase);
18923 tcg_temp_free(toffset);
18925 break;
18926 default:
18927 MIPS_INVAL("Compact branch/jump");
18928 generate_exception_end(ctx, EXCP_RI);
18929 goto out;
18932 if (bcond_compute == 0) {
18933 /* Uncoditional compact branch */
18934 switch (opc) {
18935 case OPC_BC:
18936 gen_goto_tb(ctx, 0, ctx->btarget);
18937 break;
18938 default:
18939 MIPS_INVAL("Compact branch/jump");
18940 generate_exception_end(ctx, EXCP_RI);
18941 goto out;
18943 } else {
18944 /* Conditional compact branch */
18945 TCGLabel *fs = gen_new_label();
18947 switch (opc) {
18948 case OPC_BGEUC:
18949 if (rs == 0 && rt != 0) {
18950 /* OPC_BLEZALC */
18951 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18952 } else if (rs != 0 && rt != 0 && rs == rt) {
18953 /* OPC_BGEZALC */
18954 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18955 } else {
18956 /* OPC_BGEUC */
18957 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
18959 break;
18960 case OPC_BLTUC:
18961 if (rs == 0 && rt != 0) {
18962 /* OPC_BGTZALC */
18963 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18964 } else if (rs != 0 && rt != 0 && rs == rt) {
18965 /* OPC_BLTZALC */
18966 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
18967 } else {
18968 /* OPC_BLTUC */
18969 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
18971 break;
18972 case OPC_BGEC:
18973 if (rs == 0 && rt != 0) {
18974 /* OPC_BLEZC */
18975 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18976 } else if (rs != 0 && rt != 0 && rs == rt) {
18977 /* OPC_BGEZC */
18978 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18979 } else {
18980 /* OPC_BGEC */
18981 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
18983 break;
18984 case OPC_BLTC:
18985 if (rs == 0 && rt != 0) {
18986 /* OPC_BGTZC */
18987 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18988 } else if (rs != 0 && rt != 0 && rs == rt) {
18989 /* OPC_BLTZC */
18990 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
18991 } else {
18992 /* OPC_BLTC */
18993 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
18995 break;
18996 case OPC_BEQZC:
18997 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
18998 break;
18999 default:
19000 MIPS_INVAL("Compact conditional branch/jump");
19001 generate_exception_end(ctx, EXCP_RI);
19002 goto out;
19005 /* Generating branch here as compact branches don't have delay slot */
19006 gen_goto_tb(ctx, 1, ctx->btarget);
19007 gen_set_label(fs);
19009 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19012 out:
19013 tcg_temp_free(t0);
19014 tcg_temp_free(t1);
19018 /* nanoMIPS CP1 Branches */
19019 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19020 int32_t ft, int32_t offset)
19022 target_ulong btarget;
19023 TCGv_i64 t0 = tcg_temp_new_i64();
19025 gen_load_fpr64(ctx, t0, ft);
19026 tcg_gen_andi_i64(t0, t0, 1);
19028 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19030 switch (op) {
19031 case NM_BC1EQZC:
19032 tcg_gen_xori_i64(t0, t0, 1);
19033 ctx->hflags |= MIPS_HFLAG_BC;
19034 break;
19035 case NM_BC1NEZC:
19036 /* t0 already set */
19037 ctx->hflags |= MIPS_HFLAG_BC;
19038 break;
19039 default:
19040 MIPS_INVAL("cp1 cond branch");
19041 generate_exception_end(ctx, EXCP_RI);
19042 goto out;
19045 tcg_gen_trunc_i64_tl(bcond, t0);
19047 ctx->btarget = btarget;
19049 out:
19050 tcg_temp_free_i64(t0);
19054 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19056 TCGv t0, t1;
19057 t0 = tcg_temp_new();
19058 t1 = tcg_temp_new();
19060 gen_load_gpr(t0, rs);
19061 gen_load_gpr(t1, rt);
19063 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19064 /* PP.LSXS instructions require shifting */
19065 switch (extract32(ctx->opcode, 7, 4)) {
19066 case NM_SHXS:
19067 check_nms(ctx);
19068 case NM_LHXS:
19069 case NM_LHUXS:
19070 tcg_gen_shli_tl(t0, t0, 1);
19071 break;
19072 case NM_SWXS:
19073 check_nms(ctx);
19074 case NM_LWXS:
19075 case NM_LWC1XS:
19076 case NM_SWC1XS:
19077 tcg_gen_shli_tl(t0, t0, 2);
19078 break;
19079 case NM_LDC1XS:
19080 case NM_SDC1XS:
19081 tcg_gen_shli_tl(t0, t0, 3);
19082 break;
19085 gen_op_addr_add(ctx, t0, t0, t1);
19087 switch (extract32(ctx->opcode, 7, 4)) {
19088 case NM_LBX:
19089 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19090 MO_SB);
19091 gen_store_gpr(t0, rd);
19092 break;
19093 case NM_LHX:
19094 /*case NM_LHXS:*/
19095 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19096 MO_TESW);
19097 gen_store_gpr(t0, rd);
19098 break;
19099 case NM_LWX:
19100 /*case NM_LWXS:*/
19101 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19102 MO_TESL);
19103 gen_store_gpr(t0, rd);
19104 break;
19105 case NM_LBUX:
19106 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19107 MO_UB);
19108 gen_store_gpr(t0, rd);
19109 break;
19110 case NM_LHUX:
19111 /*case NM_LHUXS:*/
19112 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19113 MO_TEUW);
19114 gen_store_gpr(t0, rd);
19115 break;
19116 case NM_SBX:
19117 check_nms(ctx);
19118 gen_load_gpr(t1, rd);
19119 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19120 MO_8);
19121 break;
19122 case NM_SHX:
19123 /*case NM_SHXS:*/
19124 check_nms(ctx);
19125 gen_load_gpr(t1, rd);
19126 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19127 MO_TEUW);
19128 break;
19129 case NM_SWX:
19130 /*case NM_SWXS:*/
19131 check_nms(ctx);
19132 gen_load_gpr(t1, rd);
19133 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19134 MO_TEUL);
19135 break;
19136 case NM_LWC1X:
19137 /*case NM_LWC1XS:*/
19138 case NM_LDC1X:
19139 /*case NM_LDC1XS:*/
19140 case NM_SWC1X:
19141 /*case NM_SWC1XS:*/
19142 case NM_SDC1X:
19143 /*case NM_SDC1XS:*/
19144 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19145 check_cp1_enabled(ctx);
19146 switch (extract32(ctx->opcode, 7, 4)) {
19147 case NM_LWC1X:
19148 /*case NM_LWC1XS:*/
19149 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19150 break;
19151 case NM_LDC1X:
19152 /*case NM_LDC1XS:*/
19153 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19154 break;
19155 case NM_SWC1X:
19156 /*case NM_SWC1XS:*/
19157 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19158 break;
19159 case NM_SDC1X:
19160 /*case NM_SDC1XS:*/
19161 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19162 break;
19164 } else {
19165 generate_exception_err(ctx, EXCP_CpU, 1);
19167 break;
19168 default:
19169 generate_exception_end(ctx, EXCP_RI);
19170 break;
19173 tcg_temp_free(t0);
19174 tcg_temp_free(t1);
19177 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19179 int rt, rs, rd;
19181 rt = extract32(ctx->opcode, 21, 5);
19182 rs = extract32(ctx->opcode, 16, 5);
19183 rd = extract32(ctx->opcode, 11, 5);
19185 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19186 generate_exception_end(ctx, EXCP_RI);
19187 return;
19189 check_cp1_enabled(ctx);
19190 switch (extract32(ctx->opcode, 0, 3)) {
19191 case NM_POOL32F_0:
19192 switch (extract32(ctx->opcode, 3, 7)) {
19193 case NM_RINT_S:
19194 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19195 break;
19196 case NM_RINT_D:
19197 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19198 break;
19199 case NM_CLASS_S:
19200 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19201 break;
19202 case NM_CLASS_D:
19203 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19204 break;
19205 case NM_ADD_S:
19206 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19207 break;
19208 case NM_ADD_D:
19209 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19210 break;
19211 case NM_SUB_S:
19212 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19213 break;
19214 case NM_SUB_D:
19215 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19216 break;
19217 case NM_MUL_S:
19218 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19219 break;
19220 case NM_MUL_D:
19221 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19222 break;
19223 case NM_DIV_S:
19224 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19225 break;
19226 case NM_DIV_D:
19227 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19228 break;
19229 case NM_SELEQZ_S:
19230 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19231 break;
19232 case NM_SELEQZ_D:
19233 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19234 break;
19235 case NM_SELNEZ_S:
19236 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19237 break;
19238 case NM_SELNEZ_D:
19239 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19240 break;
19241 case NM_SEL_S:
19242 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19243 break;
19244 case NM_SEL_D:
19245 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19246 break;
19247 case NM_MADDF_S:
19248 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19249 break;
19250 case NM_MADDF_D:
19251 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19252 break;
19253 case NM_MSUBF_S:
19254 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19255 break;
19256 case NM_MSUBF_D:
19257 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19258 break;
19259 default:
19260 generate_exception_end(ctx, EXCP_RI);
19261 break;
19263 break;
19264 case NM_POOL32F_3:
19265 switch (extract32(ctx->opcode, 3, 3)) {
19266 case NM_MIN_FMT:
19267 switch (extract32(ctx->opcode, 9, 1)) {
19268 case FMT_SDPS_S:
19269 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19270 break;
19271 case FMT_SDPS_D:
19272 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19273 break;
19275 break;
19276 case NM_MAX_FMT:
19277 switch (extract32(ctx->opcode, 9, 1)) {
19278 case FMT_SDPS_S:
19279 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19280 break;
19281 case FMT_SDPS_D:
19282 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19283 break;
19285 break;
19286 case NM_MINA_FMT:
19287 switch (extract32(ctx->opcode, 9, 1)) {
19288 case FMT_SDPS_S:
19289 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19290 break;
19291 case FMT_SDPS_D:
19292 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19293 break;
19295 break;
19296 case NM_MAXA_FMT:
19297 switch (extract32(ctx->opcode, 9, 1)) {
19298 case FMT_SDPS_S:
19299 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19300 break;
19301 case FMT_SDPS_D:
19302 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19303 break;
19305 break;
19306 case NM_POOL32FXF:
19307 switch (extract32(ctx->opcode, 6, 8)) {
19308 case NM_CFC1:
19309 gen_cp1(ctx, OPC_CFC1, rt, rs);
19310 break;
19311 case NM_CTC1:
19312 gen_cp1(ctx, OPC_CTC1, rt, rs);
19313 break;
19314 case NM_MFC1:
19315 gen_cp1(ctx, OPC_MFC1, rt, rs);
19316 break;
19317 case NM_MTC1:
19318 gen_cp1(ctx, OPC_MTC1, rt, rs);
19319 break;
19320 case NM_MFHC1:
19321 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19322 break;
19323 case NM_MTHC1:
19324 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19325 break;
19326 case NM_CVT_S_PL:
19327 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19328 break;
19329 case NM_CVT_S_PU:
19330 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19331 break;
19332 default:
19333 switch (extract32(ctx->opcode, 6, 9)) {
19334 case NM_CVT_L_S:
19335 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19336 break;
19337 case NM_CVT_L_D:
19338 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19339 break;
19340 case NM_CVT_W_S:
19341 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19342 break;
19343 case NM_CVT_W_D:
19344 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19345 break;
19346 case NM_RSQRT_S:
19347 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19348 break;
19349 case NM_RSQRT_D:
19350 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19351 break;
19352 case NM_SQRT_S:
19353 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19354 break;
19355 case NM_SQRT_D:
19356 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19357 break;
19358 case NM_RECIP_S:
19359 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19360 break;
19361 case NM_RECIP_D:
19362 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19363 break;
19364 case NM_FLOOR_L_S:
19365 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19366 break;
19367 case NM_FLOOR_L_D:
19368 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19369 break;
19370 case NM_FLOOR_W_S:
19371 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19372 break;
19373 case NM_FLOOR_W_D:
19374 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19375 break;
19376 case NM_CEIL_L_S:
19377 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19378 break;
19379 case NM_CEIL_L_D:
19380 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19381 break;
19382 case NM_CEIL_W_S:
19383 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19384 break;
19385 case NM_CEIL_W_D:
19386 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19387 break;
19388 case NM_TRUNC_L_S:
19389 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19390 break;
19391 case NM_TRUNC_L_D:
19392 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19393 break;
19394 case NM_TRUNC_W_S:
19395 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19396 break;
19397 case NM_TRUNC_W_D:
19398 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19399 break;
19400 case NM_ROUND_L_S:
19401 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19402 break;
19403 case NM_ROUND_L_D:
19404 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19405 break;
19406 case NM_ROUND_W_S:
19407 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19408 break;
19409 case NM_ROUND_W_D:
19410 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19411 break;
19412 case NM_MOV_S:
19413 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19414 break;
19415 case NM_MOV_D:
19416 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19417 break;
19418 case NM_ABS_S:
19419 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19420 break;
19421 case NM_ABS_D:
19422 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19423 break;
19424 case NM_NEG_S:
19425 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19426 break;
19427 case NM_NEG_D:
19428 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19429 break;
19430 case NM_CVT_D_S:
19431 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19432 break;
19433 case NM_CVT_D_W:
19434 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19435 break;
19436 case NM_CVT_D_L:
19437 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19438 break;
19439 case NM_CVT_S_D:
19440 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19441 break;
19442 case NM_CVT_S_W:
19443 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19444 break;
19445 case NM_CVT_S_L:
19446 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19447 break;
19448 default:
19449 generate_exception_end(ctx, EXCP_RI);
19450 break;
19452 break;
19454 break;
19456 break;
19457 case NM_POOL32F_5:
19458 switch (extract32(ctx->opcode, 3, 3)) {
19459 case NM_CMP_CONDN_S:
19460 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19461 break;
19462 case NM_CMP_CONDN_D:
19463 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19464 break;
19465 default:
19466 generate_exception_end(ctx, EXCP_RI);
19467 break;
19469 break;
19470 default:
19471 generate_exception_end(ctx, EXCP_RI);
19472 break;
19476 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19477 int rd, int rs, int rt)
19479 int ret = rd;
19480 TCGv t0 = tcg_temp_new();
19481 TCGv v1_t = tcg_temp_new();
19482 TCGv v2_t = tcg_temp_new();
19484 gen_load_gpr(v1_t, rs);
19485 gen_load_gpr(v2_t, rt);
19487 switch (opc) {
19488 case NM_CMP_EQ_PH:
19489 check_dsp(ctx);
19490 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19491 break;
19492 case NM_CMP_LT_PH:
19493 check_dsp(ctx);
19494 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19495 break;
19496 case NM_CMP_LE_PH:
19497 check_dsp(ctx);
19498 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19499 break;
19500 case NM_CMPU_EQ_QB:
19501 check_dsp(ctx);
19502 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19503 break;
19504 case NM_CMPU_LT_QB:
19505 check_dsp(ctx);
19506 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19507 break;
19508 case NM_CMPU_LE_QB:
19509 check_dsp(ctx);
19510 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19511 break;
19512 case NM_CMPGU_EQ_QB:
19513 check_dsp(ctx);
19514 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19515 gen_store_gpr(v1_t, ret);
19516 break;
19517 case NM_CMPGU_LT_QB:
19518 check_dsp(ctx);
19519 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19520 gen_store_gpr(v1_t, ret);
19521 break;
19522 case NM_CMPGU_LE_QB:
19523 check_dsp(ctx);
19524 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19525 gen_store_gpr(v1_t, ret);
19526 break;
19527 case NM_CMPGDU_EQ_QB:
19528 check_dsp_r2(ctx);
19529 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19530 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19531 gen_store_gpr(v1_t, ret);
19532 break;
19533 case NM_CMPGDU_LT_QB:
19534 check_dsp_r2(ctx);
19535 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19536 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19537 gen_store_gpr(v1_t, ret);
19538 break;
19539 case NM_CMPGDU_LE_QB:
19540 check_dsp_r2(ctx);
19541 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19542 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19543 gen_store_gpr(v1_t, ret);
19544 break;
19545 case NM_PACKRL_PH:
19546 check_dsp(ctx);
19547 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19548 gen_store_gpr(v1_t, ret);
19549 break;
19550 case NM_PICK_QB:
19551 check_dsp(ctx);
19552 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19553 gen_store_gpr(v1_t, ret);
19554 break;
19555 case NM_PICK_PH:
19556 check_dsp(ctx);
19557 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19558 gen_store_gpr(v1_t, ret);
19559 break;
19560 case NM_ADDQ_S_W:
19561 check_dsp(ctx);
19562 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19563 gen_store_gpr(v1_t, ret);
19564 break;
19565 case NM_SUBQ_S_W:
19566 check_dsp(ctx);
19567 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19568 gen_store_gpr(v1_t, ret);
19569 break;
19570 case NM_ADDSC:
19571 check_dsp(ctx);
19572 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19573 gen_store_gpr(v1_t, ret);
19574 break;
19575 case NM_ADDWC:
19576 check_dsp(ctx);
19577 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19578 gen_store_gpr(v1_t, ret);
19579 break;
19580 case NM_ADDQ_S_PH:
19581 check_dsp(ctx);
19582 switch (extract32(ctx->opcode, 10, 1)) {
19583 case 0:
19584 /* ADDQ_PH */
19585 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19586 gen_store_gpr(v1_t, ret);
19587 break;
19588 case 1:
19589 /* ADDQ_S_PH */
19590 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19591 gen_store_gpr(v1_t, ret);
19592 break;
19594 break;
19595 case NM_ADDQH_R_PH:
19596 check_dsp_r2(ctx);
19597 switch (extract32(ctx->opcode, 10, 1)) {
19598 case 0:
19599 /* ADDQH_PH */
19600 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19601 gen_store_gpr(v1_t, ret);
19602 break;
19603 case 1:
19604 /* ADDQH_R_PH */
19605 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19606 gen_store_gpr(v1_t, ret);
19607 break;
19609 break;
19610 case NM_ADDQH_R_W:
19611 check_dsp_r2(ctx);
19612 switch (extract32(ctx->opcode, 10, 1)) {
19613 case 0:
19614 /* ADDQH_W */
19615 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19616 gen_store_gpr(v1_t, ret);
19617 break;
19618 case 1:
19619 /* ADDQH_R_W */
19620 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19621 gen_store_gpr(v1_t, ret);
19622 break;
19624 break;
19625 case NM_ADDU_S_QB:
19626 check_dsp(ctx);
19627 switch (extract32(ctx->opcode, 10, 1)) {
19628 case 0:
19629 /* ADDU_QB */
19630 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19631 gen_store_gpr(v1_t, ret);
19632 break;
19633 case 1:
19634 /* ADDU_S_QB */
19635 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19636 gen_store_gpr(v1_t, ret);
19637 break;
19639 break;
19640 case NM_ADDU_S_PH:
19641 check_dsp_r2(ctx);
19642 switch (extract32(ctx->opcode, 10, 1)) {
19643 case 0:
19644 /* ADDU_PH */
19645 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19646 gen_store_gpr(v1_t, ret);
19647 break;
19648 case 1:
19649 /* ADDU_S_PH */
19650 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19651 gen_store_gpr(v1_t, ret);
19652 break;
19654 break;
19655 case NM_ADDUH_R_QB:
19656 check_dsp_r2(ctx);
19657 switch (extract32(ctx->opcode, 10, 1)) {
19658 case 0:
19659 /* ADDUH_QB */
19660 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19661 gen_store_gpr(v1_t, ret);
19662 break;
19663 case 1:
19664 /* ADDUH_R_QB */
19665 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19666 gen_store_gpr(v1_t, ret);
19667 break;
19669 break;
19670 case NM_SHRAV_R_PH:
19671 check_dsp(ctx);
19672 switch (extract32(ctx->opcode, 10, 1)) {
19673 case 0:
19674 /* SHRAV_PH */
19675 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19676 gen_store_gpr(v1_t, ret);
19677 break;
19678 case 1:
19679 /* SHRAV_R_PH */
19680 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19681 gen_store_gpr(v1_t, ret);
19682 break;
19684 break;
19685 case NM_SHRAV_R_QB:
19686 check_dsp_r2(ctx);
19687 switch (extract32(ctx->opcode, 10, 1)) {
19688 case 0:
19689 /* SHRAV_QB */
19690 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19691 gen_store_gpr(v1_t, ret);
19692 break;
19693 case 1:
19694 /* SHRAV_R_QB */
19695 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19696 gen_store_gpr(v1_t, ret);
19697 break;
19699 break;
19700 case NM_SUBQ_S_PH:
19701 check_dsp(ctx);
19702 switch (extract32(ctx->opcode, 10, 1)) {
19703 case 0:
19704 /* SUBQ_PH */
19705 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19706 gen_store_gpr(v1_t, ret);
19707 break;
19708 case 1:
19709 /* SUBQ_S_PH */
19710 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19711 gen_store_gpr(v1_t, ret);
19712 break;
19714 break;
19715 case NM_SUBQH_R_PH:
19716 check_dsp_r2(ctx);
19717 switch (extract32(ctx->opcode, 10, 1)) {
19718 case 0:
19719 /* SUBQH_PH */
19720 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19721 gen_store_gpr(v1_t, ret);
19722 break;
19723 case 1:
19724 /* SUBQH_R_PH */
19725 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19726 gen_store_gpr(v1_t, ret);
19727 break;
19729 break;
19730 case NM_SUBQH_R_W:
19731 check_dsp_r2(ctx);
19732 switch (extract32(ctx->opcode, 10, 1)) {
19733 case 0:
19734 /* SUBQH_W */
19735 gen_helper_subqh_w(v1_t, v1_t, v2_t);
19736 gen_store_gpr(v1_t, ret);
19737 break;
19738 case 1:
19739 /* SUBQH_R_W */
19740 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
19741 gen_store_gpr(v1_t, ret);
19742 break;
19744 break;
19745 case NM_SUBU_S_QB:
19746 check_dsp(ctx);
19747 switch (extract32(ctx->opcode, 10, 1)) {
19748 case 0:
19749 /* SUBU_QB */
19750 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
19751 gen_store_gpr(v1_t, ret);
19752 break;
19753 case 1:
19754 /* SUBU_S_QB */
19755 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19756 gen_store_gpr(v1_t, ret);
19757 break;
19759 break;
19760 case NM_SUBU_S_PH:
19761 check_dsp_r2(ctx);
19762 switch (extract32(ctx->opcode, 10, 1)) {
19763 case 0:
19764 /* SUBU_PH */
19765 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
19766 gen_store_gpr(v1_t, ret);
19767 break;
19768 case 1:
19769 /* SUBU_S_PH */
19770 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19771 gen_store_gpr(v1_t, ret);
19772 break;
19774 break;
19775 case NM_SUBUH_R_QB:
19776 check_dsp_r2(ctx);
19777 switch (extract32(ctx->opcode, 10, 1)) {
19778 case 0:
19779 /* SUBUH_QB */
19780 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
19781 gen_store_gpr(v1_t, ret);
19782 break;
19783 case 1:
19784 /* SUBUH_R_QB */
19785 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
19786 gen_store_gpr(v1_t, ret);
19787 break;
19789 break;
19790 case NM_SHLLV_S_PH:
19791 check_dsp(ctx);
19792 switch (extract32(ctx->opcode, 10, 1)) {
19793 case 0:
19794 /* SHLLV_PH */
19795 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
19796 gen_store_gpr(v1_t, ret);
19797 break;
19798 case 1:
19799 /* SHLLV_S_PH */
19800 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
19801 gen_store_gpr(v1_t, ret);
19802 break;
19804 break;
19805 case NM_PRECR_SRA_R_PH_W:
19806 check_dsp_r2(ctx);
19807 switch (extract32(ctx->opcode, 10, 1)) {
19808 case 0:
19809 /* PRECR_SRA_PH_W */
19811 TCGv_i32 sa_t = tcg_const_i32(rd);
19812 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
19813 cpu_gpr[rt]);
19814 gen_store_gpr(v1_t, rt);
19815 tcg_temp_free_i32(sa_t);
19817 break;
19818 case 1:
19819 /* PRECR_SRA_R_PH_W */
19821 TCGv_i32 sa_t = tcg_const_i32(rd);
19822 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
19823 cpu_gpr[rt]);
19824 gen_store_gpr(v1_t, rt);
19825 tcg_temp_free_i32(sa_t);
19827 break;
19829 break;
19830 case NM_MULEU_S_PH_QBL:
19831 check_dsp(ctx);
19832 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
19833 gen_store_gpr(v1_t, ret);
19834 break;
19835 case NM_MULEU_S_PH_QBR:
19836 check_dsp(ctx);
19837 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
19838 gen_store_gpr(v1_t, ret);
19839 break;
19840 case NM_MULQ_RS_PH:
19841 check_dsp(ctx);
19842 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
19843 gen_store_gpr(v1_t, ret);
19844 break;
19845 case NM_MULQ_S_PH:
19846 check_dsp_r2(ctx);
19847 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19848 gen_store_gpr(v1_t, ret);
19849 break;
19850 case NM_MULQ_RS_W:
19851 check_dsp_r2(ctx);
19852 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
19853 gen_store_gpr(v1_t, ret);
19854 break;
19855 case NM_MULQ_S_W:
19856 check_dsp_r2(ctx);
19857 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
19858 gen_store_gpr(v1_t, ret);
19859 break;
19860 case NM_APPEND:
19861 check_dsp_r2(ctx);
19862 gen_load_gpr(t0, rs);
19863 if (rd != 0) {
19864 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
19866 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19867 break;
19868 case NM_MODSUB:
19869 check_dsp(ctx);
19870 gen_helper_modsub(v1_t, v1_t, v2_t);
19871 gen_store_gpr(v1_t, ret);
19872 break;
19873 case NM_SHRAV_R_W:
19874 check_dsp(ctx);
19875 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
19876 gen_store_gpr(v1_t, ret);
19877 break;
19878 case NM_SHRLV_PH:
19879 check_dsp_r2(ctx);
19880 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
19881 gen_store_gpr(v1_t, ret);
19882 break;
19883 case NM_SHRLV_QB:
19884 check_dsp(ctx);
19885 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
19886 gen_store_gpr(v1_t, ret);
19887 break;
19888 case NM_SHLLV_QB:
19889 check_dsp(ctx);
19890 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
19891 gen_store_gpr(v1_t, ret);
19892 break;
19893 case NM_SHLLV_S_W:
19894 check_dsp(ctx);
19895 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
19896 gen_store_gpr(v1_t, ret);
19897 break;
19898 case NM_SHILO:
19899 check_dsp(ctx);
19901 TCGv tv0 = tcg_temp_new();
19902 TCGv tv1 = tcg_temp_new();
19903 int16_t imm = extract32(ctx->opcode, 16, 7);
19905 tcg_gen_movi_tl(tv0, rd >> 3);
19906 tcg_gen_movi_tl(tv1, imm);
19907 gen_helper_shilo(tv0, tv1, cpu_env);
19909 break;
19910 case NM_MULEQ_S_W_PHL:
19911 check_dsp(ctx);
19912 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
19913 gen_store_gpr(v1_t, ret);
19914 break;
19915 case NM_MULEQ_S_W_PHR:
19916 check_dsp(ctx);
19917 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
19918 gen_store_gpr(v1_t, ret);
19919 break;
19920 case NM_MUL_S_PH:
19921 check_dsp_r2(ctx);
19922 switch (extract32(ctx->opcode, 10, 1)) {
19923 case 0:
19924 /* MUL_PH */
19925 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
19926 gen_store_gpr(v1_t, ret);
19927 break;
19928 case 1:
19929 /* MUL_S_PH */
19930 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
19931 gen_store_gpr(v1_t, ret);
19932 break;
19934 break;
19935 case NM_PRECR_QB_PH:
19936 check_dsp_r2(ctx);
19937 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
19938 gen_store_gpr(v1_t, ret);
19939 break;
19940 case NM_PRECRQ_QB_PH:
19941 check_dsp(ctx);
19942 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
19943 gen_store_gpr(v1_t, ret);
19944 break;
19945 case NM_PRECRQ_PH_W:
19946 check_dsp(ctx);
19947 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
19948 gen_store_gpr(v1_t, ret);
19949 break;
19950 case NM_PRECRQ_RS_PH_W:
19951 check_dsp(ctx);
19952 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
19953 gen_store_gpr(v1_t, ret);
19954 break;
19955 case NM_PRECRQU_S_QB_PH:
19956 check_dsp(ctx);
19957 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
19958 gen_store_gpr(v1_t, ret);
19959 break;
19960 case NM_SHRA_R_W:
19961 check_dsp(ctx);
19962 tcg_gen_movi_tl(t0, rd);
19963 gen_helper_shra_r_w(v1_t, t0, v1_t);
19964 gen_store_gpr(v1_t, rt);
19965 break;
19966 case NM_SHRA_R_PH:
19967 check_dsp(ctx);
19968 tcg_gen_movi_tl(t0, rd >> 1);
19969 switch (extract32(ctx->opcode, 10, 1)) {
19970 case 0:
19971 /* SHRA_PH */
19972 gen_helper_shra_ph(v1_t, t0, v1_t);
19973 break;
19974 gen_store_gpr(v1_t, rt);
19975 case 1:
19976 /* SHRA_R_PH */
19977 gen_helper_shra_r_ph(v1_t, t0, v1_t);
19978 gen_store_gpr(v1_t, rt);
19979 break;
19981 break;
19982 case NM_SHLL_S_PH:
19983 check_dsp(ctx);
19984 tcg_gen_movi_tl(t0, rd >> 1);
19985 switch (extract32(ctx->opcode, 10, 2)) {
19986 case 0:
19987 /* SHLL_PH */
19988 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
19989 gen_store_gpr(v1_t, rt);
19990 break;
19991 case 2:
19992 /* SHLL_S_PH */
19993 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
19994 gen_store_gpr(v1_t, rt);
19995 break;
19996 default:
19997 generate_exception_end(ctx, EXCP_RI);
19998 break;
20000 break;
20001 case NM_SHLL_S_W:
20002 check_dsp(ctx);
20003 tcg_gen_movi_tl(t0, rd);
20004 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20005 gen_store_gpr(v1_t, rt);
20006 break;
20007 case NM_REPL_PH:
20008 check_dsp(ctx);
20010 int16_t imm;
20011 imm = sextract32(ctx->opcode, 11, 11);
20012 imm = (int16_t)(imm << 6) >> 6;
20013 if (rt != 0) {
20014 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20017 break;
20018 default:
20019 generate_exception_end(ctx, EXCP_RI);
20020 break;
20024 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20026 uint16_t insn;
20027 uint32_t op;
20028 int rt, rs, rd;
20029 int offset;
20030 int imm;
20032 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20033 ctx->opcode = (ctx->opcode << 16) | insn;
20035 rt = extract32(ctx->opcode, 21, 5);
20036 rs = extract32(ctx->opcode, 16, 5);
20037 rd = extract32(ctx->opcode, 11, 5);
20039 op = extract32(ctx->opcode, 26, 6);
20040 switch (op) {
20041 case NM_P_ADDIU:
20042 if (rt == 0) {
20043 /* P.RI */
20044 switch (extract32(ctx->opcode, 19, 2)) {
20045 case NM_SIGRIE:
20046 default:
20047 generate_exception_end(ctx, EXCP_RI);
20048 break;
20049 case NM_P_SYSCALL:
20050 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20051 generate_exception_end(ctx, EXCP_SYSCALL);
20052 } else {
20053 generate_exception_end(ctx, EXCP_RI);
20055 break;
20056 case NM_BREAK:
20057 generate_exception_end(ctx, EXCP_BREAK);
20058 break;
20059 case NM_SDBBP:
20060 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20061 gen_helper_do_semihosting(cpu_env);
20062 } else {
20063 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20064 generate_exception_end(ctx, EXCP_RI);
20065 } else {
20066 generate_exception_end(ctx, EXCP_DBp);
20069 break;
20071 } else {
20072 /* NM_ADDIU */
20073 imm = extract32(ctx->opcode, 0, 16);
20074 if (rs != 0) {
20075 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20076 } else {
20077 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20079 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20081 break;
20082 case NM_ADDIUPC:
20083 if (rt != 0) {
20084 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20085 extract32(ctx->opcode, 1, 20) << 1;
20086 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20087 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20089 break;
20090 case NM_POOL32A:
20091 switch (ctx->opcode & 0x07) {
20092 case NM_POOL32A0:
20093 gen_pool32a0_nanomips_insn(env, ctx);
20094 break;
20095 case NM_POOL32A5:
20097 int32_t op1 = extract32(ctx->opcode, 3, 7);
20098 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20100 break;
20101 case NM_POOL32A7:
20102 switch (extract32(ctx->opcode, 3, 3)) {
20103 case NM_P_LSX:
20104 gen_p_lsx(ctx, rd, rs, rt);
20105 break;
20106 case NM_LSA:
20107 /* In nanoMIPS, the shift field directly encodes the shift
20108 * amount, meaning that the supported shift values are in
20109 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20110 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20111 extract32(ctx->opcode, 9, 2) - 1);
20112 break;
20113 case NM_EXTW:
20114 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20115 break;
20116 case NM_POOL32AXF:
20117 gen_pool32axf_nanomips_insn(env, ctx);
20118 break;
20119 default:
20120 generate_exception_end(ctx, EXCP_RI);
20121 break;
20123 break;
20124 default:
20125 generate_exception_end(ctx, EXCP_RI);
20126 break;
20128 break;
20129 case NM_P_GP_W:
20130 switch (ctx->opcode & 0x03) {
20131 case NM_ADDIUGP_W:
20132 if (rt != 0) {
20133 offset = extract32(ctx->opcode, 0, 21);
20134 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20136 break;
20137 case NM_LWGP:
20138 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20139 break;
20140 case NM_SWGP:
20141 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20142 break;
20143 default:
20144 generate_exception_end(ctx, EXCP_RI);
20145 break;
20147 break;
20148 case NM_P48I:
20150 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20151 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20152 switch (extract32(ctx->opcode, 16, 5)) {
20153 case NM_LI48:
20154 check_nms(ctx);
20155 if (rt != 0) {
20156 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20158 break;
20159 case NM_ADDIU48:
20160 check_nms(ctx);
20161 if (rt != 0) {
20162 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20163 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20165 break;
20166 case NM_ADDIUGP48:
20167 check_nms(ctx);
20168 if (rt != 0) {
20169 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20171 break;
20172 case NM_ADDIUPC48:
20173 check_nms(ctx);
20174 if (rt != 0) {
20175 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20176 addr_off);
20178 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20180 break;
20181 case NM_LWPC48:
20182 check_nms(ctx);
20183 if (rt != 0) {
20184 TCGv t0;
20185 t0 = tcg_temp_new();
20187 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20188 addr_off);
20190 tcg_gen_movi_tl(t0, addr);
20191 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20192 tcg_temp_free(t0);
20194 break;
20195 case NM_SWPC48:
20196 check_nms(ctx);
20198 TCGv t0, t1;
20199 t0 = tcg_temp_new();
20200 t1 = tcg_temp_new();
20202 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20203 addr_off);
20205 tcg_gen_movi_tl(t0, addr);
20206 gen_load_gpr(t1, rt);
20208 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20210 tcg_temp_free(t0);
20211 tcg_temp_free(t1);
20213 break;
20214 default:
20215 generate_exception_end(ctx, EXCP_RI);
20216 break;
20218 return 6;
20220 case NM_P_U12:
20221 switch (extract32(ctx->opcode, 12, 4)) {
20222 case NM_ORI:
20223 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20224 break;
20225 case NM_XORI:
20226 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20227 break;
20228 case NM_ANDI:
20229 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20230 break;
20231 case NM_P_SR:
20232 switch (extract32(ctx->opcode, 20, 1)) {
20233 case NM_PP_SR:
20234 switch (ctx->opcode & 3) {
20235 case NM_SAVE:
20236 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20237 extract32(ctx->opcode, 2, 1),
20238 extract32(ctx->opcode, 3, 9) << 3);
20239 break;
20240 case NM_RESTORE:
20241 case NM_RESTORE_JRC:
20242 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20243 extract32(ctx->opcode, 2, 1),
20244 extract32(ctx->opcode, 3, 9) << 3);
20245 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20246 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20248 break;
20249 default:
20250 generate_exception_end(ctx, EXCP_RI);
20251 break;
20253 break;
20254 case NM_P_SR_F:
20255 generate_exception_end(ctx, EXCP_RI);
20256 break;
20258 break;
20259 case NM_SLTI:
20260 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20261 break;
20262 case NM_SLTIU:
20263 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20264 break;
20265 case NM_SEQI:
20267 TCGv t0 = tcg_temp_new();
20269 imm = extract32(ctx->opcode, 0, 12);
20270 gen_load_gpr(t0, rs);
20271 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20272 gen_store_gpr(t0, rt);
20274 tcg_temp_free(t0);
20276 break;
20277 case NM_ADDIUNEG:
20278 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20279 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20280 break;
20281 case NM_P_SHIFT:
20283 int shift = extract32(ctx->opcode, 0, 5);
20284 switch (extract32(ctx->opcode, 5, 4)) {
20285 case NM_P_SLL:
20286 if (rt == 0 && shift == 0) {
20287 /* NOP */
20288 } else if (rt == 0 && shift == 3) {
20289 /* EHB - treat as NOP */
20290 } else if (rt == 0 && shift == 5) {
20291 /* PAUSE - treat as NOP */
20292 } else if (rt == 0 && shift == 6) {
20293 /* SYNC */
20294 gen_sync(extract32(ctx->opcode, 16, 5));
20295 } else {
20296 /* SLL */
20297 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20298 extract32(ctx->opcode, 0, 5));
20300 break;
20301 case NM_SRL:
20302 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20303 extract32(ctx->opcode, 0, 5));
20304 break;
20305 case NM_SRA:
20306 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20307 extract32(ctx->opcode, 0, 5));
20308 break;
20309 case NM_ROTR:
20310 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20311 extract32(ctx->opcode, 0, 5));
20312 break;
20315 break;
20316 case NM_P_ROTX:
20317 check_nms(ctx);
20318 if (rt != 0) {
20319 TCGv t0 = tcg_temp_new();
20320 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20321 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20322 << 1);
20323 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20325 gen_load_gpr(t0, rs);
20326 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20327 tcg_temp_free(t0);
20329 tcg_temp_free_i32(shift);
20330 tcg_temp_free_i32(shiftx);
20331 tcg_temp_free_i32(stripe);
20333 break;
20334 case NM_P_INS:
20335 switch (((ctx->opcode >> 10) & 2) |
20336 (extract32(ctx->opcode, 5, 1))) {
20337 case NM_INS:
20338 check_nms(ctx);
20339 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20340 extract32(ctx->opcode, 6, 5));
20341 break;
20342 default:
20343 generate_exception_end(ctx, EXCP_RI);
20344 break;
20346 break;
20347 case NM_P_EXT:
20348 switch (((ctx->opcode >> 10) & 2) |
20349 (extract32(ctx->opcode, 5, 1))) {
20350 case NM_EXT:
20351 check_nms(ctx);
20352 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20353 extract32(ctx->opcode, 6, 5));
20354 break;
20355 default:
20356 generate_exception_end(ctx, EXCP_RI);
20357 break;
20359 break;
20360 default:
20361 generate_exception_end(ctx, EXCP_RI);
20362 break;
20364 break;
20365 case NM_POOL32F:
20366 gen_pool32f_nanomips_insn(ctx);
20367 break;
20368 case NM_POOL32S:
20369 break;
20370 case NM_P_LUI:
20371 switch (extract32(ctx->opcode, 1, 1)) {
20372 case NM_LUI:
20373 if (rt != 0) {
20374 tcg_gen_movi_tl(cpu_gpr[rt],
20375 sextract32(ctx->opcode, 0, 1) << 31 |
20376 extract32(ctx->opcode, 2, 10) << 21 |
20377 extract32(ctx->opcode, 12, 9) << 12);
20379 break;
20380 case NM_ALUIPC:
20381 if (rt != 0) {
20382 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20383 extract32(ctx->opcode, 2, 10) << 21 |
20384 extract32(ctx->opcode, 12, 9) << 12;
20385 target_long addr;
20386 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20387 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20389 break;
20391 break;
20392 case NM_P_GP_BH:
20394 uint32_t u = extract32(ctx->opcode, 0, 18);
20396 switch (extract32(ctx->opcode, 18, 3)) {
20397 case NM_LBGP:
20398 gen_ld(ctx, OPC_LB, rt, 28, u);
20399 break;
20400 case NM_SBGP:
20401 gen_st(ctx, OPC_SB, rt, 28, u);
20402 break;
20403 case NM_LBUGP:
20404 gen_ld(ctx, OPC_LBU, rt, 28, u);
20405 break;
20406 case NM_ADDIUGP_B:
20407 if (rt != 0) {
20408 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20410 break;
20411 case NM_P_GP_LH:
20412 u &= ~1;
20413 switch (ctx->opcode & 1) {
20414 case NM_LHGP:
20415 gen_ld(ctx, OPC_LH, rt, 28, u);
20416 break;
20417 case NM_LHUGP:
20418 gen_ld(ctx, OPC_LHU, rt, 28, u);
20419 break;
20421 break;
20422 case NM_P_GP_SH:
20423 u &= ~1;
20424 switch (ctx->opcode & 1) {
20425 case NM_SHGP:
20426 gen_st(ctx, OPC_SH, rt, 28, u);
20427 break;
20428 default:
20429 generate_exception_end(ctx, EXCP_RI);
20430 break;
20432 break;
20433 case NM_P_GP_CP1:
20434 u &= ~0x3;
20435 switch (ctx->opcode & 0x3) {
20436 case NM_LWC1GP:
20437 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20438 break;
20439 case NM_LDC1GP:
20440 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20441 break;
20442 case NM_SWC1GP:
20443 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20444 break;
20445 case NM_SDC1GP:
20446 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20447 break;
20449 break;
20450 default:
20451 generate_exception_end(ctx, EXCP_RI);
20452 break;
20455 break;
20456 case NM_P_LS_U12:
20458 uint32_t u = extract32(ctx->opcode, 0, 12);
20460 switch (extract32(ctx->opcode, 12, 4)) {
20461 case NM_P_PREFU12:
20462 if (rt == 31) {
20463 /* SYNCI */
20464 /* Break the TB to be able to sync copied instructions
20465 immediately */
20466 ctx->base.is_jmp = DISAS_STOP;
20467 } else {
20468 /* PREF */
20469 /* Treat as NOP. */
20471 break;
20472 case NM_LB:
20473 gen_ld(ctx, OPC_LB, rt, rs, u);
20474 break;
20475 case NM_LH:
20476 gen_ld(ctx, OPC_LH, rt, rs, u);
20477 break;
20478 case NM_LW:
20479 gen_ld(ctx, OPC_LW, rt, rs, u);
20480 break;
20481 case NM_LBU:
20482 gen_ld(ctx, OPC_LBU, rt, rs, u);
20483 break;
20484 case NM_LHU:
20485 gen_ld(ctx, OPC_LHU, rt, rs, u);
20486 break;
20487 case NM_SB:
20488 gen_st(ctx, OPC_SB, rt, rs, u);
20489 break;
20490 case NM_SH:
20491 gen_st(ctx, OPC_SH, rt, rs, u);
20492 break;
20493 case NM_SW:
20494 gen_st(ctx, OPC_SW, rt, rs, u);
20495 break;
20496 case NM_LWC1:
20497 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20498 break;
20499 case NM_LDC1:
20500 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20501 break;
20502 case NM_SWC1:
20503 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20504 break;
20505 case NM_SDC1:
20506 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20507 break;
20508 default:
20509 generate_exception_end(ctx, EXCP_RI);
20510 break;
20513 break;
20514 case NM_P_LS_S9:
20516 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20517 extract32(ctx->opcode, 0, 8);
20519 switch (extract32(ctx->opcode, 8, 3)) {
20520 case NM_P_LS_S0:
20521 switch (extract32(ctx->opcode, 11, 4)) {
20522 case NM_LBS9:
20523 gen_ld(ctx, OPC_LB, rt, rs, s);
20524 break;
20525 case NM_LHS9:
20526 gen_ld(ctx, OPC_LH, rt, rs, s);
20527 break;
20528 case NM_LWS9:
20529 gen_ld(ctx, OPC_LW, rt, rs, s);
20530 break;
20531 case NM_LBUS9:
20532 gen_ld(ctx, OPC_LBU, rt, rs, s);
20533 break;
20534 case NM_LHUS9:
20535 gen_ld(ctx, OPC_LHU, rt, rs, s);
20536 break;
20537 case NM_SBS9:
20538 gen_st(ctx, OPC_SB, rt, rs, s);
20539 break;
20540 case NM_SHS9:
20541 gen_st(ctx, OPC_SH, rt, rs, s);
20542 break;
20543 case NM_SWS9:
20544 gen_st(ctx, OPC_SW, rt, rs, s);
20545 break;
20546 case NM_LWC1S9:
20547 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20548 break;
20549 case NM_LDC1S9:
20550 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20551 break;
20552 case NM_SWC1S9:
20553 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20554 break;
20555 case NM_SDC1S9:
20556 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20557 break;
20558 case NM_P_PREFS9:
20559 if (rt == 31) {
20560 /* SYNCI */
20561 /* Break the TB to be able to sync copied instructions
20562 immediately */
20563 ctx->base.is_jmp = DISAS_STOP;
20564 } else {
20565 /* PREF */
20566 /* Treat as NOP. */
20568 break;
20569 default:
20570 generate_exception_end(ctx, EXCP_RI);
20571 break;
20573 break;
20574 case NM_P_LS_S1:
20575 switch (extract32(ctx->opcode, 11, 4)) {
20576 case NM_UALH:
20577 case NM_UASH:
20578 check_nms(ctx);
20580 TCGv t0 = tcg_temp_new();
20581 TCGv t1 = tcg_temp_new();
20583 gen_base_offset_addr(ctx, t0, rs, s);
20585 switch (extract32(ctx->opcode, 11, 4)) {
20586 case NM_UALH:
20587 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20588 MO_UNALN);
20589 gen_store_gpr(t0, rt);
20590 break;
20591 case NM_UASH:
20592 gen_load_gpr(t1, rt);
20593 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20594 MO_UNALN);
20595 break;
20597 tcg_temp_free(t0);
20598 tcg_temp_free(t1);
20600 break;
20601 case NM_P_LL:
20602 switch (ctx->opcode & 0x03) {
20603 case NM_LL:
20604 gen_ld(ctx, OPC_LL, rt, rs, s);
20605 break;
20606 case NM_LLWP:
20607 check_xnp(ctx);
20608 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20609 break;
20611 break;
20612 case NM_P_SC:
20613 switch (ctx->opcode & 0x03) {
20614 case NM_SC:
20615 gen_st_cond(ctx, OPC_SC, rt, rs, s);
20616 break;
20617 case NM_SCWP:
20618 check_xnp(ctx);
20619 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20620 break;
20622 break;
20623 case NM_CACHE:
20624 check_cp0_enabled(ctx);
20625 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20626 gen_cache_operation(ctx, rt, rs, s);
20628 break;
20630 break;
20631 case NM_P_LS_WM:
20632 case NM_P_LS_UAWM:
20633 check_nms(ctx);
20635 int count = extract32(ctx->opcode, 12, 3);
20636 int counter = 0;
20638 offset = sextract32(ctx->opcode, 15, 1) << 8 |
20639 extract32(ctx->opcode, 0, 8);
20640 TCGv va = tcg_temp_new();
20641 TCGv t1 = tcg_temp_new();
20642 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
20643 NM_P_LS_UAWM ? MO_UNALN : 0;
20645 count = (count == 0) ? 8 : count;
20646 while (counter != count) {
20647 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
20648 int this_offset = offset + (counter << 2);
20650 gen_base_offset_addr(ctx, va, rs, this_offset);
20652 switch (extract32(ctx->opcode, 11, 1)) {
20653 case NM_LWM:
20654 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
20655 memop | MO_TESL);
20656 gen_store_gpr(t1, this_rt);
20657 if ((this_rt == rs) &&
20658 (counter != (count - 1))) {
20659 /* UNPREDICTABLE */
20661 break;
20662 case NM_SWM:
20663 this_rt = (rt == 0) ? 0 : this_rt;
20664 gen_load_gpr(t1, this_rt);
20665 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
20666 memop | MO_TEUL);
20667 break;
20669 counter++;
20671 tcg_temp_free(va);
20672 tcg_temp_free(t1);
20674 break;
20675 default:
20676 generate_exception_end(ctx, EXCP_RI);
20677 break;
20680 break;
20681 case NM_MOVE_BALC:
20682 check_nms(ctx);
20684 TCGv t0 = tcg_temp_new();
20685 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
20686 extract32(ctx->opcode, 1, 20) << 1;
20687 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
20688 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
20689 extract32(ctx->opcode, 21, 3));
20690 gen_load_gpr(t0, rt);
20691 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20692 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20693 tcg_temp_free(t0);
20695 break;
20696 case NM_P_BAL:
20698 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
20699 extract32(ctx->opcode, 1, 24) << 1;
20701 if ((extract32(ctx->opcode, 25, 1)) == 0) {
20702 /* BC */
20703 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
20704 } else {
20705 /* BALC */
20706 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20709 break;
20710 case NM_P_J:
20711 switch (extract32(ctx->opcode, 12, 4)) {
20712 case NM_JALRC:
20713 case NM_JALRC_HB:
20714 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
20715 break;
20716 case NM_P_BALRSC:
20717 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
20718 break;
20719 default:
20720 generate_exception_end(ctx, EXCP_RI);
20721 break;
20723 break;
20724 case NM_P_BR1:
20726 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20727 extract32(ctx->opcode, 1, 13) << 1;
20728 switch (extract32(ctx->opcode, 14, 2)) {
20729 case NM_BEQC:
20730 check_nms(ctx);
20731 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
20732 break;
20733 case NM_P_BR3A:
20734 s = sextract32(ctx->opcode, 0, 1) << 14 |
20735 extract32(ctx->opcode, 1, 13) << 1;
20736 check_cp1_enabled(ctx);
20737 switch (extract32(ctx->opcode, 16, 5)) {
20738 case NM_BC1EQZC:
20739 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
20740 break;
20741 case NM_BC1NEZC:
20742 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
20743 break;
20744 case NM_BPOSGE32C:
20745 check_dsp_r3(ctx);
20747 int32_t imm = extract32(ctx->opcode, 1, 13) |
20748 extract32(ctx->opcode, 0, 1) << 13;
20750 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
20751 imm);
20753 break;
20754 default:
20755 generate_exception_end(ctx, EXCP_RI);
20756 break;
20758 break;
20759 case NM_BGEC:
20760 if (rs == rt) {
20761 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
20762 } else {
20763 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
20765 break;
20766 case NM_BGEUC:
20767 if (rs == rt || rt == 0) {
20768 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
20769 } else if (rs == 0) {
20770 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
20771 } else {
20772 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
20774 break;
20777 break;
20778 case NM_P_BR2:
20780 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20781 extract32(ctx->opcode, 1, 13) << 1;
20782 switch (extract32(ctx->opcode, 14, 2)) {
20783 case NM_BNEC:
20784 check_nms(ctx);
20785 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
20786 break;
20787 case NM_BLTC:
20788 if (rs != 0 && rt != 0 && rs == rt) {
20789 /* NOP */
20790 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
20791 } else {
20792 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
20794 break;
20795 case NM_BLTUC:
20796 if (rs == 0 || rs == rt) {
20797 /* NOP */
20798 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
20799 } else {
20800 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
20802 break;
20803 default:
20804 generate_exception_end(ctx, EXCP_RI);
20805 break;
20808 break;
20809 case NM_P_BRI:
20811 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
20812 extract32(ctx->opcode, 1, 10) << 1;
20813 uint32_t u = extract32(ctx->opcode, 11, 7);
20815 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
20816 rt, u, s);
20818 break;
20819 default:
20820 generate_exception_end(ctx, EXCP_RI);
20821 break;
20823 return 4;
20826 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
20828 uint32_t op;
20829 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
20830 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
20831 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
20832 int offset;
20833 int imm;
20835 /* make sure instructions are on a halfword boundary */
20836 if (ctx->base.pc_next & 0x1) {
20837 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
20838 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
20839 tcg_temp_free(tmp);
20840 generate_exception_end(ctx, EXCP_AdEL);
20841 return 2;
20844 op = extract32(ctx->opcode, 10, 6);
20845 switch (op) {
20846 case NM_P16_MV:
20847 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20848 if (rt != 0) {
20849 /* MOVE */
20850 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
20851 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
20852 } else {
20853 /* P16.RI */
20854 switch (extract32(ctx->opcode, 3, 2)) {
20855 case NM_P16_SYSCALL:
20856 if (extract32(ctx->opcode, 2, 1) == 0) {
20857 generate_exception_end(ctx, EXCP_SYSCALL);
20858 } else {
20859 generate_exception_end(ctx, EXCP_RI);
20861 break;
20862 case NM_BREAK16:
20863 generate_exception_end(ctx, EXCP_BREAK);
20864 break;
20865 case NM_SDBBP16:
20866 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
20867 gen_helper_do_semihosting(cpu_env);
20868 } else {
20869 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20870 generate_exception_end(ctx, EXCP_RI);
20871 } else {
20872 generate_exception_end(ctx, EXCP_DBp);
20875 break;
20876 default:
20877 generate_exception_end(ctx, EXCP_RI);
20878 break;
20881 break;
20882 case NM_P16_SHIFT:
20884 int shift = extract32(ctx->opcode, 0, 3);
20885 uint32_t opc = 0;
20886 shift = (shift == 0) ? 8 : shift;
20888 switch (extract32(ctx->opcode, 3, 1)) {
20889 case NM_SLL16:
20890 opc = OPC_SLL;
20891 break;
20892 case NM_SRL16:
20893 opc = OPC_SRL;
20894 break;
20896 gen_shift_imm(ctx, opc, rt, rs, shift);
20898 break;
20899 case NM_P16C:
20900 switch (ctx->opcode & 1) {
20901 case NM_POOL16C_0:
20902 gen_pool16c_nanomips_insn(ctx);
20903 break;
20904 case NM_LWXS16:
20905 gen_ldxs(ctx, rt, rs, rd);
20906 break;
20908 break;
20909 case NM_P16_A1:
20910 switch (extract32(ctx->opcode, 6, 1)) {
20911 case NM_ADDIUR1SP:
20912 imm = extract32(ctx->opcode, 0, 6) << 2;
20913 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
20914 break;
20915 default:
20916 generate_exception_end(ctx, EXCP_RI);
20917 break;
20919 break;
20920 case NM_P16_A2:
20921 switch (extract32(ctx->opcode, 3, 1)) {
20922 case NM_ADDIUR2:
20923 imm = extract32(ctx->opcode, 0, 3) << 2;
20924 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
20925 break;
20926 case NM_P_ADDIURS5:
20927 rt = extract32(ctx->opcode, 5, 5);
20928 if (rt != 0) {
20929 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
20930 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
20931 (extract32(ctx->opcode, 0, 3));
20932 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
20934 break;
20936 break;
20937 case NM_P16_ADDU:
20938 switch (ctx->opcode & 0x1) {
20939 case NM_ADDU16:
20940 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
20941 break;
20942 case NM_SUBU16:
20943 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
20944 break;
20946 break;
20947 case NM_P16_4X4:
20948 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20949 extract32(ctx->opcode, 5, 3);
20950 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20951 extract32(ctx->opcode, 0, 3);
20952 rt = decode_gpr_gpr4(rt);
20953 rs = decode_gpr_gpr4(rs);
20954 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
20955 (extract32(ctx->opcode, 3, 1))) {
20956 case NM_ADDU4X4:
20957 check_nms(ctx);
20958 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
20959 break;
20960 case NM_MUL4X4:
20961 check_nms(ctx);
20962 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
20963 break;
20964 default:
20965 generate_exception_end(ctx, EXCP_RI);
20966 break;
20968 break;
20969 case NM_LI16:
20971 int imm = extract32(ctx->opcode, 0, 7);
20972 imm = (imm == 0x7f ? -1 : imm);
20973 if (rt != 0) {
20974 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20977 break;
20978 case NM_ANDI16:
20980 uint32_t u = extract32(ctx->opcode, 0, 4);
20981 u = (u == 12) ? 0xff :
20982 (u == 13) ? 0xffff : u;
20983 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
20985 break;
20986 case NM_P16_LB:
20987 offset = extract32(ctx->opcode, 0, 2);
20988 switch (extract32(ctx->opcode, 2, 2)) {
20989 case NM_LB16:
20990 gen_ld(ctx, OPC_LB, rt, rs, offset);
20991 break;
20992 case NM_SB16:
20993 rt = decode_gpr_gpr3_src_store(
20994 NANOMIPS_EXTRACT_RD(ctx->opcode));
20995 gen_st(ctx, OPC_SB, rt, rs, offset);
20996 break;
20997 case NM_LBU16:
20998 gen_ld(ctx, OPC_LBU, rt, rs, offset);
20999 break;
21000 default:
21001 generate_exception_end(ctx, EXCP_RI);
21002 break;
21004 break;
21005 case NM_P16_LH:
21006 offset = extract32(ctx->opcode, 1, 2) << 1;
21007 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21008 case NM_LH16:
21009 gen_ld(ctx, OPC_LH, rt, rs, offset);
21010 break;
21011 case NM_SH16:
21012 rt = decode_gpr_gpr3_src_store(
21013 NANOMIPS_EXTRACT_RD(ctx->opcode));
21014 gen_st(ctx, OPC_SH, rt, rs, offset);
21015 break;
21016 case NM_LHU16:
21017 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21018 break;
21019 default:
21020 generate_exception_end(ctx, EXCP_RI);
21021 break;
21023 break;
21024 case NM_LW16:
21025 offset = extract32(ctx->opcode, 0, 4) << 2;
21026 gen_ld(ctx, OPC_LW, rt, rs, offset);
21027 break;
21028 case NM_LWSP16:
21029 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21030 offset = extract32(ctx->opcode, 0, 5) << 2;
21031 gen_ld(ctx, OPC_LW, rt, 29, offset);
21032 break;
21033 case NM_LW4X4:
21034 check_nms(ctx);
21035 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21036 extract32(ctx->opcode, 5, 3);
21037 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21038 extract32(ctx->opcode, 0, 3);
21039 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21040 (extract32(ctx->opcode, 8, 1) << 2);
21041 rt = decode_gpr_gpr4(rt);
21042 rs = decode_gpr_gpr4(rs);
21043 gen_ld(ctx, OPC_LW, rt, rs, offset);
21044 break;
21045 case NM_SW4X4:
21046 check_nms(ctx);
21047 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21048 extract32(ctx->opcode, 5, 3);
21049 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21050 extract32(ctx->opcode, 0, 3);
21051 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21052 (extract32(ctx->opcode, 8, 1) << 2);
21053 rt = decode_gpr_gpr4_zero(rt);
21054 rs = decode_gpr_gpr4(rs);
21055 gen_st(ctx, OPC_SW, rt, rs, offset);
21056 break;
21057 case NM_LWGP16:
21058 offset = extract32(ctx->opcode, 0, 7) << 2;
21059 gen_ld(ctx, OPC_LW, rt, 28, offset);
21060 break;
21061 case NM_SWSP16:
21062 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21063 offset = extract32(ctx->opcode, 0, 5) << 2;
21064 gen_st(ctx, OPC_SW, rt, 29, offset);
21065 break;
21066 case NM_SW16:
21067 rt = decode_gpr_gpr3_src_store(
21068 NANOMIPS_EXTRACT_RD(ctx->opcode));
21069 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21070 offset = extract32(ctx->opcode, 0, 4) << 2;
21071 gen_st(ctx, OPC_SW, rt, rs, offset);
21072 break;
21073 case NM_SWGP16:
21074 rt = decode_gpr_gpr3_src_store(
21075 NANOMIPS_EXTRACT_RD(ctx->opcode));
21076 offset = extract32(ctx->opcode, 0, 7) << 2;
21077 gen_st(ctx, OPC_SW, rt, 28, offset);
21078 break;
21079 case NM_BC16:
21080 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21081 (sextract32(ctx->opcode, 0, 1) << 10) |
21082 (extract32(ctx->opcode, 1, 9) << 1));
21083 break;
21084 case NM_BALC16:
21085 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21086 (sextract32(ctx->opcode, 0, 1) << 10) |
21087 (extract32(ctx->opcode, 1, 9) << 1));
21088 break;
21089 case NM_BEQZC16:
21090 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21091 (sextract32(ctx->opcode, 0, 1) << 7) |
21092 (extract32(ctx->opcode, 1, 6) << 1));
21093 break;
21094 case NM_BNEZC16:
21095 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21096 (sextract32(ctx->opcode, 0, 1) << 7) |
21097 (extract32(ctx->opcode, 1, 6) << 1));
21098 break;
21099 case NM_P16_BR:
21100 switch (ctx->opcode & 0xf) {
21101 case 0:
21102 /* P16.JRC */
21103 switch (extract32(ctx->opcode, 4, 1)) {
21104 case NM_JRC:
21105 gen_compute_branch_nm(ctx, OPC_JR, 2,
21106 extract32(ctx->opcode, 5, 5), 0, 0);
21107 break;
21108 case NM_JALRC16:
21109 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21110 extract32(ctx->opcode, 5, 5), 31, 0);
21111 break;
21113 break;
21114 default:
21116 /* P16.BRI */
21117 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21118 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21119 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21120 extract32(ctx->opcode, 0, 4) << 1);
21122 break;
21124 break;
21125 case NM_P16_SR:
21127 int count = extract32(ctx->opcode, 0, 4);
21128 int u = extract32(ctx->opcode, 4, 4) << 4;
21130 rt = 30 + extract32(ctx->opcode, 9, 1);
21131 switch (extract32(ctx->opcode, 8, 1)) {
21132 case NM_SAVE16:
21133 gen_save(ctx, rt, count, 0, u);
21134 break;
21135 case NM_RESTORE_JRC16:
21136 gen_restore(ctx, rt, count, 0, u);
21137 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21138 break;
21141 break;
21142 case NM_MOVEP:
21143 case NM_MOVEPREV:
21144 check_nms(ctx);
21146 static const int gpr2reg1[] = {4, 5, 6, 7};
21147 static const int gpr2reg2[] = {5, 6, 7, 8};
21148 int re;
21149 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21150 extract32(ctx->opcode, 8, 1);
21151 int r1 = gpr2reg1[rd2];
21152 int r2 = gpr2reg2[rd2];
21153 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21154 extract32(ctx->opcode, 0, 3);
21155 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21156 extract32(ctx->opcode, 5, 3);
21157 TCGv t0 = tcg_temp_new();
21158 TCGv t1 = tcg_temp_new();
21159 if (op == NM_MOVEP) {
21160 rd = r1;
21161 re = r2;
21162 rs = decode_gpr_gpr4_zero(r3);
21163 rt = decode_gpr_gpr4_zero(r4);
21164 } else {
21165 rd = decode_gpr_gpr4(r3);
21166 re = decode_gpr_gpr4(r4);
21167 rs = r1;
21168 rt = r2;
21170 gen_load_gpr(t0, rs);
21171 gen_load_gpr(t1, rt);
21172 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21173 tcg_gen_mov_tl(cpu_gpr[re], t1);
21174 tcg_temp_free(t0);
21175 tcg_temp_free(t1);
21177 break;
21178 default:
21179 return decode_nanomips_32_48_opc(env, ctx);
21182 return 2;
21186 /* SmartMIPS extension to MIPS32 */
21188 #if defined(TARGET_MIPS64)
21190 /* MDMX extension to MIPS64 */
21192 #endif
21194 /* MIPSDSP functions. */
21195 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21196 int rd, int base, int offset)
21198 TCGv t0;
21200 check_dsp(ctx);
21201 t0 = tcg_temp_new();
21203 if (base == 0) {
21204 gen_load_gpr(t0, offset);
21205 } else if (offset == 0) {
21206 gen_load_gpr(t0, base);
21207 } else {
21208 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21211 switch (opc) {
21212 case OPC_LBUX:
21213 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21214 gen_store_gpr(t0, rd);
21215 break;
21216 case OPC_LHX:
21217 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21218 gen_store_gpr(t0, rd);
21219 break;
21220 case OPC_LWX:
21221 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21222 gen_store_gpr(t0, rd);
21223 break;
21224 #if defined(TARGET_MIPS64)
21225 case OPC_LDX:
21226 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21227 gen_store_gpr(t0, rd);
21228 break;
21229 #endif
21231 tcg_temp_free(t0);
21234 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21235 int ret, int v1, int v2)
21237 TCGv v1_t;
21238 TCGv v2_t;
21240 if (ret == 0) {
21241 /* Treat as NOP. */
21242 return;
21245 v1_t = tcg_temp_new();
21246 v2_t = tcg_temp_new();
21248 gen_load_gpr(v1_t, v1);
21249 gen_load_gpr(v2_t, v2);
21251 switch (op1) {
21252 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21253 case OPC_MULT_G_2E:
21254 check_dsp_r2(ctx);
21255 switch (op2) {
21256 case OPC_ADDUH_QB:
21257 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21258 break;
21259 case OPC_ADDUH_R_QB:
21260 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21261 break;
21262 case OPC_ADDQH_PH:
21263 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21264 break;
21265 case OPC_ADDQH_R_PH:
21266 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21267 break;
21268 case OPC_ADDQH_W:
21269 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21270 break;
21271 case OPC_ADDQH_R_W:
21272 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21273 break;
21274 case OPC_SUBUH_QB:
21275 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21276 break;
21277 case OPC_SUBUH_R_QB:
21278 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21279 break;
21280 case OPC_SUBQH_PH:
21281 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21282 break;
21283 case OPC_SUBQH_R_PH:
21284 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21285 break;
21286 case OPC_SUBQH_W:
21287 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21288 break;
21289 case OPC_SUBQH_R_W:
21290 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21291 break;
21293 break;
21294 case OPC_ABSQ_S_PH_DSP:
21295 switch (op2) {
21296 case OPC_ABSQ_S_QB:
21297 check_dsp_r2(ctx);
21298 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21299 break;
21300 case OPC_ABSQ_S_PH:
21301 check_dsp(ctx);
21302 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21303 break;
21304 case OPC_ABSQ_S_W:
21305 check_dsp(ctx);
21306 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21307 break;
21308 case OPC_PRECEQ_W_PHL:
21309 check_dsp(ctx);
21310 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21311 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21312 break;
21313 case OPC_PRECEQ_W_PHR:
21314 check_dsp(ctx);
21315 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21316 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21317 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21318 break;
21319 case OPC_PRECEQU_PH_QBL:
21320 check_dsp(ctx);
21321 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21322 break;
21323 case OPC_PRECEQU_PH_QBR:
21324 check_dsp(ctx);
21325 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21326 break;
21327 case OPC_PRECEQU_PH_QBLA:
21328 check_dsp(ctx);
21329 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21330 break;
21331 case OPC_PRECEQU_PH_QBRA:
21332 check_dsp(ctx);
21333 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21334 break;
21335 case OPC_PRECEU_PH_QBL:
21336 check_dsp(ctx);
21337 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21338 break;
21339 case OPC_PRECEU_PH_QBR:
21340 check_dsp(ctx);
21341 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21342 break;
21343 case OPC_PRECEU_PH_QBLA:
21344 check_dsp(ctx);
21345 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21346 break;
21347 case OPC_PRECEU_PH_QBRA:
21348 check_dsp(ctx);
21349 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21350 break;
21352 break;
21353 case OPC_ADDU_QB_DSP:
21354 switch (op2) {
21355 case OPC_ADDQ_PH:
21356 check_dsp(ctx);
21357 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21358 break;
21359 case OPC_ADDQ_S_PH:
21360 check_dsp(ctx);
21361 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21362 break;
21363 case OPC_ADDQ_S_W:
21364 check_dsp(ctx);
21365 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21366 break;
21367 case OPC_ADDU_QB:
21368 check_dsp(ctx);
21369 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21370 break;
21371 case OPC_ADDU_S_QB:
21372 check_dsp(ctx);
21373 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21374 break;
21375 case OPC_ADDU_PH:
21376 check_dsp_r2(ctx);
21377 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21378 break;
21379 case OPC_ADDU_S_PH:
21380 check_dsp_r2(ctx);
21381 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21382 break;
21383 case OPC_SUBQ_PH:
21384 check_dsp(ctx);
21385 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21386 break;
21387 case OPC_SUBQ_S_PH:
21388 check_dsp(ctx);
21389 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21390 break;
21391 case OPC_SUBQ_S_W:
21392 check_dsp(ctx);
21393 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21394 break;
21395 case OPC_SUBU_QB:
21396 check_dsp(ctx);
21397 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21398 break;
21399 case OPC_SUBU_S_QB:
21400 check_dsp(ctx);
21401 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21402 break;
21403 case OPC_SUBU_PH:
21404 check_dsp_r2(ctx);
21405 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21406 break;
21407 case OPC_SUBU_S_PH:
21408 check_dsp_r2(ctx);
21409 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21410 break;
21411 case OPC_ADDSC:
21412 check_dsp(ctx);
21413 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21414 break;
21415 case OPC_ADDWC:
21416 check_dsp(ctx);
21417 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21418 break;
21419 case OPC_MODSUB:
21420 check_dsp(ctx);
21421 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21422 break;
21423 case OPC_RADDU_W_QB:
21424 check_dsp(ctx);
21425 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21426 break;
21428 break;
21429 case OPC_CMPU_EQ_QB_DSP:
21430 switch (op2) {
21431 case OPC_PRECR_QB_PH:
21432 check_dsp_r2(ctx);
21433 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21434 break;
21435 case OPC_PRECRQ_QB_PH:
21436 check_dsp(ctx);
21437 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21438 break;
21439 case OPC_PRECR_SRA_PH_W:
21440 check_dsp_r2(ctx);
21442 TCGv_i32 sa_t = tcg_const_i32(v2);
21443 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21444 cpu_gpr[ret]);
21445 tcg_temp_free_i32(sa_t);
21446 break;
21448 case OPC_PRECR_SRA_R_PH_W:
21449 check_dsp_r2(ctx);
21451 TCGv_i32 sa_t = tcg_const_i32(v2);
21452 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21453 cpu_gpr[ret]);
21454 tcg_temp_free_i32(sa_t);
21455 break;
21457 case OPC_PRECRQ_PH_W:
21458 check_dsp(ctx);
21459 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21460 break;
21461 case OPC_PRECRQ_RS_PH_W:
21462 check_dsp(ctx);
21463 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21464 break;
21465 case OPC_PRECRQU_S_QB_PH:
21466 check_dsp(ctx);
21467 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21468 break;
21470 break;
21471 #ifdef TARGET_MIPS64
21472 case OPC_ABSQ_S_QH_DSP:
21473 switch (op2) {
21474 case OPC_PRECEQ_L_PWL:
21475 check_dsp(ctx);
21476 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21477 break;
21478 case OPC_PRECEQ_L_PWR:
21479 check_dsp(ctx);
21480 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21481 break;
21482 case OPC_PRECEQ_PW_QHL:
21483 check_dsp(ctx);
21484 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21485 break;
21486 case OPC_PRECEQ_PW_QHR:
21487 check_dsp(ctx);
21488 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21489 break;
21490 case OPC_PRECEQ_PW_QHLA:
21491 check_dsp(ctx);
21492 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21493 break;
21494 case OPC_PRECEQ_PW_QHRA:
21495 check_dsp(ctx);
21496 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21497 break;
21498 case OPC_PRECEQU_QH_OBL:
21499 check_dsp(ctx);
21500 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21501 break;
21502 case OPC_PRECEQU_QH_OBR:
21503 check_dsp(ctx);
21504 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21505 break;
21506 case OPC_PRECEQU_QH_OBLA:
21507 check_dsp(ctx);
21508 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21509 break;
21510 case OPC_PRECEQU_QH_OBRA:
21511 check_dsp(ctx);
21512 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21513 break;
21514 case OPC_PRECEU_QH_OBL:
21515 check_dsp(ctx);
21516 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21517 break;
21518 case OPC_PRECEU_QH_OBR:
21519 check_dsp(ctx);
21520 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21521 break;
21522 case OPC_PRECEU_QH_OBLA:
21523 check_dsp(ctx);
21524 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21525 break;
21526 case OPC_PRECEU_QH_OBRA:
21527 check_dsp(ctx);
21528 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21529 break;
21530 case OPC_ABSQ_S_OB:
21531 check_dsp_r2(ctx);
21532 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21533 break;
21534 case OPC_ABSQ_S_PW:
21535 check_dsp(ctx);
21536 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21537 break;
21538 case OPC_ABSQ_S_QH:
21539 check_dsp(ctx);
21540 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21541 break;
21543 break;
21544 case OPC_ADDU_OB_DSP:
21545 switch (op2) {
21546 case OPC_RADDU_L_OB:
21547 check_dsp(ctx);
21548 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21549 break;
21550 case OPC_SUBQ_PW:
21551 check_dsp(ctx);
21552 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21553 break;
21554 case OPC_SUBQ_S_PW:
21555 check_dsp(ctx);
21556 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21557 break;
21558 case OPC_SUBQ_QH:
21559 check_dsp(ctx);
21560 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21561 break;
21562 case OPC_SUBQ_S_QH:
21563 check_dsp(ctx);
21564 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21565 break;
21566 case OPC_SUBU_OB:
21567 check_dsp(ctx);
21568 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21569 break;
21570 case OPC_SUBU_S_OB:
21571 check_dsp(ctx);
21572 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21573 break;
21574 case OPC_SUBU_QH:
21575 check_dsp_r2(ctx);
21576 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21577 break;
21578 case OPC_SUBU_S_QH:
21579 check_dsp_r2(ctx);
21580 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21581 break;
21582 case OPC_SUBUH_OB:
21583 check_dsp_r2(ctx);
21584 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21585 break;
21586 case OPC_SUBUH_R_OB:
21587 check_dsp_r2(ctx);
21588 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21589 break;
21590 case OPC_ADDQ_PW:
21591 check_dsp(ctx);
21592 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21593 break;
21594 case OPC_ADDQ_S_PW:
21595 check_dsp(ctx);
21596 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21597 break;
21598 case OPC_ADDQ_QH:
21599 check_dsp(ctx);
21600 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21601 break;
21602 case OPC_ADDQ_S_QH:
21603 check_dsp(ctx);
21604 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21605 break;
21606 case OPC_ADDU_OB:
21607 check_dsp(ctx);
21608 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21609 break;
21610 case OPC_ADDU_S_OB:
21611 check_dsp(ctx);
21612 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21613 break;
21614 case OPC_ADDU_QH:
21615 check_dsp_r2(ctx);
21616 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21617 break;
21618 case OPC_ADDU_S_QH:
21619 check_dsp_r2(ctx);
21620 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21621 break;
21622 case OPC_ADDUH_OB:
21623 check_dsp_r2(ctx);
21624 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
21625 break;
21626 case OPC_ADDUH_R_OB:
21627 check_dsp_r2(ctx);
21628 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21629 break;
21631 break;
21632 case OPC_CMPU_EQ_OB_DSP:
21633 switch (op2) {
21634 case OPC_PRECR_OB_QH:
21635 check_dsp_r2(ctx);
21636 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21637 break;
21638 case OPC_PRECR_SRA_QH_PW:
21639 check_dsp_r2(ctx);
21641 TCGv_i32 ret_t = tcg_const_i32(ret);
21642 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
21643 tcg_temp_free_i32(ret_t);
21644 break;
21646 case OPC_PRECR_SRA_R_QH_PW:
21647 check_dsp_r2(ctx);
21649 TCGv_i32 sa_v = tcg_const_i32(ret);
21650 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
21651 tcg_temp_free_i32(sa_v);
21652 break;
21654 case OPC_PRECRQ_OB_QH:
21655 check_dsp(ctx);
21656 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21657 break;
21658 case OPC_PRECRQ_PW_L:
21659 check_dsp(ctx);
21660 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
21661 break;
21662 case OPC_PRECRQ_QH_PW:
21663 check_dsp(ctx);
21664 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
21665 break;
21666 case OPC_PRECRQ_RS_QH_PW:
21667 check_dsp(ctx);
21668 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21669 break;
21670 case OPC_PRECRQU_S_OB_QH:
21671 check_dsp(ctx);
21672 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21673 break;
21675 break;
21676 #endif
21679 tcg_temp_free(v1_t);
21680 tcg_temp_free(v2_t);
21683 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
21684 int ret, int v1, int v2)
21686 uint32_t op2;
21687 TCGv t0;
21688 TCGv v1_t;
21689 TCGv v2_t;
21691 if (ret == 0) {
21692 /* Treat as NOP. */
21693 return;
21696 t0 = tcg_temp_new();
21697 v1_t = tcg_temp_new();
21698 v2_t = tcg_temp_new();
21700 tcg_gen_movi_tl(t0, v1);
21701 gen_load_gpr(v1_t, v1);
21702 gen_load_gpr(v2_t, v2);
21704 switch (opc) {
21705 case OPC_SHLL_QB_DSP:
21707 op2 = MASK_SHLL_QB(ctx->opcode);
21708 switch (op2) {
21709 case OPC_SHLL_QB:
21710 check_dsp(ctx);
21711 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
21712 break;
21713 case OPC_SHLLV_QB:
21714 check_dsp(ctx);
21715 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21716 break;
21717 case OPC_SHLL_PH:
21718 check_dsp(ctx);
21719 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21720 break;
21721 case OPC_SHLLV_PH:
21722 check_dsp(ctx);
21723 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21724 break;
21725 case OPC_SHLL_S_PH:
21726 check_dsp(ctx);
21727 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21728 break;
21729 case OPC_SHLLV_S_PH:
21730 check_dsp(ctx);
21731 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21732 break;
21733 case OPC_SHLL_S_W:
21734 check_dsp(ctx);
21735 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
21736 break;
21737 case OPC_SHLLV_S_W:
21738 check_dsp(ctx);
21739 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21740 break;
21741 case OPC_SHRL_QB:
21742 check_dsp(ctx);
21743 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
21744 break;
21745 case OPC_SHRLV_QB:
21746 check_dsp(ctx);
21747 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
21748 break;
21749 case OPC_SHRL_PH:
21750 check_dsp_r2(ctx);
21751 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
21752 break;
21753 case OPC_SHRLV_PH:
21754 check_dsp_r2(ctx);
21755 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
21756 break;
21757 case OPC_SHRA_QB:
21758 check_dsp_r2(ctx);
21759 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
21760 break;
21761 case OPC_SHRA_R_QB:
21762 check_dsp_r2(ctx);
21763 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
21764 break;
21765 case OPC_SHRAV_QB:
21766 check_dsp_r2(ctx);
21767 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
21768 break;
21769 case OPC_SHRAV_R_QB:
21770 check_dsp_r2(ctx);
21771 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
21772 break;
21773 case OPC_SHRA_PH:
21774 check_dsp(ctx);
21775 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
21776 break;
21777 case OPC_SHRA_R_PH:
21778 check_dsp(ctx);
21779 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
21780 break;
21781 case OPC_SHRAV_PH:
21782 check_dsp(ctx);
21783 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
21784 break;
21785 case OPC_SHRAV_R_PH:
21786 check_dsp(ctx);
21787 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
21788 break;
21789 case OPC_SHRA_R_W:
21790 check_dsp(ctx);
21791 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
21792 break;
21793 case OPC_SHRAV_R_W:
21794 check_dsp(ctx);
21795 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
21796 break;
21797 default: /* Invalid */
21798 MIPS_INVAL("MASK SHLL.QB");
21799 generate_exception_end(ctx, EXCP_RI);
21800 break;
21802 break;
21804 #ifdef TARGET_MIPS64
21805 case OPC_SHLL_OB_DSP:
21806 op2 = MASK_SHLL_OB(ctx->opcode);
21807 switch (op2) {
21808 case OPC_SHLL_PW:
21809 check_dsp(ctx);
21810 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
21811 break;
21812 case OPC_SHLLV_PW:
21813 check_dsp(ctx);
21814 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21815 break;
21816 case OPC_SHLL_S_PW:
21817 check_dsp(ctx);
21818 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
21819 break;
21820 case OPC_SHLLV_S_PW:
21821 check_dsp(ctx);
21822 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21823 break;
21824 case OPC_SHLL_OB:
21825 check_dsp(ctx);
21826 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
21827 break;
21828 case OPC_SHLLV_OB:
21829 check_dsp(ctx);
21830 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21831 break;
21832 case OPC_SHLL_QH:
21833 check_dsp(ctx);
21834 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
21835 break;
21836 case OPC_SHLLV_QH:
21837 check_dsp(ctx);
21838 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21839 break;
21840 case OPC_SHLL_S_QH:
21841 check_dsp(ctx);
21842 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
21843 break;
21844 case OPC_SHLLV_S_QH:
21845 check_dsp(ctx);
21846 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21847 break;
21848 case OPC_SHRA_OB:
21849 check_dsp_r2(ctx);
21850 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
21851 break;
21852 case OPC_SHRAV_OB:
21853 check_dsp_r2(ctx);
21854 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
21855 break;
21856 case OPC_SHRA_R_OB:
21857 check_dsp_r2(ctx);
21858 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
21859 break;
21860 case OPC_SHRAV_R_OB:
21861 check_dsp_r2(ctx);
21862 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
21863 break;
21864 case OPC_SHRA_PW:
21865 check_dsp(ctx);
21866 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
21867 break;
21868 case OPC_SHRAV_PW:
21869 check_dsp(ctx);
21870 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
21871 break;
21872 case OPC_SHRA_R_PW:
21873 check_dsp(ctx);
21874 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
21875 break;
21876 case OPC_SHRAV_R_PW:
21877 check_dsp(ctx);
21878 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
21879 break;
21880 case OPC_SHRA_QH:
21881 check_dsp(ctx);
21882 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
21883 break;
21884 case OPC_SHRAV_QH:
21885 check_dsp(ctx);
21886 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
21887 break;
21888 case OPC_SHRA_R_QH:
21889 check_dsp(ctx);
21890 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
21891 break;
21892 case OPC_SHRAV_R_QH:
21893 check_dsp(ctx);
21894 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
21895 break;
21896 case OPC_SHRL_OB:
21897 check_dsp(ctx);
21898 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
21899 break;
21900 case OPC_SHRLV_OB:
21901 check_dsp(ctx);
21902 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
21903 break;
21904 case OPC_SHRL_QH:
21905 check_dsp_r2(ctx);
21906 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
21907 break;
21908 case OPC_SHRLV_QH:
21909 check_dsp_r2(ctx);
21910 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
21911 break;
21912 default: /* Invalid */
21913 MIPS_INVAL("MASK SHLL.OB");
21914 generate_exception_end(ctx, EXCP_RI);
21915 break;
21917 break;
21918 #endif
21921 tcg_temp_free(t0);
21922 tcg_temp_free(v1_t);
21923 tcg_temp_free(v2_t);
21926 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
21927 int ret, int v1, int v2, int check_ret)
21929 TCGv_i32 t0;
21930 TCGv v1_t;
21931 TCGv v2_t;
21933 if ((ret == 0) && (check_ret == 1)) {
21934 /* Treat as NOP. */
21935 return;
21938 t0 = tcg_temp_new_i32();
21939 v1_t = tcg_temp_new();
21940 v2_t = tcg_temp_new();
21942 tcg_gen_movi_i32(t0, ret);
21943 gen_load_gpr(v1_t, v1);
21944 gen_load_gpr(v2_t, v2);
21946 switch (op1) {
21947 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
21948 * the same mask and op1. */
21949 case OPC_MULT_G_2E:
21950 check_dsp_r2(ctx);
21951 switch (op2) {
21952 case OPC_MUL_PH:
21953 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21954 break;
21955 case OPC_MUL_S_PH:
21956 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21957 break;
21958 case OPC_MULQ_S_W:
21959 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21960 break;
21961 case OPC_MULQ_RS_W:
21962 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21963 break;
21965 break;
21966 case OPC_DPA_W_PH_DSP:
21967 switch (op2) {
21968 case OPC_DPAU_H_QBL:
21969 check_dsp(ctx);
21970 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
21971 break;
21972 case OPC_DPAU_H_QBR:
21973 check_dsp(ctx);
21974 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
21975 break;
21976 case OPC_DPSU_H_QBL:
21977 check_dsp(ctx);
21978 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
21979 break;
21980 case OPC_DPSU_H_QBR:
21981 check_dsp(ctx);
21982 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
21983 break;
21984 case OPC_DPA_W_PH:
21985 check_dsp_r2(ctx);
21986 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
21987 break;
21988 case OPC_DPAX_W_PH:
21989 check_dsp_r2(ctx);
21990 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
21991 break;
21992 case OPC_DPAQ_S_W_PH:
21993 check_dsp(ctx);
21994 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21995 break;
21996 case OPC_DPAQX_S_W_PH:
21997 check_dsp_r2(ctx);
21998 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
21999 break;
22000 case OPC_DPAQX_SA_W_PH:
22001 check_dsp_r2(ctx);
22002 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22003 break;
22004 case OPC_DPS_W_PH:
22005 check_dsp_r2(ctx);
22006 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22007 break;
22008 case OPC_DPSX_W_PH:
22009 check_dsp_r2(ctx);
22010 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22011 break;
22012 case OPC_DPSQ_S_W_PH:
22013 check_dsp(ctx);
22014 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22015 break;
22016 case OPC_DPSQX_S_W_PH:
22017 check_dsp_r2(ctx);
22018 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22019 break;
22020 case OPC_DPSQX_SA_W_PH:
22021 check_dsp_r2(ctx);
22022 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22023 break;
22024 case OPC_MULSAQ_S_W_PH:
22025 check_dsp(ctx);
22026 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22027 break;
22028 case OPC_DPAQ_SA_L_W:
22029 check_dsp(ctx);
22030 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22031 break;
22032 case OPC_DPSQ_SA_L_W:
22033 check_dsp(ctx);
22034 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22035 break;
22036 case OPC_MAQ_S_W_PHL:
22037 check_dsp(ctx);
22038 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22039 break;
22040 case OPC_MAQ_S_W_PHR:
22041 check_dsp(ctx);
22042 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22043 break;
22044 case OPC_MAQ_SA_W_PHL:
22045 check_dsp(ctx);
22046 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22047 break;
22048 case OPC_MAQ_SA_W_PHR:
22049 check_dsp(ctx);
22050 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22051 break;
22052 case OPC_MULSA_W_PH:
22053 check_dsp_r2(ctx);
22054 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22055 break;
22057 break;
22058 #ifdef TARGET_MIPS64
22059 case OPC_DPAQ_W_QH_DSP:
22061 int ac = ret & 0x03;
22062 tcg_gen_movi_i32(t0, ac);
22064 switch (op2) {
22065 case OPC_DMADD:
22066 check_dsp(ctx);
22067 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22068 break;
22069 case OPC_DMADDU:
22070 check_dsp(ctx);
22071 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22072 break;
22073 case OPC_DMSUB:
22074 check_dsp(ctx);
22075 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22076 break;
22077 case OPC_DMSUBU:
22078 check_dsp(ctx);
22079 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22080 break;
22081 case OPC_DPA_W_QH:
22082 check_dsp_r2(ctx);
22083 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22084 break;
22085 case OPC_DPAQ_S_W_QH:
22086 check_dsp(ctx);
22087 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22088 break;
22089 case OPC_DPAQ_SA_L_PW:
22090 check_dsp(ctx);
22091 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22092 break;
22093 case OPC_DPAU_H_OBL:
22094 check_dsp(ctx);
22095 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22096 break;
22097 case OPC_DPAU_H_OBR:
22098 check_dsp(ctx);
22099 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22100 break;
22101 case OPC_DPS_W_QH:
22102 check_dsp_r2(ctx);
22103 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22104 break;
22105 case OPC_DPSQ_S_W_QH:
22106 check_dsp(ctx);
22107 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22108 break;
22109 case OPC_DPSQ_SA_L_PW:
22110 check_dsp(ctx);
22111 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22112 break;
22113 case OPC_DPSU_H_OBL:
22114 check_dsp(ctx);
22115 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22116 break;
22117 case OPC_DPSU_H_OBR:
22118 check_dsp(ctx);
22119 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22120 break;
22121 case OPC_MAQ_S_L_PWL:
22122 check_dsp(ctx);
22123 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22124 break;
22125 case OPC_MAQ_S_L_PWR:
22126 check_dsp(ctx);
22127 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22128 break;
22129 case OPC_MAQ_S_W_QHLL:
22130 check_dsp(ctx);
22131 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22132 break;
22133 case OPC_MAQ_SA_W_QHLL:
22134 check_dsp(ctx);
22135 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22136 break;
22137 case OPC_MAQ_S_W_QHLR:
22138 check_dsp(ctx);
22139 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22140 break;
22141 case OPC_MAQ_SA_W_QHLR:
22142 check_dsp(ctx);
22143 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22144 break;
22145 case OPC_MAQ_S_W_QHRL:
22146 check_dsp(ctx);
22147 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22148 break;
22149 case OPC_MAQ_SA_W_QHRL:
22150 check_dsp(ctx);
22151 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22152 break;
22153 case OPC_MAQ_S_W_QHRR:
22154 check_dsp(ctx);
22155 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22156 break;
22157 case OPC_MAQ_SA_W_QHRR:
22158 check_dsp(ctx);
22159 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22160 break;
22161 case OPC_MULSAQ_S_L_PW:
22162 check_dsp(ctx);
22163 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22164 break;
22165 case OPC_MULSAQ_S_W_QH:
22166 check_dsp(ctx);
22167 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22168 break;
22171 break;
22172 #endif
22173 case OPC_ADDU_QB_DSP:
22174 switch (op2) {
22175 case OPC_MULEU_S_PH_QBL:
22176 check_dsp(ctx);
22177 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22178 break;
22179 case OPC_MULEU_S_PH_QBR:
22180 check_dsp(ctx);
22181 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22182 break;
22183 case OPC_MULQ_RS_PH:
22184 check_dsp(ctx);
22185 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22186 break;
22187 case OPC_MULEQ_S_W_PHL:
22188 check_dsp(ctx);
22189 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22190 break;
22191 case OPC_MULEQ_S_W_PHR:
22192 check_dsp(ctx);
22193 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22194 break;
22195 case OPC_MULQ_S_PH:
22196 check_dsp_r2(ctx);
22197 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22198 break;
22200 break;
22201 #ifdef TARGET_MIPS64
22202 case OPC_ADDU_OB_DSP:
22203 switch (op2) {
22204 case OPC_MULEQ_S_PW_QHL:
22205 check_dsp(ctx);
22206 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22207 break;
22208 case OPC_MULEQ_S_PW_QHR:
22209 check_dsp(ctx);
22210 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22211 break;
22212 case OPC_MULEU_S_QH_OBL:
22213 check_dsp(ctx);
22214 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22215 break;
22216 case OPC_MULEU_S_QH_OBR:
22217 check_dsp(ctx);
22218 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22219 break;
22220 case OPC_MULQ_RS_QH:
22221 check_dsp(ctx);
22222 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22223 break;
22225 break;
22226 #endif
22229 tcg_temp_free_i32(t0);
22230 tcg_temp_free(v1_t);
22231 tcg_temp_free(v2_t);
22234 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22235 int ret, int val)
22237 int16_t imm;
22238 TCGv t0;
22239 TCGv val_t;
22241 if (ret == 0) {
22242 /* Treat as NOP. */
22243 return;
22246 t0 = tcg_temp_new();
22247 val_t = tcg_temp_new();
22248 gen_load_gpr(val_t, val);
22250 switch (op1) {
22251 case OPC_ABSQ_S_PH_DSP:
22252 switch (op2) {
22253 case OPC_BITREV:
22254 check_dsp(ctx);
22255 gen_helper_bitrev(cpu_gpr[ret], val_t);
22256 break;
22257 case OPC_REPL_QB:
22258 check_dsp(ctx);
22260 target_long result;
22261 imm = (ctx->opcode >> 16) & 0xFF;
22262 result = (uint32_t)imm << 24 |
22263 (uint32_t)imm << 16 |
22264 (uint32_t)imm << 8 |
22265 (uint32_t)imm;
22266 result = (int32_t)result;
22267 tcg_gen_movi_tl(cpu_gpr[ret], result);
22269 break;
22270 case OPC_REPLV_QB:
22271 check_dsp(ctx);
22272 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22273 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22274 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22275 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22276 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22277 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22278 break;
22279 case OPC_REPL_PH:
22280 check_dsp(ctx);
22282 imm = (ctx->opcode >> 16) & 0x03FF;
22283 imm = (int16_t)(imm << 6) >> 6;
22284 tcg_gen_movi_tl(cpu_gpr[ret], \
22285 (target_long)((int32_t)imm << 16 | \
22286 (uint16_t)imm));
22288 break;
22289 case OPC_REPLV_PH:
22290 check_dsp(ctx);
22291 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22292 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22293 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22294 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22295 break;
22297 break;
22298 #ifdef TARGET_MIPS64
22299 case OPC_ABSQ_S_QH_DSP:
22300 switch (op2) {
22301 case OPC_REPL_OB:
22302 check_dsp(ctx);
22304 target_long temp;
22306 imm = (ctx->opcode >> 16) & 0xFF;
22307 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22308 temp = (temp << 16) | temp;
22309 temp = (temp << 32) | temp;
22310 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22311 break;
22313 case OPC_REPL_PW:
22314 check_dsp(ctx);
22316 target_long temp;
22318 imm = (ctx->opcode >> 16) & 0x03FF;
22319 imm = (int16_t)(imm << 6) >> 6;
22320 temp = ((target_long)imm << 32) \
22321 | ((target_long)imm & 0xFFFFFFFF);
22322 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22323 break;
22325 case OPC_REPL_QH:
22326 check_dsp(ctx);
22328 target_long temp;
22330 imm = (ctx->opcode >> 16) & 0x03FF;
22331 imm = (int16_t)(imm << 6) >> 6;
22333 temp = ((uint64_t)(uint16_t)imm << 48) |
22334 ((uint64_t)(uint16_t)imm << 32) |
22335 ((uint64_t)(uint16_t)imm << 16) |
22336 (uint64_t)(uint16_t)imm;
22337 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22338 break;
22340 case OPC_REPLV_OB:
22341 check_dsp(ctx);
22342 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22343 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22344 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22345 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22346 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22347 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22348 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22349 break;
22350 case OPC_REPLV_PW:
22351 check_dsp(ctx);
22352 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22353 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22354 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22355 break;
22356 case OPC_REPLV_QH:
22357 check_dsp(ctx);
22358 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22359 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22360 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22361 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22362 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22363 break;
22365 break;
22366 #endif
22368 tcg_temp_free(t0);
22369 tcg_temp_free(val_t);
22372 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22373 uint32_t op1, uint32_t op2,
22374 int ret, int v1, int v2, int check_ret)
22376 TCGv t1;
22377 TCGv v1_t;
22378 TCGv v2_t;
22380 if ((ret == 0) && (check_ret == 1)) {
22381 /* Treat as NOP. */
22382 return;
22385 t1 = tcg_temp_new();
22386 v1_t = tcg_temp_new();
22387 v2_t = tcg_temp_new();
22389 gen_load_gpr(v1_t, v1);
22390 gen_load_gpr(v2_t, v2);
22392 switch (op1) {
22393 case OPC_CMPU_EQ_QB_DSP:
22394 switch (op2) {
22395 case OPC_CMPU_EQ_QB:
22396 check_dsp(ctx);
22397 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22398 break;
22399 case OPC_CMPU_LT_QB:
22400 check_dsp(ctx);
22401 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22402 break;
22403 case OPC_CMPU_LE_QB:
22404 check_dsp(ctx);
22405 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22406 break;
22407 case OPC_CMPGU_EQ_QB:
22408 check_dsp(ctx);
22409 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22410 break;
22411 case OPC_CMPGU_LT_QB:
22412 check_dsp(ctx);
22413 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22414 break;
22415 case OPC_CMPGU_LE_QB:
22416 check_dsp(ctx);
22417 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22418 break;
22419 case OPC_CMPGDU_EQ_QB:
22420 check_dsp_r2(ctx);
22421 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22422 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22423 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22424 tcg_gen_shli_tl(t1, t1, 24);
22425 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22426 break;
22427 case OPC_CMPGDU_LT_QB:
22428 check_dsp_r2(ctx);
22429 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22430 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22431 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22432 tcg_gen_shli_tl(t1, t1, 24);
22433 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22434 break;
22435 case OPC_CMPGDU_LE_QB:
22436 check_dsp_r2(ctx);
22437 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22438 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22439 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22440 tcg_gen_shli_tl(t1, t1, 24);
22441 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22442 break;
22443 case OPC_CMP_EQ_PH:
22444 check_dsp(ctx);
22445 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22446 break;
22447 case OPC_CMP_LT_PH:
22448 check_dsp(ctx);
22449 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22450 break;
22451 case OPC_CMP_LE_PH:
22452 check_dsp(ctx);
22453 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22454 break;
22455 case OPC_PICK_QB:
22456 check_dsp(ctx);
22457 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22458 break;
22459 case OPC_PICK_PH:
22460 check_dsp(ctx);
22461 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22462 break;
22463 case OPC_PACKRL_PH:
22464 check_dsp(ctx);
22465 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22466 break;
22468 break;
22469 #ifdef TARGET_MIPS64
22470 case OPC_CMPU_EQ_OB_DSP:
22471 switch (op2) {
22472 case OPC_CMP_EQ_PW:
22473 check_dsp(ctx);
22474 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22475 break;
22476 case OPC_CMP_LT_PW:
22477 check_dsp(ctx);
22478 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22479 break;
22480 case OPC_CMP_LE_PW:
22481 check_dsp(ctx);
22482 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22483 break;
22484 case OPC_CMP_EQ_QH:
22485 check_dsp(ctx);
22486 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22487 break;
22488 case OPC_CMP_LT_QH:
22489 check_dsp(ctx);
22490 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22491 break;
22492 case OPC_CMP_LE_QH:
22493 check_dsp(ctx);
22494 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22495 break;
22496 case OPC_CMPGDU_EQ_OB:
22497 check_dsp_r2(ctx);
22498 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22499 break;
22500 case OPC_CMPGDU_LT_OB:
22501 check_dsp_r2(ctx);
22502 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22503 break;
22504 case OPC_CMPGDU_LE_OB:
22505 check_dsp_r2(ctx);
22506 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22507 break;
22508 case OPC_CMPGU_EQ_OB:
22509 check_dsp(ctx);
22510 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22511 break;
22512 case OPC_CMPGU_LT_OB:
22513 check_dsp(ctx);
22514 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22515 break;
22516 case OPC_CMPGU_LE_OB:
22517 check_dsp(ctx);
22518 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22519 break;
22520 case OPC_CMPU_EQ_OB:
22521 check_dsp(ctx);
22522 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22523 break;
22524 case OPC_CMPU_LT_OB:
22525 check_dsp(ctx);
22526 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22527 break;
22528 case OPC_CMPU_LE_OB:
22529 check_dsp(ctx);
22530 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22531 break;
22532 case OPC_PACKRL_PW:
22533 check_dsp(ctx);
22534 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22535 break;
22536 case OPC_PICK_OB:
22537 check_dsp(ctx);
22538 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22539 break;
22540 case OPC_PICK_PW:
22541 check_dsp(ctx);
22542 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22543 break;
22544 case OPC_PICK_QH:
22545 check_dsp(ctx);
22546 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22547 break;
22549 break;
22550 #endif
22553 tcg_temp_free(t1);
22554 tcg_temp_free(v1_t);
22555 tcg_temp_free(v2_t);
22558 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22559 uint32_t op1, int rt, int rs, int sa)
22561 TCGv t0;
22563 check_dsp_r2(ctx);
22565 if (rt == 0) {
22566 /* Treat as NOP. */
22567 return;
22570 t0 = tcg_temp_new();
22571 gen_load_gpr(t0, rs);
22573 switch (op1) {
22574 case OPC_APPEND_DSP:
22575 switch (MASK_APPEND(ctx->opcode)) {
22576 case OPC_APPEND:
22577 if (sa != 0) {
22578 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22580 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22581 break;
22582 case OPC_PREPEND:
22583 if (sa != 0) {
22584 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22585 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22586 tcg_gen_shli_tl(t0, t0, 32 - sa);
22587 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22589 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22590 break;
22591 case OPC_BALIGN:
22592 sa &= 3;
22593 if (sa != 0 && sa != 2) {
22594 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22595 tcg_gen_ext32u_tl(t0, t0);
22596 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22597 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22599 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22600 break;
22601 default: /* Invalid */
22602 MIPS_INVAL("MASK APPEND");
22603 generate_exception_end(ctx, EXCP_RI);
22604 break;
22606 break;
22607 #ifdef TARGET_MIPS64
22608 case OPC_DAPPEND_DSP:
22609 switch (MASK_DAPPEND(ctx->opcode)) {
22610 case OPC_DAPPEND:
22611 if (sa != 0) {
22612 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22614 break;
22615 case OPC_PREPENDD:
22616 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
22617 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
22618 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
22619 break;
22620 case OPC_PREPENDW:
22621 if (sa != 0) {
22622 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22623 tcg_gen_shli_tl(t0, t0, 64 - sa);
22624 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22626 break;
22627 case OPC_DBALIGN:
22628 sa &= 7;
22629 if (sa != 0 && sa != 2 && sa != 4) {
22630 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22631 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
22632 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22634 break;
22635 default: /* Invalid */
22636 MIPS_INVAL("MASK DAPPEND");
22637 generate_exception_end(ctx, EXCP_RI);
22638 break;
22640 break;
22641 #endif
22643 tcg_temp_free(t0);
22646 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22647 int ret, int v1, int v2, int check_ret)
22650 TCGv t0;
22651 TCGv t1;
22652 TCGv v1_t;
22653 TCGv v2_t;
22654 int16_t imm;
22656 if ((ret == 0) && (check_ret == 1)) {
22657 /* Treat as NOP. */
22658 return;
22661 t0 = tcg_temp_new();
22662 t1 = tcg_temp_new();
22663 v1_t = tcg_temp_new();
22664 v2_t = tcg_temp_new();
22666 gen_load_gpr(v1_t, v1);
22667 gen_load_gpr(v2_t, v2);
22669 switch (op1) {
22670 case OPC_EXTR_W_DSP:
22671 check_dsp(ctx);
22672 switch (op2) {
22673 case OPC_EXTR_W:
22674 tcg_gen_movi_tl(t0, v2);
22675 tcg_gen_movi_tl(t1, v1);
22676 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
22677 break;
22678 case OPC_EXTR_R_W:
22679 tcg_gen_movi_tl(t0, v2);
22680 tcg_gen_movi_tl(t1, v1);
22681 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22682 break;
22683 case OPC_EXTR_RS_W:
22684 tcg_gen_movi_tl(t0, v2);
22685 tcg_gen_movi_tl(t1, v1);
22686 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22687 break;
22688 case OPC_EXTR_S_H:
22689 tcg_gen_movi_tl(t0, v2);
22690 tcg_gen_movi_tl(t1, v1);
22691 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22692 break;
22693 case OPC_EXTRV_S_H:
22694 tcg_gen_movi_tl(t0, v2);
22695 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
22696 break;
22697 case OPC_EXTRV_W:
22698 tcg_gen_movi_tl(t0, v2);
22699 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22700 break;
22701 case OPC_EXTRV_R_W:
22702 tcg_gen_movi_tl(t0, v2);
22703 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22704 break;
22705 case OPC_EXTRV_RS_W:
22706 tcg_gen_movi_tl(t0, v2);
22707 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22708 break;
22709 case OPC_EXTP:
22710 tcg_gen_movi_tl(t0, v2);
22711 tcg_gen_movi_tl(t1, v1);
22712 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
22713 break;
22714 case OPC_EXTPV:
22715 tcg_gen_movi_tl(t0, v2);
22716 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
22717 break;
22718 case OPC_EXTPDP:
22719 tcg_gen_movi_tl(t0, v2);
22720 tcg_gen_movi_tl(t1, v1);
22721 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
22722 break;
22723 case OPC_EXTPDPV:
22724 tcg_gen_movi_tl(t0, v2);
22725 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22726 break;
22727 case OPC_SHILO:
22728 imm = (ctx->opcode >> 20) & 0x3F;
22729 tcg_gen_movi_tl(t0, ret);
22730 tcg_gen_movi_tl(t1, imm);
22731 gen_helper_shilo(t0, t1, cpu_env);
22732 break;
22733 case OPC_SHILOV:
22734 tcg_gen_movi_tl(t0, ret);
22735 gen_helper_shilo(t0, v1_t, cpu_env);
22736 break;
22737 case OPC_MTHLIP:
22738 tcg_gen_movi_tl(t0, ret);
22739 gen_helper_mthlip(t0, v1_t, cpu_env);
22740 break;
22741 case OPC_WRDSP:
22742 imm = (ctx->opcode >> 11) & 0x3FF;
22743 tcg_gen_movi_tl(t0, imm);
22744 gen_helper_wrdsp(v1_t, t0, cpu_env);
22745 break;
22746 case OPC_RDDSP:
22747 imm = (ctx->opcode >> 16) & 0x03FF;
22748 tcg_gen_movi_tl(t0, imm);
22749 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
22750 break;
22752 break;
22753 #ifdef TARGET_MIPS64
22754 case OPC_DEXTR_W_DSP:
22755 check_dsp(ctx);
22756 switch (op2) {
22757 case OPC_DMTHLIP:
22758 tcg_gen_movi_tl(t0, ret);
22759 gen_helper_dmthlip(v1_t, t0, cpu_env);
22760 break;
22761 case OPC_DSHILO:
22763 int shift = (ctx->opcode >> 19) & 0x7F;
22764 int ac = (ctx->opcode >> 11) & 0x03;
22765 tcg_gen_movi_tl(t0, shift);
22766 tcg_gen_movi_tl(t1, ac);
22767 gen_helper_dshilo(t0, t1, cpu_env);
22768 break;
22770 case OPC_DSHILOV:
22772 int ac = (ctx->opcode >> 11) & 0x03;
22773 tcg_gen_movi_tl(t0, ac);
22774 gen_helper_dshilo(v1_t, t0, cpu_env);
22775 break;
22777 case OPC_DEXTP:
22778 tcg_gen_movi_tl(t0, v2);
22779 tcg_gen_movi_tl(t1, v1);
22781 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
22782 break;
22783 case OPC_DEXTPV:
22784 tcg_gen_movi_tl(t0, v2);
22785 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
22786 break;
22787 case OPC_DEXTPDP:
22788 tcg_gen_movi_tl(t0, v2);
22789 tcg_gen_movi_tl(t1, v1);
22790 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
22791 break;
22792 case OPC_DEXTPDPV:
22793 tcg_gen_movi_tl(t0, v2);
22794 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22795 break;
22796 case OPC_DEXTR_L:
22797 tcg_gen_movi_tl(t0, v2);
22798 tcg_gen_movi_tl(t1, v1);
22799 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
22800 break;
22801 case OPC_DEXTR_R_L:
22802 tcg_gen_movi_tl(t0, v2);
22803 tcg_gen_movi_tl(t1, v1);
22804 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
22805 break;
22806 case OPC_DEXTR_RS_L:
22807 tcg_gen_movi_tl(t0, v2);
22808 tcg_gen_movi_tl(t1, v1);
22809 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
22810 break;
22811 case OPC_DEXTR_W:
22812 tcg_gen_movi_tl(t0, v2);
22813 tcg_gen_movi_tl(t1, v1);
22814 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
22815 break;
22816 case OPC_DEXTR_R_W:
22817 tcg_gen_movi_tl(t0, v2);
22818 tcg_gen_movi_tl(t1, v1);
22819 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22820 break;
22821 case OPC_DEXTR_RS_W:
22822 tcg_gen_movi_tl(t0, v2);
22823 tcg_gen_movi_tl(t1, v1);
22824 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22825 break;
22826 case OPC_DEXTR_S_H:
22827 tcg_gen_movi_tl(t0, v2);
22828 tcg_gen_movi_tl(t1, v1);
22829 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22830 break;
22831 case OPC_DEXTRV_S_H:
22832 tcg_gen_movi_tl(t0, v2);
22833 tcg_gen_movi_tl(t1, v1);
22834 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22835 break;
22836 case OPC_DEXTRV_L:
22837 tcg_gen_movi_tl(t0, v2);
22838 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22839 break;
22840 case OPC_DEXTRV_R_L:
22841 tcg_gen_movi_tl(t0, v2);
22842 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22843 break;
22844 case OPC_DEXTRV_RS_L:
22845 tcg_gen_movi_tl(t0, v2);
22846 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22847 break;
22848 case OPC_DEXTRV_W:
22849 tcg_gen_movi_tl(t0, v2);
22850 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22851 break;
22852 case OPC_DEXTRV_R_W:
22853 tcg_gen_movi_tl(t0, v2);
22854 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22855 break;
22856 case OPC_DEXTRV_RS_W:
22857 tcg_gen_movi_tl(t0, v2);
22858 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22859 break;
22861 break;
22862 #endif
22865 tcg_temp_free(t0);
22866 tcg_temp_free(t1);
22867 tcg_temp_free(v1_t);
22868 tcg_temp_free(v2_t);
22871 /* End MIPSDSP functions. */
22873 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
22875 int rs, rt, rd, sa;
22876 uint32_t op1, op2;
22878 rs = (ctx->opcode >> 21) & 0x1f;
22879 rt = (ctx->opcode >> 16) & 0x1f;
22880 rd = (ctx->opcode >> 11) & 0x1f;
22881 sa = (ctx->opcode >> 6) & 0x1f;
22883 op1 = MASK_SPECIAL(ctx->opcode);
22884 switch (op1) {
22885 case OPC_LSA:
22886 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
22887 break;
22888 case OPC_MULT:
22889 case OPC_MULTU:
22890 case OPC_DIV:
22891 case OPC_DIVU:
22892 op2 = MASK_R6_MULDIV(ctx->opcode);
22893 switch (op2) {
22894 case R6_OPC_MUL:
22895 case R6_OPC_MUH:
22896 case R6_OPC_MULU:
22897 case R6_OPC_MUHU:
22898 case R6_OPC_DIV:
22899 case R6_OPC_MOD:
22900 case R6_OPC_DIVU:
22901 case R6_OPC_MODU:
22902 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22903 break;
22904 default:
22905 MIPS_INVAL("special_r6 muldiv");
22906 generate_exception_end(ctx, EXCP_RI);
22907 break;
22909 break;
22910 case OPC_SELEQZ:
22911 case OPC_SELNEZ:
22912 gen_cond_move(ctx, op1, rd, rs, rt);
22913 break;
22914 case R6_OPC_CLO:
22915 case R6_OPC_CLZ:
22916 if (rt == 0 && sa == 1) {
22917 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22918 We need additionally to check other fields */
22919 gen_cl(ctx, op1, rd, rs);
22920 } else {
22921 generate_exception_end(ctx, EXCP_RI);
22923 break;
22924 case R6_OPC_SDBBP:
22925 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
22926 gen_helper_do_semihosting(cpu_env);
22927 } else {
22928 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22929 generate_exception_end(ctx, EXCP_RI);
22930 } else {
22931 generate_exception_end(ctx, EXCP_DBp);
22934 break;
22935 #if defined(TARGET_MIPS64)
22936 case OPC_DLSA:
22937 check_mips_64(ctx);
22938 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
22939 break;
22940 case R6_OPC_DCLO:
22941 case R6_OPC_DCLZ:
22942 if (rt == 0 && sa == 1) {
22943 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22944 We need additionally to check other fields */
22945 check_mips_64(ctx);
22946 gen_cl(ctx, op1, rd, rs);
22947 } else {
22948 generate_exception_end(ctx, EXCP_RI);
22950 break;
22951 case OPC_DMULT:
22952 case OPC_DMULTU:
22953 case OPC_DDIV:
22954 case OPC_DDIVU:
22956 op2 = MASK_R6_MULDIV(ctx->opcode);
22957 switch (op2) {
22958 case R6_OPC_DMUL:
22959 case R6_OPC_DMUH:
22960 case R6_OPC_DMULU:
22961 case R6_OPC_DMUHU:
22962 case R6_OPC_DDIV:
22963 case R6_OPC_DMOD:
22964 case R6_OPC_DDIVU:
22965 case R6_OPC_DMODU:
22966 check_mips_64(ctx);
22967 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22968 break;
22969 default:
22970 MIPS_INVAL("special_r6 muldiv");
22971 generate_exception_end(ctx, EXCP_RI);
22972 break;
22974 break;
22975 #endif
22976 default: /* Invalid */
22977 MIPS_INVAL("special_r6");
22978 generate_exception_end(ctx, EXCP_RI);
22979 break;
22983 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
22985 int rs, rt, rd, sa;
22986 uint32_t op1;
22988 rs = (ctx->opcode >> 21) & 0x1f;
22989 rt = (ctx->opcode >> 16) & 0x1f;
22990 rd = (ctx->opcode >> 11) & 0x1f;
22991 sa = (ctx->opcode >> 6) & 0x1f;
22993 op1 = MASK_SPECIAL(ctx->opcode);
22994 switch (op1) {
22995 case OPC_MOVN: /* Conditional move */
22996 case OPC_MOVZ:
22997 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
22998 INSN_LOONGSON2E | INSN_LOONGSON2F);
22999 gen_cond_move(ctx, op1, rd, rs, rt);
23000 break;
23001 case OPC_MFHI: /* Move from HI/LO */
23002 case OPC_MFLO:
23003 gen_HILO(ctx, op1, rs & 3, rd);
23004 break;
23005 case OPC_MTHI:
23006 case OPC_MTLO: /* Move to HI/LO */
23007 gen_HILO(ctx, op1, rd & 3, rs);
23008 break;
23009 case OPC_MOVCI:
23010 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23011 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23012 check_cp1_enabled(ctx);
23013 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23014 (ctx->opcode >> 16) & 1);
23015 } else {
23016 generate_exception_err(ctx, EXCP_CpU, 1);
23018 break;
23019 case OPC_MULT:
23020 case OPC_MULTU:
23021 if (sa) {
23022 check_insn(ctx, INSN_VR54XX);
23023 op1 = MASK_MUL_VR54XX(ctx->opcode);
23024 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23025 } else {
23026 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23028 break;
23029 case OPC_DIV:
23030 case OPC_DIVU:
23031 gen_muldiv(ctx, op1, 0, rs, rt);
23032 break;
23033 #if defined(TARGET_MIPS64)
23034 case OPC_DMULT:
23035 case OPC_DMULTU:
23036 case OPC_DDIV:
23037 case OPC_DDIVU:
23038 check_insn(ctx, ISA_MIPS3);
23039 check_mips_64(ctx);
23040 gen_muldiv(ctx, op1, 0, rs, rt);
23041 break;
23042 #endif
23043 case OPC_JR:
23044 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23045 break;
23046 case OPC_SPIM:
23047 #ifdef MIPS_STRICT_STANDARD
23048 MIPS_INVAL("SPIM");
23049 generate_exception_end(ctx, EXCP_RI);
23050 #else
23051 /* Implemented as RI exception for now. */
23052 MIPS_INVAL("spim (unofficial)");
23053 generate_exception_end(ctx, EXCP_RI);
23054 #endif
23055 break;
23056 default: /* Invalid */
23057 MIPS_INVAL("special_legacy");
23058 generate_exception_end(ctx, EXCP_RI);
23059 break;
23063 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23065 int rs, rt, rd, sa;
23066 uint32_t op1;
23068 rs = (ctx->opcode >> 21) & 0x1f;
23069 rt = (ctx->opcode >> 16) & 0x1f;
23070 rd = (ctx->opcode >> 11) & 0x1f;
23071 sa = (ctx->opcode >> 6) & 0x1f;
23073 op1 = MASK_SPECIAL(ctx->opcode);
23074 switch (op1) {
23075 case OPC_SLL: /* Shift with immediate */
23076 if (sa == 5 && rd == 0 &&
23077 rs == 0 && rt == 0) { /* PAUSE */
23078 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23079 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23080 generate_exception_end(ctx, EXCP_RI);
23081 break;
23084 /* Fallthrough */
23085 case OPC_SRA:
23086 gen_shift_imm(ctx, op1, rd, rt, sa);
23087 break;
23088 case OPC_SRL:
23089 switch ((ctx->opcode >> 21) & 0x1f) {
23090 case 1:
23091 /* rotr is decoded as srl on non-R2 CPUs */
23092 if (ctx->insn_flags & ISA_MIPS32R2) {
23093 op1 = OPC_ROTR;
23095 /* Fallthrough */
23096 case 0:
23097 gen_shift_imm(ctx, op1, rd, rt, sa);
23098 break;
23099 default:
23100 generate_exception_end(ctx, EXCP_RI);
23101 break;
23103 break;
23104 case OPC_ADD:
23105 case OPC_ADDU:
23106 case OPC_SUB:
23107 case OPC_SUBU:
23108 gen_arith(ctx, op1, rd, rs, rt);
23109 break;
23110 case OPC_SLLV: /* Shifts */
23111 case OPC_SRAV:
23112 gen_shift(ctx, op1, rd, rs, rt);
23113 break;
23114 case OPC_SRLV:
23115 switch ((ctx->opcode >> 6) & 0x1f) {
23116 case 1:
23117 /* rotrv is decoded as srlv on non-R2 CPUs */
23118 if (ctx->insn_flags & ISA_MIPS32R2) {
23119 op1 = OPC_ROTRV;
23121 /* Fallthrough */
23122 case 0:
23123 gen_shift(ctx, op1, rd, rs, rt);
23124 break;
23125 default:
23126 generate_exception_end(ctx, EXCP_RI);
23127 break;
23129 break;
23130 case OPC_SLT: /* Set on less than */
23131 case OPC_SLTU:
23132 gen_slt(ctx, op1, rd, rs, rt);
23133 break;
23134 case OPC_AND: /* Logic*/
23135 case OPC_OR:
23136 case OPC_NOR:
23137 case OPC_XOR:
23138 gen_logic(ctx, op1, rd, rs, rt);
23139 break;
23140 case OPC_JALR:
23141 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23142 break;
23143 case OPC_TGE: /* Traps */
23144 case OPC_TGEU:
23145 case OPC_TLT:
23146 case OPC_TLTU:
23147 case OPC_TEQ:
23148 case OPC_TNE:
23149 check_insn(ctx, ISA_MIPS2);
23150 gen_trap(ctx, op1, rs, rt, -1);
23151 break;
23152 case OPC_LSA: /* OPC_PMON */
23153 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23154 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23155 decode_opc_special_r6(env, ctx);
23156 } else {
23157 /* Pmon entry point, also R4010 selsl */
23158 #ifdef MIPS_STRICT_STANDARD
23159 MIPS_INVAL("PMON / selsl");
23160 generate_exception_end(ctx, EXCP_RI);
23161 #else
23162 gen_helper_0e0i(pmon, sa);
23163 #endif
23165 break;
23166 case OPC_SYSCALL:
23167 generate_exception_end(ctx, EXCP_SYSCALL);
23168 break;
23169 case OPC_BREAK:
23170 generate_exception_end(ctx, EXCP_BREAK);
23171 break;
23172 case OPC_SYNC:
23173 check_insn(ctx, ISA_MIPS2);
23174 gen_sync(extract32(ctx->opcode, 6, 5));
23175 break;
23177 #if defined(TARGET_MIPS64)
23178 /* MIPS64 specific opcodes */
23179 case OPC_DSLL:
23180 case OPC_DSRA:
23181 case OPC_DSLL32:
23182 case OPC_DSRA32:
23183 check_insn(ctx, ISA_MIPS3);
23184 check_mips_64(ctx);
23185 gen_shift_imm(ctx, op1, rd, rt, sa);
23186 break;
23187 case OPC_DSRL:
23188 switch ((ctx->opcode >> 21) & 0x1f) {
23189 case 1:
23190 /* drotr is decoded as dsrl on non-R2 CPUs */
23191 if (ctx->insn_flags & ISA_MIPS32R2) {
23192 op1 = OPC_DROTR;
23194 /* Fallthrough */
23195 case 0:
23196 check_insn(ctx, ISA_MIPS3);
23197 check_mips_64(ctx);
23198 gen_shift_imm(ctx, op1, rd, rt, sa);
23199 break;
23200 default:
23201 generate_exception_end(ctx, EXCP_RI);
23202 break;
23204 break;
23205 case OPC_DSRL32:
23206 switch ((ctx->opcode >> 21) & 0x1f) {
23207 case 1:
23208 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23209 if (ctx->insn_flags & ISA_MIPS32R2) {
23210 op1 = OPC_DROTR32;
23212 /* Fallthrough */
23213 case 0:
23214 check_insn(ctx, ISA_MIPS3);
23215 check_mips_64(ctx);
23216 gen_shift_imm(ctx, op1, rd, rt, sa);
23217 break;
23218 default:
23219 generate_exception_end(ctx, EXCP_RI);
23220 break;
23222 break;
23223 case OPC_DADD:
23224 case OPC_DADDU:
23225 case OPC_DSUB:
23226 case OPC_DSUBU:
23227 check_insn(ctx, ISA_MIPS3);
23228 check_mips_64(ctx);
23229 gen_arith(ctx, op1, rd, rs, rt);
23230 break;
23231 case OPC_DSLLV:
23232 case OPC_DSRAV:
23233 check_insn(ctx, ISA_MIPS3);
23234 check_mips_64(ctx);
23235 gen_shift(ctx, op1, rd, rs, rt);
23236 break;
23237 case OPC_DSRLV:
23238 switch ((ctx->opcode >> 6) & 0x1f) {
23239 case 1:
23240 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23241 if (ctx->insn_flags & ISA_MIPS32R2) {
23242 op1 = OPC_DROTRV;
23244 /* Fallthrough */
23245 case 0:
23246 check_insn(ctx, ISA_MIPS3);
23247 check_mips_64(ctx);
23248 gen_shift(ctx, op1, rd, rs, rt);
23249 break;
23250 default:
23251 generate_exception_end(ctx, EXCP_RI);
23252 break;
23254 break;
23255 case OPC_DLSA:
23256 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23257 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23258 decode_opc_special_r6(env, ctx);
23260 break;
23261 #endif
23262 default:
23263 if (ctx->insn_flags & ISA_MIPS32R6) {
23264 decode_opc_special_r6(env, ctx);
23265 } else {
23266 decode_opc_special_legacy(env, ctx);
23271 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23273 int rs, rt, rd;
23274 uint32_t op1;
23276 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23278 rs = (ctx->opcode >> 21) & 0x1f;
23279 rt = (ctx->opcode >> 16) & 0x1f;
23280 rd = (ctx->opcode >> 11) & 0x1f;
23282 op1 = MASK_SPECIAL2(ctx->opcode);
23283 switch (op1) {
23284 case OPC_MADD: /* Multiply and add/sub */
23285 case OPC_MADDU:
23286 case OPC_MSUB:
23287 case OPC_MSUBU:
23288 check_insn(ctx, ISA_MIPS32);
23289 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23290 break;
23291 case OPC_MUL:
23292 gen_arith(ctx, op1, rd, rs, rt);
23293 break;
23294 case OPC_DIV_G_2F:
23295 case OPC_DIVU_G_2F:
23296 case OPC_MULT_G_2F:
23297 case OPC_MULTU_G_2F:
23298 case OPC_MOD_G_2F:
23299 case OPC_MODU_G_2F:
23300 check_insn(ctx, INSN_LOONGSON2F);
23301 gen_loongson_integer(ctx, op1, rd, rs, rt);
23302 break;
23303 case OPC_CLO:
23304 case OPC_CLZ:
23305 check_insn(ctx, ISA_MIPS32);
23306 gen_cl(ctx, op1, rd, rs);
23307 break;
23308 case OPC_SDBBP:
23309 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23310 gen_helper_do_semihosting(cpu_env);
23311 } else {
23312 /* XXX: not clear which exception should be raised
23313 * when in debug mode...
23315 check_insn(ctx, ISA_MIPS32);
23316 generate_exception_end(ctx, EXCP_DBp);
23318 break;
23319 #if defined(TARGET_MIPS64)
23320 case OPC_DCLO:
23321 case OPC_DCLZ:
23322 check_insn(ctx, ISA_MIPS64);
23323 check_mips_64(ctx);
23324 gen_cl(ctx, op1, rd, rs);
23325 break;
23326 case OPC_DMULT_G_2F:
23327 case OPC_DMULTU_G_2F:
23328 case OPC_DDIV_G_2F:
23329 case OPC_DDIVU_G_2F:
23330 case OPC_DMOD_G_2F:
23331 case OPC_DMODU_G_2F:
23332 check_insn(ctx, INSN_LOONGSON2F);
23333 gen_loongson_integer(ctx, op1, rd, rs, rt);
23334 break;
23335 #endif
23336 default: /* Invalid */
23337 MIPS_INVAL("special2_legacy");
23338 generate_exception_end(ctx, EXCP_RI);
23339 break;
23343 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23345 int rs, rt, rd, sa;
23346 uint32_t op1, op2;
23347 int16_t imm;
23349 rs = (ctx->opcode >> 21) & 0x1f;
23350 rt = (ctx->opcode >> 16) & 0x1f;
23351 rd = (ctx->opcode >> 11) & 0x1f;
23352 sa = (ctx->opcode >> 6) & 0x1f;
23353 imm = (int16_t)ctx->opcode >> 7;
23355 op1 = MASK_SPECIAL3(ctx->opcode);
23356 switch (op1) {
23357 case R6_OPC_PREF:
23358 if (rt >= 24) {
23359 /* hint codes 24-31 are reserved and signal RI */
23360 generate_exception_end(ctx, EXCP_RI);
23362 /* Treat as NOP. */
23363 break;
23364 case R6_OPC_CACHE:
23365 check_cp0_enabled(ctx);
23366 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23367 gen_cache_operation(ctx, rt, rs, imm);
23369 break;
23370 case R6_OPC_SC:
23371 gen_st_cond(ctx, op1, rt, rs, imm);
23372 break;
23373 case R6_OPC_LL:
23374 gen_ld(ctx, op1, rt, rs, imm);
23375 break;
23376 case OPC_BSHFL:
23378 if (rd == 0) {
23379 /* Treat as NOP. */
23380 break;
23382 op2 = MASK_BSHFL(ctx->opcode);
23383 switch (op2) {
23384 case OPC_ALIGN:
23385 case OPC_ALIGN_END:
23386 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23387 break;
23388 case OPC_BITSWAP:
23389 gen_bitswap(ctx, op2, rd, rt);
23390 break;
23393 break;
23394 #if defined(TARGET_MIPS64)
23395 case R6_OPC_SCD:
23396 gen_st_cond(ctx, op1, rt, rs, imm);
23397 break;
23398 case R6_OPC_LLD:
23399 gen_ld(ctx, op1, rt, rs, imm);
23400 break;
23401 case OPC_DBSHFL:
23402 check_mips_64(ctx);
23404 if (rd == 0) {
23405 /* Treat as NOP. */
23406 break;
23408 op2 = MASK_DBSHFL(ctx->opcode);
23409 switch (op2) {
23410 case OPC_DALIGN:
23411 case OPC_DALIGN_END:
23412 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23413 break;
23414 case OPC_DBITSWAP:
23415 gen_bitswap(ctx, op2, rd, rt);
23416 break;
23420 break;
23421 #endif
23422 default: /* Invalid */
23423 MIPS_INVAL("special3_r6");
23424 generate_exception_end(ctx, EXCP_RI);
23425 break;
23429 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23431 int rs, rt, rd;
23432 uint32_t op1, op2;
23434 rs = (ctx->opcode >> 21) & 0x1f;
23435 rt = (ctx->opcode >> 16) & 0x1f;
23436 rd = (ctx->opcode >> 11) & 0x1f;
23438 op1 = MASK_SPECIAL3(ctx->opcode);
23439 switch (op1) {
23440 case OPC_DIV_G_2E:
23441 case OPC_DIVU_G_2E:
23442 case OPC_MOD_G_2E:
23443 case OPC_MODU_G_2E:
23444 case OPC_MULT_G_2E:
23445 case OPC_MULTU_G_2E:
23446 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23447 * the same mask and op1. */
23448 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
23449 op2 = MASK_ADDUH_QB(ctx->opcode);
23450 switch (op2) {
23451 case OPC_ADDUH_QB:
23452 case OPC_ADDUH_R_QB:
23453 case OPC_ADDQH_PH:
23454 case OPC_ADDQH_R_PH:
23455 case OPC_ADDQH_W:
23456 case OPC_ADDQH_R_W:
23457 case OPC_SUBUH_QB:
23458 case OPC_SUBUH_R_QB:
23459 case OPC_SUBQH_PH:
23460 case OPC_SUBQH_R_PH:
23461 case OPC_SUBQH_W:
23462 case OPC_SUBQH_R_W:
23463 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23464 break;
23465 case OPC_MUL_PH:
23466 case OPC_MUL_S_PH:
23467 case OPC_MULQ_S_W:
23468 case OPC_MULQ_RS_W:
23469 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23470 break;
23471 default:
23472 MIPS_INVAL("MASK ADDUH.QB");
23473 generate_exception_end(ctx, EXCP_RI);
23474 break;
23476 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23477 gen_loongson_integer(ctx, op1, rd, rs, rt);
23478 } else {
23479 generate_exception_end(ctx, EXCP_RI);
23481 break;
23482 case OPC_LX_DSP:
23483 op2 = MASK_LX(ctx->opcode);
23484 switch (op2) {
23485 #if defined(TARGET_MIPS64)
23486 case OPC_LDX:
23487 #endif
23488 case OPC_LBUX:
23489 case OPC_LHX:
23490 case OPC_LWX:
23491 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23492 break;
23493 default: /* Invalid */
23494 MIPS_INVAL("MASK LX");
23495 generate_exception_end(ctx, EXCP_RI);
23496 break;
23498 break;
23499 case OPC_ABSQ_S_PH_DSP:
23500 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23501 switch (op2) {
23502 case OPC_ABSQ_S_QB:
23503 case OPC_ABSQ_S_PH:
23504 case OPC_ABSQ_S_W:
23505 case OPC_PRECEQ_W_PHL:
23506 case OPC_PRECEQ_W_PHR:
23507 case OPC_PRECEQU_PH_QBL:
23508 case OPC_PRECEQU_PH_QBR:
23509 case OPC_PRECEQU_PH_QBLA:
23510 case OPC_PRECEQU_PH_QBRA:
23511 case OPC_PRECEU_PH_QBL:
23512 case OPC_PRECEU_PH_QBR:
23513 case OPC_PRECEU_PH_QBLA:
23514 case OPC_PRECEU_PH_QBRA:
23515 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23516 break;
23517 case OPC_BITREV:
23518 case OPC_REPL_QB:
23519 case OPC_REPLV_QB:
23520 case OPC_REPL_PH:
23521 case OPC_REPLV_PH:
23522 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23523 break;
23524 default:
23525 MIPS_INVAL("MASK ABSQ_S.PH");
23526 generate_exception_end(ctx, EXCP_RI);
23527 break;
23529 break;
23530 case OPC_ADDU_QB_DSP:
23531 op2 = MASK_ADDU_QB(ctx->opcode);
23532 switch (op2) {
23533 case OPC_ADDQ_PH:
23534 case OPC_ADDQ_S_PH:
23535 case OPC_ADDQ_S_W:
23536 case OPC_ADDU_QB:
23537 case OPC_ADDU_S_QB:
23538 case OPC_ADDU_PH:
23539 case OPC_ADDU_S_PH:
23540 case OPC_SUBQ_PH:
23541 case OPC_SUBQ_S_PH:
23542 case OPC_SUBQ_S_W:
23543 case OPC_SUBU_QB:
23544 case OPC_SUBU_S_QB:
23545 case OPC_SUBU_PH:
23546 case OPC_SUBU_S_PH:
23547 case OPC_ADDSC:
23548 case OPC_ADDWC:
23549 case OPC_MODSUB:
23550 case OPC_RADDU_W_QB:
23551 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23552 break;
23553 case OPC_MULEU_S_PH_QBL:
23554 case OPC_MULEU_S_PH_QBR:
23555 case OPC_MULQ_RS_PH:
23556 case OPC_MULEQ_S_W_PHL:
23557 case OPC_MULEQ_S_W_PHR:
23558 case OPC_MULQ_S_PH:
23559 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23560 break;
23561 default: /* Invalid */
23562 MIPS_INVAL("MASK ADDU.QB");
23563 generate_exception_end(ctx, EXCP_RI);
23564 break;
23567 break;
23568 case OPC_CMPU_EQ_QB_DSP:
23569 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
23570 switch (op2) {
23571 case OPC_PRECR_SRA_PH_W:
23572 case OPC_PRECR_SRA_R_PH_W:
23573 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
23574 break;
23575 case OPC_PRECR_QB_PH:
23576 case OPC_PRECRQ_QB_PH:
23577 case OPC_PRECRQ_PH_W:
23578 case OPC_PRECRQ_RS_PH_W:
23579 case OPC_PRECRQU_S_QB_PH:
23580 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23581 break;
23582 case OPC_CMPU_EQ_QB:
23583 case OPC_CMPU_LT_QB:
23584 case OPC_CMPU_LE_QB:
23585 case OPC_CMP_EQ_PH:
23586 case OPC_CMP_LT_PH:
23587 case OPC_CMP_LE_PH:
23588 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
23589 break;
23590 case OPC_CMPGU_EQ_QB:
23591 case OPC_CMPGU_LT_QB:
23592 case OPC_CMPGU_LE_QB:
23593 case OPC_CMPGDU_EQ_QB:
23594 case OPC_CMPGDU_LT_QB:
23595 case OPC_CMPGDU_LE_QB:
23596 case OPC_PICK_QB:
23597 case OPC_PICK_PH:
23598 case OPC_PACKRL_PH:
23599 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
23600 break;
23601 default: /* Invalid */
23602 MIPS_INVAL("MASK CMPU.EQ.QB");
23603 generate_exception_end(ctx, EXCP_RI);
23604 break;
23606 break;
23607 case OPC_SHLL_QB_DSP:
23608 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23609 break;
23610 case OPC_DPA_W_PH_DSP:
23611 op2 = MASK_DPA_W_PH(ctx->opcode);
23612 switch (op2) {
23613 case OPC_DPAU_H_QBL:
23614 case OPC_DPAU_H_QBR:
23615 case OPC_DPSU_H_QBL:
23616 case OPC_DPSU_H_QBR:
23617 case OPC_DPA_W_PH:
23618 case OPC_DPAX_W_PH:
23619 case OPC_DPAQ_S_W_PH:
23620 case OPC_DPAQX_S_W_PH:
23621 case OPC_DPAQX_SA_W_PH:
23622 case OPC_DPS_W_PH:
23623 case OPC_DPSX_W_PH:
23624 case OPC_DPSQ_S_W_PH:
23625 case OPC_DPSQX_S_W_PH:
23626 case OPC_DPSQX_SA_W_PH:
23627 case OPC_MULSAQ_S_W_PH:
23628 case OPC_DPAQ_SA_L_W:
23629 case OPC_DPSQ_SA_L_W:
23630 case OPC_MAQ_S_W_PHL:
23631 case OPC_MAQ_S_W_PHR:
23632 case OPC_MAQ_SA_W_PHL:
23633 case OPC_MAQ_SA_W_PHR:
23634 case OPC_MULSA_W_PH:
23635 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23636 break;
23637 default: /* Invalid */
23638 MIPS_INVAL("MASK DPAW.PH");
23639 generate_exception_end(ctx, EXCP_RI);
23640 break;
23642 break;
23643 case OPC_INSV_DSP:
23644 op2 = MASK_INSV(ctx->opcode);
23645 switch (op2) {
23646 case OPC_INSV:
23647 check_dsp(ctx);
23649 TCGv t0, t1;
23651 if (rt == 0) {
23652 break;
23655 t0 = tcg_temp_new();
23656 t1 = tcg_temp_new();
23658 gen_load_gpr(t0, rt);
23659 gen_load_gpr(t1, rs);
23661 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
23663 tcg_temp_free(t0);
23664 tcg_temp_free(t1);
23665 break;
23667 default: /* Invalid */
23668 MIPS_INVAL("MASK INSV");
23669 generate_exception_end(ctx, EXCP_RI);
23670 break;
23672 break;
23673 case OPC_APPEND_DSP:
23674 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23675 break;
23676 case OPC_EXTR_W_DSP:
23677 op2 = MASK_EXTR_W(ctx->opcode);
23678 switch (op2) {
23679 case OPC_EXTR_W:
23680 case OPC_EXTR_R_W:
23681 case OPC_EXTR_RS_W:
23682 case OPC_EXTR_S_H:
23683 case OPC_EXTRV_S_H:
23684 case OPC_EXTRV_W:
23685 case OPC_EXTRV_R_W:
23686 case OPC_EXTRV_RS_W:
23687 case OPC_EXTP:
23688 case OPC_EXTPV:
23689 case OPC_EXTPDP:
23690 case OPC_EXTPDPV:
23691 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23692 break;
23693 case OPC_RDDSP:
23694 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
23695 break;
23696 case OPC_SHILO:
23697 case OPC_SHILOV:
23698 case OPC_MTHLIP:
23699 case OPC_WRDSP:
23700 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23701 break;
23702 default: /* Invalid */
23703 MIPS_INVAL("MASK EXTR.W");
23704 generate_exception_end(ctx, EXCP_RI);
23705 break;
23707 break;
23708 #if defined(TARGET_MIPS64)
23709 case OPC_DDIV_G_2E:
23710 case OPC_DDIVU_G_2E:
23711 case OPC_DMULT_G_2E:
23712 case OPC_DMULTU_G_2E:
23713 case OPC_DMOD_G_2E:
23714 case OPC_DMODU_G_2E:
23715 check_insn(ctx, INSN_LOONGSON2E);
23716 gen_loongson_integer(ctx, op1, rd, rs, rt);
23717 break;
23718 case OPC_ABSQ_S_QH_DSP:
23719 op2 = MASK_ABSQ_S_QH(ctx->opcode);
23720 switch (op2) {
23721 case OPC_PRECEQ_L_PWL:
23722 case OPC_PRECEQ_L_PWR:
23723 case OPC_PRECEQ_PW_QHL:
23724 case OPC_PRECEQ_PW_QHR:
23725 case OPC_PRECEQ_PW_QHLA:
23726 case OPC_PRECEQ_PW_QHRA:
23727 case OPC_PRECEQU_QH_OBL:
23728 case OPC_PRECEQU_QH_OBR:
23729 case OPC_PRECEQU_QH_OBLA:
23730 case OPC_PRECEQU_QH_OBRA:
23731 case OPC_PRECEU_QH_OBL:
23732 case OPC_PRECEU_QH_OBR:
23733 case OPC_PRECEU_QH_OBLA:
23734 case OPC_PRECEU_QH_OBRA:
23735 case OPC_ABSQ_S_OB:
23736 case OPC_ABSQ_S_PW:
23737 case OPC_ABSQ_S_QH:
23738 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23739 break;
23740 case OPC_REPL_OB:
23741 case OPC_REPL_PW:
23742 case OPC_REPL_QH:
23743 case OPC_REPLV_OB:
23744 case OPC_REPLV_PW:
23745 case OPC_REPLV_QH:
23746 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23747 break;
23748 default: /* Invalid */
23749 MIPS_INVAL("MASK ABSQ_S.QH");
23750 generate_exception_end(ctx, EXCP_RI);
23751 break;
23753 break;
23754 case OPC_ADDU_OB_DSP:
23755 op2 = MASK_ADDU_OB(ctx->opcode);
23756 switch (op2) {
23757 case OPC_RADDU_L_OB:
23758 case OPC_SUBQ_PW:
23759 case OPC_SUBQ_S_PW:
23760 case OPC_SUBQ_QH:
23761 case OPC_SUBQ_S_QH:
23762 case OPC_SUBU_OB:
23763 case OPC_SUBU_S_OB:
23764 case OPC_SUBU_QH:
23765 case OPC_SUBU_S_QH:
23766 case OPC_SUBUH_OB:
23767 case OPC_SUBUH_R_OB:
23768 case OPC_ADDQ_PW:
23769 case OPC_ADDQ_S_PW:
23770 case OPC_ADDQ_QH:
23771 case OPC_ADDQ_S_QH:
23772 case OPC_ADDU_OB:
23773 case OPC_ADDU_S_OB:
23774 case OPC_ADDU_QH:
23775 case OPC_ADDU_S_QH:
23776 case OPC_ADDUH_OB:
23777 case OPC_ADDUH_R_OB:
23778 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23779 break;
23780 case OPC_MULEQ_S_PW_QHL:
23781 case OPC_MULEQ_S_PW_QHR:
23782 case OPC_MULEU_S_QH_OBL:
23783 case OPC_MULEU_S_QH_OBR:
23784 case OPC_MULQ_RS_QH:
23785 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23786 break;
23787 default: /* Invalid */
23788 MIPS_INVAL("MASK ADDU.OB");
23789 generate_exception_end(ctx, EXCP_RI);
23790 break;
23792 break;
23793 case OPC_CMPU_EQ_OB_DSP:
23794 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
23795 switch (op2) {
23796 case OPC_PRECR_SRA_QH_PW:
23797 case OPC_PRECR_SRA_R_QH_PW:
23798 /* Return value is rt. */
23799 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
23800 break;
23801 case OPC_PRECR_OB_QH:
23802 case OPC_PRECRQ_OB_QH:
23803 case OPC_PRECRQ_PW_L:
23804 case OPC_PRECRQ_QH_PW:
23805 case OPC_PRECRQ_RS_QH_PW:
23806 case OPC_PRECRQU_S_OB_QH:
23807 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23808 break;
23809 case OPC_CMPU_EQ_OB:
23810 case OPC_CMPU_LT_OB:
23811 case OPC_CMPU_LE_OB:
23812 case OPC_CMP_EQ_QH:
23813 case OPC_CMP_LT_QH:
23814 case OPC_CMP_LE_QH:
23815 case OPC_CMP_EQ_PW:
23816 case OPC_CMP_LT_PW:
23817 case OPC_CMP_LE_PW:
23818 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
23819 break;
23820 case OPC_CMPGDU_EQ_OB:
23821 case OPC_CMPGDU_LT_OB:
23822 case OPC_CMPGDU_LE_OB:
23823 case OPC_CMPGU_EQ_OB:
23824 case OPC_CMPGU_LT_OB:
23825 case OPC_CMPGU_LE_OB:
23826 case OPC_PACKRL_PW:
23827 case OPC_PICK_OB:
23828 case OPC_PICK_PW:
23829 case OPC_PICK_QH:
23830 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
23831 break;
23832 default: /* Invalid */
23833 MIPS_INVAL("MASK CMPU_EQ.OB");
23834 generate_exception_end(ctx, EXCP_RI);
23835 break;
23837 break;
23838 case OPC_DAPPEND_DSP:
23839 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23840 break;
23841 case OPC_DEXTR_W_DSP:
23842 op2 = MASK_DEXTR_W(ctx->opcode);
23843 switch (op2) {
23844 case OPC_DEXTP:
23845 case OPC_DEXTPDP:
23846 case OPC_DEXTPDPV:
23847 case OPC_DEXTPV:
23848 case OPC_DEXTR_L:
23849 case OPC_DEXTR_R_L:
23850 case OPC_DEXTR_RS_L:
23851 case OPC_DEXTR_W:
23852 case OPC_DEXTR_R_W:
23853 case OPC_DEXTR_RS_W:
23854 case OPC_DEXTR_S_H:
23855 case OPC_DEXTRV_L:
23856 case OPC_DEXTRV_R_L:
23857 case OPC_DEXTRV_RS_L:
23858 case OPC_DEXTRV_S_H:
23859 case OPC_DEXTRV_W:
23860 case OPC_DEXTRV_R_W:
23861 case OPC_DEXTRV_RS_W:
23862 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23863 break;
23864 case OPC_DMTHLIP:
23865 case OPC_DSHILO:
23866 case OPC_DSHILOV:
23867 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23868 break;
23869 default: /* Invalid */
23870 MIPS_INVAL("MASK EXTR.W");
23871 generate_exception_end(ctx, EXCP_RI);
23872 break;
23874 break;
23875 case OPC_DPAQ_W_QH_DSP:
23876 op2 = MASK_DPAQ_W_QH(ctx->opcode);
23877 switch (op2) {
23878 case OPC_DPAU_H_OBL:
23879 case OPC_DPAU_H_OBR:
23880 case OPC_DPSU_H_OBL:
23881 case OPC_DPSU_H_OBR:
23882 case OPC_DPA_W_QH:
23883 case OPC_DPAQ_S_W_QH:
23884 case OPC_DPS_W_QH:
23885 case OPC_DPSQ_S_W_QH:
23886 case OPC_MULSAQ_S_W_QH:
23887 case OPC_DPAQ_SA_L_PW:
23888 case OPC_DPSQ_SA_L_PW:
23889 case OPC_MULSAQ_S_L_PW:
23890 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23891 break;
23892 case OPC_MAQ_S_W_QHLL:
23893 case OPC_MAQ_S_W_QHLR:
23894 case OPC_MAQ_S_W_QHRL:
23895 case OPC_MAQ_S_W_QHRR:
23896 case OPC_MAQ_SA_W_QHLL:
23897 case OPC_MAQ_SA_W_QHLR:
23898 case OPC_MAQ_SA_W_QHRL:
23899 case OPC_MAQ_SA_W_QHRR:
23900 case OPC_MAQ_S_L_PWL:
23901 case OPC_MAQ_S_L_PWR:
23902 case OPC_DMADD:
23903 case OPC_DMADDU:
23904 case OPC_DMSUB:
23905 case OPC_DMSUBU:
23906 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23907 break;
23908 default: /* Invalid */
23909 MIPS_INVAL("MASK DPAQ.W.QH");
23910 generate_exception_end(ctx, EXCP_RI);
23911 break;
23913 break;
23914 case OPC_DINSV_DSP:
23915 op2 = MASK_INSV(ctx->opcode);
23916 switch (op2) {
23917 case OPC_DINSV:
23919 TCGv t0, t1;
23921 if (rt == 0) {
23922 break;
23924 check_dsp(ctx);
23926 t0 = tcg_temp_new();
23927 t1 = tcg_temp_new();
23929 gen_load_gpr(t0, rt);
23930 gen_load_gpr(t1, rs);
23932 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
23934 tcg_temp_free(t0);
23935 tcg_temp_free(t1);
23936 break;
23938 default: /* Invalid */
23939 MIPS_INVAL("MASK DINSV");
23940 generate_exception_end(ctx, EXCP_RI);
23941 break;
23943 break;
23944 case OPC_SHLL_OB_DSP:
23945 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23946 break;
23947 #endif
23948 default: /* Invalid */
23949 MIPS_INVAL("special3_legacy");
23950 generate_exception_end(ctx, EXCP_RI);
23951 break;
23955 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
23957 int rs, rt, rd, sa;
23958 uint32_t op1, op2;
23959 int16_t imm;
23961 rs = (ctx->opcode >> 21) & 0x1f;
23962 rt = (ctx->opcode >> 16) & 0x1f;
23963 rd = (ctx->opcode >> 11) & 0x1f;
23964 sa = (ctx->opcode >> 6) & 0x1f;
23965 imm = sextract32(ctx->opcode, 7, 9);
23967 op1 = MASK_SPECIAL3(ctx->opcode);
23970 * EVA loads and stores overlap Loongson 2E instructions decoded by
23971 * decode_opc_special3_legacy(), so be careful to allow their decoding when
23972 * EVA is absent.
23974 if (ctx->eva) {
23975 switch (op1) {
23976 case OPC_LWLE:
23977 case OPC_LWRE:
23978 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23979 /* fall through */
23980 case OPC_LBUE:
23981 case OPC_LHUE:
23982 case OPC_LBE:
23983 case OPC_LHE:
23984 case OPC_LLE:
23985 case OPC_LWE:
23986 check_cp0_enabled(ctx);
23987 gen_ld(ctx, op1, rt, rs, imm);
23988 return;
23989 case OPC_SWLE:
23990 case OPC_SWRE:
23991 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23992 /* fall through */
23993 case OPC_SBE:
23994 case OPC_SHE:
23995 case OPC_SWE:
23996 check_cp0_enabled(ctx);
23997 gen_st(ctx, op1, rt, rs, imm);
23998 return;
23999 case OPC_SCE:
24000 check_cp0_enabled(ctx);
24001 gen_st_cond(ctx, op1, rt, rs, imm);
24002 return;
24003 case OPC_CACHEE:
24004 check_cp0_enabled(ctx);
24005 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24006 gen_cache_operation(ctx, rt, rs, imm);
24008 /* Treat as NOP. */
24009 return;
24010 case OPC_PREFE:
24011 check_cp0_enabled(ctx);
24012 /* Treat as NOP. */
24013 return;
24017 switch (op1) {
24018 case OPC_EXT:
24019 case OPC_INS:
24020 check_insn(ctx, ISA_MIPS32R2);
24021 gen_bitops(ctx, op1, rt, rs, sa, rd);
24022 break;
24023 case OPC_BSHFL:
24024 op2 = MASK_BSHFL(ctx->opcode);
24025 switch (op2) {
24026 case OPC_ALIGN:
24027 case OPC_ALIGN_END:
24028 case OPC_BITSWAP:
24029 check_insn(ctx, ISA_MIPS32R6);
24030 decode_opc_special3_r6(env, ctx);
24031 break;
24032 default:
24033 check_insn(ctx, ISA_MIPS32R2);
24034 gen_bshfl(ctx, op2, rt, rd);
24035 break;
24037 break;
24038 #if defined(TARGET_MIPS64)
24039 case OPC_DEXTM:
24040 case OPC_DEXTU:
24041 case OPC_DEXT:
24042 case OPC_DINSM:
24043 case OPC_DINSU:
24044 case OPC_DINS:
24045 check_insn(ctx, ISA_MIPS64R2);
24046 check_mips_64(ctx);
24047 gen_bitops(ctx, op1, rt, rs, sa, rd);
24048 break;
24049 case OPC_DBSHFL:
24050 op2 = MASK_DBSHFL(ctx->opcode);
24051 switch (op2) {
24052 case OPC_DALIGN:
24053 case OPC_DALIGN_END:
24054 case OPC_DBITSWAP:
24055 check_insn(ctx, ISA_MIPS32R6);
24056 decode_opc_special3_r6(env, ctx);
24057 break;
24058 default:
24059 check_insn(ctx, ISA_MIPS64R2);
24060 check_mips_64(ctx);
24061 op2 = MASK_DBSHFL(ctx->opcode);
24062 gen_bshfl(ctx, op2, rt, rd);
24063 break;
24065 break;
24066 #endif
24067 case OPC_RDHWR:
24068 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24069 break;
24070 case OPC_FORK:
24071 check_mt(ctx);
24073 TCGv t0 = tcg_temp_new();
24074 TCGv t1 = tcg_temp_new();
24076 gen_load_gpr(t0, rt);
24077 gen_load_gpr(t1, rs);
24078 gen_helper_fork(t0, t1);
24079 tcg_temp_free(t0);
24080 tcg_temp_free(t1);
24082 break;
24083 case OPC_YIELD:
24084 check_mt(ctx);
24086 TCGv t0 = tcg_temp_new();
24088 gen_load_gpr(t0, rs);
24089 gen_helper_yield(t0, cpu_env, t0);
24090 gen_store_gpr(t0, rd);
24091 tcg_temp_free(t0);
24093 break;
24094 default:
24095 if (ctx->insn_flags & ISA_MIPS32R6) {
24096 decode_opc_special3_r6(env, ctx);
24097 } else {
24098 decode_opc_special3_legacy(env, ctx);
24103 /* MIPS SIMD Architecture (MSA) */
24104 static inline int check_msa_access(DisasContext *ctx)
24106 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
24107 !(ctx->hflags & MIPS_HFLAG_F64))) {
24108 generate_exception_end(ctx, EXCP_RI);
24109 return 0;
24112 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
24113 if (ctx->insn_flags & ASE_MSA) {
24114 generate_exception_end(ctx, EXCP_MSADIS);
24115 return 0;
24116 } else {
24117 generate_exception_end(ctx, EXCP_RI);
24118 return 0;
24121 return 1;
24124 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
24126 /* generates tcg ops to check if any element is 0 */
24127 /* Note this function only works with MSA_WRLEN = 128 */
24128 uint64_t eval_zero_or_big = 0;
24129 uint64_t eval_big = 0;
24130 TCGv_i64 t0 = tcg_temp_new_i64();
24131 TCGv_i64 t1 = tcg_temp_new_i64();
24132 switch (df) {
24133 case DF_BYTE:
24134 eval_zero_or_big = 0x0101010101010101ULL;
24135 eval_big = 0x8080808080808080ULL;
24136 break;
24137 case DF_HALF:
24138 eval_zero_or_big = 0x0001000100010001ULL;
24139 eval_big = 0x8000800080008000ULL;
24140 break;
24141 case DF_WORD:
24142 eval_zero_or_big = 0x0000000100000001ULL;
24143 eval_big = 0x8000000080000000ULL;
24144 break;
24145 case DF_DOUBLE:
24146 eval_zero_or_big = 0x0000000000000001ULL;
24147 eval_big = 0x8000000000000000ULL;
24148 break;
24150 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
24151 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
24152 tcg_gen_andi_i64(t0, t0, eval_big);
24153 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
24154 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
24155 tcg_gen_andi_i64(t1, t1, eval_big);
24156 tcg_gen_or_i64(t0, t0, t1);
24157 /* if all bits are zero then all elements are not zero */
24158 /* if some bit is non-zero then some element is zero */
24159 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
24160 tcg_gen_trunc_i64_tl(tresult, t0);
24161 tcg_temp_free_i64(t0);
24162 tcg_temp_free_i64(t1);
24165 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
24167 uint8_t df = (ctx->opcode >> 21) & 0x3;
24168 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24169 int64_t s16 = (int16_t)ctx->opcode;
24171 check_msa_access(ctx);
24173 if (ctx->hflags & MIPS_HFLAG_BMASK) {
24174 generate_exception_end(ctx, EXCP_RI);
24175 return;
24177 switch (op1) {
24178 case OPC_BZ_V:
24179 case OPC_BNZ_V:
24181 TCGv_i64 t0 = tcg_temp_new_i64();
24182 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
24183 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
24184 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
24185 tcg_gen_trunc_i64_tl(bcond, t0);
24186 tcg_temp_free_i64(t0);
24188 break;
24189 case OPC_BZ_B:
24190 case OPC_BZ_H:
24191 case OPC_BZ_W:
24192 case OPC_BZ_D:
24193 gen_check_zero_element(bcond, df, wt);
24194 break;
24195 case OPC_BNZ_B:
24196 case OPC_BNZ_H:
24197 case OPC_BNZ_W:
24198 case OPC_BNZ_D:
24199 gen_check_zero_element(bcond, df, wt);
24200 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
24201 break;
24204 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
24206 ctx->hflags |= MIPS_HFLAG_BC;
24207 ctx->hflags |= MIPS_HFLAG_BDS32;
24210 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
24212 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
24213 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
24214 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24215 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24217 TCGv_i32 twd = tcg_const_i32(wd);
24218 TCGv_i32 tws = tcg_const_i32(ws);
24219 TCGv_i32 ti8 = tcg_const_i32(i8);
24221 switch (MASK_MSA_I8(ctx->opcode)) {
24222 case OPC_ANDI_B:
24223 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
24224 break;
24225 case OPC_ORI_B:
24226 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
24227 break;
24228 case OPC_NORI_B:
24229 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
24230 break;
24231 case OPC_XORI_B:
24232 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
24233 break;
24234 case OPC_BMNZI_B:
24235 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
24236 break;
24237 case OPC_BMZI_B:
24238 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
24239 break;
24240 case OPC_BSELI_B:
24241 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
24242 break;
24243 case OPC_SHF_B:
24244 case OPC_SHF_H:
24245 case OPC_SHF_W:
24247 uint8_t df = (ctx->opcode >> 24) & 0x3;
24248 if (df == DF_DOUBLE) {
24249 generate_exception_end(ctx, EXCP_RI);
24250 } else {
24251 TCGv_i32 tdf = tcg_const_i32(df);
24252 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
24253 tcg_temp_free_i32(tdf);
24256 break;
24257 default:
24258 MIPS_INVAL("MSA instruction");
24259 generate_exception_end(ctx, EXCP_RI);
24260 break;
24263 tcg_temp_free_i32(twd);
24264 tcg_temp_free_i32(tws);
24265 tcg_temp_free_i32(ti8);
24268 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
24270 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24271 uint8_t df = (ctx->opcode >> 21) & 0x3;
24272 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
24273 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
24274 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24275 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24277 TCGv_i32 tdf = tcg_const_i32(df);
24278 TCGv_i32 twd = tcg_const_i32(wd);
24279 TCGv_i32 tws = tcg_const_i32(ws);
24280 TCGv_i32 timm = tcg_temp_new_i32();
24281 tcg_gen_movi_i32(timm, u5);
24283 switch (MASK_MSA_I5(ctx->opcode)) {
24284 case OPC_ADDVI_df:
24285 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
24286 break;
24287 case OPC_SUBVI_df:
24288 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
24289 break;
24290 case OPC_MAXI_S_df:
24291 tcg_gen_movi_i32(timm, s5);
24292 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
24293 break;
24294 case OPC_MAXI_U_df:
24295 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
24296 break;
24297 case OPC_MINI_S_df:
24298 tcg_gen_movi_i32(timm, s5);
24299 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
24300 break;
24301 case OPC_MINI_U_df:
24302 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
24303 break;
24304 case OPC_CEQI_df:
24305 tcg_gen_movi_i32(timm, s5);
24306 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
24307 break;
24308 case OPC_CLTI_S_df:
24309 tcg_gen_movi_i32(timm, s5);
24310 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
24311 break;
24312 case OPC_CLTI_U_df:
24313 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
24314 break;
24315 case OPC_CLEI_S_df:
24316 tcg_gen_movi_i32(timm, s5);
24317 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
24318 break;
24319 case OPC_CLEI_U_df:
24320 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
24321 break;
24322 case OPC_LDI_df:
24324 int32_t s10 = sextract32(ctx->opcode, 11, 10);
24325 tcg_gen_movi_i32(timm, s10);
24326 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
24328 break;
24329 default:
24330 MIPS_INVAL("MSA instruction");
24331 generate_exception_end(ctx, EXCP_RI);
24332 break;
24335 tcg_temp_free_i32(tdf);
24336 tcg_temp_free_i32(twd);
24337 tcg_temp_free_i32(tws);
24338 tcg_temp_free_i32(timm);
24341 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
24343 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24344 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
24345 uint32_t df = 0, m = 0;
24346 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24347 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24349 TCGv_i32 tdf;
24350 TCGv_i32 tm;
24351 TCGv_i32 twd;
24352 TCGv_i32 tws;
24354 if ((dfm & 0x40) == 0x00) {
24355 m = dfm & 0x3f;
24356 df = DF_DOUBLE;
24357 } else if ((dfm & 0x60) == 0x40) {
24358 m = dfm & 0x1f;
24359 df = DF_WORD;
24360 } else if ((dfm & 0x70) == 0x60) {
24361 m = dfm & 0x0f;
24362 df = DF_HALF;
24363 } else if ((dfm & 0x78) == 0x70) {
24364 m = dfm & 0x7;
24365 df = DF_BYTE;
24366 } else {
24367 generate_exception_end(ctx, EXCP_RI);
24368 return;
24371 tdf = tcg_const_i32(df);
24372 tm = tcg_const_i32(m);
24373 twd = tcg_const_i32(wd);
24374 tws = tcg_const_i32(ws);
24376 switch (MASK_MSA_BIT(ctx->opcode)) {
24377 case OPC_SLLI_df:
24378 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
24379 break;
24380 case OPC_SRAI_df:
24381 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
24382 break;
24383 case OPC_SRLI_df:
24384 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
24385 break;
24386 case OPC_BCLRI_df:
24387 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
24388 break;
24389 case OPC_BSETI_df:
24390 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
24391 break;
24392 case OPC_BNEGI_df:
24393 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
24394 break;
24395 case OPC_BINSLI_df:
24396 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
24397 break;
24398 case OPC_BINSRI_df:
24399 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
24400 break;
24401 case OPC_SAT_S_df:
24402 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
24403 break;
24404 case OPC_SAT_U_df:
24405 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
24406 break;
24407 case OPC_SRARI_df:
24408 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
24409 break;
24410 case OPC_SRLRI_df:
24411 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
24412 break;
24413 default:
24414 MIPS_INVAL("MSA instruction");
24415 generate_exception_end(ctx, EXCP_RI);
24416 break;
24419 tcg_temp_free_i32(tdf);
24420 tcg_temp_free_i32(tm);
24421 tcg_temp_free_i32(twd);
24422 tcg_temp_free_i32(tws);
24425 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
24427 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24428 uint8_t df = (ctx->opcode >> 21) & 0x3;
24429 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24430 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24431 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24433 TCGv_i32 tdf = tcg_const_i32(df);
24434 TCGv_i32 twd = tcg_const_i32(wd);
24435 TCGv_i32 tws = tcg_const_i32(ws);
24436 TCGv_i32 twt = tcg_const_i32(wt);
24438 switch (MASK_MSA_3R(ctx->opcode)) {
24439 case OPC_SLL_df:
24440 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
24441 break;
24442 case OPC_ADDV_df:
24443 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
24444 break;
24445 case OPC_CEQ_df:
24446 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
24447 break;
24448 case OPC_ADD_A_df:
24449 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
24450 break;
24451 case OPC_SUBS_S_df:
24452 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
24453 break;
24454 case OPC_MULV_df:
24455 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
24456 break;
24457 case OPC_SLD_df:
24458 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
24459 break;
24460 case OPC_VSHF_df:
24461 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
24462 break;
24463 case OPC_SRA_df:
24464 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
24465 break;
24466 case OPC_SUBV_df:
24467 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
24468 break;
24469 case OPC_ADDS_A_df:
24470 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
24471 break;
24472 case OPC_SUBS_U_df:
24473 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
24474 break;
24475 case OPC_MADDV_df:
24476 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
24477 break;
24478 case OPC_SPLAT_df:
24479 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
24480 break;
24481 case OPC_SRAR_df:
24482 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
24483 break;
24484 case OPC_SRL_df:
24485 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
24486 break;
24487 case OPC_MAX_S_df:
24488 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
24489 break;
24490 case OPC_CLT_S_df:
24491 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
24492 break;
24493 case OPC_ADDS_S_df:
24494 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
24495 break;
24496 case OPC_SUBSUS_U_df:
24497 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
24498 break;
24499 case OPC_MSUBV_df:
24500 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
24501 break;
24502 case OPC_PCKEV_df:
24503 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
24504 break;
24505 case OPC_SRLR_df:
24506 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
24507 break;
24508 case OPC_BCLR_df:
24509 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
24510 break;
24511 case OPC_MAX_U_df:
24512 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
24513 break;
24514 case OPC_CLT_U_df:
24515 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
24516 break;
24517 case OPC_ADDS_U_df:
24518 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
24519 break;
24520 case OPC_SUBSUU_S_df:
24521 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
24522 break;
24523 case OPC_PCKOD_df:
24524 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
24525 break;
24526 case OPC_BSET_df:
24527 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
24528 break;
24529 case OPC_MIN_S_df:
24530 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
24531 break;
24532 case OPC_CLE_S_df:
24533 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
24534 break;
24535 case OPC_AVE_S_df:
24536 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
24537 break;
24538 case OPC_ASUB_S_df:
24539 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
24540 break;
24541 case OPC_DIV_S_df:
24542 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
24543 break;
24544 case OPC_ILVL_df:
24545 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
24546 break;
24547 case OPC_BNEG_df:
24548 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
24549 break;
24550 case OPC_MIN_U_df:
24551 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
24552 break;
24553 case OPC_CLE_U_df:
24554 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
24555 break;
24556 case OPC_AVE_U_df:
24557 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
24558 break;
24559 case OPC_ASUB_U_df:
24560 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
24561 break;
24562 case OPC_DIV_U_df:
24563 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
24564 break;
24565 case OPC_ILVR_df:
24566 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
24567 break;
24568 case OPC_BINSL_df:
24569 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
24570 break;
24571 case OPC_MAX_A_df:
24572 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
24573 break;
24574 case OPC_AVER_S_df:
24575 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
24576 break;
24577 case OPC_MOD_S_df:
24578 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
24579 break;
24580 case OPC_ILVEV_df:
24581 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
24582 break;
24583 case OPC_BINSR_df:
24584 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
24585 break;
24586 case OPC_MIN_A_df:
24587 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
24588 break;
24589 case OPC_AVER_U_df:
24590 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
24591 break;
24592 case OPC_MOD_U_df:
24593 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
24594 break;
24595 case OPC_ILVOD_df:
24596 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
24597 break;
24599 case OPC_DOTP_S_df:
24600 case OPC_DOTP_U_df:
24601 case OPC_DPADD_S_df:
24602 case OPC_DPADD_U_df:
24603 case OPC_DPSUB_S_df:
24604 case OPC_HADD_S_df:
24605 case OPC_DPSUB_U_df:
24606 case OPC_HADD_U_df:
24607 case OPC_HSUB_S_df:
24608 case OPC_HSUB_U_df:
24609 if (df == DF_BYTE) {
24610 generate_exception_end(ctx, EXCP_RI);
24611 break;
24613 switch (MASK_MSA_3R(ctx->opcode)) {
24614 case OPC_DOTP_S_df:
24615 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
24616 break;
24617 case OPC_DOTP_U_df:
24618 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
24619 break;
24620 case OPC_DPADD_S_df:
24621 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
24622 break;
24623 case OPC_DPADD_U_df:
24624 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
24625 break;
24626 case OPC_DPSUB_S_df:
24627 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
24628 break;
24629 case OPC_HADD_S_df:
24630 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
24631 break;
24632 case OPC_DPSUB_U_df:
24633 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
24634 break;
24635 case OPC_HADD_U_df:
24636 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
24637 break;
24638 case OPC_HSUB_S_df:
24639 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
24640 break;
24641 case OPC_HSUB_U_df:
24642 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
24643 break;
24645 break;
24646 default:
24647 MIPS_INVAL("MSA instruction");
24648 generate_exception_end(ctx, EXCP_RI);
24649 break;
24651 tcg_temp_free_i32(twd);
24652 tcg_temp_free_i32(tws);
24653 tcg_temp_free_i32(twt);
24654 tcg_temp_free_i32(tdf);
24657 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
24659 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
24660 uint8_t source = (ctx->opcode >> 11) & 0x1f;
24661 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
24662 TCGv telm = tcg_temp_new();
24663 TCGv_i32 tsr = tcg_const_i32(source);
24664 TCGv_i32 tdt = tcg_const_i32(dest);
24666 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
24667 case OPC_CTCMSA:
24668 gen_load_gpr(telm, source);
24669 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
24670 break;
24671 case OPC_CFCMSA:
24672 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
24673 gen_store_gpr(telm, dest);
24674 break;
24675 case OPC_MOVE_V:
24676 gen_helper_msa_move_v(cpu_env, tdt, tsr);
24677 break;
24678 default:
24679 MIPS_INVAL("MSA instruction");
24680 generate_exception_end(ctx, EXCP_RI);
24681 break;
24684 tcg_temp_free(telm);
24685 tcg_temp_free_i32(tdt);
24686 tcg_temp_free_i32(tsr);
24689 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
24690 uint32_t n)
24692 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24693 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24694 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24696 TCGv_i32 tws = tcg_const_i32(ws);
24697 TCGv_i32 twd = tcg_const_i32(wd);
24698 TCGv_i32 tn = tcg_const_i32(n);
24699 TCGv_i32 tdf = tcg_const_i32(df);
24701 switch (MASK_MSA_ELM(ctx->opcode)) {
24702 case OPC_SLDI_df:
24703 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
24704 break;
24705 case OPC_SPLATI_df:
24706 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
24707 break;
24708 case OPC_INSVE_df:
24709 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
24710 break;
24711 case OPC_COPY_S_df:
24712 case OPC_COPY_U_df:
24713 case OPC_INSERT_df:
24714 #if !defined(TARGET_MIPS64)
24715 /* Double format valid only for MIPS64 */
24716 if (df == DF_DOUBLE) {
24717 generate_exception_end(ctx, EXCP_RI);
24718 break;
24720 #endif
24721 switch (MASK_MSA_ELM(ctx->opcode)) {
24722 case OPC_COPY_S_df:
24723 if (likely(wd != 0)) {
24724 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
24726 break;
24727 case OPC_COPY_U_df:
24728 if (likely(wd != 0)) {
24729 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
24731 break;
24732 case OPC_INSERT_df:
24733 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
24734 break;
24736 break;
24737 default:
24738 MIPS_INVAL("MSA instruction");
24739 generate_exception_end(ctx, EXCP_RI);
24741 tcg_temp_free_i32(twd);
24742 tcg_temp_free_i32(tws);
24743 tcg_temp_free_i32(tn);
24744 tcg_temp_free_i32(tdf);
24747 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
24749 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
24750 uint32_t df = 0, n = 0;
24752 if ((dfn & 0x30) == 0x00) {
24753 n = dfn & 0x0f;
24754 df = DF_BYTE;
24755 } else if ((dfn & 0x38) == 0x20) {
24756 n = dfn & 0x07;
24757 df = DF_HALF;
24758 } else if ((dfn & 0x3c) == 0x30) {
24759 n = dfn & 0x03;
24760 df = DF_WORD;
24761 } else if ((dfn & 0x3e) == 0x38) {
24762 n = dfn & 0x01;
24763 df = DF_DOUBLE;
24764 } else if (dfn == 0x3E) {
24765 /* CTCMSA, CFCMSA, MOVE.V */
24766 gen_msa_elm_3e(env, ctx);
24767 return;
24768 } else {
24769 generate_exception_end(ctx, EXCP_RI);
24770 return;
24773 gen_msa_elm_df(env, ctx, df, n);
24776 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
24778 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24779 uint8_t df = (ctx->opcode >> 21) & 0x1;
24780 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24781 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24782 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24784 TCGv_i32 twd = tcg_const_i32(wd);
24785 TCGv_i32 tws = tcg_const_i32(ws);
24786 TCGv_i32 twt = tcg_const_i32(wt);
24787 TCGv_i32 tdf = tcg_temp_new_i32();
24789 /* adjust df value for floating-point instruction */
24790 tcg_gen_movi_i32(tdf, df + 2);
24792 switch (MASK_MSA_3RF(ctx->opcode)) {
24793 case OPC_FCAF_df:
24794 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
24795 break;
24796 case OPC_FADD_df:
24797 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
24798 break;
24799 case OPC_FCUN_df:
24800 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
24801 break;
24802 case OPC_FSUB_df:
24803 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
24804 break;
24805 case OPC_FCOR_df:
24806 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
24807 break;
24808 case OPC_FCEQ_df:
24809 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
24810 break;
24811 case OPC_FMUL_df:
24812 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
24813 break;
24814 case OPC_FCUNE_df:
24815 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
24816 break;
24817 case OPC_FCUEQ_df:
24818 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
24819 break;
24820 case OPC_FDIV_df:
24821 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
24822 break;
24823 case OPC_FCNE_df:
24824 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
24825 break;
24826 case OPC_FCLT_df:
24827 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
24828 break;
24829 case OPC_FMADD_df:
24830 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
24831 break;
24832 case OPC_MUL_Q_df:
24833 tcg_gen_movi_i32(tdf, df + 1);
24834 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
24835 break;
24836 case OPC_FCULT_df:
24837 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
24838 break;
24839 case OPC_FMSUB_df:
24840 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
24841 break;
24842 case OPC_MADD_Q_df:
24843 tcg_gen_movi_i32(tdf, df + 1);
24844 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
24845 break;
24846 case OPC_FCLE_df:
24847 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
24848 break;
24849 case OPC_MSUB_Q_df:
24850 tcg_gen_movi_i32(tdf, df + 1);
24851 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
24852 break;
24853 case OPC_FCULE_df:
24854 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
24855 break;
24856 case OPC_FEXP2_df:
24857 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
24858 break;
24859 case OPC_FSAF_df:
24860 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
24861 break;
24862 case OPC_FEXDO_df:
24863 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
24864 break;
24865 case OPC_FSUN_df:
24866 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
24867 break;
24868 case OPC_FSOR_df:
24869 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
24870 break;
24871 case OPC_FSEQ_df:
24872 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
24873 break;
24874 case OPC_FTQ_df:
24875 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
24876 break;
24877 case OPC_FSUNE_df:
24878 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
24879 break;
24880 case OPC_FSUEQ_df:
24881 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
24882 break;
24883 case OPC_FSNE_df:
24884 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
24885 break;
24886 case OPC_FSLT_df:
24887 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
24888 break;
24889 case OPC_FMIN_df:
24890 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
24891 break;
24892 case OPC_MULR_Q_df:
24893 tcg_gen_movi_i32(tdf, df + 1);
24894 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
24895 break;
24896 case OPC_FSULT_df:
24897 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
24898 break;
24899 case OPC_FMIN_A_df:
24900 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
24901 break;
24902 case OPC_MADDR_Q_df:
24903 tcg_gen_movi_i32(tdf, df + 1);
24904 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
24905 break;
24906 case OPC_FSLE_df:
24907 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
24908 break;
24909 case OPC_FMAX_df:
24910 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
24911 break;
24912 case OPC_MSUBR_Q_df:
24913 tcg_gen_movi_i32(tdf, df + 1);
24914 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
24915 break;
24916 case OPC_FSULE_df:
24917 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
24918 break;
24919 case OPC_FMAX_A_df:
24920 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
24921 break;
24922 default:
24923 MIPS_INVAL("MSA instruction");
24924 generate_exception_end(ctx, EXCP_RI);
24925 break;
24928 tcg_temp_free_i32(twd);
24929 tcg_temp_free_i32(tws);
24930 tcg_temp_free_i32(twt);
24931 tcg_temp_free_i32(tdf);
24934 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
24936 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24937 (op & (0x7 << 18)))
24938 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24939 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24940 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24941 uint8_t df = (ctx->opcode >> 16) & 0x3;
24942 TCGv_i32 twd = tcg_const_i32(wd);
24943 TCGv_i32 tws = tcg_const_i32(ws);
24944 TCGv_i32 twt = tcg_const_i32(wt);
24945 TCGv_i32 tdf = tcg_const_i32(df);
24947 switch (MASK_MSA_2R(ctx->opcode)) {
24948 case OPC_FILL_df:
24949 #if !defined(TARGET_MIPS64)
24950 /* Double format valid only for MIPS64 */
24951 if (df == DF_DOUBLE) {
24952 generate_exception_end(ctx, EXCP_RI);
24953 break;
24955 #endif
24956 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
24957 break;
24958 case OPC_PCNT_df:
24959 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
24960 break;
24961 case OPC_NLOC_df:
24962 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
24963 break;
24964 case OPC_NLZC_df:
24965 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
24966 break;
24967 default:
24968 MIPS_INVAL("MSA instruction");
24969 generate_exception_end(ctx, EXCP_RI);
24970 break;
24973 tcg_temp_free_i32(twd);
24974 tcg_temp_free_i32(tws);
24975 tcg_temp_free_i32(twt);
24976 tcg_temp_free_i32(tdf);
24979 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
24981 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24982 (op & (0xf << 17)))
24983 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24984 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24985 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24986 uint8_t df = (ctx->opcode >> 16) & 0x1;
24987 TCGv_i32 twd = tcg_const_i32(wd);
24988 TCGv_i32 tws = tcg_const_i32(ws);
24989 TCGv_i32 twt = tcg_const_i32(wt);
24990 /* adjust df value for floating-point instruction */
24991 TCGv_i32 tdf = tcg_const_i32(df + 2);
24993 switch (MASK_MSA_2RF(ctx->opcode)) {
24994 case OPC_FCLASS_df:
24995 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
24996 break;
24997 case OPC_FTRUNC_S_df:
24998 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
24999 break;
25000 case OPC_FTRUNC_U_df:
25001 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25002 break;
25003 case OPC_FSQRT_df:
25004 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25005 break;
25006 case OPC_FRSQRT_df:
25007 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
25008 break;
25009 case OPC_FRCP_df:
25010 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
25011 break;
25012 case OPC_FRINT_df:
25013 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
25014 break;
25015 case OPC_FLOG2_df:
25016 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
25017 break;
25018 case OPC_FEXUPL_df:
25019 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
25020 break;
25021 case OPC_FEXUPR_df:
25022 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
25023 break;
25024 case OPC_FFQL_df:
25025 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
25026 break;
25027 case OPC_FFQR_df:
25028 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
25029 break;
25030 case OPC_FTINT_S_df:
25031 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
25032 break;
25033 case OPC_FTINT_U_df:
25034 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
25035 break;
25036 case OPC_FFINT_S_df:
25037 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
25038 break;
25039 case OPC_FFINT_U_df:
25040 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
25041 break;
25044 tcg_temp_free_i32(twd);
25045 tcg_temp_free_i32(tws);
25046 tcg_temp_free_i32(twt);
25047 tcg_temp_free_i32(tdf);
25050 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
25052 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
25053 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25054 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25055 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25056 TCGv_i32 twd = tcg_const_i32(wd);
25057 TCGv_i32 tws = tcg_const_i32(ws);
25058 TCGv_i32 twt = tcg_const_i32(wt);
25060 switch (MASK_MSA_VEC(ctx->opcode)) {
25061 case OPC_AND_V:
25062 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
25063 break;
25064 case OPC_OR_V:
25065 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
25066 break;
25067 case OPC_NOR_V:
25068 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
25069 break;
25070 case OPC_XOR_V:
25071 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
25072 break;
25073 case OPC_BMNZ_V:
25074 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
25075 break;
25076 case OPC_BMZ_V:
25077 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
25078 break;
25079 case OPC_BSEL_V:
25080 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
25081 break;
25082 default:
25083 MIPS_INVAL("MSA instruction");
25084 generate_exception_end(ctx, EXCP_RI);
25085 break;
25088 tcg_temp_free_i32(twd);
25089 tcg_temp_free_i32(tws);
25090 tcg_temp_free_i32(twt);
25093 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
25095 switch (MASK_MSA_VEC(ctx->opcode)) {
25096 case OPC_AND_V:
25097 case OPC_OR_V:
25098 case OPC_NOR_V:
25099 case OPC_XOR_V:
25100 case OPC_BMNZ_V:
25101 case OPC_BMZ_V:
25102 case OPC_BSEL_V:
25103 gen_msa_vec_v(env, ctx);
25104 break;
25105 case OPC_MSA_2R:
25106 gen_msa_2r(env, ctx);
25107 break;
25108 case OPC_MSA_2RF:
25109 gen_msa_2rf(env, ctx);
25110 break;
25111 default:
25112 MIPS_INVAL("MSA instruction");
25113 generate_exception_end(ctx, EXCP_RI);
25114 break;
25118 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
25120 uint32_t opcode = ctx->opcode;
25121 check_insn(ctx, ASE_MSA);
25122 check_msa_access(ctx);
25124 switch (MASK_MSA_MINOR(opcode)) {
25125 case OPC_MSA_I8_00:
25126 case OPC_MSA_I8_01:
25127 case OPC_MSA_I8_02:
25128 gen_msa_i8(env, ctx);
25129 break;
25130 case OPC_MSA_I5_06:
25131 case OPC_MSA_I5_07:
25132 gen_msa_i5(env, ctx);
25133 break;
25134 case OPC_MSA_BIT_09:
25135 case OPC_MSA_BIT_0A:
25136 gen_msa_bit(env, ctx);
25137 break;
25138 case OPC_MSA_3R_0D:
25139 case OPC_MSA_3R_0E:
25140 case OPC_MSA_3R_0F:
25141 case OPC_MSA_3R_10:
25142 case OPC_MSA_3R_11:
25143 case OPC_MSA_3R_12:
25144 case OPC_MSA_3R_13:
25145 case OPC_MSA_3R_14:
25146 case OPC_MSA_3R_15:
25147 gen_msa_3r(env, ctx);
25148 break;
25149 case OPC_MSA_ELM:
25150 gen_msa_elm(env, ctx);
25151 break;
25152 case OPC_MSA_3RF_1A:
25153 case OPC_MSA_3RF_1B:
25154 case OPC_MSA_3RF_1C:
25155 gen_msa_3rf(env, ctx);
25156 break;
25157 case OPC_MSA_VEC:
25158 gen_msa_vec(env, ctx);
25159 break;
25160 case OPC_LD_B:
25161 case OPC_LD_H:
25162 case OPC_LD_W:
25163 case OPC_LD_D:
25164 case OPC_ST_B:
25165 case OPC_ST_H:
25166 case OPC_ST_W:
25167 case OPC_ST_D:
25169 int32_t s10 = sextract32(ctx->opcode, 16, 10);
25170 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
25171 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25172 uint8_t df = (ctx->opcode >> 0) & 0x3;
25174 TCGv_i32 twd = tcg_const_i32(wd);
25175 TCGv taddr = tcg_temp_new();
25176 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
25178 switch (MASK_MSA_MINOR(opcode)) {
25179 case OPC_LD_B:
25180 gen_helper_msa_ld_b(cpu_env, twd, taddr);
25181 break;
25182 case OPC_LD_H:
25183 gen_helper_msa_ld_h(cpu_env, twd, taddr);
25184 break;
25185 case OPC_LD_W:
25186 gen_helper_msa_ld_w(cpu_env, twd, taddr);
25187 break;
25188 case OPC_LD_D:
25189 gen_helper_msa_ld_d(cpu_env, twd, taddr);
25190 break;
25191 case OPC_ST_B:
25192 gen_helper_msa_st_b(cpu_env, twd, taddr);
25193 break;
25194 case OPC_ST_H:
25195 gen_helper_msa_st_h(cpu_env, twd, taddr);
25196 break;
25197 case OPC_ST_W:
25198 gen_helper_msa_st_w(cpu_env, twd, taddr);
25199 break;
25200 case OPC_ST_D:
25201 gen_helper_msa_st_d(cpu_env, twd, taddr);
25202 break;
25205 tcg_temp_free_i32(twd);
25206 tcg_temp_free(taddr);
25208 break;
25209 default:
25210 MIPS_INVAL("MSA instruction");
25211 generate_exception_end(ctx, EXCP_RI);
25212 break;
25217 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25219 int32_t offset;
25220 int rs, rt, rd, sa;
25221 uint32_t op, op1;
25222 int16_t imm;
25224 /* make sure instructions are on a word boundary */
25225 if (ctx->base.pc_next & 0x3) {
25226 env->CP0_BadVAddr = ctx->base.pc_next;
25227 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25228 return;
25231 /* Handle blikely not taken case */
25232 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25233 TCGLabel *l1 = gen_new_label();
25235 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25236 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25237 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25238 gen_set_label(l1);
25241 op = MASK_OP_MAJOR(ctx->opcode);
25242 rs = (ctx->opcode >> 21) & 0x1f;
25243 rt = (ctx->opcode >> 16) & 0x1f;
25244 rd = (ctx->opcode >> 11) & 0x1f;
25245 sa = (ctx->opcode >> 6) & 0x1f;
25246 imm = (int16_t)ctx->opcode;
25247 switch (op) {
25248 case OPC_SPECIAL:
25249 decode_opc_special(env, ctx);
25250 break;
25251 case OPC_SPECIAL2:
25252 decode_opc_special2_legacy(env, ctx);
25253 break;
25254 case OPC_SPECIAL3:
25255 decode_opc_special3(env, ctx);
25256 break;
25257 case OPC_REGIMM:
25258 op1 = MASK_REGIMM(ctx->opcode);
25259 switch (op1) {
25260 case OPC_BLTZL: /* REGIMM branches */
25261 case OPC_BGEZL:
25262 case OPC_BLTZALL:
25263 case OPC_BGEZALL:
25264 check_insn(ctx, ISA_MIPS2);
25265 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25266 /* Fallthrough */
25267 case OPC_BLTZ:
25268 case OPC_BGEZ:
25269 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25270 break;
25271 case OPC_BLTZAL:
25272 case OPC_BGEZAL:
25273 if (ctx->insn_flags & ISA_MIPS32R6) {
25274 if (rs == 0) {
25275 /* OPC_NAL, OPC_BAL */
25276 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
25277 } else {
25278 generate_exception_end(ctx, EXCP_RI);
25280 } else {
25281 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25283 break;
25284 case OPC_TGEI: /* REGIMM traps */
25285 case OPC_TGEIU:
25286 case OPC_TLTI:
25287 case OPC_TLTIU:
25288 case OPC_TEQI:
25290 case OPC_TNEI:
25291 check_insn(ctx, ISA_MIPS2);
25292 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25293 gen_trap(ctx, op1, rs, -1, imm);
25294 break;
25295 case OPC_SIGRIE:
25296 check_insn(ctx, ISA_MIPS32R6);
25297 generate_exception_end(ctx, EXCP_RI);
25298 break;
25299 case OPC_SYNCI:
25300 check_insn(ctx, ISA_MIPS32R2);
25301 /* Break the TB to be able to sync copied instructions
25302 immediately */
25303 ctx->base.is_jmp = DISAS_STOP;
25304 break;
25305 case OPC_BPOSGE32: /* MIPS DSP branch */
25306 #if defined(TARGET_MIPS64)
25307 case OPC_BPOSGE64:
25308 #endif
25309 check_dsp(ctx);
25310 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
25311 break;
25312 #if defined(TARGET_MIPS64)
25313 case OPC_DAHI:
25314 check_insn(ctx, ISA_MIPS32R6);
25315 check_mips_64(ctx);
25316 if (rs != 0) {
25317 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
25319 break;
25320 case OPC_DATI:
25321 check_insn(ctx, ISA_MIPS32R6);
25322 check_mips_64(ctx);
25323 if (rs != 0) {
25324 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
25326 break;
25327 #endif
25328 default: /* Invalid */
25329 MIPS_INVAL("regimm");
25330 generate_exception_end(ctx, EXCP_RI);
25331 break;
25333 break;
25334 case OPC_CP0:
25335 check_cp0_enabled(ctx);
25336 op1 = MASK_CP0(ctx->opcode);
25337 switch (op1) {
25338 case OPC_MFC0:
25339 case OPC_MTC0:
25340 case OPC_MFTR:
25341 case OPC_MTTR:
25342 case OPC_MFHC0:
25343 case OPC_MTHC0:
25344 #if defined(TARGET_MIPS64)
25345 case OPC_DMFC0:
25346 case OPC_DMTC0:
25347 #endif
25348 #ifndef CONFIG_USER_ONLY
25349 gen_cp0(env, ctx, op1, rt, rd);
25350 #endif /* !CONFIG_USER_ONLY */
25351 break;
25352 case OPC_C0:
25353 case OPC_C0_1:
25354 case OPC_C0_2:
25355 case OPC_C0_3:
25356 case OPC_C0_4:
25357 case OPC_C0_5:
25358 case OPC_C0_6:
25359 case OPC_C0_7:
25360 case OPC_C0_8:
25361 case OPC_C0_9:
25362 case OPC_C0_A:
25363 case OPC_C0_B:
25364 case OPC_C0_C:
25365 case OPC_C0_D:
25366 case OPC_C0_E:
25367 case OPC_C0_F:
25368 #ifndef CONFIG_USER_ONLY
25369 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
25370 #endif /* !CONFIG_USER_ONLY */
25371 break;
25372 case OPC_MFMC0:
25373 #ifndef CONFIG_USER_ONLY
25375 uint32_t op2;
25376 TCGv t0 = tcg_temp_new();
25378 op2 = MASK_MFMC0(ctx->opcode);
25379 switch (op2) {
25380 case OPC_DMT:
25381 check_cp0_mt(ctx);
25382 gen_helper_dmt(t0);
25383 gen_store_gpr(t0, rt);
25384 break;
25385 case OPC_EMT:
25386 check_cp0_mt(ctx);
25387 gen_helper_emt(t0);
25388 gen_store_gpr(t0, rt);
25389 break;
25390 case OPC_DVPE:
25391 check_cp0_mt(ctx);
25392 gen_helper_dvpe(t0, cpu_env);
25393 gen_store_gpr(t0, rt);
25394 break;
25395 case OPC_EVPE:
25396 check_cp0_mt(ctx);
25397 gen_helper_evpe(t0, cpu_env);
25398 gen_store_gpr(t0, rt);
25399 break;
25400 case OPC_DVP:
25401 check_insn(ctx, ISA_MIPS32R6);
25402 if (ctx->vp) {
25403 gen_helper_dvp(t0, cpu_env);
25404 gen_store_gpr(t0, rt);
25406 break;
25407 case OPC_EVP:
25408 check_insn(ctx, ISA_MIPS32R6);
25409 if (ctx->vp) {
25410 gen_helper_evp(t0, cpu_env);
25411 gen_store_gpr(t0, rt);
25413 break;
25414 case OPC_DI:
25415 check_insn(ctx, ISA_MIPS32R2);
25416 save_cpu_state(ctx, 1);
25417 gen_helper_di(t0, cpu_env);
25418 gen_store_gpr(t0, rt);
25419 /* Stop translation as we may have switched
25420 the execution mode. */
25421 ctx->base.is_jmp = DISAS_STOP;
25422 break;
25423 case OPC_EI:
25424 check_insn(ctx, ISA_MIPS32R2);
25425 save_cpu_state(ctx, 1);
25426 gen_helper_ei(t0, cpu_env);
25427 gen_store_gpr(t0, rt);
25428 /* DISAS_STOP isn't sufficient, we need to ensure we break
25429 out of translated code to check for pending interrupts */
25430 gen_save_pc(ctx->base.pc_next + 4);
25431 ctx->base.is_jmp = DISAS_EXIT;
25432 break;
25433 default: /* Invalid */
25434 MIPS_INVAL("mfmc0");
25435 generate_exception_end(ctx, EXCP_RI);
25436 break;
25438 tcg_temp_free(t0);
25440 #endif /* !CONFIG_USER_ONLY */
25441 break;
25442 case OPC_RDPGPR:
25443 check_insn(ctx, ISA_MIPS32R2);
25444 gen_load_srsgpr(rt, rd);
25445 break;
25446 case OPC_WRPGPR:
25447 check_insn(ctx, ISA_MIPS32R2);
25448 gen_store_srsgpr(rt, rd);
25449 break;
25450 default:
25451 MIPS_INVAL("cp0");
25452 generate_exception_end(ctx, EXCP_RI);
25453 break;
25455 break;
25456 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
25457 if (ctx->insn_flags & ISA_MIPS32R6) {
25458 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
25459 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25460 } else {
25461 /* OPC_ADDI */
25462 /* Arithmetic with immediate opcode */
25463 gen_arith_imm(ctx, op, rt, rs, imm);
25465 break;
25466 case OPC_ADDIU:
25467 gen_arith_imm(ctx, op, rt, rs, imm);
25468 break;
25469 case OPC_SLTI: /* Set on less than with immediate opcode */
25470 case OPC_SLTIU:
25471 gen_slt_imm(ctx, op, rt, rs, imm);
25472 break;
25473 case OPC_ANDI: /* Arithmetic with immediate opcode */
25474 case OPC_LUI: /* OPC_AUI */
25475 case OPC_ORI:
25476 case OPC_XORI:
25477 gen_logic_imm(ctx, op, rt, rs, imm);
25478 break;
25479 case OPC_J: /* Jump */
25480 case OPC_JAL:
25481 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25482 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25483 break;
25484 /* Branch */
25485 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
25486 if (ctx->insn_flags & ISA_MIPS32R6) {
25487 if (rt == 0) {
25488 generate_exception_end(ctx, EXCP_RI);
25489 break;
25491 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
25492 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25493 } else {
25494 /* OPC_BLEZL */
25495 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25497 break;
25498 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
25499 if (ctx->insn_flags & ISA_MIPS32R6) {
25500 if (rt == 0) {
25501 generate_exception_end(ctx, EXCP_RI);
25502 break;
25504 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
25505 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25506 } else {
25507 /* OPC_BGTZL */
25508 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25510 break;
25511 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
25512 if (rt == 0) {
25513 /* OPC_BLEZ */
25514 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25515 } else {
25516 check_insn(ctx, ISA_MIPS32R6);
25517 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
25518 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25520 break;
25521 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
25522 if (rt == 0) {
25523 /* OPC_BGTZ */
25524 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25525 } else {
25526 check_insn(ctx, ISA_MIPS32R6);
25527 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
25528 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25530 break;
25531 case OPC_BEQL:
25532 case OPC_BNEL:
25533 check_insn(ctx, ISA_MIPS2);
25534 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25535 /* Fallthrough */
25536 case OPC_BEQ:
25537 case OPC_BNE:
25538 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25539 break;
25540 case OPC_LL: /* Load and stores */
25541 check_insn(ctx, ISA_MIPS2);
25542 /* Fallthrough */
25543 case OPC_LWL:
25544 case OPC_LWR:
25545 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25546 /* Fallthrough */
25547 case OPC_LB:
25548 case OPC_LH:
25549 case OPC_LW:
25550 case OPC_LWPC:
25551 case OPC_LBU:
25552 case OPC_LHU:
25553 gen_ld(ctx, op, rt, rs, imm);
25554 break;
25555 case OPC_SWL:
25556 case OPC_SWR:
25557 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25558 /* fall through */
25559 case OPC_SB:
25560 case OPC_SH:
25561 case OPC_SW:
25562 gen_st(ctx, op, rt, rs, imm);
25563 break;
25564 case OPC_SC:
25565 check_insn(ctx, ISA_MIPS2);
25566 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25567 gen_st_cond(ctx, op, rt, rs, imm);
25568 break;
25569 case OPC_CACHE:
25570 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25571 check_cp0_enabled(ctx);
25572 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
25573 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25574 gen_cache_operation(ctx, rt, rs, imm);
25576 /* Treat as NOP. */
25577 break;
25578 case OPC_PREF:
25579 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25580 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
25581 /* Treat as NOP. */
25582 break;
25584 /* Floating point (COP1). */
25585 case OPC_LWC1:
25586 case OPC_LDC1:
25587 case OPC_SWC1:
25588 case OPC_SDC1:
25589 gen_cop1_ldst(ctx, op, rt, rs, imm);
25590 break;
25592 case OPC_CP1:
25593 op1 = MASK_CP1(ctx->opcode);
25595 switch (op1) {
25596 case OPC_MFHC1:
25597 case OPC_MTHC1:
25598 check_cp1_enabled(ctx);
25599 check_insn(ctx, ISA_MIPS32R2);
25600 /* fall through */
25601 case OPC_MFC1:
25602 case OPC_CFC1:
25603 case OPC_MTC1:
25604 case OPC_CTC1:
25605 check_cp1_enabled(ctx);
25606 gen_cp1(ctx, op1, rt, rd);
25607 break;
25608 #if defined(TARGET_MIPS64)
25609 case OPC_DMFC1:
25610 case OPC_DMTC1:
25611 check_cp1_enabled(ctx);
25612 check_insn(ctx, ISA_MIPS3);
25613 check_mips_64(ctx);
25614 gen_cp1(ctx, op1, rt, rd);
25615 break;
25616 #endif
25617 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25618 check_cp1_enabled(ctx);
25619 if (ctx->insn_flags & ISA_MIPS32R6) {
25620 /* OPC_BC1EQZ */
25621 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25622 rt, imm << 2, 4);
25623 } else {
25624 /* OPC_BC1ANY2 */
25625 check_cop1x(ctx);
25626 check_insn(ctx, ASE_MIPS3D);
25627 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25628 (rt >> 2) & 0x7, imm << 2);
25630 break;
25631 case OPC_BC1NEZ:
25632 check_cp1_enabled(ctx);
25633 check_insn(ctx, ISA_MIPS32R6);
25634 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25635 rt, imm << 2, 4);
25636 break;
25637 case OPC_BC1ANY4:
25638 check_cp1_enabled(ctx);
25639 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25640 check_cop1x(ctx);
25641 check_insn(ctx, ASE_MIPS3D);
25642 /* fall through */
25643 case OPC_BC1:
25644 check_cp1_enabled(ctx);
25645 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25646 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25647 (rt >> 2) & 0x7, imm << 2);
25648 break;
25649 case OPC_PS_FMT:
25650 check_ps(ctx);
25651 /* fall through */
25652 case OPC_S_FMT:
25653 case OPC_D_FMT:
25654 check_cp1_enabled(ctx);
25655 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25656 (imm >> 8) & 0x7);
25657 break;
25658 case OPC_W_FMT:
25659 case OPC_L_FMT:
25661 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25662 check_cp1_enabled(ctx);
25663 if (ctx->insn_flags & ISA_MIPS32R6) {
25664 switch (r6_op) {
25665 case R6_OPC_CMP_AF_S:
25666 case R6_OPC_CMP_UN_S:
25667 case R6_OPC_CMP_EQ_S:
25668 case R6_OPC_CMP_UEQ_S:
25669 case R6_OPC_CMP_LT_S:
25670 case R6_OPC_CMP_ULT_S:
25671 case R6_OPC_CMP_LE_S:
25672 case R6_OPC_CMP_ULE_S:
25673 case R6_OPC_CMP_SAF_S:
25674 case R6_OPC_CMP_SUN_S:
25675 case R6_OPC_CMP_SEQ_S:
25676 case R6_OPC_CMP_SEUQ_S:
25677 case R6_OPC_CMP_SLT_S:
25678 case R6_OPC_CMP_SULT_S:
25679 case R6_OPC_CMP_SLE_S:
25680 case R6_OPC_CMP_SULE_S:
25681 case R6_OPC_CMP_OR_S:
25682 case R6_OPC_CMP_UNE_S:
25683 case R6_OPC_CMP_NE_S:
25684 case R6_OPC_CMP_SOR_S:
25685 case R6_OPC_CMP_SUNE_S:
25686 case R6_OPC_CMP_SNE_S:
25687 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25688 break;
25689 case R6_OPC_CMP_AF_D:
25690 case R6_OPC_CMP_UN_D:
25691 case R6_OPC_CMP_EQ_D:
25692 case R6_OPC_CMP_UEQ_D:
25693 case R6_OPC_CMP_LT_D:
25694 case R6_OPC_CMP_ULT_D:
25695 case R6_OPC_CMP_LE_D:
25696 case R6_OPC_CMP_ULE_D:
25697 case R6_OPC_CMP_SAF_D:
25698 case R6_OPC_CMP_SUN_D:
25699 case R6_OPC_CMP_SEQ_D:
25700 case R6_OPC_CMP_SEUQ_D:
25701 case R6_OPC_CMP_SLT_D:
25702 case R6_OPC_CMP_SULT_D:
25703 case R6_OPC_CMP_SLE_D:
25704 case R6_OPC_CMP_SULE_D:
25705 case R6_OPC_CMP_OR_D:
25706 case R6_OPC_CMP_UNE_D:
25707 case R6_OPC_CMP_NE_D:
25708 case R6_OPC_CMP_SOR_D:
25709 case R6_OPC_CMP_SUNE_D:
25710 case R6_OPC_CMP_SNE_D:
25711 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25712 break;
25713 default:
25714 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25715 rt, rd, sa, (imm >> 8) & 0x7);
25717 break;
25719 } else {
25720 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25721 (imm >> 8) & 0x7);
25723 break;
25725 case OPC_BZ_V:
25726 case OPC_BNZ_V:
25727 case OPC_BZ_B:
25728 case OPC_BZ_H:
25729 case OPC_BZ_W:
25730 case OPC_BZ_D:
25731 case OPC_BNZ_B:
25732 case OPC_BNZ_H:
25733 case OPC_BNZ_W:
25734 case OPC_BNZ_D:
25735 check_insn(ctx, ASE_MSA);
25736 gen_msa_branch(env, ctx, op1);
25737 break;
25738 default:
25739 MIPS_INVAL("cp1");
25740 generate_exception_end(ctx, EXCP_RI);
25741 break;
25743 break;
25745 /* Compact branches [R6] and COP2 [non-R6] */
25746 case OPC_BC: /* OPC_LWC2 */
25747 case OPC_BALC: /* OPC_SWC2 */
25748 if (ctx->insn_flags & ISA_MIPS32R6) {
25749 /* OPC_BC, OPC_BALC */
25750 gen_compute_compact_branch(ctx, op, 0, 0,
25751 sextract32(ctx->opcode << 2, 0, 28));
25752 } else {
25753 /* OPC_LWC2, OPC_SWC2 */
25754 /* COP2: Not implemented. */
25755 generate_exception_err(ctx, EXCP_CpU, 2);
25757 break;
25758 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25759 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25760 if (ctx->insn_flags & ISA_MIPS32R6) {
25761 if (rs != 0) {
25762 /* OPC_BEQZC, OPC_BNEZC */
25763 gen_compute_compact_branch(ctx, op, rs, 0,
25764 sextract32(ctx->opcode << 2, 0, 23));
25765 } else {
25766 /* OPC_JIC, OPC_JIALC */
25767 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25769 } else {
25770 /* OPC_LWC2, OPC_SWC2 */
25771 /* COP2: Not implemented. */
25772 generate_exception_err(ctx, EXCP_CpU, 2);
25774 break;
25775 case OPC_CP2:
25776 check_insn(ctx, INSN_LOONGSON2F);
25777 /* Note that these instructions use different fields. */
25778 gen_loongson_multimedia(ctx, sa, rd, rt);
25779 break;
25781 case OPC_CP3:
25782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25783 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
25784 check_cp1_enabled(ctx);
25785 op1 = MASK_CP3(ctx->opcode);
25786 switch (op1) {
25787 case OPC_LUXC1:
25788 case OPC_SUXC1:
25789 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
25790 /* Fallthrough */
25791 case OPC_LWXC1:
25792 case OPC_LDXC1:
25793 case OPC_SWXC1:
25794 case OPC_SDXC1:
25795 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25796 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
25797 break;
25798 case OPC_PREFX:
25799 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25800 /* Treat as NOP. */
25801 break;
25802 case OPC_ALNV_PS:
25803 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
25804 /* Fallthrough */
25805 case OPC_MADD_S:
25806 case OPC_MADD_D:
25807 case OPC_MADD_PS:
25808 case OPC_MSUB_S:
25809 case OPC_MSUB_D:
25810 case OPC_MSUB_PS:
25811 case OPC_NMADD_S:
25812 case OPC_NMADD_D:
25813 case OPC_NMADD_PS:
25814 case OPC_NMSUB_S:
25815 case OPC_NMSUB_D:
25816 case OPC_NMSUB_PS:
25817 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25818 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25819 break;
25820 default:
25821 MIPS_INVAL("cp3");
25822 generate_exception_end(ctx, EXCP_RI);
25823 break;
25825 } else {
25826 generate_exception_err(ctx, EXCP_CpU, 1);
25828 break;
25830 #if defined(TARGET_MIPS64)
25831 /* MIPS64 opcodes */
25832 case OPC_LDL:
25833 case OPC_LDR:
25834 case OPC_LLD:
25835 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25836 /* fall through */
25837 case OPC_LWU:
25838 case OPC_LD:
25839 check_insn(ctx, ISA_MIPS3);
25840 check_mips_64(ctx);
25841 gen_ld(ctx, op, rt, rs, imm);
25842 break;
25843 case OPC_SDL:
25844 case OPC_SDR:
25845 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25846 /* fall through */
25847 case OPC_SD:
25848 check_insn(ctx, ISA_MIPS3);
25849 check_mips_64(ctx);
25850 gen_st(ctx, op, rt, rs, imm);
25851 break;
25852 case OPC_SCD:
25853 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25854 check_insn(ctx, ISA_MIPS3);
25855 check_mips_64(ctx);
25856 gen_st_cond(ctx, op, rt, rs, imm);
25857 break;
25858 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25859 if (ctx->insn_flags & ISA_MIPS32R6) {
25860 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25861 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25862 } else {
25863 /* OPC_DADDI */
25864 check_insn(ctx, ISA_MIPS3);
25865 check_mips_64(ctx);
25866 gen_arith_imm(ctx, op, rt, rs, imm);
25868 break;
25869 case OPC_DADDIU:
25870 check_insn(ctx, ISA_MIPS3);
25871 check_mips_64(ctx);
25872 gen_arith_imm(ctx, op, rt, rs, imm);
25873 break;
25874 #else
25875 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25876 if (ctx->insn_flags & ISA_MIPS32R6) {
25877 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25878 } else {
25879 MIPS_INVAL("major opcode");
25880 generate_exception_end(ctx, EXCP_RI);
25882 break;
25883 #endif
25884 case OPC_DAUI: /* OPC_JALX */
25885 if (ctx->insn_flags & ISA_MIPS32R6) {
25886 #if defined(TARGET_MIPS64)
25887 /* OPC_DAUI */
25888 check_mips_64(ctx);
25889 if (rs == 0) {
25890 generate_exception(ctx, EXCP_RI);
25891 } else if (rt != 0) {
25892 TCGv t0 = tcg_temp_new();
25893 gen_load_gpr(t0, rs);
25894 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25895 tcg_temp_free(t0);
25897 #else
25898 generate_exception_end(ctx, EXCP_RI);
25899 MIPS_INVAL("major opcode");
25900 #endif
25901 } else {
25902 /* OPC_JALX */
25903 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25904 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25905 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25907 break;
25908 case OPC_MSA: /* OPC_MDMX */
25909 /* MDMX: Not implemented. */
25910 gen_msa(env, ctx);
25911 break;
25912 case OPC_PCREL:
25913 check_insn(ctx, ISA_MIPS32R6);
25914 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
25915 break;
25916 default: /* Invalid */
25917 MIPS_INVAL("major opcode");
25918 generate_exception_end(ctx, EXCP_RI);
25919 break;
25923 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
25925 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25926 CPUMIPSState *env = cs->env_ptr;
25928 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
25929 ctx->saved_pc = -1;
25930 ctx->insn_flags = env->insn_flags;
25931 ctx->CP0_Config1 = env->CP0_Config1;
25932 ctx->CP0_Config2 = env->CP0_Config2;
25933 ctx->CP0_Config3 = env->CP0_Config3;
25934 ctx->CP0_Config5 = env->CP0_Config5;
25935 ctx->btarget = 0;
25936 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25937 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25938 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25939 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25940 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25941 ctx->PAMask = env->PAMask;
25942 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25943 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25944 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25945 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25946 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
25947 /* Restore delay slot state from the tb context. */
25948 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25949 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25950 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
25951 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
25952 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25953 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25954 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25955 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25956 restore_cpu_state(env, ctx);
25957 #ifdef CONFIG_USER_ONLY
25958 ctx->mem_idx = MIPS_HFLAG_UM;
25959 #else
25960 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
25961 #endif
25962 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
25963 MO_UNALN : MO_ALIGN;
25965 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25966 ctx->hflags);
25969 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25973 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25975 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25977 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25978 ctx->btarget);
25981 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25982 const CPUBreakpoint *bp)
25984 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25986 save_cpu_state(ctx, 1);
25987 ctx->base.is_jmp = DISAS_NORETURN;
25988 gen_helper_raise_exception_debug(cpu_env);
25989 /* The address covered by the breakpoint must be included in
25990 [tb->pc, tb->pc + tb->size) in order to for it to be
25991 properly cleared -- thus we increment the PC here so that
25992 the logic setting tb->size below does the right thing. */
25993 ctx->base.pc_next += 4;
25994 return true;
25997 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25999 CPUMIPSState *env = cs->env_ptr;
26000 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26001 int insn_bytes;
26002 int is_slot;
26004 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
26005 if (ctx->insn_flags & ISA_NANOMIPS32) {
26006 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26007 insn_bytes = decode_nanomips_opc(env, ctx);
26008 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
26009 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
26010 insn_bytes = 4;
26011 decode_opc(env, ctx);
26012 } else if (ctx->insn_flags & ASE_MICROMIPS) {
26013 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26014 insn_bytes = decode_micromips_opc(env, ctx);
26015 } else if (ctx->insn_flags & ASE_MIPS16) {
26016 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26017 insn_bytes = decode_mips16_opc(env, ctx);
26018 } else {
26019 generate_exception_end(ctx, EXCP_RI);
26020 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
26021 return;
26024 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26025 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
26026 MIPS_HFLAG_FBNSLOT))) {
26027 /* force to generate branch as there is neither delay nor
26028 forbidden slot */
26029 is_slot = 1;
26031 if ((ctx->hflags & MIPS_HFLAG_M16) &&
26032 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
26033 /* Force to generate branch as microMIPS R6 doesn't restrict
26034 branches in the forbidden slot. */
26035 is_slot = 1;
26038 if (is_slot) {
26039 gen_branch(ctx, insn_bytes);
26041 ctx->base.pc_next += insn_bytes;
26043 if (ctx->base.is_jmp != DISAS_NEXT) {
26044 return;
26046 /* Execute a branch and its delay slot as a single instruction.
26047 This is what GDB expects and is consistent with what the
26048 hardware does (e.g. if a delay slot instruction faults, the
26049 reported PC is the PC of the branch). */
26050 if (ctx->base.singlestep_enabled &&
26051 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
26052 ctx->base.is_jmp = DISAS_TOO_MANY;
26054 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
26055 ctx->base.is_jmp = DISAS_TOO_MANY;
26059 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
26061 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26063 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
26064 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
26065 gen_helper_raise_exception_debug(cpu_env);
26066 } else {
26067 switch (ctx->base.is_jmp) {
26068 case DISAS_STOP:
26069 gen_save_pc(ctx->base.pc_next);
26070 tcg_gen_lookup_and_goto_ptr();
26071 break;
26072 case DISAS_NEXT:
26073 case DISAS_TOO_MANY:
26074 save_cpu_state(ctx, 0);
26075 gen_goto_tb(ctx, 0, ctx->base.pc_next);
26076 break;
26077 case DISAS_EXIT:
26078 tcg_gen_exit_tb(NULL, 0);
26079 break;
26080 case DISAS_NORETURN:
26081 break;
26082 default:
26083 g_assert_not_reached();
26088 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
26090 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
26091 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
26094 static const TranslatorOps mips_tr_ops = {
26095 .init_disas_context = mips_tr_init_disas_context,
26096 .tb_start = mips_tr_tb_start,
26097 .insn_start = mips_tr_insn_start,
26098 .breakpoint_check = mips_tr_breakpoint_check,
26099 .translate_insn = mips_tr_translate_insn,
26100 .tb_stop = mips_tr_tb_stop,
26101 .disas_log = mips_tr_disas_log,
26104 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
26106 DisasContext ctx;
26108 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
26111 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
26112 int flags)
26114 int i;
26115 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
26117 #define printfpr(fp) \
26118 do { \
26119 if (is_fpu64) \
26120 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26121 " fd:%13g fs:%13g psu: %13g\n", \
26122 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
26123 (double)(fp)->fd, \
26124 (double)(fp)->fs[FP_ENDIAN_IDX], \
26125 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
26126 else { \
26127 fpr_t tmp; \
26128 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
26129 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
26130 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26131 " fd:%13g fs:%13g psu:%13g\n", \
26132 tmp.w[FP_ENDIAN_IDX], tmp.d, \
26133 (double)tmp.fd, \
26134 (double)tmp.fs[FP_ENDIAN_IDX], \
26135 (double)tmp.fs[!FP_ENDIAN_IDX]); \
26137 } while(0)
26140 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
26141 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
26142 get_float_exception_flags(&env->active_fpu.fp_status));
26143 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
26144 fpu_fprintf(f, "%3s: ", fregnames[i]);
26145 printfpr(&env->active_fpu.fpr[i]);
26148 #undef printfpr
26151 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
26152 int flags)
26154 MIPSCPU *cpu = MIPS_CPU(cs);
26155 CPUMIPSState *env = &cpu->env;
26156 int i;
26158 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
26159 " LO=0x" TARGET_FMT_lx " ds %04x "
26160 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
26161 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
26162 env->hflags, env->btarget, env->bcond);
26163 for (i = 0; i < 32; i++) {
26164 if ((i & 3) == 0)
26165 cpu_fprintf(f, "GPR%02d:", i);
26166 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
26167 if ((i & 3) == 3)
26168 cpu_fprintf(f, "\n");
26171 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
26172 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
26173 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
26174 PRIx64 "\n",
26175 env->CP0_Config0, env->CP0_Config1, env->lladdr);
26176 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
26177 env->CP0_Config2, env->CP0_Config3);
26178 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
26179 env->CP0_Config4, env->CP0_Config5);
26180 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
26181 fpu_dump_state(env, f, cpu_fprintf, flags);
26185 void mips_tcg_init(void)
26187 int i;
26189 cpu_gpr[0] = NULL;
26190 for (i = 1; i < 32; i++)
26191 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
26192 offsetof(CPUMIPSState, active_tc.gpr[i]),
26193 regnames[i]);
26195 for (i = 0; i < 32; i++) {
26196 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
26197 msa_wr_d[i * 2] =
26198 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
26199 /* The scalar floating-point unit (FPU) registers are mapped on
26200 * the MSA vector registers. */
26201 fpu_f64[i] = msa_wr_d[i * 2];
26202 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
26203 msa_wr_d[i * 2 + 1] =
26204 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
26207 cpu_PC = tcg_global_mem_new(cpu_env,
26208 offsetof(CPUMIPSState, active_tc.PC), "PC");
26209 for (i = 0; i < MIPS_DSP_ACC; i++) {
26210 cpu_HI[i] = tcg_global_mem_new(cpu_env,
26211 offsetof(CPUMIPSState, active_tc.HI[i]),
26212 regnames_HI[i]);
26213 cpu_LO[i] = tcg_global_mem_new(cpu_env,
26214 offsetof(CPUMIPSState, active_tc.LO[i]),
26215 regnames_LO[i]);
26217 cpu_dspctrl = tcg_global_mem_new(cpu_env,
26218 offsetof(CPUMIPSState, active_tc.DSPControl),
26219 "DSPControl");
26220 bcond = tcg_global_mem_new(cpu_env,
26221 offsetof(CPUMIPSState, bcond), "bcond");
26222 btarget = tcg_global_mem_new(cpu_env,
26223 offsetof(CPUMIPSState, btarget), "btarget");
26224 hflags = tcg_global_mem_new_i32(cpu_env,
26225 offsetof(CPUMIPSState, hflags), "hflags");
26227 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
26228 offsetof(CPUMIPSState, active_fpu.fcr0),
26229 "fcr0");
26230 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
26231 offsetof(CPUMIPSState, active_fpu.fcr31),
26232 "fcr31");
26235 #include "translate_init.inc.c"
26237 void cpu_mips_realize_env(CPUMIPSState *env)
26239 env->exception_base = (int32_t)0xBFC00000;
26241 #ifndef CONFIG_USER_ONLY
26242 mmu_init(env, env->cpu_model);
26243 #endif
26244 fpu_init(env, env->cpu_model);
26245 mvp_init(env, env->cpu_model);
26248 bool cpu_supports_cps_smp(const char *cpu_type)
26250 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
26251 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
26254 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
26256 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
26257 return (mcc->cpu_def->insn_flags & isa) != 0;
26260 void cpu_set_exception_base(int vp_index, target_ulong address)
26262 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
26263 vp->env.exception_base = address;
26266 void cpu_state_reset(CPUMIPSState *env)
26268 MIPSCPU *cpu = mips_env_get_cpu(env);
26269 CPUState *cs = CPU(cpu);
26271 /* Reset registers to their default values */
26272 env->CP0_PRid = env->cpu_model->CP0_PRid;
26273 env->CP0_Config0 = env->cpu_model->CP0_Config0;
26274 #ifdef TARGET_WORDS_BIGENDIAN
26275 env->CP0_Config0 |= (1 << CP0C0_BE);
26276 #endif
26277 env->CP0_Config1 = env->cpu_model->CP0_Config1;
26278 env->CP0_Config2 = env->cpu_model->CP0_Config2;
26279 env->CP0_Config3 = env->cpu_model->CP0_Config3;
26280 env->CP0_Config4 = env->cpu_model->CP0_Config4;
26281 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
26282 env->CP0_Config5 = env->cpu_model->CP0_Config5;
26283 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
26284 env->CP0_Config6 = env->cpu_model->CP0_Config6;
26285 env->CP0_Config7 = env->cpu_model->CP0_Config7;
26286 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
26287 << env->cpu_model->CP0_LLAddr_shift;
26288 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
26289 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
26290 env->CCRes = env->cpu_model->CCRes;
26291 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
26292 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
26293 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
26294 env->current_tc = 0;
26295 env->SEGBITS = env->cpu_model->SEGBITS;
26296 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
26297 #if defined(TARGET_MIPS64)
26298 if (env->cpu_model->insn_flags & ISA_MIPS3) {
26299 env->SEGMask |= 3ULL << 62;
26301 #endif
26302 env->PABITS = env->cpu_model->PABITS;
26303 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
26304 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
26305 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
26306 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
26307 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
26308 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
26309 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
26310 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
26311 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
26312 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
26313 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
26314 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
26315 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
26316 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
26317 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
26318 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
26319 env->msair = env->cpu_model->MSAIR;
26320 env->insn_flags = env->cpu_model->insn_flags;
26322 #if defined(CONFIG_USER_ONLY)
26323 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
26324 # ifdef TARGET_MIPS64
26325 /* Enable 64-bit register mode. */
26326 env->CP0_Status |= (1 << CP0St_PX);
26327 # endif
26328 # ifdef TARGET_ABI_MIPSN64
26329 /* Enable 64-bit address mode. */
26330 env->CP0_Status |= (1 << CP0St_UX);
26331 # endif
26332 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
26333 hardware registers. */
26334 env->CP0_HWREna |= 0x0000000F;
26335 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
26336 env->CP0_Status |= (1 << CP0St_CU1);
26338 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
26339 env->CP0_Status |= (1 << CP0St_MX);
26341 # if defined(TARGET_MIPS64)
26342 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
26343 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
26344 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
26345 env->CP0_Status |= (1 << CP0St_FR);
26347 # endif
26348 #else
26349 if (env->hflags & MIPS_HFLAG_BMASK) {
26350 /* If the exception was raised from a delay slot,
26351 come back to the jump. */
26352 env->CP0_ErrorEPC = (env->active_tc.PC
26353 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
26354 } else {
26355 env->CP0_ErrorEPC = env->active_tc.PC;
26357 env->active_tc.PC = env->exception_base;
26358 env->CP0_Random = env->tlb->nb_tlb - 1;
26359 env->tlb->tlb_in_use = env->tlb->nb_tlb;
26360 env->CP0_Wired = 0;
26361 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
26362 env->CP0_EBase = (cs->cpu_index & 0x3FF);
26363 if (mips_um_ksegs_enabled()) {
26364 env->CP0_EBase |= 0x40000000;
26365 } else {
26366 env->CP0_EBase |= (int32_t)0x80000000;
26368 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
26369 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
26371 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
26372 0x3ff : 0xff;
26373 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
26374 /* vectored interrupts not implemented, timer on int 7,
26375 no performance counters. */
26376 env->CP0_IntCtl = 0xe0000000;
26378 int i;
26380 for (i = 0; i < 7; i++) {
26381 env->CP0_WatchLo[i] = 0;
26382 env->CP0_WatchHi[i] = 0x80000000;
26384 env->CP0_WatchLo[7] = 0;
26385 env->CP0_WatchHi[7] = 0;
26387 /* Count register increments in debug mode, EJTAG version 1 */
26388 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
26390 cpu_mips_store_count(env, 1);
26392 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
26393 int i;
26395 /* Only TC0 on VPE 0 starts as active. */
26396 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
26397 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
26398 env->tcs[i].CP0_TCHalt = 1;
26400 env->active_tc.CP0_TCHalt = 1;
26401 cs->halted = 1;
26403 if (cs->cpu_index == 0) {
26404 /* VPE0 starts up enabled. */
26405 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
26406 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
26408 /* TC0 starts up unhalted. */
26409 cs->halted = 0;
26410 env->active_tc.CP0_TCHalt = 0;
26411 env->tcs[0].CP0_TCHalt = 0;
26412 /* With thread 0 active. */
26413 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
26414 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
26419 * Configure default legacy segmentation control. We use this regardless of
26420 * whether segmentation control is presented to the guest.
26422 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
26423 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
26424 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
26425 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
26426 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
26427 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26428 (2 << CP0SC_C);
26429 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
26430 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26431 (3 << CP0SC_C)) << 16;
26432 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
26433 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26434 (1 << CP0SC_EU) | (2 << CP0SC_C);
26435 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
26436 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26437 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
26438 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
26439 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
26440 #endif
26441 if ((env->insn_flags & ISA_MIPS32R6) &&
26442 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
26443 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
26444 env->CP0_Status |= (1 << CP0St_FR);
26447 if (env->insn_flags & ISA_MIPS32R6) {
26448 /* PTW = 1 */
26449 env->CP0_PWSize = 0x40;
26450 /* GDI = 12 */
26451 /* UDI = 12 */
26452 /* MDI = 12 */
26453 /* PRI = 12 */
26454 /* PTEI = 2 */
26455 env->CP0_PWField = 0x0C30C302;
26456 } else {
26457 /* GDI = 0 */
26458 /* UDI = 0 */
26459 /* MDI = 0 */
26460 /* PRI = 0 */
26461 /* PTEI = 2 */
26462 env->CP0_PWField = 0x02;
26465 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
26466 /* microMIPS on reset when Config3.ISA is 3 */
26467 env->hflags |= MIPS_HFLAG_M16;
26470 /* MSA */
26471 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
26472 msa_reset(env);
26475 compute_hflags(env);
26476 restore_fp_status(env);
26477 restore_pamask(env);
26478 cs->exception_index = EXCP_NONE;
26480 if (semihosting_get_argc()) {
26481 /* UHI interface can be used to obtain argc and argv */
26482 env->active_tc.gpr[4] = -1;
26486 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
26487 target_ulong *data)
26489 env->active_tc.PC = data[0];
26490 env->hflags &= ~MIPS_HFLAG_BMASK;
26491 env->hflags |= data[1];
26492 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
26493 case MIPS_HFLAG_BR:
26494 break;
26495 case MIPS_HFLAG_BC:
26496 case MIPS_HFLAG_BL:
26497 case MIPS_HFLAG_B:
26498 env->btarget = data[2];
26499 break;