pcnet: fix possible buffer overflow
[qemu/kevin.git] / target / mips / translate.c
blobab16cdb91191fcb0cd12764d8669aecf45f11009
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
467 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
468 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
471 /* DBSHFL opcodes */
472 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
474 enum {
475 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
476 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
477 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
478 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
479 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
482 /* MIPS DSP REGIMM opcodes */
483 enum {
484 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
485 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
488 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
489 /* MIPS DSP Load */
490 enum {
491 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
492 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
493 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
494 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
497 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498 enum {
499 /* MIPS DSP Arithmetic Sub-class */
500 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
501 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
502 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
503 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
507 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
508 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
509 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
516 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
517 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
518 /* MIPS DSP Multiply Sub-class insns */
519 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
521 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
522 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
527 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
528 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
532 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
533 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
543 /* MIPS DSP Multiply Sub-class insns */
544 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
545 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
546 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
550 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551 enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
554 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
555 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
566 /* DSP Bit/Manipulation Sub-class */
567 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
574 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
584 /* DSP Compare-Pick Sub-class */
585 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
602 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
603 enum {
604 /* MIPS DSP GPR-Based Shift Sub-class */
605 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
607 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
629 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
630 enum {
631 /* MIPS DSP Multiply Sub-class insns */
632 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
634 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
656 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657 enum {
658 /* DSP Bit/Manipulation Sub-class */
659 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
662 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
663 enum {
664 /* MIPS DSP Append Sub-class */
665 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
666 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
667 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
670 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
673 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
674 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
675 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
685 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
686 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
687 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
688 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
689 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
692 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
693 enum {
694 /* MIPS DSP Arithmetic Sub-class */
695 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
721 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
722 enum {
723 /* MIPS DSP Multiply Sub-class insns */
724 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
725 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
726 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
729 /* MIPS DSP Arithmetic Sub-class */
730 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
731 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
732 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
741 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
742 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
753 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
754 enum {
755 /* DSP Compare-Pick Sub-class */
756 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
786 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
787 enum {
788 /* DSP Append Sub-class */
789 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
790 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
791 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
792 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
795 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
798 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
799 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
800 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
801 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
821 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
822 enum {
823 /* DSP Bit/Manipulation Sub-class */
824 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
827 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
828 enum {
829 /* MIPS DSP Multiply Sub-class insns */
830 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
858 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
859 enum {
860 /* MIPS DSP GPR-Based Shift Sub-class */
861 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
889 /* Coprocessor 0 (rs field) */
890 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
892 enum {
893 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
894 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
895 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
896 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
897 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
898 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
899 OPC_MFTR = (0x08 << 21) | OPC_CP0,
900 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
901 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
902 OPC_MTTR = (0x0C << 21) | OPC_CP0,
903 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
904 OPC_C0 = (0x10 << 21) | OPC_CP0,
905 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
906 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
907 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
908 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
909 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
910 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
911 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
912 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
913 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
914 OPC_C0_A = (0x1A << 21) | OPC_CP0,
915 OPC_C0_B = (0x1B << 21) | OPC_CP0,
916 OPC_C0_C = (0x1C << 21) | OPC_CP0,
917 OPC_C0_D = (0x1D << 21) | OPC_CP0,
918 OPC_C0_E = (0x1E << 21) | OPC_CP0,
919 OPC_C0_F = (0x1F << 21) | OPC_CP0,
922 /* MFMC0 opcodes */
923 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
925 enum {
926 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
927 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
928 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
929 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
930 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
931 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
932 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
933 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
936 /* Coprocessor 0 (with rs == C0) */
937 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
939 enum {
940 OPC_TLBR = 0x01 | OPC_C0,
941 OPC_TLBWI = 0x02 | OPC_C0,
942 OPC_TLBINV = 0x03 | OPC_C0,
943 OPC_TLBINVF = 0x04 | OPC_C0,
944 OPC_TLBWR = 0x06 | OPC_C0,
945 OPC_TLBP = 0x08 | OPC_C0,
946 OPC_RFE = 0x10 | OPC_C0,
947 OPC_ERET = 0x18 | OPC_C0,
948 OPC_DERET = 0x1F | OPC_C0,
949 OPC_WAIT = 0x20 | OPC_C0,
952 /* Coprocessor 1 (rs field) */
953 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
955 /* Values for the fmt field in FP instructions */
956 enum {
957 /* 0 - 15 are reserved */
958 FMT_S = 16, /* single fp */
959 FMT_D = 17, /* double fp */
960 FMT_E = 18, /* extended fp */
961 FMT_Q = 19, /* quad fp */
962 FMT_W = 20, /* 32-bit fixed */
963 FMT_L = 21, /* 64-bit fixed */
964 FMT_PS = 22, /* paired single fp */
965 /* 23 - 31 are reserved */
968 enum {
969 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
970 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
971 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
972 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
973 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
974 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
975 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
976 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
977 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
978 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
979 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
980 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
981 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
982 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
983 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
984 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
985 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
986 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
987 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
988 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
989 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
990 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
991 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
992 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
993 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
994 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
995 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
996 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
997 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
998 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1001 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1002 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1004 enum {
1005 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1006 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1007 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1008 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1011 enum {
1012 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1013 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1016 enum {
1017 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1018 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1021 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1023 enum {
1024 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1025 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1026 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1027 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1028 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1029 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1030 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1031 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1032 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1033 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1034 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1037 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1039 enum {
1040 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1041 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1042 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1043 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1044 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1045 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1046 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1047 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1049 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1050 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1051 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1052 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1053 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1054 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1055 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1056 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1059 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1060 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1061 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1062 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1063 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1064 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1065 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1067 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1068 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1069 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1070 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1071 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1072 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1073 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1074 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1076 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1077 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1078 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1079 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1080 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1081 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1083 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1084 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1085 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1086 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1087 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1088 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1090 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1091 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1092 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1093 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1094 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1095 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1097 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1098 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1099 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1100 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1101 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1102 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1104 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1105 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1106 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1107 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1108 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1109 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1111 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1112 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1113 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1114 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1115 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1116 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1118 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1119 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1120 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1121 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1122 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1123 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1125 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1126 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1127 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1128 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1129 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1130 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1134 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1136 enum {
1137 OPC_LWXC1 = 0x00 | OPC_CP3,
1138 OPC_LDXC1 = 0x01 | OPC_CP3,
1139 OPC_LUXC1 = 0x05 | OPC_CP3,
1140 OPC_SWXC1 = 0x08 | OPC_CP3,
1141 OPC_SDXC1 = 0x09 | OPC_CP3,
1142 OPC_SUXC1 = 0x0D | OPC_CP3,
1143 OPC_PREFX = 0x0F | OPC_CP3,
1144 OPC_ALNV_PS = 0x1E | OPC_CP3,
1145 OPC_MADD_S = 0x20 | OPC_CP3,
1146 OPC_MADD_D = 0x21 | OPC_CP3,
1147 OPC_MADD_PS = 0x26 | OPC_CP3,
1148 OPC_MSUB_S = 0x28 | OPC_CP3,
1149 OPC_MSUB_D = 0x29 | OPC_CP3,
1150 OPC_MSUB_PS = 0x2E | OPC_CP3,
1151 OPC_NMADD_S = 0x30 | OPC_CP3,
1152 OPC_NMADD_D = 0x31 | OPC_CP3,
1153 OPC_NMADD_PS= 0x36 | OPC_CP3,
1154 OPC_NMSUB_S = 0x38 | OPC_CP3,
1155 OPC_NMSUB_D = 0x39 | OPC_CP3,
1156 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1159 /* MSA Opcodes */
1160 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1161 enum {
1162 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1163 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1164 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1165 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1166 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1167 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1168 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1169 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1170 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1171 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1172 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1173 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1174 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1175 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1176 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1177 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1178 OPC_MSA_ELM = 0x19 | OPC_MSA,
1179 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1180 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1181 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1182 OPC_MSA_VEC = 0x1E | OPC_MSA,
1184 /* MI10 instruction */
1185 OPC_LD_B = (0x20) | OPC_MSA,
1186 OPC_LD_H = (0x21) | OPC_MSA,
1187 OPC_LD_W = (0x22) | OPC_MSA,
1188 OPC_LD_D = (0x23) | OPC_MSA,
1189 OPC_ST_B = (0x24) | OPC_MSA,
1190 OPC_ST_H = (0x25) | OPC_MSA,
1191 OPC_ST_W = (0x26) | OPC_MSA,
1192 OPC_ST_D = (0x27) | OPC_MSA,
1195 enum {
1196 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1197 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1198 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1199 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1200 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1201 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1202 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1203 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1204 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1205 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1206 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1207 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1208 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1210 /* I8 instruction */
1211 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1212 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1213 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1214 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1215 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1216 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1217 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1218 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1219 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1220 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1222 /* VEC/2R/2RF instruction */
1223 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1224 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1225 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1226 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1227 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1228 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1229 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1231 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1232 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1234 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1235 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1236 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1237 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1238 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1240 /* 2RF instruction df(bit 16) = _w, _d */
1241 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1242 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1243 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1244 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1245 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1246 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1247 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1248 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1249 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1250 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1251 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1252 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1253 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1254 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1255 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1256 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1258 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1259 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1260 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1261 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1262 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1263 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1264 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1265 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1266 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1267 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1268 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1269 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1270 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1272 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1274 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1275 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1276 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1278 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1279 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1281 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1282 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1283 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1284 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1285 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1290 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1292 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1293 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1294 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1295 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1296 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1297 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1298 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1299 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1300 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1301 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1310 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1311 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1312 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1313 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1314 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1315 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1316 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1317 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1318 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1319 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1320 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1321 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1323 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1324 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1325 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1326 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1327 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1328 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1329 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1330 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1331 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1332 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1334 /* 3RF instruction _df(bit 21) = _w, _d */
1335 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1337 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1338 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1339 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1340 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1342 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1343 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1346 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1348 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1351 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1353 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1357 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1358 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1361 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1362 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1363 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1364 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1365 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1366 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1367 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1369 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1370 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1372 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1373 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1377 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1378 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1379 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1380 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1381 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1382 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1383 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1384 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1385 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1386 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1387 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1388 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1389 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1392 /* global register indices */
1393 static TCGv cpu_gpr[32], cpu_PC;
1394 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1395 static TCGv cpu_dspctrl, btarget, bcond;
1396 static TCGv_i32 hflags;
1397 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1398 static TCGv_i64 fpu_f64[32];
1399 static TCGv_i64 msa_wr_d[64];
1401 #include "exec/gen-icount.h"
1403 #define gen_helper_0e0i(name, arg) do { \
1404 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1405 gen_helper_##name(cpu_env, helper_tmp); \
1406 tcg_temp_free_i32(helper_tmp); \
1407 } while(0)
1409 #define gen_helper_0e1i(name, arg1, arg2) do { \
1410 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1411 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1412 tcg_temp_free_i32(helper_tmp); \
1413 } while(0)
1415 #define gen_helper_1e0i(name, ret, arg1) do { \
1416 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1417 gen_helper_##name(ret, cpu_env, helper_tmp); \
1418 tcg_temp_free_i32(helper_tmp); \
1419 } while(0)
1421 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1422 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1423 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1424 tcg_temp_free_i32(helper_tmp); \
1425 } while(0)
1427 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1428 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1429 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1430 tcg_temp_free_i32(helper_tmp); \
1431 } while(0)
1433 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1434 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1435 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1436 tcg_temp_free_i32(helper_tmp); \
1437 } while(0)
1439 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1440 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1441 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1442 tcg_temp_free_i32(helper_tmp); \
1443 } while(0)
1445 typedef struct DisasContext {
1446 DisasContextBase base;
1447 target_ulong saved_pc;
1448 target_ulong page_start;
1449 uint32_t opcode;
1450 int insn_flags;
1451 int32_t CP0_Config1;
1452 int32_t CP0_Config3;
1453 int32_t CP0_Config5;
1454 /* Routine used to access memory */
1455 int mem_idx;
1456 TCGMemOp default_tcg_memop_mask;
1457 uint32_t hflags, saved_hflags;
1458 target_ulong btarget;
1459 bool ulri;
1460 int kscrexist;
1461 bool rxi;
1462 int ie;
1463 bool bi;
1464 bool bp;
1465 uint64_t PAMask;
1466 bool mvh;
1467 bool eva;
1468 bool sc;
1469 int CP0_LLAddr_shift;
1470 bool ps;
1471 bool vp;
1472 bool cmgcr;
1473 bool mrp;
1474 bool nan2008;
1475 bool abs2008;
1476 } DisasContext;
1478 #define DISAS_STOP DISAS_TARGET_0
1479 #define DISAS_EXIT DISAS_TARGET_1
1481 static const char * const regnames[] = {
1482 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1483 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1484 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1485 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1488 static const char * const regnames_HI[] = {
1489 "HI0", "HI1", "HI2", "HI3",
1492 static const char * const regnames_LO[] = {
1493 "LO0", "LO1", "LO2", "LO3",
1496 static const char * const fregnames[] = {
1497 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1498 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1499 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1500 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1503 static const char * const msaregnames[] = {
1504 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1505 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1506 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1507 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1508 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1509 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1510 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1511 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1512 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1513 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1514 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1515 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1516 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1517 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1518 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1519 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1522 #define LOG_DISAS(...) \
1523 do { \
1524 if (MIPS_DEBUG_DISAS) { \
1525 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1527 } while (0)
1529 #define MIPS_INVAL(op) \
1530 do { \
1531 if (MIPS_DEBUG_DISAS) { \
1532 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1533 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1534 ctx->base.pc_next, ctx->opcode, op, \
1535 ctx->opcode >> 26, ctx->opcode & 0x3F, \
1536 ((ctx->opcode >> 16) & 0x1F)); \
1538 } while (0)
1540 /* General purpose registers moves. */
1541 static inline void gen_load_gpr (TCGv t, int reg)
1543 if (reg == 0)
1544 tcg_gen_movi_tl(t, 0);
1545 else
1546 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1549 static inline void gen_store_gpr (TCGv t, int reg)
1551 if (reg != 0)
1552 tcg_gen_mov_tl(cpu_gpr[reg], t);
1555 /* Moves to/from shadow registers. */
1556 static inline void gen_load_srsgpr (int from, int to)
1558 TCGv t0 = tcg_temp_new();
1560 if (from == 0)
1561 tcg_gen_movi_tl(t0, 0);
1562 else {
1563 TCGv_i32 t2 = tcg_temp_new_i32();
1564 TCGv_ptr addr = tcg_temp_new_ptr();
1566 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1567 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1568 tcg_gen_andi_i32(t2, t2, 0xf);
1569 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1570 tcg_gen_ext_i32_ptr(addr, t2);
1571 tcg_gen_add_ptr(addr, cpu_env, addr);
1573 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1574 tcg_temp_free_ptr(addr);
1575 tcg_temp_free_i32(t2);
1577 gen_store_gpr(t0, to);
1578 tcg_temp_free(t0);
1581 static inline void gen_store_srsgpr (int from, int to)
1583 if (to != 0) {
1584 TCGv t0 = tcg_temp_new();
1585 TCGv_i32 t2 = tcg_temp_new_i32();
1586 TCGv_ptr addr = tcg_temp_new_ptr();
1588 gen_load_gpr(t0, from);
1589 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1590 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1591 tcg_gen_andi_i32(t2, t2, 0xf);
1592 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1593 tcg_gen_ext_i32_ptr(addr, t2);
1594 tcg_gen_add_ptr(addr, cpu_env, addr);
1596 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1597 tcg_temp_free_ptr(addr);
1598 tcg_temp_free_i32(t2);
1599 tcg_temp_free(t0);
1603 /* Tests */
1604 static inline void gen_save_pc(target_ulong pc)
1606 tcg_gen_movi_tl(cpu_PC, pc);
1609 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1611 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1612 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1613 gen_save_pc(ctx->base.pc_next);
1614 ctx->saved_pc = ctx->base.pc_next;
1616 if (ctx->hflags != ctx->saved_hflags) {
1617 tcg_gen_movi_i32(hflags, ctx->hflags);
1618 ctx->saved_hflags = ctx->hflags;
1619 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1620 case MIPS_HFLAG_BR:
1621 break;
1622 case MIPS_HFLAG_BC:
1623 case MIPS_HFLAG_BL:
1624 case MIPS_HFLAG_B:
1625 tcg_gen_movi_tl(btarget, ctx->btarget);
1626 break;
1631 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1633 ctx->saved_hflags = ctx->hflags;
1634 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1635 case MIPS_HFLAG_BR:
1636 break;
1637 case MIPS_HFLAG_BC:
1638 case MIPS_HFLAG_BL:
1639 case MIPS_HFLAG_B:
1640 ctx->btarget = env->btarget;
1641 break;
1645 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1647 TCGv_i32 texcp = tcg_const_i32(excp);
1648 TCGv_i32 terr = tcg_const_i32(err);
1649 save_cpu_state(ctx, 1);
1650 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1651 tcg_temp_free_i32(terr);
1652 tcg_temp_free_i32(texcp);
1653 ctx->base.is_jmp = DISAS_NORETURN;
1656 static inline void generate_exception(DisasContext *ctx, int excp)
1658 gen_helper_0e0i(raise_exception, excp);
1661 static inline void generate_exception_end(DisasContext *ctx, int excp)
1663 generate_exception_err(ctx, excp, 0);
1666 /* Floating point register moves. */
1667 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1669 if (ctx->hflags & MIPS_HFLAG_FRE) {
1670 generate_exception(ctx, EXCP_RI);
1672 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1675 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1677 TCGv_i64 t64;
1678 if (ctx->hflags & MIPS_HFLAG_FRE) {
1679 generate_exception(ctx, EXCP_RI);
1681 t64 = tcg_temp_new_i64();
1682 tcg_gen_extu_i32_i64(t64, t);
1683 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1684 tcg_temp_free_i64(t64);
1687 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1689 if (ctx->hflags & MIPS_HFLAG_F64) {
1690 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1691 } else {
1692 gen_load_fpr32(ctx, t, reg | 1);
1696 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1698 if (ctx->hflags & MIPS_HFLAG_F64) {
1699 TCGv_i64 t64 = tcg_temp_new_i64();
1700 tcg_gen_extu_i32_i64(t64, t);
1701 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1702 tcg_temp_free_i64(t64);
1703 } else {
1704 gen_store_fpr32(ctx, t, reg | 1);
1708 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1710 if (ctx->hflags & MIPS_HFLAG_F64) {
1711 tcg_gen_mov_i64(t, fpu_f64[reg]);
1712 } else {
1713 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1717 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1719 if (ctx->hflags & MIPS_HFLAG_F64) {
1720 tcg_gen_mov_i64(fpu_f64[reg], t);
1721 } else {
1722 TCGv_i64 t0;
1723 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1724 t0 = tcg_temp_new_i64();
1725 tcg_gen_shri_i64(t0, t, 32);
1726 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1727 tcg_temp_free_i64(t0);
1731 static inline int get_fp_bit (int cc)
1733 if (cc)
1734 return 24 + cc;
1735 else
1736 return 23;
1739 /* Addresses computation */
1740 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1742 tcg_gen_add_tl(ret, arg0, arg1);
1744 #if defined(TARGET_MIPS64)
1745 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1746 tcg_gen_ext32s_i64(ret, ret);
1748 #endif
1751 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1752 target_long ofs)
1754 tcg_gen_addi_tl(ret, base, ofs);
1756 #if defined(TARGET_MIPS64)
1757 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1758 tcg_gen_ext32s_i64(ret, ret);
1760 #endif
1763 /* Addresses computation (translation time) */
1764 static target_long addr_add(DisasContext *ctx, target_long base,
1765 target_long offset)
1767 target_long sum = base + offset;
1769 #if defined(TARGET_MIPS64)
1770 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1771 sum = (int32_t)sum;
1773 #endif
1774 return sum;
1777 /* Sign-extract the low 32-bits to a target_long. */
1778 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1780 #if defined(TARGET_MIPS64)
1781 tcg_gen_ext32s_i64(ret, arg);
1782 #else
1783 tcg_gen_extrl_i64_i32(ret, arg);
1784 #endif
1787 /* Sign-extract the high 32-bits to a target_long. */
1788 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1790 #if defined(TARGET_MIPS64)
1791 tcg_gen_sari_i64(ret, arg, 32);
1792 #else
1793 tcg_gen_extrh_i64_i32(ret, arg);
1794 #endif
1797 static inline void check_cp0_enabled(DisasContext *ctx)
1799 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1800 generate_exception_err(ctx, EXCP_CpU, 0);
1803 static inline void check_cp1_enabled(DisasContext *ctx)
1805 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1806 generate_exception_err(ctx, EXCP_CpU, 1);
1809 /* Verify that the processor is running with COP1X instructions enabled.
1810 This is associated with the nabla symbol in the MIPS32 and MIPS64
1811 opcode tables. */
1813 static inline void check_cop1x(DisasContext *ctx)
1815 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1816 generate_exception_end(ctx, EXCP_RI);
1819 /* Verify that the processor is running with 64-bit floating-point
1820 operations enabled. */
1822 static inline void check_cp1_64bitmode(DisasContext *ctx)
1824 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1825 generate_exception_end(ctx, EXCP_RI);
1829 * Verify if floating point register is valid; an operation is not defined
1830 * if bit 0 of any register specification is set and the FR bit in the
1831 * Status register equals zero, since the register numbers specify an
1832 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1833 * in the Status register equals one, both even and odd register numbers
1834 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1836 * Multiple 64 bit wide registers can be checked by calling
1837 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1839 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1841 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1842 generate_exception_end(ctx, EXCP_RI);
1845 /* Verify that the processor is running with DSP instructions enabled.
1846 This is enabled by CP0 Status register MX(24) bit.
1849 static inline void check_dsp(DisasContext *ctx)
1851 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1852 if (ctx->insn_flags & ASE_DSP) {
1853 generate_exception_end(ctx, EXCP_DSPDIS);
1854 } else {
1855 generate_exception_end(ctx, EXCP_RI);
1860 static inline void check_dspr2(DisasContext *ctx)
1862 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1863 if (ctx->insn_flags & ASE_DSP) {
1864 generate_exception_end(ctx, EXCP_DSPDIS);
1865 } else {
1866 generate_exception_end(ctx, EXCP_RI);
1871 /* This code generates a "reserved instruction" exception if the
1872 CPU does not support the instruction set corresponding to flags. */
1873 static inline void check_insn(DisasContext *ctx, int flags)
1875 if (unlikely(!(ctx->insn_flags & flags))) {
1876 generate_exception_end(ctx, EXCP_RI);
1880 /* This code generates a "reserved instruction" exception if the
1881 CPU has corresponding flag set which indicates that the instruction
1882 has been removed. */
1883 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1885 if (unlikely(ctx->insn_flags & flags)) {
1886 generate_exception_end(ctx, EXCP_RI);
1890 /* This code generates a "reserved instruction" exception if the
1891 CPU does not support 64-bit paired-single (PS) floating point data type */
1892 static inline void check_ps(DisasContext *ctx)
1894 if (unlikely(!ctx->ps)) {
1895 generate_exception(ctx, EXCP_RI);
1897 check_cp1_64bitmode(ctx);
1900 #ifdef TARGET_MIPS64
1901 /* This code generates a "reserved instruction" exception if 64-bit
1902 instructions are not enabled. */
1903 static inline void check_mips_64(DisasContext *ctx)
1905 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1906 generate_exception_end(ctx, EXCP_RI);
1908 #endif
1910 #ifndef CONFIG_USER_ONLY
1911 static inline void check_mvh(DisasContext *ctx)
1913 if (unlikely(!ctx->mvh)) {
1914 generate_exception(ctx, EXCP_RI);
1917 #endif
1920 * This code generates a "reserved instruction" exception if the
1921 * Config5 XNP bit is set.
1923 static inline void check_xnp(DisasContext *ctx)
1925 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1926 generate_exception_end(ctx, EXCP_RI);
1931 * This code generates a "reserved instruction" exception if the
1932 * Config3 MT bit is NOT set.
1934 static inline void check_mt(DisasContext *ctx)
1936 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1937 generate_exception_end(ctx, EXCP_RI);
1941 #ifndef CONFIG_USER_ONLY
1943 * This code generates a "coprocessor unusable" exception if CP0 is not
1944 * available, and, if that is not the case, generates a "reserved instruction"
1945 * exception if the Config5 MT bit is NOT set. This is needed for availability
1946 * control of some of MT ASE instructions.
1948 static inline void check_cp0_mt(DisasContext *ctx)
1950 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1951 generate_exception_err(ctx, EXCP_CpU, 0);
1952 } else {
1953 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1954 generate_exception_err(ctx, EXCP_RI, 0);
1958 #endif
1961 * This code generates a "reserved instruction" exception if the
1962 * Config5 NMS bit is set.
1964 static inline void check_nms(DisasContext *ctx)
1966 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1967 generate_exception_end(ctx, EXCP_RI);
1972 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1973 calling interface for 32 and 64-bit FPRs. No sense in changing
1974 all callers for gen_load_fpr32 when we need the CTX parameter for
1975 this one use. */
1976 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1977 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1978 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1979 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1980 int ft, int fs, int cc) \
1982 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1983 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1984 switch (ifmt) { \
1985 case FMT_PS: \
1986 check_ps(ctx); \
1987 break; \
1988 case FMT_D: \
1989 if (abs) { \
1990 check_cop1x(ctx); \
1992 check_cp1_registers(ctx, fs | ft); \
1993 break; \
1994 case FMT_S: \
1995 if (abs) { \
1996 check_cop1x(ctx); \
1998 break; \
2000 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
2001 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
2002 switch (n) { \
2003 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
2004 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
2005 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
2006 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
2007 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
2008 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
2009 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
2010 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
2011 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
2012 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
2013 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
2014 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
2015 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
2016 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
2017 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
2018 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
2019 default: abort(); \
2021 tcg_temp_free_i##bits (fp0); \
2022 tcg_temp_free_i##bits (fp1); \
2025 FOP_CONDS(, 0, d, FMT_D, 64)
2026 FOP_CONDS(abs, 1, d, FMT_D, 64)
2027 FOP_CONDS(, 0, s, FMT_S, 32)
2028 FOP_CONDS(abs, 1, s, FMT_S, 32)
2029 FOP_CONDS(, 0, ps, FMT_PS, 64)
2030 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2031 #undef FOP_CONDS
2033 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2034 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
2035 int ft, int fs, int fd) \
2037 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2038 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2039 if (ifmt == FMT_D) { \
2040 check_cp1_registers(ctx, fs | ft | fd); \
2042 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2043 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2044 switch (n) { \
2045 case 0: \
2046 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2047 break; \
2048 case 1: \
2049 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2050 break; \
2051 case 2: \
2052 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2053 break; \
2054 case 3: \
2055 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2056 break; \
2057 case 4: \
2058 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2059 break; \
2060 case 5: \
2061 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2062 break; \
2063 case 6: \
2064 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2065 break; \
2066 case 7: \
2067 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2068 break; \
2069 case 8: \
2070 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2071 break; \
2072 case 9: \
2073 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2074 break; \
2075 case 10: \
2076 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2077 break; \
2078 case 11: \
2079 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2080 break; \
2081 case 12: \
2082 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2083 break; \
2084 case 13: \
2085 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2086 break; \
2087 case 14: \
2088 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2089 break; \
2090 case 15: \
2091 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2092 break; \
2093 case 17: \
2094 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2095 break; \
2096 case 18: \
2097 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2098 break; \
2099 case 19: \
2100 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2101 break; \
2102 case 25: \
2103 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2104 break; \
2105 case 26: \
2106 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2107 break; \
2108 case 27: \
2109 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2110 break; \
2111 default: \
2112 abort(); \
2114 STORE; \
2115 tcg_temp_free_i ## bits (fp0); \
2116 tcg_temp_free_i ## bits (fp1); \
2119 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2120 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2121 #undef FOP_CONDNS
2122 #undef gen_ldcmp_fpr32
2123 #undef gen_ldcmp_fpr64
2125 /* load/store instructions. */
2126 #ifdef CONFIG_USER_ONLY
2127 #define OP_LD_ATOMIC(insn,fname) \
2128 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2129 DisasContext *ctx) \
2131 TCGv t0 = tcg_temp_new(); \
2132 tcg_gen_mov_tl(t0, arg1); \
2133 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2134 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2135 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2136 tcg_temp_free(t0); \
2138 #else
2139 #define OP_LD_ATOMIC(insn,fname) \
2140 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2141 DisasContext *ctx) \
2143 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2145 #endif
2146 OP_LD_ATOMIC(ll,ld32s);
2147 #if defined(TARGET_MIPS64)
2148 OP_LD_ATOMIC(lld,ld64);
2149 #endif
2150 #undef OP_LD_ATOMIC
2152 #ifdef CONFIG_USER_ONLY
2153 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2154 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2155 DisasContext *ctx) \
2157 TCGv t0 = tcg_temp_new(); \
2158 TCGLabel *l1 = gen_new_label(); \
2159 TCGLabel *l2 = gen_new_label(); \
2161 tcg_gen_andi_tl(t0, arg2, almask); \
2162 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2163 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2164 generate_exception(ctx, EXCP_AdES); \
2165 gen_set_label(l1); \
2166 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2167 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2168 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2169 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2170 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2171 generate_exception_end(ctx, EXCP_SC); \
2172 gen_set_label(l2); \
2173 tcg_gen_movi_tl(t0, 0); \
2174 gen_store_gpr(t0, rt); \
2175 tcg_temp_free(t0); \
2177 #else
2178 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2179 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2180 DisasContext *ctx) \
2182 TCGv t0 = tcg_temp_new(); \
2183 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
2184 gen_store_gpr(t0, rt); \
2185 tcg_temp_free(t0); \
2187 #endif
2188 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2189 #if defined(TARGET_MIPS64)
2190 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2191 #endif
2192 #undef OP_ST_ATOMIC
2194 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2195 int base, int offset)
2197 if (base == 0) {
2198 tcg_gen_movi_tl(addr, offset);
2199 } else if (offset == 0) {
2200 gen_load_gpr(addr, base);
2201 } else {
2202 tcg_gen_movi_tl(addr, offset);
2203 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2207 static target_ulong pc_relative_pc (DisasContext *ctx)
2209 target_ulong pc = ctx->base.pc_next;
2211 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2212 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2214 pc -= branch_bytes;
2217 pc &= ~(target_ulong)3;
2218 return pc;
2221 /* Load */
2222 static void gen_ld(DisasContext *ctx, uint32_t opc,
2223 int rt, int base, int offset)
2225 TCGv t0, t1, t2;
2226 int mem_idx = ctx->mem_idx;
2228 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2229 /* Loongson CPU uses a load to zero register for prefetch.
2230 We emulate it as a NOP. On other CPU we must perform the
2231 actual memory access. */
2232 return;
2235 t0 = tcg_temp_new();
2236 gen_base_offset_addr(ctx, t0, base, offset);
2238 switch (opc) {
2239 #if defined(TARGET_MIPS64)
2240 case OPC_LWU:
2241 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2242 ctx->default_tcg_memop_mask);
2243 gen_store_gpr(t0, rt);
2244 break;
2245 case OPC_LD:
2246 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2247 ctx->default_tcg_memop_mask);
2248 gen_store_gpr(t0, rt);
2249 break;
2250 case OPC_LLD:
2251 case R6_OPC_LLD:
2252 op_ld_lld(t0, t0, mem_idx, ctx);
2253 gen_store_gpr(t0, rt);
2254 break;
2255 case OPC_LDL:
2256 t1 = tcg_temp_new();
2257 /* Do a byte access to possibly trigger a page
2258 fault with the unaligned address. */
2259 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2260 tcg_gen_andi_tl(t1, t0, 7);
2261 #ifndef TARGET_WORDS_BIGENDIAN
2262 tcg_gen_xori_tl(t1, t1, 7);
2263 #endif
2264 tcg_gen_shli_tl(t1, t1, 3);
2265 tcg_gen_andi_tl(t0, t0, ~7);
2266 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2267 tcg_gen_shl_tl(t0, t0, t1);
2268 t2 = tcg_const_tl(-1);
2269 tcg_gen_shl_tl(t2, t2, t1);
2270 gen_load_gpr(t1, rt);
2271 tcg_gen_andc_tl(t1, t1, t2);
2272 tcg_temp_free(t2);
2273 tcg_gen_or_tl(t0, t0, t1);
2274 tcg_temp_free(t1);
2275 gen_store_gpr(t0, rt);
2276 break;
2277 case OPC_LDR:
2278 t1 = tcg_temp_new();
2279 /* Do a byte access to possibly trigger a page
2280 fault with the unaligned address. */
2281 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2282 tcg_gen_andi_tl(t1, t0, 7);
2283 #ifdef TARGET_WORDS_BIGENDIAN
2284 tcg_gen_xori_tl(t1, t1, 7);
2285 #endif
2286 tcg_gen_shli_tl(t1, t1, 3);
2287 tcg_gen_andi_tl(t0, t0, ~7);
2288 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2289 tcg_gen_shr_tl(t0, t0, t1);
2290 tcg_gen_xori_tl(t1, t1, 63);
2291 t2 = tcg_const_tl(0xfffffffffffffffeull);
2292 tcg_gen_shl_tl(t2, t2, t1);
2293 gen_load_gpr(t1, rt);
2294 tcg_gen_and_tl(t1, t1, t2);
2295 tcg_temp_free(t2);
2296 tcg_gen_or_tl(t0, t0, t1);
2297 tcg_temp_free(t1);
2298 gen_store_gpr(t0, rt);
2299 break;
2300 case OPC_LDPC:
2301 t1 = tcg_const_tl(pc_relative_pc(ctx));
2302 gen_op_addr_add(ctx, t0, t0, t1);
2303 tcg_temp_free(t1);
2304 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2305 gen_store_gpr(t0, rt);
2306 break;
2307 #endif
2308 case OPC_LWPC:
2309 t1 = tcg_const_tl(pc_relative_pc(ctx));
2310 gen_op_addr_add(ctx, t0, t0, t1);
2311 tcg_temp_free(t1);
2312 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2313 gen_store_gpr(t0, rt);
2314 break;
2315 case OPC_LWE:
2316 mem_idx = MIPS_HFLAG_UM;
2317 /* fall through */
2318 case OPC_LW:
2319 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2320 ctx->default_tcg_memop_mask);
2321 gen_store_gpr(t0, rt);
2322 break;
2323 case OPC_LHE:
2324 mem_idx = MIPS_HFLAG_UM;
2325 /* fall through */
2326 case OPC_LH:
2327 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2328 ctx->default_tcg_memop_mask);
2329 gen_store_gpr(t0, rt);
2330 break;
2331 case OPC_LHUE:
2332 mem_idx = MIPS_HFLAG_UM;
2333 /* fall through */
2334 case OPC_LHU:
2335 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2336 ctx->default_tcg_memop_mask);
2337 gen_store_gpr(t0, rt);
2338 break;
2339 case OPC_LBE:
2340 mem_idx = MIPS_HFLAG_UM;
2341 /* fall through */
2342 case OPC_LB:
2343 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2344 gen_store_gpr(t0, rt);
2345 break;
2346 case OPC_LBUE:
2347 mem_idx = MIPS_HFLAG_UM;
2348 /* fall through */
2349 case OPC_LBU:
2350 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2351 gen_store_gpr(t0, rt);
2352 break;
2353 case OPC_LWLE:
2354 mem_idx = MIPS_HFLAG_UM;
2355 /* fall through */
2356 case OPC_LWL:
2357 t1 = tcg_temp_new();
2358 /* Do a byte access to possibly trigger a page
2359 fault with the unaligned address. */
2360 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2361 tcg_gen_andi_tl(t1, t0, 3);
2362 #ifndef TARGET_WORDS_BIGENDIAN
2363 tcg_gen_xori_tl(t1, t1, 3);
2364 #endif
2365 tcg_gen_shli_tl(t1, t1, 3);
2366 tcg_gen_andi_tl(t0, t0, ~3);
2367 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2368 tcg_gen_shl_tl(t0, t0, t1);
2369 t2 = tcg_const_tl(-1);
2370 tcg_gen_shl_tl(t2, t2, t1);
2371 gen_load_gpr(t1, rt);
2372 tcg_gen_andc_tl(t1, t1, t2);
2373 tcg_temp_free(t2);
2374 tcg_gen_or_tl(t0, t0, t1);
2375 tcg_temp_free(t1);
2376 tcg_gen_ext32s_tl(t0, t0);
2377 gen_store_gpr(t0, rt);
2378 break;
2379 case OPC_LWRE:
2380 mem_idx = MIPS_HFLAG_UM;
2381 /* fall through */
2382 case OPC_LWR:
2383 t1 = tcg_temp_new();
2384 /* Do a byte access to possibly trigger a page
2385 fault with the unaligned address. */
2386 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2387 tcg_gen_andi_tl(t1, t0, 3);
2388 #ifdef TARGET_WORDS_BIGENDIAN
2389 tcg_gen_xori_tl(t1, t1, 3);
2390 #endif
2391 tcg_gen_shli_tl(t1, t1, 3);
2392 tcg_gen_andi_tl(t0, t0, ~3);
2393 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2394 tcg_gen_shr_tl(t0, t0, t1);
2395 tcg_gen_xori_tl(t1, t1, 31);
2396 t2 = tcg_const_tl(0xfffffffeull);
2397 tcg_gen_shl_tl(t2, t2, t1);
2398 gen_load_gpr(t1, rt);
2399 tcg_gen_and_tl(t1, t1, t2);
2400 tcg_temp_free(t2);
2401 tcg_gen_or_tl(t0, t0, t1);
2402 tcg_temp_free(t1);
2403 tcg_gen_ext32s_tl(t0, t0);
2404 gen_store_gpr(t0, rt);
2405 break;
2406 case OPC_LLE:
2407 mem_idx = MIPS_HFLAG_UM;
2408 /* fall through */
2409 case OPC_LL:
2410 case R6_OPC_LL:
2411 op_ld_ll(t0, t0, mem_idx, ctx);
2412 gen_store_gpr(t0, rt);
2413 break;
2415 tcg_temp_free(t0);
2418 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2419 uint32_t reg1, uint32_t reg2)
2421 TCGv taddr = tcg_temp_new();
2422 TCGv_i64 tval = tcg_temp_new_i64();
2423 TCGv tmp1 = tcg_temp_new();
2424 TCGv tmp2 = tcg_temp_new();
2426 gen_base_offset_addr(ctx, taddr, base, offset);
2427 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2428 #ifdef TARGET_WORDS_BIGENDIAN
2429 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2430 #else
2431 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2432 #endif
2433 gen_store_gpr(tmp1, reg1);
2434 tcg_temp_free(tmp1);
2435 gen_store_gpr(tmp2, reg2);
2436 tcg_temp_free(tmp2);
2437 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2438 tcg_temp_free_i64(tval);
2439 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2440 tcg_temp_free(taddr);
2443 /* Store */
2444 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2445 int base, int offset)
2447 TCGv t0 = tcg_temp_new();
2448 TCGv t1 = tcg_temp_new();
2449 int mem_idx = ctx->mem_idx;
2451 gen_base_offset_addr(ctx, t0, base, offset);
2452 gen_load_gpr(t1, rt);
2453 switch (opc) {
2454 #if defined(TARGET_MIPS64)
2455 case OPC_SD:
2456 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2457 ctx->default_tcg_memop_mask);
2458 break;
2459 case OPC_SDL:
2460 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2461 break;
2462 case OPC_SDR:
2463 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2464 break;
2465 #endif
2466 case OPC_SWE:
2467 mem_idx = MIPS_HFLAG_UM;
2468 /* fall through */
2469 case OPC_SW:
2470 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2471 ctx->default_tcg_memop_mask);
2472 break;
2473 case OPC_SHE:
2474 mem_idx = MIPS_HFLAG_UM;
2475 /* fall through */
2476 case OPC_SH:
2477 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2478 ctx->default_tcg_memop_mask);
2479 break;
2480 case OPC_SBE:
2481 mem_idx = MIPS_HFLAG_UM;
2482 /* fall through */
2483 case OPC_SB:
2484 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2485 break;
2486 case OPC_SWLE:
2487 mem_idx = MIPS_HFLAG_UM;
2488 /* fall through */
2489 case OPC_SWL:
2490 gen_helper_0e2i(swl, t1, t0, mem_idx);
2491 break;
2492 case OPC_SWRE:
2493 mem_idx = MIPS_HFLAG_UM;
2494 /* fall through */
2495 case OPC_SWR:
2496 gen_helper_0e2i(swr, t1, t0, mem_idx);
2497 break;
2499 tcg_temp_free(t0);
2500 tcg_temp_free(t1);
2504 /* Store conditional */
2505 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2506 int base, int16_t offset)
2508 TCGv t0, t1;
2509 int mem_idx = ctx->mem_idx;
2511 #ifdef CONFIG_USER_ONLY
2512 t0 = tcg_temp_local_new();
2513 t1 = tcg_temp_local_new();
2514 #else
2515 t0 = tcg_temp_new();
2516 t1 = tcg_temp_new();
2517 #endif
2518 gen_base_offset_addr(ctx, t0, base, offset);
2519 gen_load_gpr(t1, rt);
2520 switch (opc) {
2521 #if defined(TARGET_MIPS64)
2522 case OPC_SCD:
2523 case R6_OPC_SCD:
2524 op_st_scd(t1, t0, rt, mem_idx, ctx);
2525 break;
2526 #endif
2527 case OPC_SCE:
2528 mem_idx = MIPS_HFLAG_UM;
2529 /* fall through */
2530 case OPC_SC:
2531 case R6_OPC_SC:
2532 op_st_sc(t1, t0, rt, mem_idx, ctx);
2533 break;
2535 tcg_temp_free(t1);
2536 tcg_temp_free(t0);
2539 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2540 uint32_t reg1, uint32_t reg2)
2542 TCGv taddr = tcg_temp_local_new();
2543 TCGv lladdr = tcg_temp_local_new();
2544 TCGv_i64 tval = tcg_temp_new_i64();
2545 TCGv_i64 llval = tcg_temp_new_i64();
2546 TCGv_i64 val = tcg_temp_new_i64();
2547 TCGv tmp1 = tcg_temp_new();
2548 TCGv tmp2 = tcg_temp_new();
2549 TCGLabel *lab_fail = gen_new_label();
2550 TCGLabel *lab_done = gen_new_label();
2552 gen_base_offset_addr(ctx, taddr, base, offset);
2554 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2555 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2557 gen_load_gpr(tmp1, reg1);
2558 gen_load_gpr(tmp2, reg2);
2560 #ifdef TARGET_WORDS_BIGENDIAN
2561 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2562 #else
2563 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2564 #endif
2566 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2567 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2568 ctx->mem_idx, MO_64);
2569 if (reg1 != 0) {
2570 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2572 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2574 gen_set_label(lab_fail);
2576 if (reg1 != 0) {
2577 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2579 gen_set_label(lab_done);
2580 tcg_gen_movi_tl(lladdr, -1);
2581 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2584 /* Load and store */
2585 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2586 TCGv t0)
2588 /* Don't do NOP if destination is zero: we must perform the actual
2589 memory access. */
2590 switch (opc) {
2591 case OPC_LWC1:
2593 TCGv_i32 fp0 = tcg_temp_new_i32();
2594 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2595 ctx->default_tcg_memop_mask);
2596 gen_store_fpr32(ctx, fp0, ft);
2597 tcg_temp_free_i32(fp0);
2599 break;
2600 case OPC_SWC1:
2602 TCGv_i32 fp0 = tcg_temp_new_i32();
2603 gen_load_fpr32(ctx, fp0, ft);
2604 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2605 ctx->default_tcg_memop_mask);
2606 tcg_temp_free_i32(fp0);
2608 break;
2609 case OPC_LDC1:
2611 TCGv_i64 fp0 = tcg_temp_new_i64();
2612 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2613 ctx->default_tcg_memop_mask);
2614 gen_store_fpr64(ctx, fp0, ft);
2615 tcg_temp_free_i64(fp0);
2617 break;
2618 case OPC_SDC1:
2620 TCGv_i64 fp0 = tcg_temp_new_i64();
2621 gen_load_fpr64(ctx, fp0, ft);
2622 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2623 ctx->default_tcg_memop_mask);
2624 tcg_temp_free_i64(fp0);
2626 break;
2627 default:
2628 MIPS_INVAL("flt_ldst");
2629 generate_exception_end(ctx, EXCP_RI);
2630 break;
2634 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2635 int rs, int16_t imm)
2637 TCGv t0 = tcg_temp_new();
2639 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2640 check_cp1_enabled(ctx);
2641 switch (op) {
2642 case OPC_LDC1:
2643 case OPC_SDC1:
2644 check_insn(ctx, ISA_MIPS2);
2645 /* Fallthrough */
2646 default:
2647 gen_base_offset_addr(ctx, t0, rs, imm);
2648 gen_flt_ldst(ctx, op, rt, t0);
2650 } else {
2651 generate_exception_err(ctx, EXCP_CpU, 1);
2653 tcg_temp_free(t0);
2656 /* Arithmetic with immediate operand */
2657 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2658 int rt, int rs, int imm)
2660 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2662 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2663 /* If no destination, treat it as a NOP.
2664 For addi, we must generate the overflow exception when needed. */
2665 return;
2667 switch (opc) {
2668 case OPC_ADDI:
2670 TCGv t0 = tcg_temp_local_new();
2671 TCGv t1 = tcg_temp_new();
2672 TCGv t2 = tcg_temp_new();
2673 TCGLabel *l1 = gen_new_label();
2675 gen_load_gpr(t1, rs);
2676 tcg_gen_addi_tl(t0, t1, uimm);
2677 tcg_gen_ext32s_tl(t0, t0);
2679 tcg_gen_xori_tl(t1, t1, ~uimm);
2680 tcg_gen_xori_tl(t2, t0, uimm);
2681 tcg_gen_and_tl(t1, t1, t2);
2682 tcg_temp_free(t2);
2683 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2684 tcg_temp_free(t1);
2685 /* operands of same sign, result different sign */
2686 generate_exception(ctx, EXCP_OVERFLOW);
2687 gen_set_label(l1);
2688 tcg_gen_ext32s_tl(t0, t0);
2689 gen_store_gpr(t0, rt);
2690 tcg_temp_free(t0);
2692 break;
2693 case OPC_ADDIU:
2694 if (rs != 0) {
2695 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2696 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2697 } else {
2698 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2700 break;
2701 #if defined(TARGET_MIPS64)
2702 case OPC_DADDI:
2704 TCGv t0 = tcg_temp_local_new();
2705 TCGv t1 = tcg_temp_new();
2706 TCGv t2 = tcg_temp_new();
2707 TCGLabel *l1 = gen_new_label();
2709 gen_load_gpr(t1, rs);
2710 tcg_gen_addi_tl(t0, t1, uimm);
2712 tcg_gen_xori_tl(t1, t1, ~uimm);
2713 tcg_gen_xori_tl(t2, t0, uimm);
2714 tcg_gen_and_tl(t1, t1, t2);
2715 tcg_temp_free(t2);
2716 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2717 tcg_temp_free(t1);
2718 /* operands of same sign, result different sign */
2719 generate_exception(ctx, EXCP_OVERFLOW);
2720 gen_set_label(l1);
2721 gen_store_gpr(t0, rt);
2722 tcg_temp_free(t0);
2724 break;
2725 case OPC_DADDIU:
2726 if (rs != 0) {
2727 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2728 } else {
2729 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2731 break;
2732 #endif
2736 /* Logic with immediate operand */
2737 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2738 int rt, int rs, int16_t imm)
2740 target_ulong uimm;
2742 if (rt == 0) {
2743 /* If no destination, treat it as a NOP. */
2744 return;
2746 uimm = (uint16_t)imm;
2747 switch (opc) {
2748 case OPC_ANDI:
2749 if (likely(rs != 0))
2750 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2751 else
2752 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2753 break;
2754 case OPC_ORI:
2755 if (rs != 0)
2756 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2757 else
2758 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2759 break;
2760 case OPC_XORI:
2761 if (likely(rs != 0))
2762 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2763 else
2764 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2765 break;
2766 case OPC_LUI:
2767 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2768 /* OPC_AUI */
2769 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2770 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2771 } else {
2772 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2774 break;
2776 default:
2777 break;
2781 /* Set on less than with immediate operand */
2782 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2783 int rt, int rs, int16_t imm)
2785 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2786 TCGv t0;
2788 if (rt == 0) {
2789 /* If no destination, treat it as a NOP. */
2790 return;
2792 t0 = tcg_temp_new();
2793 gen_load_gpr(t0, rs);
2794 switch (opc) {
2795 case OPC_SLTI:
2796 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2797 break;
2798 case OPC_SLTIU:
2799 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2800 break;
2802 tcg_temp_free(t0);
2805 /* Shifts with immediate operand */
2806 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2807 int rt, int rs, int16_t imm)
2809 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2810 TCGv t0;
2812 if (rt == 0) {
2813 /* If no destination, treat it as a NOP. */
2814 return;
2817 t0 = tcg_temp_new();
2818 gen_load_gpr(t0, rs);
2819 switch (opc) {
2820 case OPC_SLL:
2821 tcg_gen_shli_tl(t0, t0, uimm);
2822 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2823 break;
2824 case OPC_SRA:
2825 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2826 break;
2827 case OPC_SRL:
2828 if (uimm != 0) {
2829 tcg_gen_ext32u_tl(t0, t0);
2830 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2831 } else {
2832 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2834 break;
2835 case OPC_ROTR:
2836 if (uimm != 0) {
2837 TCGv_i32 t1 = tcg_temp_new_i32();
2839 tcg_gen_trunc_tl_i32(t1, t0);
2840 tcg_gen_rotri_i32(t1, t1, uimm);
2841 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2842 tcg_temp_free_i32(t1);
2843 } else {
2844 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2846 break;
2847 #if defined(TARGET_MIPS64)
2848 case OPC_DSLL:
2849 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2850 break;
2851 case OPC_DSRA:
2852 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2853 break;
2854 case OPC_DSRL:
2855 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2856 break;
2857 case OPC_DROTR:
2858 if (uimm != 0) {
2859 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2860 } else {
2861 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2863 break;
2864 case OPC_DSLL32:
2865 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2866 break;
2867 case OPC_DSRA32:
2868 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2869 break;
2870 case OPC_DSRL32:
2871 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2872 break;
2873 case OPC_DROTR32:
2874 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2875 break;
2876 #endif
2878 tcg_temp_free(t0);
2881 /* Arithmetic */
2882 static void gen_arith(DisasContext *ctx, uint32_t opc,
2883 int rd, int rs, int rt)
2885 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2886 && opc != OPC_DADD && opc != OPC_DSUB) {
2887 /* If no destination, treat it as a NOP.
2888 For add & sub, we must generate the overflow exception when needed. */
2889 return;
2892 switch (opc) {
2893 case OPC_ADD:
2895 TCGv t0 = tcg_temp_local_new();
2896 TCGv t1 = tcg_temp_new();
2897 TCGv t2 = tcg_temp_new();
2898 TCGLabel *l1 = gen_new_label();
2900 gen_load_gpr(t1, rs);
2901 gen_load_gpr(t2, rt);
2902 tcg_gen_add_tl(t0, t1, t2);
2903 tcg_gen_ext32s_tl(t0, t0);
2904 tcg_gen_xor_tl(t1, t1, t2);
2905 tcg_gen_xor_tl(t2, t0, t2);
2906 tcg_gen_andc_tl(t1, t2, t1);
2907 tcg_temp_free(t2);
2908 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2909 tcg_temp_free(t1);
2910 /* operands of same sign, result different sign */
2911 generate_exception(ctx, EXCP_OVERFLOW);
2912 gen_set_label(l1);
2913 gen_store_gpr(t0, rd);
2914 tcg_temp_free(t0);
2916 break;
2917 case OPC_ADDU:
2918 if (rs != 0 && rt != 0) {
2919 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2920 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2921 } else if (rs == 0 && rt != 0) {
2922 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2923 } else if (rs != 0 && rt == 0) {
2924 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2925 } else {
2926 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2928 break;
2929 case OPC_SUB:
2931 TCGv t0 = tcg_temp_local_new();
2932 TCGv t1 = tcg_temp_new();
2933 TCGv t2 = tcg_temp_new();
2934 TCGLabel *l1 = gen_new_label();
2936 gen_load_gpr(t1, rs);
2937 gen_load_gpr(t2, rt);
2938 tcg_gen_sub_tl(t0, t1, t2);
2939 tcg_gen_ext32s_tl(t0, t0);
2940 tcg_gen_xor_tl(t2, t1, t2);
2941 tcg_gen_xor_tl(t1, t0, t1);
2942 tcg_gen_and_tl(t1, t1, t2);
2943 tcg_temp_free(t2);
2944 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2945 tcg_temp_free(t1);
2946 /* operands of different sign, first operand and result different sign */
2947 generate_exception(ctx, EXCP_OVERFLOW);
2948 gen_set_label(l1);
2949 gen_store_gpr(t0, rd);
2950 tcg_temp_free(t0);
2952 break;
2953 case OPC_SUBU:
2954 if (rs != 0 && rt != 0) {
2955 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2956 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2957 } else if (rs == 0 && rt != 0) {
2958 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2959 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2960 } else if (rs != 0 && rt == 0) {
2961 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2962 } else {
2963 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2965 break;
2966 #if defined(TARGET_MIPS64)
2967 case OPC_DADD:
2969 TCGv t0 = tcg_temp_local_new();
2970 TCGv t1 = tcg_temp_new();
2971 TCGv t2 = tcg_temp_new();
2972 TCGLabel *l1 = gen_new_label();
2974 gen_load_gpr(t1, rs);
2975 gen_load_gpr(t2, rt);
2976 tcg_gen_add_tl(t0, t1, t2);
2977 tcg_gen_xor_tl(t1, t1, t2);
2978 tcg_gen_xor_tl(t2, t0, t2);
2979 tcg_gen_andc_tl(t1, t2, t1);
2980 tcg_temp_free(t2);
2981 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2982 tcg_temp_free(t1);
2983 /* operands of same sign, result different sign */
2984 generate_exception(ctx, EXCP_OVERFLOW);
2985 gen_set_label(l1);
2986 gen_store_gpr(t0, rd);
2987 tcg_temp_free(t0);
2989 break;
2990 case OPC_DADDU:
2991 if (rs != 0 && rt != 0) {
2992 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2993 } else if (rs == 0 && rt != 0) {
2994 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2995 } else if (rs != 0 && rt == 0) {
2996 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2997 } else {
2998 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3000 break;
3001 case OPC_DSUB:
3003 TCGv t0 = tcg_temp_local_new();
3004 TCGv t1 = tcg_temp_new();
3005 TCGv t2 = tcg_temp_new();
3006 TCGLabel *l1 = gen_new_label();
3008 gen_load_gpr(t1, rs);
3009 gen_load_gpr(t2, rt);
3010 tcg_gen_sub_tl(t0, t1, t2);
3011 tcg_gen_xor_tl(t2, t1, t2);
3012 tcg_gen_xor_tl(t1, t0, t1);
3013 tcg_gen_and_tl(t1, t1, t2);
3014 tcg_temp_free(t2);
3015 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3016 tcg_temp_free(t1);
3017 /* operands of different sign, first operand and result different sign */
3018 generate_exception(ctx, EXCP_OVERFLOW);
3019 gen_set_label(l1);
3020 gen_store_gpr(t0, rd);
3021 tcg_temp_free(t0);
3023 break;
3024 case OPC_DSUBU:
3025 if (rs != 0 && rt != 0) {
3026 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3027 } else if (rs == 0 && rt != 0) {
3028 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3029 } else if (rs != 0 && rt == 0) {
3030 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3031 } else {
3032 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3034 break;
3035 #endif
3036 case OPC_MUL:
3037 if (likely(rs != 0 && rt != 0)) {
3038 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3039 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3040 } else {
3041 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3043 break;
3047 /* Conditional move */
3048 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3049 int rd, int rs, int rt)
3051 TCGv t0, t1, t2;
3053 if (rd == 0) {
3054 /* If no destination, treat it as a NOP. */
3055 return;
3058 t0 = tcg_temp_new();
3059 gen_load_gpr(t0, rt);
3060 t1 = tcg_const_tl(0);
3061 t2 = tcg_temp_new();
3062 gen_load_gpr(t2, rs);
3063 switch (opc) {
3064 case OPC_MOVN:
3065 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3066 break;
3067 case OPC_MOVZ:
3068 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3069 break;
3070 case OPC_SELNEZ:
3071 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3072 break;
3073 case OPC_SELEQZ:
3074 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3075 break;
3077 tcg_temp_free(t2);
3078 tcg_temp_free(t1);
3079 tcg_temp_free(t0);
3082 /* Logic */
3083 static void gen_logic(DisasContext *ctx, uint32_t opc,
3084 int rd, int rs, int rt)
3086 if (rd == 0) {
3087 /* If no destination, treat it as a NOP. */
3088 return;
3091 switch (opc) {
3092 case OPC_AND:
3093 if (likely(rs != 0 && rt != 0)) {
3094 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3095 } else {
3096 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3098 break;
3099 case OPC_NOR:
3100 if (rs != 0 && rt != 0) {
3101 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3102 } else if (rs == 0 && rt != 0) {
3103 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3104 } else if (rs != 0 && rt == 0) {
3105 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3106 } else {
3107 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3109 break;
3110 case OPC_OR:
3111 if (likely(rs != 0 && rt != 0)) {
3112 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3113 } else if (rs == 0 && rt != 0) {
3114 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3115 } else if (rs != 0 && rt == 0) {
3116 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3117 } else {
3118 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3120 break;
3121 case OPC_XOR:
3122 if (likely(rs != 0 && rt != 0)) {
3123 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3124 } else if (rs == 0 && rt != 0) {
3125 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3126 } else if (rs != 0 && rt == 0) {
3127 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3128 } else {
3129 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3131 break;
3135 /* Set on lower than */
3136 static void gen_slt(DisasContext *ctx, uint32_t opc,
3137 int rd, int rs, int rt)
3139 TCGv t0, t1;
3141 if (rd == 0) {
3142 /* If no destination, treat it as a NOP. */
3143 return;
3146 t0 = tcg_temp_new();
3147 t1 = tcg_temp_new();
3148 gen_load_gpr(t0, rs);
3149 gen_load_gpr(t1, rt);
3150 switch (opc) {
3151 case OPC_SLT:
3152 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3153 break;
3154 case OPC_SLTU:
3155 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3156 break;
3158 tcg_temp_free(t0);
3159 tcg_temp_free(t1);
3162 /* Shifts */
3163 static void gen_shift(DisasContext *ctx, uint32_t opc,
3164 int rd, int rs, int rt)
3166 TCGv t0, t1;
3168 if (rd == 0) {
3169 /* If no destination, treat it as a NOP.
3170 For add & sub, we must generate the overflow exception when needed. */
3171 return;
3174 t0 = tcg_temp_new();
3175 t1 = tcg_temp_new();
3176 gen_load_gpr(t0, rs);
3177 gen_load_gpr(t1, rt);
3178 switch (opc) {
3179 case OPC_SLLV:
3180 tcg_gen_andi_tl(t0, t0, 0x1f);
3181 tcg_gen_shl_tl(t0, t1, t0);
3182 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3183 break;
3184 case OPC_SRAV:
3185 tcg_gen_andi_tl(t0, t0, 0x1f);
3186 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3187 break;
3188 case OPC_SRLV:
3189 tcg_gen_ext32u_tl(t1, t1);
3190 tcg_gen_andi_tl(t0, t0, 0x1f);
3191 tcg_gen_shr_tl(t0, t1, t0);
3192 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3193 break;
3194 case OPC_ROTRV:
3196 TCGv_i32 t2 = tcg_temp_new_i32();
3197 TCGv_i32 t3 = tcg_temp_new_i32();
3199 tcg_gen_trunc_tl_i32(t2, t0);
3200 tcg_gen_trunc_tl_i32(t3, t1);
3201 tcg_gen_andi_i32(t2, t2, 0x1f);
3202 tcg_gen_rotr_i32(t2, t3, t2);
3203 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3204 tcg_temp_free_i32(t2);
3205 tcg_temp_free_i32(t3);
3207 break;
3208 #if defined(TARGET_MIPS64)
3209 case OPC_DSLLV:
3210 tcg_gen_andi_tl(t0, t0, 0x3f);
3211 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3212 break;
3213 case OPC_DSRAV:
3214 tcg_gen_andi_tl(t0, t0, 0x3f);
3215 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3216 break;
3217 case OPC_DSRLV:
3218 tcg_gen_andi_tl(t0, t0, 0x3f);
3219 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3220 break;
3221 case OPC_DROTRV:
3222 tcg_gen_andi_tl(t0, t0, 0x3f);
3223 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3224 break;
3225 #endif
3227 tcg_temp_free(t0);
3228 tcg_temp_free(t1);
3231 /* Arithmetic on HI/LO registers */
3232 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3234 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3235 /* Treat as NOP. */
3236 return;
3239 if (acc != 0) {
3240 check_dsp(ctx);
3243 switch (opc) {
3244 case OPC_MFHI:
3245 #if defined(TARGET_MIPS64)
3246 if (acc != 0) {
3247 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3248 } else
3249 #endif
3251 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3253 break;
3254 case OPC_MFLO:
3255 #if defined(TARGET_MIPS64)
3256 if (acc != 0) {
3257 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3258 } else
3259 #endif
3261 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3263 break;
3264 case OPC_MTHI:
3265 if (reg != 0) {
3266 #if defined(TARGET_MIPS64)
3267 if (acc != 0) {
3268 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3269 } else
3270 #endif
3272 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3274 } else {
3275 tcg_gen_movi_tl(cpu_HI[acc], 0);
3277 break;
3278 case OPC_MTLO:
3279 if (reg != 0) {
3280 #if defined(TARGET_MIPS64)
3281 if (acc != 0) {
3282 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3283 } else
3284 #endif
3286 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3288 } else {
3289 tcg_gen_movi_tl(cpu_LO[acc], 0);
3291 break;
3295 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3296 TCGMemOp memop)
3298 TCGv t0 = tcg_const_tl(addr);
3299 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3300 gen_store_gpr(t0, reg);
3301 tcg_temp_free(t0);
3304 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3305 int rs)
3307 target_long offset;
3308 target_long addr;
3310 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3311 case OPC_ADDIUPC:
3312 if (rs != 0) {
3313 offset = sextract32(ctx->opcode << 2, 0, 21);
3314 addr = addr_add(ctx, pc, offset);
3315 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3317 break;
3318 case R6_OPC_LWPC:
3319 offset = sextract32(ctx->opcode << 2, 0, 21);
3320 addr = addr_add(ctx, pc, offset);
3321 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3322 break;
3323 #if defined(TARGET_MIPS64)
3324 case OPC_LWUPC:
3325 check_mips_64(ctx);
3326 offset = sextract32(ctx->opcode << 2, 0, 21);
3327 addr = addr_add(ctx, pc, offset);
3328 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3329 break;
3330 #endif
3331 default:
3332 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3333 case OPC_AUIPC:
3334 if (rs != 0) {
3335 offset = sextract32(ctx->opcode, 0, 16) << 16;
3336 addr = addr_add(ctx, pc, offset);
3337 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3339 break;
3340 case OPC_ALUIPC:
3341 if (rs != 0) {
3342 offset = sextract32(ctx->opcode, 0, 16) << 16;
3343 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3344 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3346 break;
3347 #if defined(TARGET_MIPS64)
3348 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3349 case R6_OPC_LDPC + (1 << 16):
3350 case R6_OPC_LDPC + (2 << 16):
3351 case R6_OPC_LDPC + (3 << 16):
3352 check_mips_64(ctx);
3353 offset = sextract32(ctx->opcode << 3, 0, 21);
3354 addr = addr_add(ctx, (pc & ~0x7), offset);
3355 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3356 break;
3357 #endif
3358 default:
3359 MIPS_INVAL("OPC_PCREL");
3360 generate_exception_end(ctx, EXCP_RI);
3361 break;
3363 break;
3367 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3369 TCGv t0, t1;
3371 if (rd == 0) {
3372 /* Treat as NOP. */
3373 return;
3376 t0 = tcg_temp_new();
3377 t1 = tcg_temp_new();
3379 gen_load_gpr(t0, rs);
3380 gen_load_gpr(t1, rt);
3382 switch (opc) {
3383 case R6_OPC_DIV:
3385 TCGv t2 = tcg_temp_new();
3386 TCGv t3 = tcg_temp_new();
3387 tcg_gen_ext32s_tl(t0, t0);
3388 tcg_gen_ext32s_tl(t1, t1);
3389 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3390 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3391 tcg_gen_and_tl(t2, t2, t3);
3392 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3393 tcg_gen_or_tl(t2, t2, t3);
3394 tcg_gen_movi_tl(t3, 0);
3395 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3396 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3397 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3398 tcg_temp_free(t3);
3399 tcg_temp_free(t2);
3401 break;
3402 case R6_OPC_MOD:
3404 TCGv t2 = tcg_temp_new();
3405 TCGv t3 = tcg_temp_new();
3406 tcg_gen_ext32s_tl(t0, t0);
3407 tcg_gen_ext32s_tl(t1, t1);
3408 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3409 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3410 tcg_gen_and_tl(t2, t2, t3);
3411 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3412 tcg_gen_or_tl(t2, t2, t3);
3413 tcg_gen_movi_tl(t3, 0);
3414 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3415 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3416 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3417 tcg_temp_free(t3);
3418 tcg_temp_free(t2);
3420 break;
3421 case R6_OPC_DIVU:
3423 TCGv t2 = tcg_const_tl(0);
3424 TCGv t3 = tcg_const_tl(1);
3425 tcg_gen_ext32u_tl(t0, t0);
3426 tcg_gen_ext32u_tl(t1, t1);
3427 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3428 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3429 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3430 tcg_temp_free(t3);
3431 tcg_temp_free(t2);
3433 break;
3434 case R6_OPC_MODU:
3436 TCGv t2 = tcg_const_tl(0);
3437 TCGv t3 = tcg_const_tl(1);
3438 tcg_gen_ext32u_tl(t0, t0);
3439 tcg_gen_ext32u_tl(t1, t1);
3440 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3441 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3442 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3443 tcg_temp_free(t3);
3444 tcg_temp_free(t2);
3446 break;
3447 case R6_OPC_MUL:
3449 TCGv_i32 t2 = tcg_temp_new_i32();
3450 TCGv_i32 t3 = tcg_temp_new_i32();
3451 tcg_gen_trunc_tl_i32(t2, t0);
3452 tcg_gen_trunc_tl_i32(t3, t1);
3453 tcg_gen_mul_i32(t2, t2, t3);
3454 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3455 tcg_temp_free_i32(t2);
3456 tcg_temp_free_i32(t3);
3458 break;
3459 case R6_OPC_MUH:
3461 TCGv_i32 t2 = tcg_temp_new_i32();
3462 TCGv_i32 t3 = tcg_temp_new_i32();
3463 tcg_gen_trunc_tl_i32(t2, t0);
3464 tcg_gen_trunc_tl_i32(t3, t1);
3465 tcg_gen_muls2_i32(t2, t3, t2, t3);
3466 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3467 tcg_temp_free_i32(t2);
3468 tcg_temp_free_i32(t3);
3470 break;
3471 case R6_OPC_MULU:
3473 TCGv_i32 t2 = tcg_temp_new_i32();
3474 TCGv_i32 t3 = tcg_temp_new_i32();
3475 tcg_gen_trunc_tl_i32(t2, t0);
3476 tcg_gen_trunc_tl_i32(t3, t1);
3477 tcg_gen_mul_i32(t2, t2, t3);
3478 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3479 tcg_temp_free_i32(t2);
3480 tcg_temp_free_i32(t3);
3482 break;
3483 case R6_OPC_MUHU:
3485 TCGv_i32 t2 = tcg_temp_new_i32();
3486 TCGv_i32 t3 = tcg_temp_new_i32();
3487 tcg_gen_trunc_tl_i32(t2, t0);
3488 tcg_gen_trunc_tl_i32(t3, t1);
3489 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3490 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3491 tcg_temp_free_i32(t2);
3492 tcg_temp_free_i32(t3);
3494 break;
3495 #if defined(TARGET_MIPS64)
3496 case R6_OPC_DDIV:
3498 TCGv t2 = tcg_temp_new();
3499 TCGv t3 = tcg_temp_new();
3500 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3501 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3502 tcg_gen_and_tl(t2, t2, t3);
3503 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3504 tcg_gen_or_tl(t2, t2, t3);
3505 tcg_gen_movi_tl(t3, 0);
3506 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3507 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3508 tcg_temp_free(t3);
3509 tcg_temp_free(t2);
3511 break;
3512 case R6_OPC_DMOD:
3514 TCGv t2 = tcg_temp_new();
3515 TCGv t3 = tcg_temp_new();
3516 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3517 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3518 tcg_gen_and_tl(t2, t2, t3);
3519 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3520 tcg_gen_or_tl(t2, t2, t3);
3521 tcg_gen_movi_tl(t3, 0);
3522 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3523 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3524 tcg_temp_free(t3);
3525 tcg_temp_free(t2);
3527 break;
3528 case R6_OPC_DDIVU:
3530 TCGv t2 = tcg_const_tl(0);
3531 TCGv t3 = tcg_const_tl(1);
3532 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3533 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3534 tcg_temp_free(t3);
3535 tcg_temp_free(t2);
3537 break;
3538 case R6_OPC_DMODU:
3540 TCGv t2 = tcg_const_tl(0);
3541 TCGv t3 = tcg_const_tl(1);
3542 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3543 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3544 tcg_temp_free(t3);
3545 tcg_temp_free(t2);
3547 break;
3548 case R6_OPC_DMUL:
3549 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3550 break;
3551 case R6_OPC_DMUH:
3553 TCGv t2 = tcg_temp_new();
3554 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3555 tcg_temp_free(t2);
3557 break;
3558 case R6_OPC_DMULU:
3559 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3560 break;
3561 case R6_OPC_DMUHU:
3563 TCGv t2 = tcg_temp_new();
3564 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3565 tcg_temp_free(t2);
3567 break;
3568 #endif
3569 default:
3570 MIPS_INVAL("r6 mul/div");
3571 generate_exception_end(ctx, EXCP_RI);
3572 goto out;
3574 out:
3575 tcg_temp_free(t0);
3576 tcg_temp_free(t1);
3579 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3580 int acc, int rs, int rt)
3582 TCGv t0, t1;
3584 t0 = tcg_temp_new();
3585 t1 = tcg_temp_new();
3587 gen_load_gpr(t0, rs);
3588 gen_load_gpr(t1, rt);
3590 if (acc != 0) {
3591 check_dsp(ctx);
3594 switch (opc) {
3595 case OPC_DIV:
3597 TCGv t2 = tcg_temp_new();
3598 TCGv t3 = tcg_temp_new();
3599 tcg_gen_ext32s_tl(t0, t0);
3600 tcg_gen_ext32s_tl(t1, t1);
3601 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3602 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3603 tcg_gen_and_tl(t2, t2, t3);
3604 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3605 tcg_gen_or_tl(t2, t2, t3);
3606 tcg_gen_movi_tl(t3, 0);
3607 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3608 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3609 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3610 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3611 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3612 tcg_temp_free(t3);
3613 tcg_temp_free(t2);
3615 break;
3616 case OPC_DIVU:
3618 TCGv t2 = tcg_const_tl(0);
3619 TCGv t3 = tcg_const_tl(1);
3620 tcg_gen_ext32u_tl(t0, t0);
3621 tcg_gen_ext32u_tl(t1, t1);
3622 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3623 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3624 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3625 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3626 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3627 tcg_temp_free(t3);
3628 tcg_temp_free(t2);
3630 break;
3631 case OPC_MULT:
3633 TCGv_i32 t2 = tcg_temp_new_i32();
3634 TCGv_i32 t3 = tcg_temp_new_i32();
3635 tcg_gen_trunc_tl_i32(t2, t0);
3636 tcg_gen_trunc_tl_i32(t3, t1);
3637 tcg_gen_muls2_i32(t2, t3, t2, t3);
3638 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3639 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3640 tcg_temp_free_i32(t2);
3641 tcg_temp_free_i32(t3);
3643 break;
3644 case OPC_MULTU:
3646 TCGv_i32 t2 = tcg_temp_new_i32();
3647 TCGv_i32 t3 = tcg_temp_new_i32();
3648 tcg_gen_trunc_tl_i32(t2, t0);
3649 tcg_gen_trunc_tl_i32(t3, t1);
3650 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3651 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3652 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3653 tcg_temp_free_i32(t2);
3654 tcg_temp_free_i32(t3);
3656 break;
3657 #if defined(TARGET_MIPS64)
3658 case OPC_DDIV:
3660 TCGv t2 = tcg_temp_new();
3661 TCGv t3 = tcg_temp_new();
3662 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3663 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3664 tcg_gen_and_tl(t2, t2, t3);
3665 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3666 tcg_gen_or_tl(t2, t2, t3);
3667 tcg_gen_movi_tl(t3, 0);
3668 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3669 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3670 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3671 tcg_temp_free(t3);
3672 tcg_temp_free(t2);
3674 break;
3675 case OPC_DDIVU:
3677 TCGv t2 = tcg_const_tl(0);
3678 TCGv t3 = tcg_const_tl(1);
3679 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3680 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3681 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3682 tcg_temp_free(t3);
3683 tcg_temp_free(t2);
3685 break;
3686 case OPC_DMULT:
3687 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3688 break;
3689 case OPC_DMULTU:
3690 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3691 break;
3692 #endif
3693 case OPC_MADD:
3695 TCGv_i64 t2 = tcg_temp_new_i64();
3696 TCGv_i64 t3 = tcg_temp_new_i64();
3698 tcg_gen_ext_tl_i64(t2, t0);
3699 tcg_gen_ext_tl_i64(t3, t1);
3700 tcg_gen_mul_i64(t2, t2, t3);
3701 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3702 tcg_gen_add_i64(t2, t2, t3);
3703 tcg_temp_free_i64(t3);
3704 gen_move_low32(cpu_LO[acc], t2);
3705 gen_move_high32(cpu_HI[acc], t2);
3706 tcg_temp_free_i64(t2);
3708 break;
3709 case OPC_MADDU:
3711 TCGv_i64 t2 = tcg_temp_new_i64();
3712 TCGv_i64 t3 = tcg_temp_new_i64();
3714 tcg_gen_ext32u_tl(t0, t0);
3715 tcg_gen_ext32u_tl(t1, t1);
3716 tcg_gen_extu_tl_i64(t2, t0);
3717 tcg_gen_extu_tl_i64(t3, t1);
3718 tcg_gen_mul_i64(t2, t2, t3);
3719 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3720 tcg_gen_add_i64(t2, t2, t3);
3721 tcg_temp_free_i64(t3);
3722 gen_move_low32(cpu_LO[acc], t2);
3723 gen_move_high32(cpu_HI[acc], t2);
3724 tcg_temp_free_i64(t2);
3726 break;
3727 case OPC_MSUB:
3729 TCGv_i64 t2 = tcg_temp_new_i64();
3730 TCGv_i64 t3 = tcg_temp_new_i64();
3732 tcg_gen_ext_tl_i64(t2, t0);
3733 tcg_gen_ext_tl_i64(t3, t1);
3734 tcg_gen_mul_i64(t2, t2, t3);
3735 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3736 tcg_gen_sub_i64(t2, t3, t2);
3737 tcg_temp_free_i64(t3);
3738 gen_move_low32(cpu_LO[acc], t2);
3739 gen_move_high32(cpu_HI[acc], t2);
3740 tcg_temp_free_i64(t2);
3742 break;
3743 case OPC_MSUBU:
3745 TCGv_i64 t2 = tcg_temp_new_i64();
3746 TCGv_i64 t3 = tcg_temp_new_i64();
3748 tcg_gen_ext32u_tl(t0, t0);
3749 tcg_gen_ext32u_tl(t1, t1);
3750 tcg_gen_extu_tl_i64(t2, t0);
3751 tcg_gen_extu_tl_i64(t3, t1);
3752 tcg_gen_mul_i64(t2, t2, t3);
3753 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3754 tcg_gen_sub_i64(t2, t3, t2);
3755 tcg_temp_free_i64(t3);
3756 gen_move_low32(cpu_LO[acc], t2);
3757 gen_move_high32(cpu_HI[acc], t2);
3758 tcg_temp_free_i64(t2);
3760 break;
3761 default:
3762 MIPS_INVAL("mul/div");
3763 generate_exception_end(ctx, EXCP_RI);
3764 goto out;
3766 out:
3767 tcg_temp_free(t0);
3768 tcg_temp_free(t1);
3771 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3772 int rd, int rs, int rt)
3774 TCGv t0 = tcg_temp_new();
3775 TCGv t1 = tcg_temp_new();
3777 gen_load_gpr(t0, rs);
3778 gen_load_gpr(t1, rt);
3780 switch (opc) {
3781 case OPC_VR54XX_MULS:
3782 gen_helper_muls(t0, cpu_env, t0, t1);
3783 break;
3784 case OPC_VR54XX_MULSU:
3785 gen_helper_mulsu(t0, cpu_env, t0, t1);
3786 break;
3787 case OPC_VR54XX_MACC:
3788 gen_helper_macc(t0, cpu_env, t0, t1);
3789 break;
3790 case OPC_VR54XX_MACCU:
3791 gen_helper_maccu(t0, cpu_env, t0, t1);
3792 break;
3793 case OPC_VR54XX_MSAC:
3794 gen_helper_msac(t0, cpu_env, t0, t1);
3795 break;
3796 case OPC_VR54XX_MSACU:
3797 gen_helper_msacu(t0, cpu_env, t0, t1);
3798 break;
3799 case OPC_VR54XX_MULHI:
3800 gen_helper_mulhi(t0, cpu_env, t0, t1);
3801 break;
3802 case OPC_VR54XX_MULHIU:
3803 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3804 break;
3805 case OPC_VR54XX_MULSHI:
3806 gen_helper_mulshi(t0, cpu_env, t0, t1);
3807 break;
3808 case OPC_VR54XX_MULSHIU:
3809 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3810 break;
3811 case OPC_VR54XX_MACCHI:
3812 gen_helper_macchi(t0, cpu_env, t0, t1);
3813 break;
3814 case OPC_VR54XX_MACCHIU:
3815 gen_helper_macchiu(t0, cpu_env, t0, t1);
3816 break;
3817 case OPC_VR54XX_MSACHI:
3818 gen_helper_msachi(t0, cpu_env, t0, t1);
3819 break;
3820 case OPC_VR54XX_MSACHIU:
3821 gen_helper_msachiu(t0, cpu_env, t0, t1);
3822 break;
3823 default:
3824 MIPS_INVAL("mul vr54xx");
3825 generate_exception_end(ctx, EXCP_RI);
3826 goto out;
3828 gen_store_gpr(t0, rd);
3830 out:
3831 tcg_temp_free(t0);
3832 tcg_temp_free(t1);
3835 static void gen_cl (DisasContext *ctx, uint32_t opc,
3836 int rd, int rs)
3838 TCGv t0;
3840 if (rd == 0) {
3841 /* Treat as NOP. */
3842 return;
3844 t0 = cpu_gpr[rd];
3845 gen_load_gpr(t0, rs);
3847 switch (opc) {
3848 case OPC_CLO:
3849 case R6_OPC_CLO:
3850 #if defined(TARGET_MIPS64)
3851 case OPC_DCLO:
3852 case R6_OPC_DCLO:
3853 #endif
3854 tcg_gen_not_tl(t0, t0);
3855 break;
3858 switch (opc) {
3859 case OPC_CLO:
3860 case R6_OPC_CLO:
3861 case OPC_CLZ:
3862 case R6_OPC_CLZ:
3863 tcg_gen_ext32u_tl(t0, t0);
3864 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3865 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3866 break;
3867 #if defined(TARGET_MIPS64)
3868 case OPC_DCLO:
3869 case R6_OPC_DCLO:
3870 case OPC_DCLZ:
3871 case R6_OPC_DCLZ:
3872 tcg_gen_clzi_i64(t0, t0, 64);
3873 break;
3874 #endif
3878 /* Godson integer instructions */
3879 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3880 int rd, int rs, int rt)
3882 TCGv t0, t1;
3884 if (rd == 0) {
3885 /* Treat as NOP. */
3886 return;
3889 switch (opc) {
3890 case OPC_MULT_G_2E:
3891 case OPC_MULT_G_2F:
3892 case OPC_MULTU_G_2E:
3893 case OPC_MULTU_G_2F:
3894 #if defined(TARGET_MIPS64)
3895 case OPC_DMULT_G_2E:
3896 case OPC_DMULT_G_2F:
3897 case OPC_DMULTU_G_2E:
3898 case OPC_DMULTU_G_2F:
3899 #endif
3900 t0 = tcg_temp_new();
3901 t1 = tcg_temp_new();
3902 break;
3903 default:
3904 t0 = tcg_temp_local_new();
3905 t1 = tcg_temp_local_new();
3906 break;
3909 gen_load_gpr(t0, rs);
3910 gen_load_gpr(t1, rt);
3912 switch (opc) {
3913 case OPC_MULT_G_2E:
3914 case OPC_MULT_G_2F:
3915 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3916 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3917 break;
3918 case OPC_MULTU_G_2E:
3919 case OPC_MULTU_G_2F:
3920 tcg_gen_ext32u_tl(t0, t0);
3921 tcg_gen_ext32u_tl(t1, t1);
3922 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3923 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3924 break;
3925 case OPC_DIV_G_2E:
3926 case OPC_DIV_G_2F:
3928 TCGLabel *l1 = gen_new_label();
3929 TCGLabel *l2 = gen_new_label();
3930 TCGLabel *l3 = gen_new_label();
3931 tcg_gen_ext32s_tl(t0, t0);
3932 tcg_gen_ext32s_tl(t1, t1);
3933 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3934 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3935 tcg_gen_br(l3);
3936 gen_set_label(l1);
3937 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3938 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3939 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3940 tcg_gen_br(l3);
3941 gen_set_label(l2);
3942 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3943 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3944 gen_set_label(l3);
3946 break;
3947 case OPC_DIVU_G_2E:
3948 case OPC_DIVU_G_2F:
3950 TCGLabel *l1 = gen_new_label();
3951 TCGLabel *l2 = gen_new_label();
3952 tcg_gen_ext32u_tl(t0, t0);
3953 tcg_gen_ext32u_tl(t1, t1);
3954 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3955 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3956 tcg_gen_br(l2);
3957 gen_set_label(l1);
3958 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3959 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3960 gen_set_label(l2);
3962 break;
3963 case OPC_MOD_G_2E:
3964 case OPC_MOD_G_2F:
3966 TCGLabel *l1 = gen_new_label();
3967 TCGLabel *l2 = gen_new_label();
3968 TCGLabel *l3 = gen_new_label();
3969 tcg_gen_ext32u_tl(t0, t0);
3970 tcg_gen_ext32u_tl(t1, t1);
3971 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3972 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3973 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3974 gen_set_label(l1);
3975 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3976 tcg_gen_br(l3);
3977 gen_set_label(l2);
3978 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3979 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3980 gen_set_label(l3);
3982 break;
3983 case OPC_MODU_G_2E:
3984 case OPC_MODU_G_2F:
3986 TCGLabel *l1 = gen_new_label();
3987 TCGLabel *l2 = gen_new_label();
3988 tcg_gen_ext32u_tl(t0, t0);
3989 tcg_gen_ext32u_tl(t1, t1);
3990 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3991 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3992 tcg_gen_br(l2);
3993 gen_set_label(l1);
3994 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3995 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3996 gen_set_label(l2);
3998 break;
3999 #if defined(TARGET_MIPS64)
4000 case OPC_DMULT_G_2E:
4001 case OPC_DMULT_G_2F:
4002 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4003 break;
4004 case OPC_DMULTU_G_2E:
4005 case OPC_DMULTU_G_2F:
4006 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4007 break;
4008 case OPC_DDIV_G_2E:
4009 case OPC_DDIV_G_2F:
4011 TCGLabel *l1 = gen_new_label();
4012 TCGLabel *l2 = gen_new_label();
4013 TCGLabel *l3 = gen_new_label();
4014 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4015 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4016 tcg_gen_br(l3);
4017 gen_set_label(l1);
4018 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4019 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4020 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4021 tcg_gen_br(l3);
4022 gen_set_label(l2);
4023 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4024 gen_set_label(l3);
4026 break;
4027 case OPC_DDIVU_G_2E:
4028 case OPC_DDIVU_G_2F:
4030 TCGLabel *l1 = gen_new_label();
4031 TCGLabel *l2 = gen_new_label();
4032 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4033 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4034 tcg_gen_br(l2);
4035 gen_set_label(l1);
4036 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4037 gen_set_label(l2);
4039 break;
4040 case OPC_DMOD_G_2E:
4041 case OPC_DMOD_G_2F:
4043 TCGLabel *l1 = gen_new_label();
4044 TCGLabel *l2 = gen_new_label();
4045 TCGLabel *l3 = gen_new_label();
4046 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4047 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4048 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4049 gen_set_label(l1);
4050 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4051 tcg_gen_br(l3);
4052 gen_set_label(l2);
4053 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4054 gen_set_label(l3);
4056 break;
4057 case OPC_DMODU_G_2E:
4058 case OPC_DMODU_G_2F:
4060 TCGLabel *l1 = gen_new_label();
4061 TCGLabel *l2 = gen_new_label();
4062 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4063 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4064 tcg_gen_br(l2);
4065 gen_set_label(l1);
4066 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4067 gen_set_label(l2);
4069 break;
4070 #endif
4073 tcg_temp_free(t0);
4074 tcg_temp_free(t1);
4077 /* Loongson multimedia instructions */
4078 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4080 uint32_t opc, shift_max;
4081 TCGv_i64 t0, t1;
4083 opc = MASK_LMI(ctx->opcode);
4084 switch (opc) {
4085 case OPC_ADD_CP2:
4086 case OPC_SUB_CP2:
4087 case OPC_DADD_CP2:
4088 case OPC_DSUB_CP2:
4089 t0 = tcg_temp_local_new_i64();
4090 t1 = tcg_temp_local_new_i64();
4091 break;
4092 default:
4093 t0 = tcg_temp_new_i64();
4094 t1 = tcg_temp_new_i64();
4095 break;
4098 check_cp1_enabled(ctx);
4099 gen_load_fpr64(ctx, t0, rs);
4100 gen_load_fpr64(ctx, t1, rt);
4102 #define LMI_HELPER(UP, LO) \
4103 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
4104 #define LMI_HELPER_1(UP, LO) \
4105 case OPC_##UP: gen_helper_##LO(t0, t0); break
4106 #define LMI_DIRECT(UP, LO, OP) \
4107 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
4109 switch (opc) {
4110 LMI_HELPER(PADDSH, paddsh);
4111 LMI_HELPER(PADDUSH, paddush);
4112 LMI_HELPER(PADDH, paddh);
4113 LMI_HELPER(PADDW, paddw);
4114 LMI_HELPER(PADDSB, paddsb);
4115 LMI_HELPER(PADDUSB, paddusb);
4116 LMI_HELPER(PADDB, paddb);
4118 LMI_HELPER(PSUBSH, psubsh);
4119 LMI_HELPER(PSUBUSH, psubush);
4120 LMI_HELPER(PSUBH, psubh);
4121 LMI_HELPER(PSUBW, psubw);
4122 LMI_HELPER(PSUBSB, psubsb);
4123 LMI_HELPER(PSUBUSB, psubusb);
4124 LMI_HELPER(PSUBB, psubb);
4126 LMI_HELPER(PSHUFH, pshufh);
4127 LMI_HELPER(PACKSSWH, packsswh);
4128 LMI_HELPER(PACKSSHB, packsshb);
4129 LMI_HELPER(PACKUSHB, packushb);
4131 LMI_HELPER(PUNPCKLHW, punpcklhw);
4132 LMI_HELPER(PUNPCKHHW, punpckhhw);
4133 LMI_HELPER(PUNPCKLBH, punpcklbh);
4134 LMI_HELPER(PUNPCKHBH, punpckhbh);
4135 LMI_HELPER(PUNPCKLWD, punpcklwd);
4136 LMI_HELPER(PUNPCKHWD, punpckhwd);
4138 LMI_HELPER(PAVGH, pavgh);
4139 LMI_HELPER(PAVGB, pavgb);
4140 LMI_HELPER(PMAXSH, pmaxsh);
4141 LMI_HELPER(PMINSH, pminsh);
4142 LMI_HELPER(PMAXUB, pmaxub);
4143 LMI_HELPER(PMINUB, pminub);
4145 LMI_HELPER(PCMPEQW, pcmpeqw);
4146 LMI_HELPER(PCMPGTW, pcmpgtw);
4147 LMI_HELPER(PCMPEQH, pcmpeqh);
4148 LMI_HELPER(PCMPGTH, pcmpgth);
4149 LMI_HELPER(PCMPEQB, pcmpeqb);
4150 LMI_HELPER(PCMPGTB, pcmpgtb);
4152 LMI_HELPER(PSLLW, psllw);
4153 LMI_HELPER(PSLLH, psllh);
4154 LMI_HELPER(PSRLW, psrlw);
4155 LMI_HELPER(PSRLH, psrlh);
4156 LMI_HELPER(PSRAW, psraw);
4157 LMI_HELPER(PSRAH, psrah);
4159 LMI_HELPER(PMULLH, pmullh);
4160 LMI_HELPER(PMULHH, pmulhh);
4161 LMI_HELPER(PMULHUH, pmulhuh);
4162 LMI_HELPER(PMADDHW, pmaddhw);
4164 LMI_HELPER(PASUBUB, pasubub);
4165 LMI_HELPER_1(BIADD, biadd);
4166 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4168 LMI_DIRECT(PADDD, paddd, add);
4169 LMI_DIRECT(PSUBD, psubd, sub);
4170 LMI_DIRECT(XOR_CP2, xor, xor);
4171 LMI_DIRECT(NOR_CP2, nor, nor);
4172 LMI_DIRECT(AND_CP2, and, and);
4173 LMI_DIRECT(OR_CP2, or, or);
4175 case OPC_PANDN:
4176 tcg_gen_andc_i64(t0, t1, t0);
4177 break;
4179 case OPC_PINSRH_0:
4180 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4181 break;
4182 case OPC_PINSRH_1:
4183 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4184 break;
4185 case OPC_PINSRH_2:
4186 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4187 break;
4188 case OPC_PINSRH_3:
4189 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4190 break;
4192 case OPC_PEXTRH:
4193 tcg_gen_andi_i64(t1, t1, 3);
4194 tcg_gen_shli_i64(t1, t1, 4);
4195 tcg_gen_shr_i64(t0, t0, t1);
4196 tcg_gen_ext16u_i64(t0, t0);
4197 break;
4199 case OPC_ADDU_CP2:
4200 tcg_gen_add_i64(t0, t0, t1);
4201 tcg_gen_ext32s_i64(t0, t0);
4202 break;
4203 case OPC_SUBU_CP2:
4204 tcg_gen_sub_i64(t0, t0, t1);
4205 tcg_gen_ext32s_i64(t0, t0);
4206 break;
4208 case OPC_SLL_CP2:
4209 shift_max = 32;
4210 goto do_shift;
4211 case OPC_SRL_CP2:
4212 shift_max = 32;
4213 goto do_shift;
4214 case OPC_SRA_CP2:
4215 shift_max = 32;
4216 goto do_shift;
4217 case OPC_DSLL_CP2:
4218 shift_max = 64;
4219 goto do_shift;
4220 case OPC_DSRL_CP2:
4221 shift_max = 64;
4222 goto do_shift;
4223 case OPC_DSRA_CP2:
4224 shift_max = 64;
4225 goto do_shift;
4226 do_shift:
4227 /* Make sure shift count isn't TCG undefined behaviour. */
4228 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4230 switch (opc) {
4231 case OPC_SLL_CP2:
4232 case OPC_DSLL_CP2:
4233 tcg_gen_shl_i64(t0, t0, t1);
4234 break;
4235 case OPC_SRA_CP2:
4236 case OPC_DSRA_CP2:
4237 /* Since SRA is UndefinedResult without sign-extended inputs,
4238 we can treat SRA and DSRA the same. */
4239 tcg_gen_sar_i64(t0, t0, t1);
4240 break;
4241 case OPC_SRL_CP2:
4242 /* We want to shift in zeros for SRL; zero-extend first. */
4243 tcg_gen_ext32u_i64(t0, t0);
4244 /* FALLTHRU */
4245 case OPC_DSRL_CP2:
4246 tcg_gen_shr_i64(t0, t0, t1);
4247 break;
4250 if (shift_max == 32) {
4251 tcg_gen_ext32s_i64(t0, t0);
4254 /* Shifts larger than MAX produce zero. */
4255 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4256 tcg_gen_neg_i64(t1, t1);
4257 tcg_gen_and_i64(t0, t0, t1);
4258 break;
4260 case OPC_ADD_CP2:
4261 case OPC_DADD_CP2:
4263 TCGv_i64 t2 = tcg_temp_new_i64();
4264 TCGLabel *lab = gen_new_label();
4266 tcg_gen_mov_i64(t2, t0);
4267 tcg_gen_add_i64(t0, t1, t2);
4268 if (opc == OPC_ADD_CP2) {
4269 tcg_gen_ext32s_i64(t0, t0);
4271 tcg_gen_xor_i64(t1, t1, t2);
4272 tcg_gen_xor_i64(t2, t2, t0);
4273 tcg_gen_andc_i64(t1, t2, t1);
4274 tcg_temp_free_i64(t2);
4275 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4276 generate_exception(ctx, EXCP_OVERFLOW);
4277 gen_set_label(lab);
4278 break;
4281 case OPC_SUB_CP2:
4282 case OPC_DSUB_CP2:
4284 TCGv_i64 t2 = tcg_temp_new_i64();
4285 TCGLabel *lab = gen_new_label();
4287 tcg_gen_mov_i64(t2, t0);
4288 tcg_gen_sub_i64(t0, t1, t2);
4289 if (opc == OPC_SUB_CP2) {
4290 tcg_gen_ext32s_i64(t0, t0);
4292 tcg_gen_xor_i64(t1, t1, t2);
4293 tcg_gen_xor_i64(t2, t2, t0);
4294 tcg_gen_and_i64(t1, t1, t2);
4295 tcg_temp_free_i64(t2);
4296 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4297 generate_exception(ctx, EXCP_OVERFLOW);
4298 gen_set_label(lab);
4299 break;
4302 case OPC_PMULUW:
4303 tcg_gen_ext32u_i64(t0, t0);
4304 tcg_gen_ext32u_i64(t1, t1);
4305 tcg_gen_mul_i64(t0, t0, t1);
4306 break;
4308 case OPC_SEQU_CP2:
4309 case OPC_SEQ_CP2:
4310 case OPC_SLTU_CP2:
4311 case OPC_SLT_CP2:
4312 case OPC_SLEU_CP2:
4313 case OPC_SLE_CP2:
4314 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4315 FD field is the CC field? */
4316 default:
4317 MIPS_INVAL("loongson_cp2");
4318 generate_exception_end(ctx, EXCP_RI);
4319 return;
4322 #undef LMI_HELPER
4323 #undef LMI_DIRECT
4325 gen_store_fpr64(ctx, t0, rd);
4327 tcg_temp_free_i64(t0);
4328 tcg_temp_free_i64(t1);
4331 /* Traps */
4332 static void gen_trap (DisasContext *ctx, uint32_t opc,
4333 int rs, int rt, int16_t imm)
4335 int cond;
4336 TCGv t0 = tcg_temp_new();
4337 TCGv t1 = tcg_temp_new();
4339 cond = 0;
4340 /* Load needed operands */
4341 switch (opc) {
4342 case OPC_TEQ:
4343 case OPC_TGE:
4344 case OPC_TGEU:
4345 case OPC_TLT:
4346 case OPC_TLTU:
4347 case OPC_TNE:
4348 /* Compare two registers */
4349 if (rs != rt) {
4350 gen_load_gpr(t0, rs);
4351 gen_load_gpr(t1, rt);
4352 cond = 1;
4354 break;
4355 case OPC_TEQI:
4356 case OPC_TGEI:
4357 case OPC_TGEIU:
4358 case OPC_TLTI:
4359 case OPC_TLTIU:
4360 case OPC_TNEI:
4361 /* Compare register to immediate */
4362 if (rs != 0 || imm != 0) {
4363 gen_load_gpr(t0, rs);
4364 tcg_gen_movi_tl(t1, (int32_t)imm);
4365 cond = 1;
4367 break;
4369 if (cond == 0) {
4370 switch (opc) {
4371 case OPC_TEQ: /* rs == rs */
4372 case OPC_TEQI: /* r0 == 0 */
4373 case OPC_TGE: /* rs >= rs */
4374 case OPC_TGEI: /* r0 >= 0 */
4375 case OPC_TGEU: /* rs >= rs unsigned */
4376 case OPC_TGEIU: /* r0 >= 0 unsigned */
4377 /* Always trap */
4378 generate_exception_end(ctx, EXCP_TRAP);
4379 break;
4380 case OPC_TLT: /* rs < rs */
4381 case OPC_TLTI: /* r0 < 0 */
4382 case OPC_TLTU: /* rs < rs unsigned */
4383 case OPC_TLTIU: /* r0 < 0 unsigned */
4384 case OPC_TNE: /* rs != rs */
4385 case OPC_TNEI: /* r0 != 0 */
4386 /* Never trap: treat as NOP. */
4387 break;
4389 } else {
4390 TCGLabel *l1 = gen_new_label();
4392 switch (opc) {
4393 case OPC_TEQ:
4394 case OPC_TEQI:
4395 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4396 break;
4397 case OPC_TGE:
4398 case OPC_TGEI:
4399 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4400 break;
4401 case OPC_TGEU:
4402 case OPC_TGEIU:
4403 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4404 break;
4405 case OPC_TLT:
4406 case OPC_TLTI:
4407 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4408 break;
4409 case OPC_TLTU:
4410 case OPC_TLTIU:
4411 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4412 break;
4413 case OPC_TNE:
4414 case OPC_TNEI:
4415 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4416 break;
4418 generate_exception(ctx, EXCP_TRAP);
4419 gen_set_label(l1);
4421 tcg_temp_free(t0);
4422 tcg_temp_free(t1);
4425 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4427 if (unlikely(ctx->base.singlestep_enabled)) {
4428 return false;
4431 #ifndef CONFIG_USER_ONLY
4432 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4433 #else
4434 return true;
4435 #endif
4438 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4440 if (use_goto_tb(ctx, dest)) {
4441 tcg_gen_goto_tb(n);
4442 gen_save_pc(dest);
4443 tcg_gen_exit_tb(ctx->base.tb, n);
4444 } else {
4445 gen_save_pc(dest);
4446 if (ctx->base.singlestep_enabled) {
4447 save_cpu_state(ctx, 0);
4448 gen_helper_raise_exception_debug(cpu_env);
4450 tcg_gen_lookup_and_goto_ptr();
4454 /* Branches (before delay slot) */
4455 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4456 int insn_bytes,
4457 int rs, int rt, int32_t offset,
4458 int delayslot_size)
4460 target_ulong btgt = -1;
4461 int blink = 0;
4462 int bcond_compute = 0;
4463 TCGv t0 = tcg_temp_new();
4464 TCGv t1 = tcg_temp_new();
4466 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4467 #ifdef MIPS_DEBUG_DISAS
4468 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4469 TARGET_FMT_lx "\n", ctx->base.pc_next);
4470 #endif
4471 generate_exception_end(ctx, EXCP_RI);
4472 goto out;
4475 /* Load needed operands */
4476 switch (opc) {
4477 case OPC_BEQ:
4478 case OPC_BEQL:
4479 case OPC_BNE:
4480 case OPC_BNEL:
4481 /* Compare two registers */
4482 if (rs != rt) {
4483 gen_load_gpr(t0, rs);
4484 gen_load_gpr(t1, rt);
4485 bcond_compute = 1;
4487 btgt = ctx->base.pc_next + insn_bytes + offset;
4488 break;
4489 case OPC_BGEZ:
4490 case OPC_BGEZAL:
4491 case OPC_BGEZALL:
4492 case OPC_BGEZL:
4493 case OPC_BGTZ:
4494 case OPC_BGTZL:
4495 case OPC_BLEZ:
4496 case OPC_BLEZL:
4497 case OPC_BLTZ:
4498 case OPC_BLTZAL:
4499 case OPC_BLTZALL:
4500 case OPC_BLTZL:
4501 /* Compare to zero */
4502 if (rs != 0) {
4503 gen_load_gpr(t0, rs);
4504 bcond_compute = 1;
4506 btgt = ctx->base.pc_next + insn_bytes + offset;
4507 break;
4508 case OPC_BPOSGE32:
4509 #if defined(TARGET_MIPS64)
4510 case OPC_BPOSGE64:
4511 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4512 #else
4513 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4514 #endif
4515 bcond_compute = 1;
4516 btgt = ctx->base.pc_next + insn_bytes + offset;
4517 break;
4518 case OPC_J:
4519 case OPC_JAL:
4520 case OPC_JALX:
4521 /* Jump to immediate */
4522 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
4523 (uint32_t)offset;
4524 break;
4525 case OPC_JR:
4526 case OPC_JALR:
4527 /* Jump to register */
4528 if (offset != 0 && offset != 16) {
4529 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4530 others are reserved. */
4531 MIPS_INVAL("jump hint");
4532 generate_exception_end(ctx, EXCP_RI);
4533 goto out;
4535 gen_load_gpr(btarget, rs);
4536 break;
4537 default:
4538 MIPS_INVAL("branch/jump");
4539 generate_exception_end(ctx, EXCP_RI);
4540 goto out;
4542 if (bcond_compute == 0) {
4543 /* No condition to be computed */
4544 switch (opc) {
4545 case OPC_BEQ: /* rx == rx */
4546 case OPC_BEQL: /* rx == rx likely */
4547 case OPC_BGEZ: /* 0 >= 0 */
4548 case OPC_BGEZL: /* 0 >= 0 likely */
4549 case OPC_BLEZ: /* 0 <= 0 */
4550 case OPC_BLEZL: /* 0 <= 0 likely */
4551 /* Always take */
4552 ctx->hflags |= MIPS_HFLAG_B;
4553 break;
4554 case OPC_BGEZAL: /* 0 >= 0 */
4555 case OPC_BGEZALL: /* 0 >= 0 likely */
4556 /* Always take and link */
4557 blink = 31;
4558 ctx->hflags |= MIPS_HFLAG_B;
4559 break;
4560 case OPC_BNE: /* rx != rx */
4561 case OPC_BGTZ: /* 0 > 0 */
4562 case OPC_BLTZ: /* 0 < 0 */
4563 /* Treat as NOP. */
4564 goto out;
4565 case OPC_BLTZAL: /* 0 < 0 */
4566 /* Handle as an unconditional branch to get correct delay
4567 slot checking. */
4568 blink = 31;
4569 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
4570 ctx->hflags |= MIPS_HFLAG_B;
4571 break;
4572 case OPC_BLTZALL: /* 0 < 0 likely */
4573 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
4574 /* Skip the instruction in the delay slot */
4575 ctx->base.pc_next += 4;
4576 goto out;
4577 case OPC_BNEL: /* rx != rx likely */
4578 case OPC_BGTZL: /* 0 > 0 likely */
4579 case OPC_BLTZL: /* 0 < 0 likely */
4580 /* Skip the instruction in the delay slot */
4581 ctx->base.pc_next += 4;
4582 goto out;
4583 case OPC_J:
4584 ctx->hflags |= MIPS_HFLAG_B;
4585 break;
4586 case OPC_JALX:
4587 ctx->hflags |= MIPS_HFLAG_BX;
4588 /* Fallthrough */
4589 case OPC_JAL:
4590 blink = 31;
4591 ctx->hflags |= MIPS_HFLAG_B;
4592 break;
4593 case OPC_JR:
4594 ctx->hflags |= MIPS_HFLAG_BR;
4595 break;
4596 case OPC_JALR:
4597 blink = rt;
4598 ctx->hflags |= MIPS_HFLAG_BR;
4599 break;
4600 default:
4601 MIPS_INVAL("branch/jump");
4602 generate_exception_end(ctx, EXCP_RI);
4603 goto out;
4605 } else {
4606 switch (opc) {
4607 case OPC_BEQ:
4608 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4609 goto not_likely;
4610 case OPC_BEQL:
4611 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4612 goto likely;
4613 case OPC_BNE:
4614 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4615 goto not_likely;
4616 case OPC_BNEL:
4617 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4618 goto likely;
4619 case OPC_BGEZ:
4620 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4621 goto not_likely;
4622 case OPC_BGEZL:
4623 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4624 goto likely;
4625 case OPC_BGEZAL:
4626 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4627 blink = 31;
4628 goto not_likely;
4629 case OPC_BGEZALL:
4630 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4631 blink = 31;
4632 goto likely;
4633 case OPC_BGTZ:
4634 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4635 goto not_likely;
4636 case OPC_BGTZL:
4637 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4638 goto likely;
4639 case OPC_BLEZ:
4640 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4641 goto not_likely;
4642 case OPC_BLEZL:
4643 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4644 goto likely;
4645 case OPC_BLTZ:
4646 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4647 goto not_likely;
4648 case OPC_BLTZL:
4649 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4650 goto likely;
4651 case OPC_BPOSGE32:
4652 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4653 goto not_likely;
4654 #if defined(TARGET_MIPS64)
4655 case OPC_BPOSGE64:
4656 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4657 goto not_likely;
4658 #endif
4659 case OPC_BLTZAL:
4660 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4661 blink = 31;
4662 not_likely:
4663 ctx->hflags |= MIPS_HFLAG_BC;
4664 break;
4665 case OPC_BLTZALL:
4666 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4667 blink = 31;
4668 likely:
4669 ctx->hflags |= MIPS_HFLAG_BL;
4670 break;
4671 default:
4672 MIPS_INVAL("conditional branch/jump");
4673 generate_exception_end(ctx, EXCP_RI);
4674 goto out;
4678 ctx->btarget = btgt;
4680 switch (delayslot_size) {
4681 case 2:
4682 ctx->hflags |= MIPS_HFLAG_BDS16;
4683 break;
4684 case 4:
4685 ctx->hflags |= MIPS_HFLAG_BDS32;
4686 break;
4689 if (blink > 0) {
4690 int post_delay = insn_bytes + delayslot_size;
4691 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4693 tcg_gen_movi_tl(cpu_gpr[blink],
4694 ctx->base.pc_next + post_delay + lowbit);
4697 out:
4698 if (insn_bytes == 2)
4699 ctx->hflags |= MIPS_HFLAG_B16;
4700 tcg_temp_free(t0);
4701 tcg_temp_free(t1);
4705 /* nanoMIPS Branches */
4706 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
4707 int insn_bytes,
4708 int rs, int rt, int32_t offset)
4710 target_ulong btgt = -1;
4711 int bcond_compute = 0;
4712 TCGv t0 = tcg_temp_new();
4713 TCGv t1 = tcg_temp_new();
4715 /* Load needed operands */
4716 switch (opc) {
4717 case OPC_BEQ:
4718 case OPC_BNE:
4719 /* Compare two registers */
4720 if (rs != rt) {
4721 gen_load_gpr(t0, rs);
4722 gen_load_gpr(t1, rt);
4723 bcond_compute = 1;
4725 btgt = ctx->base.pc_next + insn_bytes + offset;
4726 break;
4727 case OPC_BGEZAL:
4728 /* Compare to zero */
4729 if (rs != 0) {
4730 gen_load_gpr(t0, rs);
4731 bcond_compute = 1;
4733 btgt = ctx->base.pc_next + insn_bytes + offset;
4734 break;
4735 case OPC_BPOSGE32:
4736 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4737 bcond_compute = 1;
4738 btgt = ctx->base.pc_next + insn_bytes + offset;
4739 break;
4740 case OPC_JR:
4741 case OPC_JALR:
4742 /* Jump to register */
4743 if (offset != 0 && offset != 16) {
4744 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4745 others are reserved. */
4746 MIPS_INVAL("jump hint");
4747 generate_exception_end(ctx, EXCP_RI);
4748 goto out;
4750 gen_load_gpr(btarget, rs);
4751 break;
4752 default:
4753 MIPS_INVAL("branch/jump");
4754 generate_exception_end(ctx, EXCP_RI);
4755 goto out;
4757 if (bcond_compute == 0) {
4758 /* No condition to be computed */
4759 switch (opc) {
4760 case OPC_BEQ: /* rx == rx */
4761 /* Always take */
4762 ctx->hflags |= MIPS_HFLAG_B;
4763 break;
4764 case OPC_BGEZAL: /* 0 >= 0 */
4765 /* Always take and link */
4766 tcg_gen_movi_tl(cpu_gpr[31],
4767 ctx->base.pc_next + insn_bytes);
4768 ctx->hflags |= MIPS_HFLAG_B;
4769 break;
4770 case OPC_BNE: /* rx != rx */
4771 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
4772 /* Skip the instruction in the delay slot */
4773 ctx->base.pc_next += 4;
4774 goto out;
4775 case OPC_JR:
4776 ctx->hflags |= MIPS_HFLAG_BR;
4777 break;
4778 case OPC_JALR:
4779 if (rt > 0) {
4780 tcg_gen_movi_tl(cpu_gpr[rt],
4781 ctx->base.pc_next + insn_bytes);
4783 ctx->hflags |= MIPS_HFLAG_BR;
4784 break;
4785 default:
4786 MIPS_INVAL("branch/jump");
4787 generate_exception_end(ctx, EXCP_RI);
4788 goto out;
4790 } else {
4791 switch (opc) {
4792 case OPC_BEQ:
4793 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4794 goto not_likely;
4795 case OPC_BNE:
4796 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4797 goto not_likely;
4798 case OPC_BGEZAL:
4799 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4800 tcg_gen_movi_tl(cpu_gpr[31],
4801 ctx->base.pc_next + insn_bytes);
4802 goto not_likely;
4803 case OPC_BPOSGE32:
4804 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4805 not_likely:
4806 ctx->hflags |= MIPS_HFLAG_BC;
4807 break;
4808 default:
4809 MIPS_INVAL("conditional branch/jump");
4810 generate_exception_end(ctx, EXCP_RI);
4811 goto out;
4815 ctx->btarget = btgt;
4817 out:
4818 if (insn_bytes == 2) {
4819 ctx->hflags |= MIPS_HFLAG_B16;
4821 tcg_temp_free(t0);
4822 tcg_temp_free(t1);
4826 /* special3 bitfield operations */
4827 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4828 int rs, int lsb, int msb)
4830 TCGv t0 = tcg_temp_new();
4831 TCGv t1 = tcg_temp_new();
4833 gen_load_gpr(t1, rs);
4834 switch (opc) {
4835 case OPC_EXT:
4836 if (lsb + msb > 31) {
4837 goto fail;
4839 if (msb != 31) {
4840 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4841 } else {
4842 /* The two checks together imply that lsb == 0,
4843 so this is a simple sign-extension. */
4844 tcg_gen_ext32s_tl(t0, t1);
4846 break;
4847 #if defined(TARGET_MIPS64)
4848 case OPC_DEXTU:
4849 lsb += 32;
4850 goto do_dext;
4851 case OPC_DEXTM:
4852 msb += 32;
4853 goto do_dext;
4854 case OPC_DEXT:
4855 do_dext:
4856 if (lsb + msb > 63) {
4857 goto fail;
4859 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4860 break;
4861 #endif
4862 case OPC_INS:
4863 if (lsb > msb) {
4864 goto fail;
4866 gen_load_gpr(t0, rt);
4867 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4868 tcg_gen_ext32s_tl(t0, t0);
4869 break;
4870 #if defined(TARGET_MIPS64)
4871 case OPC_DINSU:
4872 lsb += 32;
4873 /* FALLTHRU */
4874 case OPC_DINSM:
4875 msb += 32;
4876 /* FALLTHRU */
4877 case OPC_DINS:
4878 if (lsb > msb) {
4879 goto fail;
4881 gen_load_gpr(t0, rt);
4882 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4883 break;
4884 #endif
4885 default:
4886 fail:
4887 MIPS_INVAL("bitops");
4888 generate_exception_end(ctx, EXCP_RI);
4889 tcg_temp_free(t0);
4890 tcg_temp_free(t1);
4891 return;
4893 gen_store_gpr(t0, rt);
4894 tcg_temp_free(t0);
4895 tcg_temp_free(t1);
4898 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4900 TCGv t0;
4902 if (rd == 0) {
4903 /* If no destination, treat it as a NOP. */
4904 return;
4907 t0 = tcg_temp_new();
4908 gen_load_gpr(t0, rt);
4909 switch (op2) {
4910 case OPC_WSBH:
4912 TCGv t1 = tcg_temp_new();
4913 TCGv t2 = tcg_const_tl(0x00FF00FF);
4915 tcg_gen_shri_tl(t1, t0, 8);
4916 tcg_gen_and_tl(t1, t1, t2);
4917 tcg_gen_and_tl(t0, t0, t2);
4918 tcg_gen_shli_tl(t0, t0, 8);
4919 tcg_gen_or_tl(t0, t0, t1);
4920 tcg_temp_free(t2);
4921 tcg_temp_free(t1);
4922 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4924 break;
4925 case OPC_SEB:
4926 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4927 break;
4928 case OPC_SEH:
4929 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4930 break;
4931 #if defined(TARGET_MIPS64)
4932 case OPC_DSBH:
4934 TCGv t1 = tcg_temp_new();
4935 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
4937 tcg_gen_shri_tl(t1, t0, 8);
4938 tcg_gen_and_tl(t1, t1, t2);
4939 tcg_gen_and_tl(t0, t0, t2);
4940 tcg_gen_shli_tl(t0, t0, 8);
4941 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4942 tcg_temp_free(t2);
4943 tcg_temp_free(t1);
4945 break;
4946 case OPC_DSHD:
4948 TCGv t1 = tcg_temp_new();
4949 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
4951 tcg_gen_shri_tl(t1, t0, 16);
4952 tcg_gen_and_tl(t1, t1, t2);
4953 tcg_gen_and_tl(t0, t0, t2);
4954 tcg_gen_shli_tl(t0, t0, 16);
4955 tcg_gen_or_tl(t0, t0, t1);
4956 tcg_gen_shri_tl(t1, t0, 32);
4957 tcg_gen_shli_tl(t0, t0, 32);
4958 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4959 tcg_temp_free(t2);
4960 tcg_temp_free(t1);
4962 break;
4963 #endif
4964 default:
4965 MIPS_INVAL("bsfhl");
4966 generate_exception_end(ctx, EXCP_RI);
4967 tcg_temp_free(t0);
4968 return;
4970 tcg_temp_free(t0);
4973 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4974 int imm2)
4976 TCGv t0;
4977 TCGv t1;
4978 if (rd == 0) {
4979 /* Treat as NOP. */
4980 return;
4982 t0 = tcg_temp_new();
4983 t1 = tcg_temp_new();
4984 gen_load_gpr(t0, rs);
4985 gen_load_gpr(t1, rt);
4986 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4987 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4988 if (opc == OPC_LSA) {
4989 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4992 tcg_temp_free(t1);
4993 tcg_temp_free(t0);
4995 return;
4998 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
4999 int rt, int bits)
5001 TCGv t0;
5002 if (rd == 0) {
5003 /* Treat as NOP. */
5004 return;
5006 t0 = tcg_temp_new();
5007 if (bits == 0 || bits == wordsz) {
5008 if (bits == 0) {
5009 gen_load_gpr(t0, rt);
5010 } else {
5011 gen_load_gpr(t0, rs);
5013 switch (wordsz) {
5014 case 32:
5015 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5016 break;
5017 #if defined(TARGET_MIPS64)
5018 case 64:
5019 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5020 break;
5021 #endif
5023 } else {
5024 TCGv t1 = tcg_temp_new();
5025 gen_load_gpr(t0, rt);
5026 gen_load_gpr(t1, rs);
5027 switch (wordsz) {
5028 case 32:
5030 TCGv_i64 t2 = tcg_temp_new_i64();
5031 tcg_gen_concat_tl_i64(t2, t1, t0);
5032 tcg_gen_shri_i64(t2, t2, 32 - bits);
5033 gen_move_low32(cpu_gpr[rd], t2);
5034 tcg_temp_free_i64(t2);
5036 break;
5037 #if defined(TARGET_MIPS64)
5038 case 64:
5039 tcg_gen_shli_tl(t0, t0, bits);
5040 tcg_gen_shri_tl(t1, t1, 64 - bits);
5041 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5042 break;
5043 #endif
5045 tcg_temp_free(t1);
5048 tcg_temp_free(t0);
5051 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5052 int bp)
5054 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5057 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5058 int shift)
5060 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5063 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5065 TCGv t0;
5066 if (rd == 0) {
5067 /* Treat as NOP. */
5068 return;
5070 t0 = tcg_temp_new();
5071 gen_load_gpr(t0, rt);
5072 switch (opc) {
5073 case OPC_BITSWAP:
5074 gen_helper_bitswap(cpu_gpr[rd], t0);
5075 break;
5076 #if defined(TARGET_MIPS64)
5077 case OPC_DBITSWAP:
5078 gen_helper_dbitswap(cpu_gpr[rd], t0);
5079 break;
5080 #endif
5082 tcg_temp_free(t0);
5085 #ifndef CONFIG_USER_ONLY
5086 /* CP0 (MMU and control) */
5087 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5089 TCGv_i64 t0 = tcg_temp_new_i64();
5090 TCGv_i64 t1 = tcg_temp_new_i64();
5092 tcg_gen_ext_tl_i64(t0, arg);
5093 tcg_gen_ld_i64(t1, cpu_env, off);
5094 #if defined(TARGET_MIPS64)
5095 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5096 #else
5097 tcg_gen_concat32_i64(t1, t1, t0);
5098 #endif
5099 tcg_gen_st_i64(t1, cpu_env, off);
5100 tcg_temp_free_i64(t1);
5101 tcg_temp_free_i64(t0);
5104 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5106 TCGv_i64 t0 = tcg_temp_new_i64();
5107 TCGv_i64 t1 = tcg_temp_new_i64();
5109 tcg_gen_ext_tl_i64(t0, arg);
5110 tcg_gen_ld_i64(t1, cpu_env, off);
5111 tcg_gen_concat32_i64(t1, t1, t0);
5112 tcg_gen_st_i64(t1, cpu_env, off);
5113 tcg_temp_free_i64(t1);
5114 tcg_temp_free_i64(t0);
5117 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5119 TCGv_i64 t0 = tcg_temp_new_i64();
5121 tcg_gen_ld_i64(t0, cpu_env, off);
5122 #if defined(TARGET_MIPS64)
5123 tcg_gen_shri_i64(t0, t0, 30);
5124 #else
5125 tcg_gen_shri_i64(t0, t0, 32);
5126 #endif
5127 gen_move_low32(arg, t0);
5128 tcg_temp_free_i64(t0);
5131 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5133 TCGv_i64 t0 = tcg_temp_new_i64();
5135 tcg_gen_ld_i64(t0, cpu_env, off);
5136 tcg_gen_shri_i64(t0, t0, 32 + shift);
5137 gen_move_low32(arg, t0);
5138 tcg_temp_free_i64(t0);
5141 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5143 TCGv_i32 t0 = tcg_temp_new_i32();
5145 tcg_gen_ld_i32(t0, cpu_env, off);
5146 tcg_gen_ext_i32_tl(arg, t0);
5147 tcg_temp_free_i32(t0);
5150 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5152 tcg_gen_ld_tl(arg, cpu_env, off);
5153 tcg_gen_ext32s_tl(arg, arg);
5156 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5158 TCGv_i32 t0 = tcg_temp_new_i32();
5160 tcg_gen_trunc_tl_i32(t0, arg);
5161 tcg_gen_st_i32(t0, cpu_env, off);
5162 tcg_temp_free_i32(t0);
5165 #define CP0_CHECK(c) \
5166 do { \
5167 if (!(c)) { \
5168 goto cp0_unimplemented; \
5170 } while (0)
5172 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5174 const char *rn = "invalid";
5176 switch (reg) {
5177 case 2:
5178 switch (sel) {
5179 case 0:
5180 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5181 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5182 rn = "EntryLo0";
5183 break;
5184 default:
5185 goto cp0_unimplemented;
5187 break;
5188 case 3:
5189 switch (sel) {
5190 case 0:
5191 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5192 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5193 rn = "EntryLo1";
5194 break;
5195 default:
5196 goto cp0_unimplemented;
5198 break;
5199 case 17:
5200 switch (sel) {
5201 case 0:
5202 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5203 ctx->CP0_LLAddr_shift);
5204 rn = "LLAddr";
5205 break;
5206 case 1:
5207 CP0_CHECK(ctx->mrp);
5208 gen_helper_mfhc0_maar(arg, cpu_env);
5209 rn = "MAAR";
5210 break;
5211 default:
5212 goto cp0_unimplemented;
5214 break;
5215 case 28:
5216 switch (sel) {
5217 case 0:
5218 case 2:
5219 case 4:
5220 case 6:
5221 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5222 rn = "TagLo";
5223 break;
5224 default:
5225 goto cp0_unimplemented;
5227 break;
5228 default:
5229 goto cp0_unimplemented;
5231 trace_mips_translate_c0("mfhc0", rn, reg, sel);
5232 return;
5234 cp0_unimplemented:
5235 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5236 tcg_gen_movi_tl(arg, 0);
5239 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5241 const char *rn = "invalid";
5242 uint64_t mask = ctx->PAMask >> 36;
5244 switch (reg) {
5245 case 2:
5246 switch (sel) {
5247 case 0:
5248 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5249 tcg_gen_andi_tl(arg, arg, mask);
5250 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5251 rn = "EntryLo0";
5252 break;
5253 default:
5254 goto cp0_unimplemented;
5256 break;
5257 case 3:
5258 switch (sel) {
5259 case 0:
5260 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5261 tcg_gen_andi_tl(arg, arg, mask);
5262 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5263 rn = "EntryLo1";
5264 break;
5265 default:
5266 goto cp0_unimplemented;
5268 break;
5269 case 17:
5270 switch (sel) {
5271 case 0:
5272 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5273 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5274 relevant for modern MIPS cores supporting MTHC0, therefore
5275 treating MTHC0 to LLAddr as NOP. */
5276 rn = "LLAddr";
5277 break;
5278 case 1:
5279 CP0_CHECK(ctx->mrp);
5280 gen_helper_mthc0_maar(cpu_env, arg);
5281 rn = "MAAR";
5282 break;
5283 default:
5284 goto cp0_unimplemented;
5286 break;
5287 case 28:
5288 switch (sel) {
5289 case 0:
5290 case 2:
5291 case 4:
5292 case 6:
5293 tcg_gen_andi_tl(arg, arg, mask);
5294 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5295 rn = "TagLo";
5296 break;
5297 default:
5298 goto cp0_unimplemented;
5300 break;
5301 default:
5302 goto cp0_unimplemented;
5304 trace_mips_translate_c0("mthc0", rn, reg, sel);
5306 cp0_unimplemented:
5307 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5310 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5312 if (ctx->insn_flags & ISA_MIPS32R6) {
5313 tcg_gen_movi_tl(arg, 0);
5314 } else {
5315 tcg_gen_movi_tl(arg, ~0);
5319 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5321 const char *rn = "invalid";
5323 if (sel != 0)
5324 check_insn(ctx, ISA_MIPS32);
5326 switch (reg) {
5327 case 0:
5328 switch (sel) {
5329 case 0:
5330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5331 rn = "Index";
5332 break;
5333 case 1:
5334 CP0_CHECK(ctx->insn_flags & ASE_MT);
5335 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5336 rn = "MVPControl";
5337 break;
5338 case 2:
5339 CP0_CHECK(ctx->insn_flags & ASE_MT);
5340 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5341 rn = "MVPConf0";
5342 break;
5343 case 3:
5344 CP0_CHECK(ctx->insn_flags & ASE_MT);
5345 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5346 rn = "MVPConf1";
5347 break;
5348 case 4:
5349 CP0_CHECK(ctx->vp);
5350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5351 rn = "VPControl";
5352 break;
5353 default:
5354 goto cp0_unimplemented;
5356 break;
5357 case 1:
5358 switch (sel) {
5359 case 0:
5360 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5361 gen_helper_mfc0_random(arg, cpu_env);
5362 rn = "Random";
5363 break;
5364 case 1:
5365 CP0_CHECK(ctx->insn_flags & ASE_MT);
5366 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5367 rn = "VPEControl";
5368 break;
5369 case 2:
5370 CP0_CHECK(ctx->insn_flags & ASE_MT);
5371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5372 rn = "VPEConf0";
5373 break;
5374 case 3:
5375 CP0_CHECK(ctx->insn_flags & ASE_MT);
5376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5377 rn = "VPEConf1";
5378 break;
5379 case 4:
5380 CP0_CHECK(ctx->insn_flags & ASE_MT);
5381 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5382 rn = "YQMask";
5383 break;
5384 case 5:
5385 CP0_CHECK(ctx->insn_flags & ASE_MT);
5386 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5387 rn = "VPESchedule";
5388 break;
5389 case 6:
5390 CP0_CHECK(ctx->insn_flags & ASE_MT);
5391 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5392 rn = "VPEScheFBack";
5393 break;
5394 case 7:
5395 CP0_CHECK(ctx->insn_flags & ASE_MT);
5396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5397 rn = "VPEOpt";
5398 break;
5399 default:
5400 goto cp0_unimplemented;
5402 break;
5403 case 2:
5404 switch (sel) {
5405 case 0:
5407 TCGv_i64 tmp = tcg_temp_new_i64();
5408 tcg_gen_ld_i64(tmp, cpu_env,
5409 offsetof(CPUMIPSState, CP0_EntryLo0));
5410 #if defined(TARGET_MIPS64)
5411 if (ctx->rxi) {
5412 /* Move RI/XI fields to bits 31:30 */
5413 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5414 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5416 #endif
5417 gen_move_low32(arg, tmp);
5418 tcg_temp_free_i64(tmp);
5420 rn = "EntryLo0";
5421 break;
5422 case 1:
5423 CP0_CHECK(ctx->insn_flags & ASE_MT);
5424 gen_helper_mfc0_tcstatus(arg, cpu_env);
5425 rn = "TCStatus";
5426 break;
5427 case 2:
5428 CP0_CHECK(ctx->insn_flags & ASE_MT);
5429 gen_helper_mfc0_tcbind(arg, cpu_env);
5430 rn = "TCBind";
5431 break;
5432 case 3:
5433 CP0_CHECK(ctx->insn_flags & ASE_MT);
5434 gen_helper_mfc0_tcrestart(arg, cpu_env);
5435 rn = "TCRestart";
5436 break;
5437 case 4:
5438 CP0_CHECK(ctx->insn_flags & ASE_MT);
5439 gen_helper_mfc0_tchalt(arg, cpu_env);
5440 rn = "TCHalt";
5441 break;
5442 case 5:
5443 CP0_CHECK(ctx->insn_flags & ASE_MT);
5444 gen_helper_mfc0_tccontext(arg, cpu_env);
5445 rn = "TCContext";
5446 break;
5447 case 6:
5448 CP0_CHECK(ctx->insn_flags & ASE_MT);
5449 gen_helper_mfc0_tcschedule(arg, cpu_env);
5450 rn = "TCSchedule";
5451 break;
5452 case 7:
5453 CP0_CHECK(ctx->insn_flags & ASE_MT);
5454 gen_helper_mfc0_tcschefback(arg, cpu_env);
5455 rn = "TCScheFBack";
5456 break;
5457 default:
5458 goto cp0_unimplemented;
5460 break;
5461 case 3:
5462 switch (sel) {
5463 case 0:
5465 TCGv_i64 tmp = tcg_temp_new_i64();
5466 tcg_gen_ld_i64(tmp, cpu_env,
5467 offsetof(CPUMIPSState, CP0_EntryLo1));
5468 #if defined(TARGET_MIPS64)
5469 if (ctx->rxi) {
5470 /* Move RI/XI fields to bits 31:30 */
5471 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5472 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5474 #endif
5475 gen_move_low32(arg, tmp);
5476 tcg_temp_free_i64(tmp);
5478 rn = "EntryLo1";
5479 break;
5480 case 1:
5481 CP0_CHECK(ctx->vp);
5482 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5483 rn = "GlobalNumber";
5484 break;
5485 default:
5486 goto cp0_unimplemented;
5488 break;
5489 case 4:
5490 switch (sel) {
5491 case 0:
5492 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5493 tcg_gen_ext32s_tl(arg, arg);
5494 rn = "Context";
5495 break;
5496 case 1:
5497 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5498 rn = "ContextConfig";
5499 goto cp0_unimplemented;
5500 case 2:
5501 CP0_CHECK(ctx->ulri);
5502 tcg_gen_ld_tl(arg, cpu_env,
5503 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5504 tcg_gen_ext32s_tl(arg, arg);
5505 rn = "UserLocal";
5506 break;
5507 default:
5508 goto cp0_unimplemented;
5510 break;
5511 case 5:
5512 switch (sel) {
5513 case 0:
5514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5515 rn = "PageMask";
5516 break;
5517 case 1:
5518 check_insn(ctx, ISA_MIPS32R2);
5519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5520 rn = "PageGrain";
5521 break;
5522 case 2:
5523 CP0_CHECK(ctx->sc);
5524 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5525 tcg_gen_ext32s_tl(arg, arg);
5526 rn = "SegCtl0";
5527 break;
5528 case 3:
5529 CP0_CHECK(ctx->sc);
5530 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5531 tcg_gen_ext32s_tl(arg, arg);
5532 rn = "SegCtl1";
5533 break;
5534 case 4:
5535 CP0_CHECK(ctx->sc);
5536 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5537 tcg_gen_ext32s_tl(arg, arg);
5538 rn = "SegCtl2";
5539 break;
5540 default:
5541 goto cp0_unimplemented;
5543 break;
5544 case 6:
5545 switch (sel) {
5546 case 0:
5547 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5548 rn = "Wired";
5549 break;
5550 case 1:
5551 check_insn(ctx, ISA_MIPS32R2);
5552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5553 rn = "SRSConf0";
5554 break;
5555 case 2:
5556 check_insn(ctx, ISA_MIPS32R2);
5557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5558 rn = "SRSConf1";
5559 break;
5560 case 3:
5561 check_insn(ctx, ISA_MIPS32R2);
5562 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5563 rn = "SRSConf2";
5564 break;
5565 case 4:
5566 check_insn(ctx, ISA_MIPS32R2);
5567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5568 rn = "SRSConf3";
5569 break;
5570 case 5:
5571 check_insn(ctx, ISA_MIPS32R2);
5572 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5573 rn = "SRSConf4";
5574 break;
5575 default:
5576 goto cp0_unimplemented;
5578 break;
5579 case 7:
5580 switch (sel) {
5581 case 0:
5582 check_insn(ctx, ISA_MIPS32R2);
5583 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5584 rn = "HWREna";
5585 break;
5586 default:
5587 goto cp0_unimplemented;
5589 break;
5590 case 8:
5591 switch (sel) {
5592 case 0:
5593 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5594 tcg_gen_ext32s_tl(arg, arg);
5595 rn = "BadVAddr";
5596 break;
5597 case 1:
5598 CP0_CHECK(ctx->bi);
5599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5600 rn = "BadInstr";
5601 break;
5602 case 2:
5603 CP0_CHECK(ctx->bp);
5604 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5605 rn = "BadInstrP";
5606 break;
5607 case 3:
5608 CP0_CHECK(ctx->bi);
5609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
5610 tcg_gen_andi_tl(arg, arg, ~0xffff);
5611 rn = "BadInstrX";
5612 break;
5613 default:
5614 goto cp0_unimplemented;
5616 break;
5617 case 9:
5618 switch (sel) {
5619 case 0:
5620 /* Mark as an IO operation because we read the time. */
5621 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
5622 gen_io_start();
5624 gen_helper_mfc0_count(arg, cpu_env);
5625 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
5626 gen_io_end();
5628 /* Break the TB to be able to take timer interrupts immediately
5629 after reading count. DISAS_STOP isn't sufficient, we need to
5630 ensure we break completely out of translated code. */
5631 gen_save_pc(ctx->base.pc_next + 4);
5632 ctx->base.is_jmp = DISAS_EXIT;
5633 rn = "Count";
5634 break;
5635 /* 6,7 are implementation dependent */
5636 default:
5637 goto cp0_unimplemented;
5639 break;
5640 case 10:
5641 switch (sel) {
5642 case 0:
5643 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5644 tcg_gen_ext32s_tl(arg, arg);
5645 rn = "EntryHi";
5646 break;
5647 default:
5648 goto cp0_unimplemented;
5650 break;
5651 case 11:
5652 switch (sel) {
5653 case 0:
5654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5655 rn = "Compare";
5656 break;
5657 /* 6,7 are implementation dependent */
5658 default:
5659 goto cp0_unimplemented;
5661 break;
5662 case 12:
5663 switch (sel) {
5664 case 0:
5665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5666 rn = "Status";
5667 break;
5668 case 1:
5669 check_insn(ctx, ISA_MIPS32R2);
5670 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5671 rn = "IntCtl";
5672 break;
5673 case 2:
5674 check_insn(ctx, ISA_MIPS32R2);
5675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5676 rn = "SRSCtl";
5677 break;
5678 case 3:
5679 check_insn(ctx, ISA_MIPS32R2);
5680 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5681 rn = "SRSMap";
5682 break;
5683 default:
5684 goto cp0_unimplemented;
5686 break;
5687 case 13:
5688 switch (sel) {
5689 case 0:
5690 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5691 rn = "Cause";
5692 break;
5693 default:
5694 goto cp0_unimplemented;
5696 break;
5697 case 14:
5698 switch (sel) {
5699 case 0:
5700 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5701 tcg_gen_ext32s_tl(arg, arg);
5702 rn = "EPC";
5703 break;
5704 default:
5705 goto cp0_unimplemented;
5707 break;
5708 case 15:
5709 switch (sel) {
5710 case 0:
5711 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5712 rn = "PRid";
5713 break;
5714 case 1:
5715 check_insn(ctx, ISA_MIPS32R2);
5716 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
5717 tcg_gen_ext32s_tl(arg, arg);
5718 rn = "EBase";
5719 break;
5720 case 3:
5721 check_insn(ctx, ISA_MIPS32R2);
5722 CP0_CHECK(ctx->cmgcr);
5723 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5724 tcg_gen_ext32s_tl(arg, arg);
5725 rn = "CMGCRBase";
5726 break;
5727 default:
5728 goto cp0_unimplemented;
5730 break;
5731 case 16:
5732 switch (sel) {
5733 case 0:
5734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5735 rn = "Config";
5736 break;
5737 case 1:
5738 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5739 rn = "Config1";
5740 break;
5741 case 2:
5742 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5743 rn = "Config2";
5744 break;
5745 case 3:
5746 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5747 rn = "Config3";
5748 break;
5749 case 4:
5750 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5751 rn = "Config4";
5752 break;
5753 case 5:
5754 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5755 rn = "Config5";
5756 break;
5757 /* 6,7 are implementation dependent */
5758 case 6:
5759 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5760 rn = "Config6";
5761 break;
5762 case 7:
5763 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5764 rn = "Config7";
5765 break;
5766 default:
5767 goto cp0_unimplemented;
5769 break;
5770 case 17:
5771 switch (sel) {
5772 case 0:
5773 gen_helper_mfc0_lladdr(arg, cpu_env);
5774 rn = "LLAddr";
5775 break;
5776 case 1:
5777 CP0_CHECK(ctx->mrp);
5778 gen_helper_mfc0_maar(arg, cpu_env);
5779 rn = "MAAR";
5780 break;
5781 case 2:
5782 CP0_CHECK(ctx->mrp);
5783 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5784 rn = "MAARI";
5785 break;
5786 default:
5787 goto cp0_unimplemented;
5789 break;
5790 case 18:
5791 switch (sel) {
5792 case 0:
5793 case 1:
5794 case 2:
5795 case 3:
5796 case 4:
5797 case 5:
5798 case 6:
5799 case 7:
5800 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
5801 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5802 rn = "WatchLo";
5803 break;
5804 default:
5805 goto cp0_unimplemented;
5807 break;
5808 case 19:
5809 switch (sel) {
5810 case 0:
5811 case 1:
5812 case 2:
5813 case 3:
5814 case 4:
5815 case 5:
5816 case 6:
5817 case 7:
5818 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
5819 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5820 rn = "WatchHi";
5821 break;
5822 default:
5823 goto cp0_unimplemented;
5825 break;
5826 case 20:
5827 switch (sel) {
5828 case 0:
5829 #if defined(TARGET_MIPS64)
5830 check_insn(ctx, ISA_MIPS3);
5831 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5832 tcg_gen_ext32s_tl(arg, arg);
5833 rn = "XContext";
5834 break;
5835 #endif
5836 default:
5837 goto cp0_unimplemented;
5839 break;
5840 case 21:
5841 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5842 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5843 switch (sel) {
5844 case 0:
5845 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5846 rn = "Framemask";
5847 break;
5848 default:
5849 goto cp0_unimplemented;
5851 break;
5852 case 22:
5853 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5854 rn = "'Diagnostic"; /* implementation dependent */
5855 break;
5856 case 23:
5857 switch (sel) {
5858 case 0:
5859 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5860 rn = "Debug";
5861 break;
5862 case 1:
5863 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5864 rn = "TraceControl";
5865 goto cp0_unimplemented;
5866 case 2:
5867 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5868 rn = "TraceControl2";
5869 goto cp0_unimplemented;
5870 case 3:
5871 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5872 rn = "UserTraceData";
5873 goto cp0_unimplemented;
5874 case 4:
5875 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5876 rn = "TraceBPC";
5877 goto cp0_unimplemented;
5878 default:
5879 goto cp0_unimplemented;
5881 break;
5882 case 24:
5883 switch (sel) {
5884 case 0:
5885 /* EJTAG support */
5886 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5887 tcg_gen_ext32s_tl(arg, arg);
5888 rn = "DEPC";
5889 break;
5890 default:
5891 goto cp0_unimplemented;
5893 break;
5894 case 25:
5895 switch (sel) {
5896 case 0:
5897 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5898 rn = "Performance0";
5899 break;
5900 case 1:
5901 // gen_helper_mfc0_performance1(arg);
5902 rn = "Performance1";
5903 goto cp0_unimplemented;
5904 case 2:
5905 // gen_helper_mfc0_performance2(arg);
5906 rn = "Performance2";
5907 goto cp0_unimplemented;
5908 case 3:
5909 // gen_helper_mfc0_performance3(arg);
5910 rn = "Performance3";
5911 goto cp0_unimplemented;
5912 case 4:
5913 // gen_helper_mfc0_performance4(arg);
5914 rn = "Performance4";
5915 goto cp0_unimplemented;
5916 case 5:
5917 // gen_helper_mfc0_performance5(arg);
5918 rn = "Performance5";
5919 goto cp0_unimplemented;
5920 case 6:
5921 // gen_helper_mfc0_performance6(arg);
5922 rn = "Performance6";
5923 goto cp0_unimplemented;
5924 case 7:
5925 // gen_helper_mfc0_performance7(arg);
5926 rn = "Performance7";
5927 goto cp0_unimplemented;
5928 default:
5929 goto cp0_unimplemented;
5931 break;
5932 case 26:
5933 switch (sel) {
5934 case 0:
5935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5936 rn = "ErrCtl";
5937 break;
5938 default:
5939 goto cp0_unimplemented;
5941 break;
5942 case 27:
5943 switch (sel) {
5944 case 0:
5945 case 1:
5946 case 2:
5947 case 3:
5948 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5949 rn = "CacheErr";
5950 break;
5951 default:
5952 goto cp0_unimplemented;
5954 break;
5955 case 28:
5956 switch (sel) {
5957 case 0:
5958 case 2:
5959 case 4:
5960 case 6:
5962 TCGv_i64 tmp = tcg_temp_new_i64();
5963 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5964 gen_move_low32(arg, tmp);
5965 tcg_temp_free_i64(tmp);
5967 rn = "TagLo";
5968 break;
5969 case 1:
5970 case 3:
5971 case 5:
5972 case 7:
5973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5974 rn = "DataLo";
5975 break;
5976 default:
5977 goto cp0_unimplemented;
5979 break;
5980 case 29:
5981 switch (sel) {
5982 case 0:
5983 case 2:
5984 case 4:
5985 case 6:
5986 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5987 rn = "TagHi";
5988 break;
5989 case 1:
5990 case 3:
5991 case 5:
5992 case 7:
5993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5994 rn = "DataHi";
5995 break;
5996 default:
5997 goto cp0_unimplemented;
5999 break;
6000 case 30:
6001 switch (sel) {
6002 case 0:
6003 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6004 tcg_gen_ext32s_tl(arg, arg);
6005 rn = "ErrorEPC";
6006 break;
6007 default:
6008 goto cp0_unimplemented;
6010 break;
6011 case 31:
6012 switch (sel) {
6013 case 0:
6014 /* EJTAG support */
6015 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6016 rn = "DESAVE";
6017 break;
6018 case 2:
6019 case 3:
6020 case 4:
6021 case 5:
6022 case 6:
6023 case 7:
6024 CP0_CHECK(ctx->kscrexist & (1 << sel));
6025 tcg_gen_ld_tl(arg, cpu_env,
6026 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6027 tcg_gen_ext32s_tl(arg, arg);
6028 rn = "KScratch";
6029 break;
6030 default:
6031 goto cp0_unimplemented;
6033 break;
6034 default:
6035 goto cp0_unimplemented;
6037 trace_mips_translate_c0("mfc0", rn, reg, sel);
6038 return;
6040 cp0_unimplemented:
6041 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6042 gen_mfc0_unimplemented(ctx, arg);
6045 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6047 const char *rn = "invalid";
6049 if (sel != 0)
6050 check_insn(ctx, ISA_MIPS32);
6052 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6053 gen_io_start();
6056 switch (reg) {
6057 case 0:
6058 switch (sel) {
6059 case 0:
6060 gen_helper_mtc0_index(cpu_env, arg);
6061 rn = "Index";
6062 break;
6063 case 1:
6064 CP0_CHECK(ctx->insn_flags & ASE_MT);
6065 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6066 rn = "MVPControl";
6067 break;
6068 case 2:
6069 CP0_CHECK(ctx->insn_flags & ASE_MT);
6070 /* ignored */
6071 rn = "MVPConf0";
6072 break;
6073 case 3:
6074 CP0_CHECK(ctx->insn_flags & ASE_MT);
6075 /* ignored */
6076 rn = "MVPConf1";
6077 break;
6078 case 4:
6079 CP0_CHECK(ctx->vp);
6080 /* ignored */
6081 rn = "VPControl";
6082 break;
6083 default:
6084 goto cp0_unimplemented;
6086 break;
6087 case 1:
6088 switch (sel) {
6089 case 0:
6090 /* ignored */
6091 rn = "Random";
6092 break;
6093 case 1:
6094 CP0_CHECK(ctx->insn_flags & ASE_MT);
6095 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6096 rn = "VPEControl";
6097 break;
6098 case 2:
6099 CP0_CHECK(ctx->insn_flags & ASE_MT);
6100 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6101 rn = "VPEConf0";
6102 break;
6103 case 3:
6104 CP0_CHECK(ctx->insn_flags & ASE_MT);
6105 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6106 rn = "VPEConf1";
6107 break;
6108 case 4:
6109 CP0_CHECK(ctx->insn_flags & ASE_MT);
6110 gen_helper_mtc0_yqmask(cpu_env, arg);
6111 rn = "YQMask";
6112 break;
6113 case 5:
6114 CP0_CHECK(ctx->insn_flags & ASE_MT);
6115 tcg_gen_st_tl(arg, cpu_env,
6116 offsetof(CPUMIPSState, CP0_VPESchedule));
6117 rn = "VPESchedule";
6118 break;
6119 case 6:
6120 CP0_CHECK(ctx->insn_flags & ASE_MT);
6121 tcg_gen_st_tl(arg, cpu_env,
6122 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6123 rn = "VPEScheFBack";
6124 break;
6125 case 7:
6126 CP0_CHECK(ctx->insn_flags & ASE_MT);
6127 gen_helper_mtc0_vpeopt(cpu_env, arg);
6128 rn = "VPEOpt";
6129 break;
6130 default:
6131 goto cp0_unimplemented;
6133 break;
6134 case 2:
6135 switch (sel) {
6136 case 0:
6137 gen_helper_mtc0_entrylo0(cpu_env, arg);
6138 rn = "EntryLo0";
6139 break;
6140 case 1:
6141 CP0_CHECK(ctx->insn_flags & ASE_MT);
6142 gen_helper_mtc0_tcstatus(cpu_env, arg);
6143 rn = "TCStatus";
6144 break;
6145 case 2:
6146 CP0_CHECK(ctx->insn_flags & ASE_MT);
6147 gen_helper_mtc0_tcbind(cpu_env, arg);
6148 rn = "TCBind";
6149 break;
6150 case 3:
6151 CP0_CHECK(ctx->insn_flags & ASE_MT);
6152 gen_helper_mtc0_tcrestart(cpu_env, arg);
6153 rn = "TCRestart";
6154 break;
6155 case 4:
6156 CP0_CHECK(ctx->insn_flags & ASE_MT);
6157 gen_helper_mtc0_tchalt(cpu_env, arg);
6158 rn = "TCHalt";
6159 break;
6160 case 5:
6161 CP0_CHECK(ctx->insn_flags & ASE_MT);
6162 gen_helper_mtc0_tccontext(cpu_env, arg);
6163 rn = "TCContext";
6164 break;
6165 case 6:
6166 CP0_CHECK(ctx->insn_flags & ASE_MT);
6167 gen_helper_mtc0_tcschedule(cpu_env, arg);
6168 rn = "TCSchedule";
6169 break;
6170 case 7:
6171 CP0_CHECK(ctx->insn_flags & ASE_MT);
6172 gen_helper_mtc0_tcschefback(cpu_env, arg);
6173 rn = "TCScheFBack";
6174 break;
6175 default:
6176 goto cp0_unimplemented;
6178 break;
6179 case 3:
6180 switch (sel) {
6181 case 0:
6182 gen_helper_mtc0_entrylo1(cpu_env, arg);
6183 rn = "EntryLo1";
6184 break;
6185 case 1:
6186 CP0_CHECK(ctx->vp);
6187 /* ignored */
6188 rn = "GlobalNumber";
6189 break;
6190 default:
6191 goto cp0_unimplemented;
6193 break;
6194 case 4:
6195 switch (sel) {
6196 case 0:
6197 gen_helper_mtc0_context(cpu_env, arg);
6198 rn = "Context";
6199 break;
6200 case 1:
6201 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6202 rn = "ContextConfig";
6203 goto cp0_unimplemented;
6204 case 2:
6205 CP0_CHECK(ctx->ulri);
6206 tcg_gen_st_tl(arg, cpu_env,
6207 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6208 rn = "UserLocal";
6209 break;
6210 default:
6211 goto cp0_unimplemented;
6213 break;
6214 case 5:
6215 switch (sel) {
6216 case 0:
6217 gen_helper_mtc0_pagemask(cpu_env, arg);
6218 rn = "PageMask";
6219 break;
6220 case 1:
6221 check_insn(ctx, ISA_MIPS32R2);
6222 gen_helper_mtc0_pagegrain(cpu_env, arg);
6223 rn = "PageGrain";
6224 ctx->base.is_jmp = DISAS_STOP;
6225 break;
6226 case 2:
6227 CP0_CHECK(ctx->sc);
6228 gen_helper_mtc0_segctl0(cpu_env, arg);
6229 rn = "SegCtl0";
6230 break;
6231 case 3:
6232 CP0_CHECK(ctx->sc);
6233 gen_helper_mtc0_segctl1(cpu_env, arg);
6234 rn = "SegCtl1";
6235 break;
6236 case 4:
6237 CP0_CHECK(ctx->sc);
6238 gen_helper_mtc0_segctl2(cpu_env, arg);
6239 rn = "SegCtl2";
6240 break;
6241 default:
6242 goto cp0_unimplemented;
6244 break;
6245 case 6:
6246 switch (sel) {
6247 case 0:
6248 gen_helper_mtc0_wired(cpu_env, arg);
6249 rn = "Wired";
6250 break;
6251 case 1:
6252 check_insn(ctx, ISA_MIPS32R2);
6253 gen_helper_mtc0_srsconf0(cpu_env, arg);
6254 rn = "SRSConf0";
6255 break;
6256 case 2:
6257 check_insn(ctx, ISA_MIPS32R2);
6258 gen_helper_mtc0_srsconf1(cpu_env, arg);
6259 rn = "SRSConf1";
6260 break;
6261 case 3:
6262 check_insn(ctx, ISA_MIPS32R2);
6263 gen_helper_mtc0_srsconf2(cpu_env, arg);
6264 rn = "SRSConf2";
6265 break;
6266 case 4:
6267 check_insn(ctx, ISA_MIPS32R2);
6268 gen_helper_mtc0_srsconf3(cpu_env, arg);
6269 rn = "SRSConf3";
6270 break;
6271 case 5:
6272 check_insn(ctx, ISA_MIPS32R2);
6273 gen_helper_mtc0_srsconf4(cpu_env, arg);
6274 rn = "SRSConf4";
6275 break;
6276 default:
6277 goto cp0_unimplemented;
6279 break;
6280 case 7:
6281 switch (sel) {
6282 case 0:
6283 check_insn(ctx, ISA_MIPS32R2);
6284 gen_helper_mtc0_hwrena(cpu_env, arg);
6285 ctx->base.is_jmp = DISAS_STOP;
6286 rn = "HWREna";
6287 break;
6288 default:
6289 goto cp0_unimplemented;
6291 break;
6292 case 8:
6293 switch (sel) {
6294 case 0:
6295 /* ignored */
6296 rn = "BadVAddr";
6297 break;
6298 case 1:
6299 /* ignored */
6300 rn = "BadInstr";
6301 break;
6302 case 2:
6303 /* ignored */
6304 rn = "BadInstrP";
6305 break;
6306 case 3:
6307 /* ignored */
6308 rn = "BadInstrX";
6309 break;
6310 default:
6311 goto cp0_unimplemented;
6313 break;
6314 case 9:
6315 switch (sel) {
6316 case 0:
6317 gen_helper_mtc0_count(cpu_env, arg);
6318 rn = "Count";
6319 break;
6320 /* 6,7 are implementation dependent */
6321 default:
6322 goto cp0_unimplemented;
6324 break;
6325 case 10:
6326 switch (sel) {
6327 case 0:
6328 gen_helper_mtc0_entryhi(cpu_env, arg);
6329 rn = "EntryHi";
6330 break;
6331 default:
6332 goto cp0_unimplemented;
6334 break;
6335 case 11:
6336 switch (sel) {
6337 case 0:
6338 gen_helper_mtc0_compare(cpu_env, arg);
6339 rn = "Compare";
6340 break;
6341 /* 6,7 are implementation dependent */
6342 default:
6343 goto cp0_unimplemented;
6345 break;
6346 case 12:
6347 switch (sel) {
6348 case 0:
6349 save_cpu_state(ctx, 1);
6350 gen_helper_mtc0_status(cpu_env, arg);
6351 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6352 gen_save_pc(ctx->base.pc_next + 4);
6353 ctx->base.is_jmp = DISAS_EXIT;
6354 rn = "Status";
6355 break;
6356 case 1:
6357 check_insn(ctx, ISA_MIPS32R2);
6358 gen_helper_mtc0_intctl(cpu_env, arg);
6359 /* Stop translation as we may have switched the execution mode */
6360 ctx->base.is_jmp = DISAS_STOP;
6361 rn = "IntCtl";
6362 break;
6363 case 2:
6364 check_insn(ctx, ISA_MIPS32R2);
6365 gen_helper_mtc0_srsctl(cpu_env, arg);
6366 /* Stop translation as we may have switched the execution mode */
6367 ctx->base.is_jmp = DISAS_STOP;
6368 rn = "SRSCtl";
6369 break;
6370 case 3:
6371 check_insn(ctx, ISA_MIPS32R2);
6372 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6373 /* Stop translation as we may have switched the execution mode */
6374 ctx->base.is_jmp = DISAS_STOP;
6375 rn = "SRSMap";
6376 break;
6377 default:
6378 goto cp0_unimplemented;
6380 break;
6381 case 13:
6382 switch (sel) {
6383 case 0:
6384 save_cpu_state(ctx, 1);
6385 gen_helper_mtc0_cause(cpu_env, arg);
6386 /* Stop translation as we may have triggered an interrupt.
6387 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6388 * translated code to check for pending interrupts. */
6389 gen_save_pc(ctx->base.pc_next + 4);
6390 ctx->base.is_jmp = DISAS_EXIT;
6391 rn = "Cause";
6392 break;
6393 default:
6394 goto cp0_unimplemented;
6396 break;
6397 case 14:
6398 switch (sel) {
6399 case 0:
6400 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6401 rn = "EPC";
6402 break;
6403 default:
6404 goto cp0_unimplemented;
6406 break;
6407 case 15:
6408 switch (sel) {
6409 case 0:
6410 /* ignored */
6411 rn = "PRid";
6412 break;
6413 case 1:
6414 check_insn(ctx, ISA_MIPS32R2);
6415 gen_helper_mtc0_ebase(cpu_env, arg);
6416 rn = "EBase";
6417 break;
6418 default:
6419 goto cp0_unimplemented;
6421 break;
6422 case 16:
6423 switch (sel) {
6424 case 0:
6425 gen_helper_mtc0_config0(cpu_env, arg);
6426 rn = "Config";
6427 /* Stop translation as we may have switched the execution mode */
6428 ctx->base.is_jmp = DISAS_STOP;
6429 break;
6430 case 1:
6431 /* ignored, read only */
6432 rn = "Config1";
6433 break;
6434 case 2:
6435 gen_helper_mtc0_config2(cpu_env, arg);
6436 rn = "Config2";
6437 /* Stop translation as we may have switched the execution mode */
6438 ctx->base.is_jmp = DISAS_STOP;
6439 break;
6440 case 3:
6441 gen_helper_mtc0_config3(cpu_env, arg);
6442 rn = "Config3";
6443 /* Stop translation as we may have switched the execution mode */
6444 ctx->base.is_jmp = DISAS_STOP;
6445 break;
6446 case 4:
6447 gen_helper_mtc0_config4(cpu_env, arg);
6448 rn = "Config4";
6449 ctx->base.is_jmp = DISAS_STOP;
6450 break;
6451 case 5:
6452 gen_helper_mtc0_config5(cpu_env, arg);
6453 rn = "Config5";
6454 /* Stop translation as we may have switched the execution mode */
6455 ctx->base.is_jmp = DISAS_STOP;
6456 break;
6457 /* 6,7 are implementation dependent */
6458 case 6:
6459 /* ignored */
6460 rn = "Config6";
6461 break;
6462 case 7:
6463 /* ignored */
6464 rn = "Config7";
6465 break;
6466 default:
6467 rn = "Invalid config selector";
6468 goto cp0_unimplemented;
6470 break;
6471 case 17:
6472 switch (sel) {
6473 case 0:
6474 gen_helper_mtc0_lladdr(cpu_env, arg);
6475 rn = "LLAddr";
6476 break;
6477 case 1:
6478 CP0_CHECK(ctx->mrp);
6479 gen_helper_mtc0_maar(cpu_env, arg);
6480 rn = "MAAR";
6481 break;
6482 case 2:
6483 CP0_CHECK(ctx->mrp);
6484 gen_helper_mtc0_maari(cpu_env, arg);
6485 rn = "MAARI";
6486 break;
6487 default:
6488 goto cp0_unimplemented;
6490 break;
6491 case 18:
6492 switch (sel) {
6493 case 0:
6494 case 1:
6495 case 2:
6496 case 3:
6497 case 4:
6498 case 5:
6499 case 6:
6500 case 7:
6501 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6502 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6503 rn = "WatchLo";
6504 break;
6505 default:
6506 goto cp0_unimplemented;
6508 break;
6509 case 19:
6510 switch (sel) {
6511 case 0:
6512 case 1:
6513 case 2:
6514 case 3:
6515 case 4:
6516 case 5:
6517 case 6:
6518 case 7:
6519 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6520 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6521 rn = "WatchHi";
6522 break;
6523 default:
6524 goto cp0_unimplemented;
6526 break;
6527 case 20:
6528 switch (sel) {
6529 case 0:
6530 #if defined(TARGET_MIPS64)
6531 check_insn(ctx, ISA_MIPS3);
6532 gen_helper_mtc0_xcontext(cpu_env, arg);
6533 rn = "XContext";
6534 break;
6535 #endif
6536 default:
6537 goto cp0_unimplemented;
6539 break;
6540 case 21:
6541 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6542 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6543 switch (sel) {
6544 case 0:
6545 gen_helper_mtc0_framemask(cpu_env, arg);
6546 rn = "Framemask";
6547 break;
6548 default:
6549 goto cp0_unimplemented;
6551 break;
6552 case 22:
6553 /* ignored */
6554 rn = "Diagnostic"; /* implementation dependent */
6555 break;
6556 case 23:
6557 switch (sel) {
6558 case 0:
6559 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6560 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6561 gen_save_pc(ctx->base.pc_next + 4);
6562 ctx->base.is_jmp = DISAS_EXIT;
6563 rn = "Debug";
6564 break;
6565 case 1:
6566 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6567 rn = "TraceControl";
6568 /* Stop translation as we may have switched the execution mode */
6569 ctx->base.is_jmp = DISAS_STOP;
6570 goto cp0_unimplemented;
6571 case 2:
6572 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6573 rn = "TraceControl2";
6574 /* Stop translation as we may have switched the execution mode */
6575 ctx->base.is_jmp = DISAS_STOP;
6576 goto cp0_unimplemented;
6577 case 3:
6578 /* Stop translation as we may have switched the execution mode */
6579 ctx->base.is_jmp = DISAS_STOP;
6580 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6581 rn = "UserTraceData";
6582 /* Stop translation as we may have switched the execution mode */
6583 ctx->base.is_jmp = DISAS_STOP;
6584 goto cp0_unimplemented;
6585 case 4:
6586 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6587 /* Stop translation as we may have switched the execution mode */
6588 ctx->base.is_jmp = DISAS_STOP;
6589 rn = "TraceBPC";
6590 goto cp0_unimplemented;
6591 default:
6592 goto cp0_unimplemented;
6594 break;
6595 case 24:
6596 switch (sel) {
6597 case 0:
6598 /* EJTAG support */
6599 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6600 rn = "DEPC";
6601 break;
6602 default:
6603 goto cp0_unimplemented;
6605 break;
6606 case 25:
6607 switch (sel) {
6608 case 0:
6609 gen_helper_mtc0_performance0(cpu_env, arg);
6610 rn = "Performance0";
6611 break;
6612 case 1:
6613 // gen_helper_mtc0_performance1(arg);
6614 rn = "Performance1";
6615 goto cp0_unimplemented;
6616 case 2:
6617 // gen_helper_mtc0_performance2(arg);
6618 rn = "Performance2";
6619 goto cp0_unimplemented;
6620 case 3:
6621 // gen_helper_mtc0_performance3(arg);
6622 rn = "Performance3";
6623 goto cp0_unimplemented;
6624 case 4:
6625 // gen_helper_mtc0_performance4(arg);
6626 rn = "Performance4";
6627 goto cp0_unimplemented;
6628 case 5:
6629 // gen_helper_mtc0_performance5(arg);
6630 rn = "Performance5";
6631 goto cp0_unimplemented;
6632 case 6:
6633 // gen_helper_mtc0_performance6(arg);
6634 rn = "Performance6";
6635 goto cp0_unimplemented;
6636 case 7:
6637 // gen_helper_mtc0_performance7(arg);
6638 rn = "Performance7";
6639 goto cp0_unimplemented;
6640 default:
6641 goto cp0_unimplemented;
6643 break;
6644 case 26:
6645 switch (sel) {
6646 case 0:
6647 gen_helper_mtc0_errctl(cpu_env, arg);
6648 ctx->base.is_jmp = DISAS_STOP;
6649 rn = "ErrCtl";
6650 break;
6651 default:
6652 goto cp0_unimplemented;
6654 break;
6655 case 27:
6656 switch (sel) {
6657 case 0:
6658 case 1:
6659 case 2:
6660 case 3:
6661 /* ignored */
6662 rn = "CacheErr";
6663 break;
6664 default:
6665 goto cp0_unimplemented;
6667 break;
6668 case 28:
6669 switch (sel) {
6670 case 0:
6671 case 2:
6672 case 4:
6673 case 6:
6674 gen_helper_mtc0_taglo(cpu_env, arg);
6675 rn = "TagLo";
6676 break;
6677 case 1:
6678 case 3:
6679 case 5:
6680 case 7:
6681 gen_helper_mtc0_datalo(cpu_env, arg);
6682 rn = "DataLo";
6683 break;
6684 default:
6685 goto cp0_unimplemented;
6687 break;
6688 case 29:
6689 switch (sel) {
6690 case 0:
6691 case 2:
6692 case 4:
6693 case 6:
6694 gen_helper_mtc0_taghi(cpu_env, arg);
6695 rn = "TagHi";
6696 break;
6697 case 1:
6698 case 3:
6699 case 5:
6700 case 7:
6701 gen_helper_mtc0_datahi(cpu_env, arg);
6702 rn = "DataHi";
6703 break;
6704 default:
6705 rn = "invalid sel";
6706 goto cp0_unimplemented;
6708 break;
6709 case 30:
6710 switch (sel) {
6711 case 0:
6712 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6713 rn = "ErrorEPC";
6714 break;
6715 default:
6716 goto cp0_unimplemented;
6718 break;
6719 case 31:
6720 switch (sel) {
6721 case 0:
6722 /* EJTAG support */
6723 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6724 rn = "DESAVE";
6725 break;
6726 case 2:
6727 case 3:
6728 case 4:
6729 case 5:
6730 case 6:
6731 case 7:
6732 CP0_CHECK(ctx->kscrexist & (1 << sel));
6733 tcg_gen_st_tl(arg, cpu_env,
6734 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6735 rn = "KScratch";
6736 break;
6737 default:
6738 goto cp0_unimplemented;
6740 break;
6741 default:
6742 goto cp0_unimplemented;
6744 trace_mips_translate_c0("mtc0", rn, reg, sel);
6746 /* For simplicity assume that all writes can cause interrupts. */
6747 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6748 gen_io_end();
6749 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
6750 * translated code to check for pending interrupts. */
6751 gen_save_pc(ctx->base.pc_next + 4);
6752 ctx->base.is_jmp = DISAS_EXIT;
6754 return;
6756 cp0_unimplemented:
6757 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6760 #if defined(TARGET_MIPS64)
6761 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6763 const char *rn = "invalid";
6765 if (sel != 0)
6766 check_insn(ctx, ISA_MIPS64);
6768 switch (reg) {
6769 case 0:
6770 switch (sel) {
6771 case 0:
6772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6773 rn = "Index";
6774 break;
6775 case 1:
6776 CP0_CHECK(ctx->insn_flags & ASE_MT);
6777 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6778 rn = "MVPControl";
6779 break;
6780 case 2:
6781 CP0_CHECK(ctx->insn_flags & ASE_MT);
6782 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6783 rn = "MVPConf0";
6784 break;
6785 case 3:
6786 CP0_CHECK(ctx->insn_flags & ASE_MT);
6787 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6788 rn = "MVPConf1";
6789 break;
6790 case 4:
6791 CP0_CHECK(ctx->vp);
6792 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6793 rn = "VPControl";
6794 break;
6795 default:
6796 goto cp0_unimplemented;
6798 break;
6799 case 1:
6800 switch (sel) {
6801 case 0:
6802 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6803 gen_helper_mfc0_random(arg, cpu_env);
6804 rn = "Random";
6805 break;
6806 case 1:
6807 CP0_CHECK(ctx->insn_flags & ASE_MT);
6808 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6809 rn = "VPEControl";
6810 break;
6811 case 2:
6812 CP0_CHECK(ctx->insn_flags & ASE_MT);
6813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6814 rn = "VPEConf0";
6815 break;
6816 case 3:
6817 CP0_CHECK(ctx->insn_flags & ASE_MT);
6818 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6819 rn = "VPEConf1";
6820 break;
6821 case 4:
6822 CP0_CHECK(ctx->insn_flags & ASE_MT);
6823 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6824 rn = "YQMask";
6825 break;
6826 case 5:
6827 CP0_CHECK(ctx->insn_flags & ASE_MT);
6828 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6829 rn = "VPESchedule";
6830 break;
6831 case 6:
6832 CP0_CHECK(ctx->insn_flags & ASE_MT);
6833 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6834 rn = "VPEScheFBack";
6835 break;
6836 case 7:
6837 CP0_CHECK(ctx->insn_flags & ASE_MT);
6838 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6839 rn = "VPEOpt";
6840 break;
6841 default:
6842 goto cp0_unimplemented;
6844 break;
6845 case 2:
6846 switch (sel) {
6847 case 0:
6848 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6849 rn = "EntryLo0";
6850 break;
6851 case 1:
6852 CP0_CHECK(ctx->insn_flags & ASE_MT);
6853 gen_helper_mfc0_tcstatus(arg, cpu_env);
6854 rn = "TCStatus";
6855 break;
6856 case 2:
6857 CP0_CHECK(ctx->insn_flags & ASE_MT);
6858 gen_helper_mfc0_tcbind(arg, cpu_env);
6859 rn = "TCBind";
6860 break;
6861 case 3:
6862 CP0_CHECK(ctx->insn_flags & ASE_MT);
6863 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6864 rn = "TCRestart";
6865 break;
6866 case 4:
6867 CP0_CHECK(ctx->insn_flags & ASE_MT);
6868 gen_helper_dmfc0_tchalt(arg, cpu_env);
6869 rn = "TCHalt";
6870 break;
6871 case 5:
6872 CP0_CHECK(ctx->insn_flags & ASE_MT);
6873 gen_helper_dmfc0_tccontext(arg, cpu_env);
6874 rn = "TCContext";
6875 break;
6876 case 6:
6877 CP0_CHECK(ctx->insn_flags & ASE_MT);
6878 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6879 rn = "TCSchedule";
6880 break;
6881 case 7:
6882 CP0_CHECK(ctx->insn_flags & ASE_MT);
6883 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6884 rn = "TCScheFBack";
6885 break;
6886 default:
6887 goto cp0_unimplemented;
6889 break;
6890 case 3:
6891 switch (sel) {
6892 case 0:
6893 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6894 rn = "EntryLo1";
6895 break;
6896 case 1:
6897 CP0_CHECK(ctx->vp);
6898 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6899 rn = "GlobalNumber";
6900 break;
6901 default:
6902 goto cp0_unimplemented;
6904 break;
6905 case 4:
6906 switch (sel) {
6907 case 0:
6908 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6909 rn = "Context";
6910 break;
6911 case 1:
6912 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6913 rn = "ContextConfig";
6914 goto cp0_unimplemented;
6915 case 2:
6916 CP0_CHECK(ctx->ulri);
6917 tcg_gen_ld_tl(arg, cpu_env,
6918 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6919 rn = "UserLocal";
6920 break;
6921 default:
6922 goto cp0_unimplemented;
6924 break;
6925 case 5:
6926 switch (sel) {
6927 case 0:
6928 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6929 rn = "PageMask";
6930 break;
6931 case 1:
6932 check_insn(ctx, ISA_MIPS32R2);
6933 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6934 rn = "PageGrain";
6935 break;
6936 case 2:
6937 CP0_CHECK(ctx->sc);
6938 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6939 rn = "SegCtl0";
6940 break;
6941 case 3:
6942 CP0_CHECK(ctx->sc);
6943 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6944 rn = "SegCtl1";
6945 break;
6946 case 4:
6947 CP0_CHECK(ctx->sc);
6948 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6949 rn = "SegCtl2";
6950 break;
6951 default:
6952 goto cp0_unimplemented;
6954 break;
6955 case 6:
6956 switch (sel) {
6957 case 0:
6958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6959 rn = "Wired";
6960 break;
6961 case 1:
6962 check_insn(ctx, ISA_MIPS32R2);
6963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6964 rn = "SRSConf0";
6965 break;
6966 case 2:
6967 check_insn(ctx, ISA_MIPS32R2);
6968 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6969 rn = "SRSConf1";
6970 break;
6971 case 3:
6972 check_insn(ctx, ISA_MIPS32R2);
6973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6974 rn = "SRSConf2";
6975 break;
6976 case 4:
6977 check_insn(ctx, ISA_MIPS32R2);
6978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6979 rn = "SRSConf3";
6980 break;
6981 case 5:
6982 check_insn(ctx, ISA_MIPS32R2);
6983 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6984 rn = "SRSConf4";
6985 break;
6986 default:
6987 goto cp0_unimplemented;
6989 break;
6990 case 7:
6991 switch (sel) {
6992 case 0:
6993 check_insn(ctx, ISA_MIPS32R2);
6994 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6995 rn = "HWREna";
6996 break;
6997 default:
6998 goto cp0_unimplemented;
7000 break;
7001 case 8:
7002 switch (sel) {
7003 case 0:
7004 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7005 rn = "BadVAddr";
7006 break;
7007 case 1:
7008 CP0_CHECK(ctx->bi);
7009 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7010 rn = "BadInstr";
7011 break;
7012 case 2:
7013 CP0_CHECK(ctx->bp);
7014 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7015 rn = "BadInstrP";
7016 break;
7017 case 3:
7018 CP0_CHECK(ctx->bi);
7019 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7020 tcg_gen_andi_tl(arg, arg, ~0xffff);
7021 rn = "BadInstrX";
7022 break;
7023 default:
7024 goto cp0_unimplemented;
7026 break;
7027 case 9:
7028 switch (sel) {
7029 case 0:
7030 /* Mark as an IO operation because we read the time. */
7031 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7032 gen_io_start();
7034 gen_helper_mfc0_count(arg, cpu_env);
7035 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7036 gen_io_end();
7038 /* Break the TB to be able to take timer interrupts immediately
7039 after reading count. DISAS_STOP isn't sufficient, we need to
7040 ensure we break completely out of translated code. */
7041 gen_save_pc(ctx->base.pc_next + 4);
7042 ctx->base.is_jmp = DISAS_EXIT;
7043 rn = "Count";
7044 break;
7045 /* 6,7 are implementation dependent */
7046 default:
7047 goto cp0_unimplemented;
7049 break;
7050 case 10:
7051 switch (sel) {
7052 case 0:
7053 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7054 rn = "EntryHi";
7055 break;
7056 default:
7057 goto cp0_unimplemented;
7059 break;
7060 case 11:
7061 switch (sel) {
7062 case 0:
7063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7064 rn = "Compare";
7065 break;
7066 /* 6,7 are implementation dependent */
7067 default:
7068 goto cp0_unimplemented;
7070 break;
7071 case 12:
7072 switch (sel) {
7073 case 0:
7074 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7075 rn = "Status";
7076 break;
7077 case 1:
7078 check_insn(ctx, ISA_MIPS32R2);
7079 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7080 rn = "IntCtl";
7081 break;
7082 case 2:
7083 check_insn(ctx, ISA_MIPS32R2);
7084 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7085 rn = "SRSCtl";
7086 break;
7087 case 3:
7088 check_insn(ctx, ISA_MIPS32R2);
7089 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7090 rn = "SRSMap";
7091 break;
7092 default:
7093 goto cp0_unimplemented;
7095 break;
7096 case 13:
7097 switch (sel) {
7098 case 0:
7099 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7100 rn = "Cause";
7101 break;
7102 default:
7103 goto cp0_unimplemented;
7105 break;
7106 case 14:
7107 switch (sel) {
7108 case 0:
7109 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7110 rn = "EPC";
7111 break;
7112 default:
7113 goto cp0_unimplemented;
7115 break;
7116 case 15:
7117 switch (sel) {
7118 case 0:
7119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7120 rn = "PRid";
7121 break;
7122 case 1:
7123 check_insn(ctx, ISA_MIPS32R2);
7124 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7125 rn = "EBase";
7126 break;
7127 case 3:
7128 check_insn(ctx, ISA_MIPS32R2);
7129 CP0_CHECK(ctx->cmgcr);
7130 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7131 rn = "CMGCRBase";
7132 break;
7133 default:
7134 goto cp0_unimplemented;
7136 break;
7137 case 16:
7138 switch (sel) {
7139 case 0:
7140 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7141 rn = "Config";
7142 break;
7143 case 1:
7144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7145 rn = "Config1";
7146 break;
7147 case 2:
7148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7149 rn = "Config2";
7150 break;
7151 case 3:
7152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7153 rn = "Config3";
7154 break;
7155 case 4:
7156 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7157 rn = "Config4";
7158 break;
7159 case 5:
7160 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7161 rn = "Config5";
7162 break;
7163 /* 6,7 are implementation dependent */
7164 case 6:
7165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7166 rn = "Config6";
7167 break;
7168 case 7:
7169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7170 rn = "Config7";
7171 break;
7172 default:
7173 goto cp0_unimplemented;
7175 break;
7176 case 17:
7177 switch (sel) {
7178 case 0:
7179 gen_helper_dmfc0_lladdr(arg, cpu_env);
7180 rn = "LLAddr";
7181 break;
7182 case 1:
7183 CP0_CHECK(ctx->mrp);
7184 gen_helper_dmfc0_maar(arg, cpu_env);
7185 rn = "MAAR";
7186 break;
7187 case 2:
7188 CP0_CHECK(ctx->mrp);
7189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7190 rn = "MAARI";
7191 break;
7192 default:
7193 goto cp0_unimplemented;
7195 break;
7196 case 18:
7197 switch (sel) {
7198 case 0:
7199 case 1:
7200 case 2:
7201 case 3:
7202 case 4:
7203 case 5:
7204 case 6:
7205 case 7:
7206 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7207 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7208 rn = "WatchLo";
7209 break;
7210 default:
7211 goto cp0_unimplemented;
7213 break;
7214 case 19:
7215 switch (sel) {
7216 case 0:
7217 case 1:
7218 case 2:
7219 case 3:
7220 case 4:
7221 case 5:
7222 case 6:
7223 case 7:
7224 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7225 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7226 rn = "WatchHi";
7227 break;
7228 default:
7229 goto cp0_unimplemented;
7231 break;
7232 case 20:
7233 switch (sel) {
7234 case 0:
7235 check_insn(ctx, ISA_MIPS3);
7236 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7237 rn = "XContext";
7238 break;
7239 default:
7240 goto cp0_unimplemented;
7242 break;
7243 case 21:
7244 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7245 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7246 switch (sel) {
7247 case 0:
7248 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7249 rn = "Framemask";
7250 break;
7251 default:
7252 goto cp0_unimplemented;
7254 break;
7255 case 22:
7256 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7257 rn = "'Diagnostic"; /* implementation dependent */
7258 break;
7259 case 23:
7260 switch (sel) {
7261 case 0:
7262 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7263 rn = "Debug";
7264 break;
7265 case 1:
7266 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
7267 rn = "TraceControl";
7268 goto cp0_unimplemented;
7269 case 2:
7270 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
7271 rn = "TraceControl2";
7272 goto cp0_unimplemented;
7273 case 3:
7274 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
7275 rn = "UserTraceData";
7276 goto cp0_unimplemented;
7277 case 4:
7278 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
7279 rn = "TraceBPC";
7280 goto cp0_unimplemented;
7281 default:
7282 goto cp0_unimplemented;
7284 break;
7285 case 24:
7286 switch (sel) {
7287 case 0:
7288 /* EJTAG support */
7289 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7290 rn = "DEPC";
7291 break;
7292 default:
7293 goto cp0_unimplemented;
7295 break;
7296 case 25:
7297 switch (sel) {
7298 case 0:
7299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7300 rn = "Performance0";
7301 break;
7302 case 1:
7303 // gen_helper_dmfc0_performance1(arg);
7304 rn = "Performance1";
7305 goto cp0_unimplemented;
7306 case 2:
7307 // gen_helper_dmfc0_performance2(arg);
7308 rn = "Performance2";
7309 goto cp0_unimplemented;
7310 case 3:
7311 // gen_helper_dmfc0_performance3(arg);
7312 rn = "Performance3";
7313 goto cp0_unimplemented;
7314 case 4:
7315 // gen_helper_dmfc0_performance4(arg);
7316 rn = "Performance4";
7317 goto cp0_unimplemented;
7318 case 5:
7319 // gen_helper_dmfc0_performance5(arg);
7320 rn = "Performance5";
7321 goto cp0_unimplemented;
7322 case 6:
7323 // gen_helper_dmfc0_performance6(arg);
7324 rn = "Performance6";
7325 goto cp0_unimplemented;
7326 case 7:
7327 // gen_helper_dmfc0_performance7(arg);
7328 rn = "Performance7";
7329 goto cp0_unimplemented;
7330 default:
7331 goto cp0_unimplemented;
7333 break;
7334 case 26:
7335 switch (sel) {
7336 case 0:
7337 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7338 rn = "ErrCtl";
7339 break;
7340 default:
7341 goto cp0_unimplemented;
7343 break;
7344 case 27:
7345 switch (sel) {
7346 /* ignored */
7347 case 0:
7348 case 1:
7349 case 2:
7350 case 3:
7351 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7352 rn = "CacheErr";
7353 break;
7354 default:
7355 goto cp0_unimplemented;
7357 break;
7358 case 28:
7359 switch (sel) {
7360 case 0:
7361 case 2:
7362 case 4:
7363 case 6:
7364 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7365 rn = "TagLo";
7366 break;
7367 case 1:
7368 case 3:
7369 case 5:
7370 case 7:
7371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7372 rn = "DataLo";
7373 break;
7374 default:
7375 goto cp0_unimplemented;
7377 break;
7378 case 29:
7379 switch (sel) {
7380 case 0:
7381 case 2:
7382 case 4:
7383 case 6:
7384 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7385 rn = "TagHi";
7386 break;
7387 case 1:
7388 case 3:
7389 case 5:
7390 case 7:
7391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7392 rn = "DataHi";
7393 break;
7394 default:
7395 goto cp0_unimplemented;
7397 break;
7398 case 30:
7399 switch (sel) {
7400 case 0:
7401 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7402 rn = "ErrorEPC";
7403 break;
7404 default:
7405 goto cp0_unimplemented;
7407 break;
7408 case 31:
7409 switch (sel) {
7410 case 0:
7411 /* EJTAG support */
7412 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7413 rn = "DESAVE";
7414 break;
7415 case 2:
7416 case 3:
7417 case 4:
7418 case 5:
7419 case 6:
7420 case 7:
7421 CP0_CHECK(ctx->kscrexist & (1 << sel));
7422 tcg_gen_ld_tl(arg, cpu_env,
7423 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7424 rn = "KScratch";
7425 break;
7426 default:
7427 goto cp0_unimplemented;
7429 break;
7430 default:
7431 goto cp0_unimplemented;
7433 trace_mips_translate_c0("dmfc0", rn, reg, sel);
7434 return;
7436 cp0_unimplemented:
7437 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7438 gen_mfc0_unimplemented(ctx, arg);
7441 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7443 const char *rn = "invalid";
7445 if (sel != 0)
7446 check_insn(ctx, ISA_MIPS64);
7448 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7449 gen_io_start();
7452 switch (reg) {
7453 case 0:
7454 switch (sel) {
7455 case 0:
7456 gen_helper_mtc0_index(cpu_env, arg);
7457 rn = "Index";
7458 break;
7459 case 1:
7460 CP0_CHECK(ctx->insn_flags & ASE_MT);
7461 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7462 rn = "MVPControl";
7463 break;
7464 case 2:
7465 CP0_CHECK(ctx->insn_flags & ASE_MT);
7466 /* ignored */
7467 rn = "MVPConf0";
7468 break;
7469 case 3:
7470 CP0_CHECK(ctx->insn_flags & ASE_MT);
7471 /* ignored */
7472 rn = "MVPConf1";
7473 break;
7474 case 4:
7475 CP0_CHECK(ctx->vp);
7476 /* ignored */
7477 rn = "VPControl";
7478 break;
7479 default:
7480 goto cp0_unimplemented;
7482 break;
7483 case 1:
7484 switch (sel) {
7485 case 0:
7486 /* ignored */
7487 rn = "Random";
7488 break;
7489 case 1:
7490 CP0_CHECK(ctx->insn_flags & ASE_MT);
7491 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7492 rn = "VPEControl";
7493 break;
7494 case 2:
7495 CP0_CHECK(ctx->insn_flags & ASE_MT);
7496 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7497 rn = "VPEConf0";
7498 break;
7499 case 3:
7500 CP0_CHECK(ctx->insn_flags & ASE_MT);
7501 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7502 rn = "VPEConf1";
7503 break;
7504 case 4:
7505 CP0_CHECK(ctx->insn_flags & ASE_MT);
7506 gen_helper_mtc0_yqmask(cpu_env, arg);
7507 rn = "YQMask";
7508 break;
7509 case 5:
7510 CP0_CHECK(ctx->insn_flags & ASE_MT);
7511 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7512 rn = "VPESchedule";
7513 break;
7514 case 6:
7515 CP0_CHECK(ctx->insn_flags & ASE_MT);
7516 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7517 rn = "VPEScheFBack";
7518 break;
7519 case 7:
7520 CP0_CHECK(ctx->insn_flags & ASE_MT);
7521 gen_helper_mtc0_vpeopt(cpu_env, arg);
7522 rn = "VPEOpt";
7523 break;
7524 default:
7525 goto cp0_unimplemented;
7527 break;
7528 case 2:
7529 switch (sel) {
7530 case 0:
7531 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7532 rn = "EntryLo0";
7533 break;
7534 case 1:
7535 CP0_CHECK(ctx->insn_flags & ASE_MT);
7536 gen_helper_mtc0_tcstatus(cpu_env, arg);
7537 rn = "TCStatus";
7538 break;
7539 case 2:
7540 CP0_CHECK(ctx->insn_flags & ASE_MT);
7541 gen_helper_mtc0_tcbind(cpu_env, arg);
7542 rn = "TCBind";
7543 break;
7544 case 3:
7545 CP0_CHECK(ctx->insn_flags & ASE_MT);
7546 gen_helper_mtc0_tcrestart(cpu_env, arg);
7547 rn = "TCRestart";
7548 break;
7549 case 4:
7550 CP0_CHECK(ctx->insn_flags & ASE_MT);
7551 gen_helper_mtc0_tchalt(cpu_env, arg);
7552 rn = "TCHalt";
7553 break;
7554 case 5:
7555 CP0_CHECK(ctx->insn_flags & ASE_MT);
7556 gen_helper_mtc0_tccontext(cpu_env, arg);
7557 rn = "TCContext";
7558 break;
7559 case 6:
7560 CP0_CHECK(ctx->insn_flags & ASE_MT);
7561 gen_helper_mtc0_tcschedule(cpu_env, arg);
7562 rn = "TCSchedule";
7563 break;
7564 case 7:
7565 CP0_CHECK(ctx->insn_flags & ASE_MT);
7566 gen_helper_mtc0_tcschefback(cpu_env, arg);
7567 rn = "TCScheFBack";
7568 break;
7569 default:
7570 goto cp0_unimplemented;
7572 break;
7573 case 3:
7574 switch (sel) {
7575 case 0:
7576 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7577 rn = "EntryLo1";
7578 break;
7579 case 1:
7580 CP0_CHECK(ctx->vp);
7581 /* ignored */
7582 rn = "GlobalNumber";
7583 break;
7584 default:
7585 goto cp0_unimplemented;
7587 break;
7588 case 4:
7589 switch (sel) {
7590 case 0:
7591 gen_helper_mtc0_context(cpu_env, arg);
7592 rn = "Context";
7593 break;
7594 case 1:
7595 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7596 rn = "ContextConfig";
7597 goto cp0_unimplemented;
7598 case 2:
7599 CP0_CHECK(ctx->ulri);
7600 tcg_gen_st_tl(arg, cpu_env,
7601 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7602 rn = "UserLocal";
7603 break;
7604 default:
7605 goto cp0_unimplemented;
7607 break;
7608 case 5:
7609 switch (sel) {
7610 case 0:
7611 gen_helper_mtc0_pagemask(cpu_env, arg);
7612 rn = "PageMask";
7613 break;
7614 case 1:
7615 check_insn(ctx, ISA_MIPS32R2);
7616 gen_helper_mtc0_pagegrain(cpu_env, arg);
7617 rn = "PageGrain";
7618 break;
7619 case 2:
7620 CP0_CHECK(ctx->sc);
7621 gen_helper_mtc0_segctl0(cpu_env, arg);
7622 rn = "SegCtl0";
7623 break;
7624 case 3:
7625 CP0_CHECK(ctx->sc);
7626 gen_helper_mtc0_segctl1(cpu_env, arg);
7627 rn = "SegCtl1";
7628 break;
7629 case 4:
7630 CP0_CHECK(ctx->sc);
7631 gen_helper_mtc0_segctl2(cpu_env, arg);
7632 rn = "SegCtl2";
7633 break;
7634 default:
7635 goto cp0_unimplemented;
7637 break;
7638 case 6:
7639 switch (sel) {
7640 case 0:
7641 gen_helper_mtc0_wired(cpu_env, arg);
7642 rn = "Wired";
7643 break;
7644 case 1:
7645 check_insn(ctx, ISA_MIPS32R2);
7646 gen_helper_mtc0_srsconf0(cpu_env, arg);
7647 rn = "SRSConf0";
7648 break;
7649 case 2:
7650 check_insn(ctx, ISA_MIPS32R2);
7651 gen_helper_mtc0_srsconf1(cpu_env, arg);
7652 rn = "SRSConf1";
7653 break;
7654 case 3:
7655 check_insn(ctx, ISA_MIPS32R2);
7656 gen_helper_mtc0_srsconf2(cpu_env, arg);
7657 rn = "SRSConf2";
7658 break;
7659 case 4:
7660 check_insn(ctx, ISA_MIPS32R2);
7661 gen_helper_mtc0_srsconf3(cpu_env, arg);
7662 rn = "SRSConf3";
7663 break;
7664 case 5:
7665 check_insn(ctx, ISA_MIPS32R2);
7666 gen_helper_mtc0_srsconf4(cpu_env, arg);
7667 rn = "SRSConf4";
7668 break;
7669 default:
7670 goto cp0_unimplemented;
7672 break;
7673 case 7:
7674 switch (sel) {
7675 case 0:
7676 check_insn(ctx, ISA_MIPS32R2);
7677 gen_helper_mtc0_hwrena(cpu_env, arg);
7678 ctx->base.is_jmp = DISAS_STOP;
7679 rn = "HWREna";
7680 break;
7681 default:
7682 goto cp0_unimplemented;
7684 break;
7685 case 8:
7686 switch (sel) {
7687 case 0:
7688 /* ignored */
7689 rn = "BadVAddr";
7690 break;
7691 case 1:
7692 /* ignored */
7693 rn = "BadInstr";
7694 break;
7695 case 2:
7696 /* ignored */
7697 rn = "BadInstrP";
7698 break;
7699 case 3:
7700 /* ignored */
7701 rn = "BadInstrX";
7702 break;
7703 default:
7704 goto cp0_unimplemented;
7706 break;
7707 case 9:
7708 switch (sel) {
7709 case 0:
7710 gen_helper_mtc0_count(cpu_env, arg);
7711 rn = "Count";
7712 break;
7713 /* 6,7 are implementation dependent */
7714 default:
7715 goto cp0_unimplemented;
7717 /* Stop translation as we may have switched the execution mode */
7718 ctx->base.is_jmp = DISAS_STOP;
7719 break;
7720 case 10:
7721 switch (sel) {
7722 case 0:
7723 gen_helper_mtc0_entryhi(cpu_env, arg);
7724 rn = "EntryHi";
7725 break;
7726 default:
7727 goto cp0_unimplemented;
7729 break;
7730 case 11:
7731 switch (sel) {
7732 case 0:
7733 gen_helper_mtc0_compare(cpu_env, arg);
7734 rn = "Compare";
7735 break;
7736 /* 6,7 are implementation dependent */
7737 default:
7738 goto cp0_unimplemented;
7740 /* Stop translation as we may have switched the execution mode */
7741 ctx->base.is_jmp = DISAS_STOP;
7742 break;
7743 case 12:
7744 switch (sel) {
7745 case 0:
7746 save_cpu_state(ctx, 1);
7747 gen_helper_mtc0_status(cpu_env, arg);
7748 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7749 gen_save_pc(ctx->base.pc_next + 4);
7750 ctx->base.is_jmp = DISAS_EXIT;
7751 rn = "Status";
7752 break;
7753 case 1:
7754 check_insn(ctx, ISA_MIPS32R2);
7755 gen_helper_mtc0_intctl(cpu_env, arg);
7756 /* Stop translation as we may have switched the execution mode */
7757 ctx->base.is_jmp = DISAS_STOP;
7758 rn = "IntCtl";
7759 break;
7760 case 2:
7761 check_insn(ctx, ISA_MIPS32R2);
7762 gen_helper_mtc0_srsctl(cpu_env, arg);
7763 /* Stop translation as we may have switched the execution mode */
7764 ctx->base.is_jmp = DISAS_STOP;
7765 rn = "SRSCtl";
7766 break;
7767 case 3:
7768 check_insn(ctx, ISA_MIPS32R2);
7769 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7770 /* Stop translation as we may have switched the execution mode */
7771 ctx->base.is_jmp = DISAS_STOP;
7772 rn = "SRSMap";
7773 break;
7774 default:
7775 goto cp0_unimplemented;
7777 break;
7778 case 13:
7779 switch (sel) {
7780 case 0:
7781 save_cpu_state(ctx, 1);
7782 gen_helper_mtc0_cause(cpu_env, arg);
7783 /* Stop translation as we may have triggered an interrupt.
7784 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7785 * translated code to check for pending interrupts. */
7786 gen_save_pc(ctx->base.pc_next + 4);
7787 ctx->base.is_jmp = DISAS_EXIT;
7788 rn = "Cause";
7789 break;
7790 default:
7791 goto cp0_unimplemented;
7793 break;
7794 case 14:
7795 switch (sel) {
7796 case 0:
7797 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7798 rn = "EPC";
7799 break;
7800 default:
7801 goto cp0_unimplemented;
7803 break;
7804 case 15:
7805 switch (sel) {
7806 case 0:
7807 /* ignored */
7808 rn = "PRid";
7809 break;
7810 case 1:
7811 check_insn(ctx, ISA_MIPS32R2);
7812 gen_helper_mtc0_ebase(cpu_env, arg);
7813 rn = "EBase";
7814 break;
7815 default:
7816 goto cp0_unimplemented;
7818 break;
7819 case 16:
7820 switch (sel) {
7821 case 0:
7822 gen_helper_mtc0_config0(cpu_env, arg);
7823 rn = "Config";
7824 /* Stop translation as we may have switched the execution mode */
7825 ctx->base.is_jmp = DISAS_STOP;
7826 break;
7827 case 1:
7828 /* ignored, read only */
7829 rn = "Config1";
7830 break;
7831 case 2:
7832 gen_helper_mtc0_config2(cpu_env, arg);
7833 rn = "Config2";
7834 /* Stop translation as we may have switched the execution mode */
7835 ctx->base.is_jmp = DISAS_STOP;
7836 break;
7837 case 3:
7838 gen_helper_mtc0_config3(cpu_env, arg);
7839 rn = "Config3";
7840 /* Stop translation as we may have switched the execution mode */
7841 ctx->base.is_jmp = DISAS_STOP;
7842 break;
7843 case 4:
7844 /* currently ignored */
7845 rn = "Config4";
7846 break;
7847 case 5:
7848 gen_helper_mtc0_config5(cpu_env, arg);
7849 rn = "Config5";
7850 /* Stop translation as we may have switched the execution mode */
7851 ctx->base.is_jmp = DISAS_STOP;
7852 break;
7853 /* 6,7 are implementation dependent */
7854 default:
7855 rn = "Invalid config selector";
7856 goto cp0_unimplemented;
7858 break;
7859 case 17:
7860 switch (sel) {
7861 case 0:
7862 gen_helper_mtc0_lladdr(cpu_env, arg);
7863 rn = "LLAddr";
7864 break;
7865 case 1:
7866 CP0_CHECK(ctx->mrp);
7867 gen_helper_mtc0_maar(cpu_env, arg);
7868 rn = "MAAR";
7869 break;
7870 case 2:
7871 CP0_CHECK(ctx->mrp);
7872 gen_helper_mtc0_maari(cpu_env, arg);
7873 rn = "MAARI";
7874 break;
7875 default:
7876 goto cp0_unimplemented;
7878 break;
7879 case 18:
7880 switch (sel) {
7881 case 0:
7882 case 1:
7883 case 2:
7884 case 3:
7885 case 4:
7886 case 5:
7887 case 6:
7888 case 7:
7889 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7890 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7891 rn = "WatchLo";
7892 break;
7893 default:
7894 goto cp0_unimplemented;
7896 break;
7897 case 19:
7898 switch (sel) {
7899 case 0:
7900 case 1:
7901 case 2:
7902 case 3:
7903 case 4:
7904 case 5:
7905 case 6:
7906 case 7:
7907 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7908 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7909 rn = "WatchHi";
7910 break;
7911 default:
7912 goto cp0_unimplemented;
7914 break;
7915 case 20:
7916 switch (sel) {
7917 case 0:
7918 check_insn(ctx, ISA_MIPS3);
7919 gen_helper_mtc0_xcontext(cpu_env, arg);
7920 rn = "XContext";
7921 break;
7922 default:
7923 goto cp0_unimplemented;
7925 break;
7926 case 21:
7927 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7928 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7929 switch (sel) {
7930 case 0:
7931 gen_helper_mtc0_framemask(cpu_env, arg);
7932 rn = "Framemask";
7933 break;
7934 default:
7935 goto cp0_unimplemented;
7937 break;
7938 case 22:
7939 /* ignored */
7940 rn = "Diagnostic"; /* implementation dependent */
7941 break;
7942 case 23:
7943 switch (sel) {
7944 case 0:
7945 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7946 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7947 gen_save_pc(ctx->base.pc_next + 4);
7948 ctx->base.is_jmp = DISAS_EXIT;
7949 rn = "Debug";
7950 break;
7951 case 1:
7952 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7953 /* Stop translation as we may have switched the execution mode */
7954 ctx->base.is_jmp = DISAS_STOP;
7955 rn = "TraceControl";
7956 goto cp0_unimplemented;
7957 case 2:
7958 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7959 /* Stop translation as we may have switched the execution mode */
7960 ctx->base.is_jmp = DISAS_STOP;
7961 rn = "TraceControl2";
7962 goto cp0_unimplemented;
7963 case 3:
7964 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7965 /* Stop translation as we may have switched the execution mode */
7966 ctx->base.is_jmp = DISAS_STOP;
7967 rn = "UserTraceData";
7968 goto cp0_unimplemented;
7969 case 4:
7970 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7971 /* Stop translation as we may have switched the execution mode */
7972 ctx->base.is_jmp = DISAS_STOP;
7973 rn = "TraceBPC";
7974 goto cp0_unimplemented;
7975 default:
7976 goto cp0_unimplemented;
7978 break;
7979 case 24:
7980 switch (sel) {
7981 case 0:
7982 /* EJTAG support */
7983 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7984 rn = "DEPC";
7985 break;
7986 default:
7987 goto cp0_unimplemented;
7989 break;
7990 case 25:
7991 switch (sel) {
7992 case 0:
7993 gen_helper_mtc0_performance0(cpu_env, arg);
7994 rn = "Performance0";
7995 break;
7996 case 1:
7997 // gen_helper_mtc0_performance1(cpu_env, arg);
7998 rn = "Performance1";
7999 goto cp0_unimplemented;
8000 case 2:
8001 // gen_helper_mtc0_performance2(cpu_env, arg);
8002 rn = "Performance2";
8003 goto cp0_unimplemented;
8004 case 3:
8005 // gen_helper_mtc0_performance3(cpu_env, arg);
8006 rn = "Performance3";
8007 goto cp0_unimplemented;
8008 case 4:
8009 // gen_helper_mtc0_performance4(cpu_env, arg);
8010 rn = "Performance4";
8011 goto cp0_unimplemented;
8012 case 5:
8013 // gen_helper_mtc0_performance5(cpu_env, arg);
8014 rn = "Performance5";
8015 goto cp0_unimplemented;
8016 case 6:
8017 // gen_helper_mtc0_performance6(cpu_env, arg);
8018 rn = "Performance6";
8019 goto cp0_unimplemented;
8020 case 7:
8021 // gen_helper_mtc0_performance7(cpu_env, arg);
8022 rn = "Performance7";
8023 goto cp0_unimplemented;
8024 default:
8025 goto cp0_unimplemented;
8027 break;
8028 case 26:
8029 switch (sel) {
8030 case 0:
8031 gen_helper_mtc0_errctl(cpu_env, arg);
8032 ctx->base.is_jmp = DISAS_STOP;
8033 rn = "ErrCtl";
8034 break;
8035 default:
8036 goto cp0_unimplemented;
8038 break;
8039 case 27:
8040 switch (sel) {
8041 case 0:
8042 case 1:
8043 case 2:
8044 case 3:
8045 /* ignored */
8046 rn = "CacheErr";
8047 break;
8048 default:
8049 goto cp0_unimplemented;
8051 break;
8052 case 28:
8053 switch (sel) {
8054 case 0:
8055 case 2:
8056 case 4:
8057 case 6:
8058 gen_helper_mtc0_taglo(cpu_env, arg);
8059 rn = "TagLo";
8060 break;
8061 case 1:
8062 case 3:
8063 case 5:
8064 case 7:
8065 gen_helper_mtc0_datalo(cpu_env, arg);
8066 rn = "DataLo";
8067 break;
8068 default:
8069 goto cp0_unimplemented;
8071 break;
8072 case 29:
8073 switch (sel) {
8074 case 0:
8075 case 2:
8076 case 4:
8077 case 6:
8078 gen_helper_mtc0_taghi(cpu_env, arg);
8079 rn = "TagHi";
8080 break;
8081 case 1:
8082 case 3:
8083 case 5:
8084 case 7:
8085 gen_helper_mtc0_datahi(cpu_env, arg);
8086 rn = "DataHi";
8087 break;
8088 default:
8089 rn = "invalid sel";
8090 goto cp0_unimplemented;
8092 break;
8093 case 30:
8094 switch (sel) {
8095 case 0:
8096 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8097 rn = "ErrorEPC";
8098 break;
8099 default:
8100 goto cp0_unimplemented;
8102 break;
8103 case 31:
8104 switch (sel) {
8105 case 0:
8106 /* EJTAG support */
8107 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8108 rn = "DESAVE";
8109 break;
8110 case 2:
8111 case 3:
8112 case 4:
8113 case 5:
8114 case 6:
8115 case 7:
8116 CP0_CHECK(ctx->kscrexist & (1 << sel));
8117 tcg_gen_st_tl(arg, cpu_env,
8118 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8119 rn = "KScratch";
8120 break;
8121 default:
8122 goto cp0_unimplemented;
8124 break;
8125 default:
8126 goto cp0_unimplemented;
8128 trace_mips_translate_c0("dmtc0", rn, reg, sel);
8130 /* For simplicity assume that all writes can cause interrupts. */
8131 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8132 gen_io_end();
8133 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8134 * translated code to check for pending interrupts. */
8135 gen_save_pc(ctx->base.pc_next + 4);
8136 ctx->base.is_jmp = DISAS_EXIT;
8138 return;
8140 cp0_unimplemented:
8141 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8143 #endif /* TARGET_MIPS64 */
8145 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8146 int u, int sel, int h)
8148 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8149 TCGv t0 = tcg_temp_local_new();
8151 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8152 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8153 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
8154 tcg_gen_movi_tl(t0, -1);
8155 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8156 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
8157 tcg_gen_movi_tl(t0, -1);
8158 else if (u == 0) {
8159 switch (rt) {
8160 case 1:
8161 switch (sel) {
8162 case 1:
8163 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8164 break;
8165 case 2:
8166 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8167 break;
8168 default:
8169 goto die;
8170 break;
8172 break;
8173 case 2:
8174 switch (sel) {
8175 case 1:
8176 gen_helper_mftc0_tcstatus(t0, cpu_env);
8177 break;
8178 case 2:
8179 gen_helper_mftc0_tcbind(t0, cpu_env);
8180 break;
8181 case 3:
8182 gen_helper_mftc0_tcrestart(t0, cpu_env);
8183 break;
8184 case 4:
8185 gen_helper_mftc0_tchalt(t0, cpu_env);
8186 break;
8187 case 5:
8188 gen_helper_mftc0_tccontext(t0, cpu_env);
8189 break;
8190 case 6:
8191 gen_helper_mftc0_tcschedule(t0, cpu_env);
8192 break;
8193 case 7:
8194 gen_helper_mftc0_tcschefback(t0, cpu_env);
8195 break;
8196 default:
8197 gen_mfc0(ctx, t0, rt, sel);
8198 break;
8200 break;
8201 case 10:
8202 switch (sel) {
8203 case 0:
8204 gen_helper_mftc0_entryhi(t0, cpu_env);
8205 break;
8206 default:
8207 gen_mfc0(ctx, t0, rt, sel);
8208 break;
8210 case 12:
8211 switch (sel) {
8212 case 0:
8213 gen_helper_mftc0_status(t0, cpu_env);
8214 break;
8215 default:
8216 gen_mfc0(ctx, t0, rt, sel);
8217 break;
8219 case 13:
8220 switch (sel) {
8221 case 0:
8222 gen_helper_mftc0_cause(t0, cpu_env);
8223 break;
8224 default:
8225 goto die;
8226 break;
8228 break;
8229 case 14:
8230 switch (sel) {
8231 case 0:
8232 gen_helper_mftc0_epc(t0, cpu_env);
8233 break;
8234 default:
8235 goto die;
8236 break;
8238 break;
8239 case 15:
8240 switch (sel) {
8241 case 1:
8242 gen_helper_mftc0_ebase(t0, cpu_env);
8243 break;
8244 default:
8245 goto die;
8246 break;
8248 break;
8249 case 16:
8250 switch (sel) {
8251 case 0:
8252 case 1:
8253 case 2:
8254 case 3:
8255 case 4:
8256 case 5:
8257 case 6:
8258 case 7:
8259 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
8260 break;
8261 default:
8262 goto die;
8263 break;
8265 break;
8266 case 23:
8267 switch (sel) {
8268 case 0:
8269 gen_helper_mftc0_debug(t0, cpu_env);
8270 break;
8271 default:
8272 gen_mfc0(ctx, t0, rt, sel);
8273 break;
8275 break;
8276 default:
8277 gen_mfc0(ctx, t0, rt, sel);
8279 } else switch (sel) {
8280 /* GPR registers. */
8281 case 0:
8282 gen_helper_1e0i(mftgpr, t0, rt);
8283 break;
8284 /* Auxiliary CPU registers */
8285 case 1:
8286 switch (rt) {
8287 case 0:
8288 gen_helper_1e0i(mftlo, t0, 0);
8289 break;
8290 case 1:
8291 gen_helper_1e0i(mfthi, t0, 0);
8292 break;
8293 case 2:
8294 gen_helper_1e0i(mftacx, t0, 0);
8295 break;
8296 case 4:
8297 gen_helper_1e0i(mftlo, t0, 1);
8298 break;
8299 case 5:
8300 gen_helper_1e0i(mfthi, t0, 1);
8301 break;
8302 case 6:
8303 gen_helper_1e0i(mftacx, t0, 1);
8304 break;
8305 case 8:
8306 gen_helper_1e0i(mftlo, t0, 2);
8307 break;
8308 case 9:
8309 gen_helper_1e0i(mfthi, t0, 2);
8310 break;
8311 case 10:
8312 gen_helper_1e0i(mftacx, t0, 2);
8313 break;
8314 case 12:
8315 gen_helper_1e0i(mftlo, t0, 3);
8316 break;
8317 case 13:
8318 gen_helper_1e0i(mfthi, t0, 3);
8319 break;
8320 case 14:
8321 gen_helper_1e0i(mftacx, t0, 3);
8322 break;
8323 case 16:
8324 gen_helper_mftdsp(t0, cpu_env);
8325 break;
8326 default:
8327 goto die;
8329 break;
8330 /* Floating point (COP1). */
8331 case 2:
8332 /* XXX: For now we support only a single FPU context. */
8333 if (h == 0) {
8334 TCGv_i32 fp0 = tcg_temp_new_i32();
8336 gen_load_fpr32(ctx, fp0, rt);
8337 tcg_gen_ext_i32_tl(t0, fp0);
8338 tcg_temp_free_i32(fp0);
8339 } else {
8340 TCGv_i32 fp0 = tcg_temp_new_i32();
8342 gen_load_fpr32h(ctx, fp0, rt);
8343 tcg_gen_ext_i32_tl(t0, fp0);
8344 tcg_temp_free_i32(fp0);
8346 break;
8347 case 3:
8348 /* XXX: For now we support only a single FPU context. */
8349 gen_helper_1e0i(cfc1, t0, rt);
8350 break;
8351 /* COP2: Not implemented. */
8352 case 4:
8353 case 5:
8354 /* fall through */
8355 default:
8356 goto die;
8358 trace_mips_translate_tr("mftr", rt, u, sel, h);
8359 gen_store_gpr(t0, rd);
8360 tcg_temp_free(t0);
8361 return;
8363 die:
8364 tcg_temp_free(t0);
8365 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
8366 generate_exception_end(ctx, EXCP_RI);
8369 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
8370 int u, int sel, int h)
8372 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8373 TCGv t0 = tcg_temp_local_new();
8375 gen_load_gpr(t0, rt);
8376 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8377 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8378 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
8379 /* NOP */ ;
8380 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8381 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
8382 /* NOP */ ;
8383 else if (u == 0) {
8384 switch (rd) {
8385 case 1:
8386 switch (sel) {
8387 case 1:
8388 gen_helper_mttc0_vpecontrol(cpu_env, t0);
8389 break;
8390 case 2:
8391 gen_helper_mttc0_vpeconf0(cpu_env, t0);
8392 break;
8393 default:
8394 goto die;
8395 break;
8397 break;
8398 case 2:
8399 switch (sel) {
8400 case 1:
8401 gen_helper_mttc0_tcstatus(cpu_env, t0);
8402 break;
8403 case 2:
8404 gen_helper_mttc0_tcbind(cpu_env, t0);
8405 break;
8406 case 3:
8407 gen_helper_mttc0_tcrestart(cpu_env, t0);
8408 break;
8409 case 4:
8410 gen_helper_mttc0_tchalt(cpu_env, t0);
8411 break;
8412 case 5:
8413 gen_helper_mttc0_tccontext(cpu_env, t0);
8414 break;
8415 case 6:
8416 gen_helper_mttc0_tcschedule(cpu_env, t0);
8417 break;
8418 case 7:
8419 gen_helper_mttc0_tcschefback(cpu_env, t0);
8420 break;
8421 default:
8422 gen_mtc0(ctx, t0, rd, sel);
8423 break;
8425 break;
8426 case 10:
8427 switch (sel) {
8428 case 0:
8429 gen_helper_mttc0_entryhi(cpu_env, t0);
8430 break;
8431 default:
8432 gen_mtc0(ctx, t0, rd, sel);
8433 break;
8435 case 12:
8436 switch (sel) {
8437 case 0:
8438 gen_helper_mttc0_status(cpu_env, t0);
8439 break;
8440 default:
8441 gen_mtc0(ctx, t0, rd, sel);
8442 break;
8444 case 13:
8445 switch (sel) {
8446 case 0:
8447 gen_helper_mttc0_cause(cpu_env, t0);
8448 break;
8449 default:
8450 goto die;
8451 break;
8453 break;
8454 case 15:
8455 switch (sel) {
8456 case 1:
8457 gen_helper_mttc0_ebase(cpu_env, t0);
8458 break;
8459 default:
8460 goto die;
8461 break;
8463 break;
8464 case 23:
8465 switch (sel) {
8466 case 0:
8467 gen_helper_mttc0_debug(cpu_env, t0);
8468 break;
8469 default:
8470 gen_mtc0(ctx, t0, rd, sel);
8471 break;
8473 break;
8474 default:
8475 gen_mtc0(ctx, t0, rd, sel);
8477 } else switch (sel) {
8478 /* GPR registers. */
8479 case 0:
8480 gen_helper_0e1i(mttgpr, t0, rd);
8481 break;
8482 /* Auxiliary CPU registers */
8483 case 1:
8484 switch (rd) {
8485 case 0:
8486 gen_helper_0e1i(mttlo, t0, 0);
8487 break;
8488 case 1:
8489 gen_helper_0e1i(mtthi, t0, 0);
8490 break;
8491 case 2:
8492 gen_helper_0e1i(mttacx, t0, 0);
8493 break;
8494 case 4:
8495 gen_helper_0e1i(mttlo, t0, 1);
8496 break;
8497 case 5:
8498 gen_helper_0e1i(mtthi, t0, 1);
8499 break;
8500 case 6:
8501 gen_helper_0e1i(mttacx, t0, 1);
8502 break;
8503 case 8:
8504 gen_helper_0e1i(mttlo, t0, 2);
8505 break;
8506 case 9:
8507 gen_helper_0e1i(mtthi, t0, 2);
8508 break;
8509 case 10:
8510 gen_helper_0e1i(mttacx, t0, 2);
8511 break;
8512 case 12:
8513 gen_helper_0e1i(mttlo, t0, 3);
8514 break;
8515 case 13:
8516 gen_helper_0e1i(mtthi, t0, 3);
8517 break;
8518 case 14:
8519 gen_helper_0e1i(mttacx, t0, 3);
8520 break;
8521 case 16:
8522 gen_helper_mttdsp(cpu_env, t0);
8523 break;
8524 default:
8525 goto die;
8527 break;
8528 /* Floating point (COP1). */
8529 case 2:
8530 /* XXX: For now we support only a single FPU context. */
8531 if (h == 0) {
8532 TCGv_i32 fp0 = tcg_temp_new_i32();
8534 tcg_gen_trunc_tl_i32(fp0, t0);
8535 gen_store_fpr32(ctx, fp0, rd);
8536 tcg_temp_free_i32(fp0);
8537 } else {
8538 TCGv_i32 fp0 = tcg_temp_new_i32();
8540 tcg_gen_trunc_tl_i32(fp0, t0);
8541 gen_store_fpr32h(ctx, fp0, rd);
8542 tcg_temp_free_i32(fp0);
8544 break;
8545 case 3:
8546 /* XXX: For now we support only a single FPU context. */
8548 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8550 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8551 tcg_temp_free_i32(fs_tmp);
8553 /* Stop translation as we may have changed hflags */
8554 ctx->base.is_jmp = DISAS_STOP;
8555 break;
8556 /* COP2: Not implemented. */
8557 case 4:
8558 case 5:
8559 /* fall through */
8560 default:
8561 goto die;
8563 trace_mips_translate_tr("mttr", rd, u, sel, h);
8564 tcg_temp_free(t0);
8565 return;
8567 die:
8568 tcg_temp_free(t0);
8569 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8570 generate_exception_end(ctx, EXCP_RI);
8573 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8575 const char *opn = "ldst";
8577 check_cp0_enabled(ctx);
8578 switch (opc) {
8579 case OPC_MFC0:
8580 if (rt == 0) {
8581 /* Treat as NOP. */
8582 return;
8584 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8585 opn = "mfc0";
8586 break;
8587 case OPC_MTC0:
8589 TCGv t0 = tcg_temp_new();
8591 gen_load_gpr(t0, rt);
8592 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8593 tcg_temp_free(t0);
8595 opn = "mtc0";
8596 break;
8597 #if defined(TARGET_MIPS64)
8598 case OPC_DMFC0:
8599 check_insn(ctx, ISA_MIPS3);
8600 if (rt == 0) {
8601 /* Treat as NOP. */
8602 return;
8604 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8605 opn = "dmfc0";
8606 break;
8607 case OPC_DMTC0:
8608 check_insn(ctx, ISA_MIPS3);
8610 TCGv t0 = tcg_temp_new();
8612 gen_load_gpr(t0, rt);
8613 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8614 tcg_temp_free(t0);
8616 opn = "dmtc0";
8617 break;
8618 #endif
8619 case OPC_MFHC0:
8620 check_mvh(ctx);
8621 if (rt == 0) {
8622 /* Treat as NOP. */
8623 return;
8625 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8626 opn = "mfhc0";
8627 break;
8628 case OPC_MTHC0:
8629 check_mvh(ctx);
8631 TCGv t0 = tcg_temp_new();
8632 gen_load_gpr(t0, rt);
8633 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8634 tcg_temp_free(t0);
8636 opn = "mthc0";
8637 break;
8638 case OPC_MFTR:
8639 check_cp0_enabled(ctx);
8640 if (rd == 0) {
8641 /* Treat as NOP. */
8642 return;
8644 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8645 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8646 opn = "mftr";
8647 break;
8648 case OPC_MTTR:
8649 check_cp0_enabled(ctx);
8650 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8651 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8652 opn = "mttr";
8653 break;
8654 case OPC_TLBWI:
8655 opn = "tlbwi";
8656 if (!env->tlb->helper_tlbwi)
8657 goto die;
8658 gen_helper_tlbwi(cpu_env);
8659 break;
8660 case OPC_TLBINV:
8661 opn = "tlbinv";
8662 if (ctx->ie >= 2) {
8663 if (!env->tlb->helper_tlbinv) {
8664 goto die;
8666 gen_helper_tlbinv(cpu_env);
8667 } /* treat as nop if TLBINV not supported */
8668 break;
8669 case OPC_TLBINVF:
8670 opn = "tlbinvf";
8671 if (ctx->ie >= 2) {
8672 if (!env->tlb->helper_tlbinvf) {
8673 goto die;
8675 gen_helper_tlbinvf(cpu_env);
8676 } /* treat as nop if TLBINV not supported */
8677 break;
8678 case OPC_TLBWR:
8679 opn = "tlbwr";
8680 if (!env->tlb->helper_tlbwr)
8681 goto die;
8682 gen_helper_tlbwr(cpu_env);
8683 break;
8684 case OPC_TLBP:
8685 opn = "tlbp";
8686 if (!env->tlb->helper_tlbp)
8687 goto die;
8688 gen_helper_tlbp(cpu_env);
8689 break;
8690 case OPC_TLBR:
8691 opn = "tlbr";
8692 if (!env->tlb->helper_tlbr)
8693 goto die;
8694 gen_helper_tlbr(cpu_env);
8695 break;
8696 case OPC_ERET: /* OPC_ERETNC */
8697 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8698 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8699 goto die;
8700 } else {
8701 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8702 if (ctx->opcode & (1 << bit_shift)) {
8703 /* OPC_ERETNC */
8704 opn = "eretnc";
8705 check_insn(ctx, ISA_MIPS32R5);
8706 gen_helper_eretnc(cpu_env);
8707 } else {
8708 /* OPC_ERET */
8709 opn = "eret";
8710 check_insn(ctx, ISA_MIPS2);
8711 gen_helper_eret(cpu_env);
8713 ctx->base.is_jmp = DISAS_EXIT;
8715 break;
8716 case OPC_DERET:
8717 opn = "deret";
8718 check_insn(ctx, ISA_MIPS32);
8719 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8720 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8721 goto die;
8723 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8724 MIPS_INVAL(opn);
8725 generate_exception_end(ctx, EXCP_RI);
8726 } else {
8727 gen_helper_deret(cpu_env);
8728 ctx->base.is_jmp = DISAS_EXIT;
8730 break;
8731 case OPC_WAIT:
8732 opn = "wait";
8733 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8734 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8735 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8736 goto die;
8738 /* If we get an exception, we want to restart at next instruction */
8739 ctx->base.pc_next += 4;
8740 save_cpu_state(ctx, 1);
8741 ctx->base.pc_next -= 4;
8742 gen_helper_wait(cpu_env);
8743 ctx->base.is_jmp = DISAS_NORETURN;
8744 break;
8745 default:
8746 die:
8747 MIPS_INVAL(opn);
8748 generate_exception_end(ctx, EXCP_RI);
8749 return;
8751 (void)opn; /* avoid a compiler warning */
8753 #endif /* !CONFIG_USER_ONLY */
8755 /* CP1 Branches (before delay slot) */
8756 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8757 int32_t cc, int32_t offset)
8759 target_ulong btarget;
8760 TCGv_i32 t0 = tcg_temp_new_i32();
8762 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8763 generate_exception_end(ctx, EXCP_RI);
8764 goto out;
8767 if (cc != 0)
8768 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8770 btarget = ctx->base.pc_next + 4 + offset;
8772 switch (op) {
8773 case OPC_BC1F:
8774 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8775 tcg_gen_not_i32(t0, t0);
8776 tcg_gen_andi_i32(t0, t0, 1);
8777 tcg_gen_extu_i32_tl(bcond, t0);
8778 goto not_likely;
8779 case OPC_BC1FL:
8780 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8781 tcg_gen_not_i32(t0, t0);
8782 tcg_gen_andi_i32(t0, t0, 1);
8783 tcg_gen_extu_i32_tl(bcond, t0);
8784 goto likely;
8785 case OPC_BC1T:
8786 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8787 tcg_gen_andi_i32(t0, t0, 1);
8788 tcg_gen_extu_i32_tl(bcond, t0);
8789 goto not_likely;
8790 case OPC_BC1TL:
8791 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8792 tcg_gen_andi_i32(t0, t0, 1);
8793 tcg_gen_extu_i32_tl(bcond, t0);
8794 likely:
8795 ctx->hflags |= MIPS_HFLAG_BL;
8796 break;
8797 case OPC_BC1FANY2:
8799 TCGv_i32 t1 = tcg_temp_new_i32();
8800 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8801 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8802 tcg_gen_nand_i32(t0, t0, t1);
8803 tcg_temp_free_i32(t1);
8804 tcg_gen_andi_i32(t0, t0, 1);
8805 tcg_gen_extu_i32_tl(bcond, t0);
8807 goto not_likely;
8808 case OPC_BC1TANY2:
8810 TCGv_i32 t1 = tcg_temp_new_i32();
8811 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8812 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8813 tcg_gen_or_i32(t0, t0, t1);
8814 tcg_temp_free_i32(t1);
8815 tcg_gen_andi_i32(t0, t0, 1);
8816 tcg_gen_extu_i32_tl(bcond, t0);
8818 goto not_likely;
8819 case OPC_BC1FANY4:
8821 TCGv_i32 t1 = tcg_temp_new_i32();
8822 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8823 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8824 tcg_gen_and_i32(t0, t0, t1);
8825 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8826 tcg_gen_and_i32(t0, t0, t1);
8827 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8828 tcg_gen_nand_i32(t0, t0, t1);
8829 tcg_temp_free_i32(t1);
8830 tcg_gen_andi_i32(t0, t0, 1);
8831 tcg_gen_extu_i32_tl(bcond, t0);
8833 goto not_likely;
8834 case OPC_BC1TANY4:
8836 TCGv_i32 t1 = tcg_temp_new_i32();
8837 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8838 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8839 tcg_gen_or_i32(t0, t0, t1);
8840 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8841 tcg_gen_or_i32(t0, t0, t1);
8842 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8843 tcg_gen_or_i32(t0, t0, t1);
8844 tcg_temp_free_i32(t1);
8845 tcg_gen_andi_i32(t0, t0, 1);
8846 tcg_gen_extu_i32_tl(bcond, t0);
8848 not_likely:
8849 ctx->hflags |= MIPS_HFLAG_BC;
8850 break;
8851 default:
8852 MIPS_INVAL("cp1 cond branch");
8853 generate_exception_end(ctx, EXCP_RI);
8854 goto out;
8856 ctx->btarget = btarget;
8857 ctx->hflags |= MIPS_HFLAG_BDS32;
8858 out:
8859 tcg_temp_free_i32(t0);
8862 /* R6 CP1 Branches */
8863 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8864 int32_t ft, int32_t offset,
8865 int delayslot_size)
8867 target_ulong btarget;
8868 TCGv_i64 t0 = tcg_temp_new_i64();
8870 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8871 #ifdef MIPS_DEBUG_DISAS
8872 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8873 "\n", ctx->base.pc_next);
8874 #endif
8875 generate_exception_end(ctx, EXCP_RI);
8876 goto out;
8879 gen_load_fpr64(ctx, t0, ft);
8880 tcg_gen_andi_i64(t0, t0, 1);
8882 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
8884 switch (op) {
8885 case OPC_BC1EQZ:
8886 tcg_gen_xori_i64(t0, t0, 1);
8887 ctx->hflags |= MIPS_HFLAG_BC;
8888 break;
8889 case OPC_BC1NEZ:
8890 /* t0 already set */
8891 ctx->hflags |= MIPS_HFLAG_BC;
8892 break;
8893 default:
8894 MIPS_INVAL("cp1 cond branch");
8895 generate_exception_end(ctx, EXCP_RI);
8896 goto out;
8899 tcg_gen_trunc_i64_tl(bcond, t0);
8901 ctx->btarget = btarget;
8903 switch (delayslot_size) {
8904 case 2:
8905 ctx->hflags |= MIPS_HFLAG_BDS16;
8906 break;
8907 case 4:
8908 ctx->hflags |= MIPS_HFLAG_BDS32;
8909 break;
8912 out:
8913 tcg_temp_free_i64(t0);
8916 /* Coprocessor 1 (FPU) */
8918 #define FOP(func, fmt) (((fmt) << 21) | (func))
8920 enum fopcode {
8921 OPC_ADD_S = FOP(0, FMT_S),
8922 OPC_SUB_S = FOP(1, FMT_S),
8923 OPC_MUL_S = FOP(2, FMT_S),
8924 OPC_DIV_S = FOP(3, FMT_S),
8925 OPC_SQRT_S = FOP(4, FMT_S),
8926 OPC_ABS_S = FOP(5, FMT_S),
8927 OPC_MOV_S = FOP(6, FMT_S),
8928 OPC_NEG_S = FOP(7, FMT_S),
8929 OPC_ROUND_L_S = FOP(8, FMT_S),
8930 OPC_TRUNC_L_S = FOP(9, FMT_S),
8931 OPC_CEIL_L_S = FOP(10, FMT_S),
8932 OPC_FLOOR_L_S = FOP(11, FMT_S),
8933 OPC_ROUND_W_S = FOP(12, FMT_S),
8934 OPC_TRUNC_W_S = FOP(13, FMT_S),
8935 OPC_CEIL_W_S = FOP(14, FMT_S),
8936 OPC_FLOOR_W_S = FOP(15, FMT_S),
8937 OPC_SEL_S = FOP(16, FMT_S),
8938 OPC_MOVCF_S = FOP(17, FMT_S),
8939 OPC_MOVZ_S = FOP(18, FMT_S),
8940 OPC_MOVN_S = FOP(19, FMT_S),
8941 OPC_SELEQZ_S = FOP(20, FMT_S),
8942 OPC_RECIP_S = FOP(21, FMT_S),
8943 OPC_RSQRT_S = FOP(22, FMT_S),
8944 OPC_SELNEZ_S = FOP(23, FMT_S),
8945 OPC_MADDF_S = FOP(24, FMT_S),
8946 OPC_MSUBF_S = FOP(25, FMT_S),
8947 OPC_RINT_S = FOP(26, FMT_S),
8948 OPC_CLASS_S = FOP(27, FMT_S),
8949 OPC_MIN_S = FOP(28, FMT_S),
8950 OPC_RECIP2_S = FOP(28, FMT_S),
8951 OPC_MINA_S = FOP(29, FMT_S),
8952 OPC_RECIP1_S = FOP(29, FMT_S),
8953 OPC_MAX_S = FOP(30, FMT_S),
8954 OPC_RSQRT1_S = FOP(30, FMT_S),
8955 OPC_MAXA_S = FOP(31, FMT_S),
8956 OPC_RSQRT2_S = FOP(31, FMT_S),
8957 OPC_CVT_D_S = FOP(33, FMT_S),
8958 OPC_CVT_W_S = FOP(36, FMT_S),
8959 OPC_CVT_L_S = FOP(37, FMT_S),
8960 OPC_CVT_PS_S = FOP(38, FMT_S),
8961 OPC_CMP_F_S = FOP (48, FMT_S),
8962 OPC_CMP_UN_S = FOP (49, FMT_S),
8963 OPC_CMP_EQ_S = FOP (50, FMT_S),
8964 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8965 OPC_CMP_OLT_S = FOP (52, FMT_S),
8966 OPC_CMP_ULT_S = FOP (53, FMT_S),
8967 OPC_CMP_OLE_S = FOP (54, FMT_S),
8968 OPC_CMP_ULE_S = FOP (55, FMT_S),
8969 OPC_CMP_SF_S = FOP (56, FMT_S),
8970 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8971 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8972 OPC_CMP_NGL_S = FOP (59, FMT_S),
8973 OPC_CMP_LT_S = FOP (60, FMT_S),
8974 OPC_CMP_NGE_S = FOP (61, FMT_S),
8975 OPC_CMP_LE_S = FOP (62, FMT_S),
8976 OPC_CMP_NGT_S = FOP (63, FMT_S),
8978 OPC_ADD_D = FOP(0, FMT_D),
8979 OPC_SUB_D = FOP(1, FMT_D),
8980 OPC_MUL_D = FOP(2, FMT_D),
8981 OPC_DIV_D = FOP(3, FMT_D),
8982 OPC_SQRT_D = FOP(4, FMT_D),
8983 OPC_ABS_D = FOP(5, FMT_D),
8984 OPC_MOV_D = FOP(6, FMT_D),
8985 OPC_NEG_D = FOP(7, FMT_D),
8986 OPC_ROUND_L_D = FOP(8, FMT_D),
8987 OPC_TRUNC_L_D = FOP(9, FMT_D),
8988 OPC_CEIL_L_D = FOP(10, FMT_D),
8989 OPC_FLOOR_L_D = FOP(11, FMT_D),
8990 OPC_ROUND_W_D = FOP(12, FMT_D),
8991 OPC_TRUNC_W_D = FOP(13, FMT_D),
8992 OPC_CEIL_W_D = FOP(14, FMT_D),
8993 OPC_FLOOR_W_D = FOP(15, FMT_D),
8994 OPC_SEL_D = FOP(16, FMT_D),
8995 OPC_MOVCF_D = FOP(17, FMT_D),
8996 OPC_MOVZ_D = FOP(18, FMT_D),
8997 OPC_MOVN_D = FOP(19, FMT_D),
8998 OPC_SELEQZ_D = FOP(20, FMT_D),
8999 OPC_RECIP_D = FOP(21, FMT_D),
9000 OPC_RSQRT_D = FOP(22, FMT_D),
9001 OPC_SELNEZ_D = FOP(23, FMT_D),
9002 OPC_MADDF_D = FOP(24, FMT_D),
9003 OPC_MSUBF_D = FOP(25, FMT_D),
9004 OPC_RINT_D = FOP(26, FMT_D),
9005 OPC_CLASS_D = FOP(27, FMT_D),
9006 OPC_MIN_D = FOP(28, FMT_D),
9007 OPC_RECIP2_D = FOP(28, FMT_D),
9008 OPC_MINA_D = FOP(29, FMT_D),
9009 OPC_RECIP1_D = FOP(29, FMT_D),
9010 OPC_MAX_D = FOP(30, FMT_D),
9011 OPC_RSQRT1_D = FOP(30, FMT_D),
9012 OPC_MAXA_D = FOP(31, FMT_D),
9013 OPC_RSQRT2_D = FOP(31, FMT_D),
9014 OPC_CVT_S_D = FOP(32, FMT_D),
9015 OPC_CVT_W_D = FOP(36, FMT_D),
9016 OPC_CVT_L_D = FOP(37, FMT_D),
9017 OPC_CMP_F_D = FOP (48, FMT_D),
9018 OPC_CMP_UN_D = FOP (49, FMT_D),
9019 OPC_CMP_EQ_D = FOP (50, FMT_D),
9020 OPC_CMP_UEQ_D = FOP (51, FMT_D),
9021 OPC_CMP_OLT_D = FOP (52, FMT_D),
9022 OPC_CMP_ULT_D = FOP (53, FMT_D),
9023 OPC_CMP_OLE_D = FOP (54, FMT_D),
9024 OPC_CMP_ULE_D = FOP (55, FMT_D),
9025 OPC_CMP_SF_D = FOP (56, FMT_D),
9026 OPC_CMP_NGLE_D = FOP (57, FMT_D),
9027 OPC_CMP_SEQ_D = FOP (58, FMT_D),
9028 OPC_CMP_NGL_D = FOP (59, FMT_D),
9029 OPC_CMP_LT_D = FOP (60, FMT_D),
9030 OPC_CMP_NGE_D = FOP (61, FMT_D),
9031 OPC_CMP_LE_D = FOP (62, FMT_D),
9032 OPC_CMP_NGT_D = FOP (63, FMT_D),
9034 OPC_CVT_S_W = FOP(32, FMT_W),
9035 OPC_CVT_D_W = FOP(33, FMT_W),
9036 OPC_CVT_S_L = FOP(32, FMT_L),
9037 OPC_CVT_D_L = FOP(33, FMT_L),
9038 OPC_CVT_PS_PW = FOP(38, FMT_W),
9040 OPC_ADD_PS = FOP(0, FMT_PS),
9041 OPC_SUB_PS = FOP(1, FMT_PS),
9042 OPC_MUL_PS = FOP(2, FMT_PS),
9043 OPC_DIV_PS = FOP(3, FMT_PS),
9044 OPC_ABS_PS = FOP(5, FMT_PS),
9045 OPC_MOV_PS = FOP(6, FMT_PS),
9046 OPC_NEG_PS = FOP(7, FMT_PS),
9047 OPC_MOVCF_PS = FOP(17, FMT_PS),
9048 OPC_MOVZ_PS = FOP(18, FMT_PS),
9049 OPC_MOVN_PS = FOP(19, FMT_PS),
9050 OPC_ADDR_PS = FOP(24, FMT_PS),
9051 OPC_MULR_PS = FOP(26, FMT_PS),
9052 OPC_RECIP2_PS = FOP(28, FMT_PS),
9053 OPC_RECIP1_PS = FOP(29, FMT_PS),
9054 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9055 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9057 OPC_CVT_S_PU = FOP(32, FMT_PS),
9058 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9059 OPC_CVT_S_PL = FOP(40, FMT_PS),
9060 OPC_PLL_PS = FOP(44, FMT_PS),
9061 OPC_PLU_PS = FOP(45, FMT_PS),
9062 OPC_PUL_PS = FOP(46, FMT_PS),
9063 OPC_PUU_PS = FOP(47, FMT_PS),
9064 OPC_CMP_F_PS = FOP (48, FMT_PS),
9065 OPC_CMP_UN_PS = FOP (49, FMT_PS),
9066 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
9067 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
9068 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
9069 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
9070 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
9071 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
9072 OPC_CMP_SF_PS = FOP (56, FMT_PS),
9073 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
9074 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
9075 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
9076 OPC_CMP_LT_PS = FOP (60, FMT_PS),
9077 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
9078 OPC_CMP_LE_PS = FOP (62, FMT_PS),
9079 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
9082 enum r6_f_cmp_op {
9083 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9084 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9085 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9086 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9087 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9088 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9089 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9090 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9091 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9092 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9093 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9094 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9095 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9096 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9097 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9098 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9099 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9100 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9101 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9102 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9103 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9104 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9106 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9107 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9108 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9109 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9110 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9111 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9112 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9113 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9114 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9115 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9116 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9117 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9118 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9119 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9120 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9121 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9122 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9123 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9124 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9125 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9126 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9127 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9129 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
9131 TCGv t0 = tcg_temp_new();
9133 switch (opc) {
9134 case OPC_MFC1:
9136 TCGv_i32 fp0 = tcg_temp_new_i32();
9138 gen_load_fpr32(ctx, fp0, fs);
9139 tcg_gen_ext_i32_tl(t0, fp0);
9140 tcg_temp_free_i32(fp0);
9142 gen_store_gpr(t0, rt);
9143 break;
9144 case OPC_MTC1:
9145 gen_load_gpr(t0, rt);
9147 TCGv_i32 fp0 = tcg_temp_new_i32();
9149 tcg_gen_trunc_tl_i32(fp0, t0);
9150 gen_store_fpr32(ctx, fp0, fs);
9151 tcg_temp_free_i32(fp0);
9153 break;
9154 case OPC_CFC1:
9155 gen_helper_1e0i(cfc1, t0, fs);
9156 gen_store_gpr(t0, rt);
9157 break;
9158 case OPC_CTC1:
9159 gen_load_gpr(t0, rt);
9160 save_cpu_state(ctx, 0);
9162 TCGv_i32 fs_tmp = tcg_const_i32(fs);
9164 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9165 tcg_temp_free_i32(fs_tmp);
9167 /* Stop translation as we may have changed hflags */
9168 ctx->base.is_jmp = DISAS_STOP;
9169 break;
9170 #if defined(TARGET_MIPS64)
9171 case OPC_DMFC1:
9172 gen_load_fpr64(ctx, t0, fs);
9173 gen_store_gpr(t0, rt);
9174 break;
9175 case OPC_DMTC1:
9176 gen_load_gpr(t0, rt);
9177 gen_store_fpr64(ctx, t0, fs);
9178 break;
9179 #endif
9180 case OPC_MFHC1:
9182 TCGv_i32 fp0 = tcg_temp_new_i32();
9184 gen_load_fpr32h(ctx, fp0, fs);
9185 tcg_gen_ext_i32_tl(t0, fp0);
9186 tcg_temp_free_i32(fp0);
9188 gen_store_gpr(t0, rt);
9189 break;
9190 case OPC_MTHC1:
9191 gen_load_gpr(t0, rt);
9193 TCGv_i32 fp0 = tcg_temp_new_i32();
9195 tcg_gen_trunc_tl_i32(fp0, t0);
9196 gen_store_fpr32h(ctx, fp0, fs);
9197 tcg_temp_free_i32(fp0);
9199 break;
9200 default:
9201 MIPS_INVAL("cp1 move");
9202 generate_exception_end(ctx, EXCP_RI);
9203 goto out;
9206 out:
9207 tcg_temp_free(t0);
9210 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
9212 TCGLabel *l1;
9213 TCGCond cond;
9214 TCGv_i32 t0;
9216 if (rd == 0) {
9217 /* Treat as NOP. */
9218 return;
9221 if (tf)
9222 cond = TCG_COND_EQ;
9223 else
9224 cond = TCG_COND_NE;
9226 l1 = gen_new_label();
9227 t0 = tcg_temp_new_i32();
9228 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9229 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9230 tcg_temp_free_i32(t0);
9231 if (rs == 0) {
9232 tcg_gen_movi_tl(cpu_gpr[rd], 0);
9233 } else {
9234 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
9236 gen_set_label(l1);
9239 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9240 int tf)
9242 int cond;
9243 TCGv_i32 t0 = tcg_temp_new_i32();
9244 TCGLabel *l1 = gen_new_label();
9246 if (tf)
9247 cond = TCG_COND_EQ;
9248 else
9249 cond = TCG_COND_NE;
9251 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9252 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9253 gen_load_fpr32(ctx, t0, fs);
9254 gen_store_fpr32(ctx, t0, fd);
9255 gen_set_label(l1);
9256 tcg_temp_free_i32(t0);
9259 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
9261 int cond;
9262 TCGv_i32 t0 = tcg_temp_new_i32();
9263 TCGv_i64 fp0;
9264 TCGLabel *l1 = gen_new_label();
9266 if (tf)
9267 cond = TCG_COND_EQ;
9268 else
9269 cond = TCG_COND_NE;
9271 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9272 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9273 tcg_temp_free_i32(t0);
9274 fp0 = tcg_temp_new_i64();
9275 gen_load_fpr64(ctx, fp0, fs);
9276 gen_store_fpr64(ctx, fp0, fd);
9277 tcg_temp_free_i64(fp0);
9278 gen_set_label(l1);
9281 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9282 int cc, int tf)
9284 int cond;
9285 TCGv_i32 t0 = tcg_temp_new_i32();
9286 TCGLabel *l1 = gen_new_label();
9287 TCGLabel *l2 = gen_new_label();
9289 if (tf)
9290 cond = TCG_COND_EQ;
9291 else
9292 cond = TCG_COND_NE;
9294 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9295 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9296 gen_load_fpr32(ctx, t0, fs);
9297 gen_store_fpr32(ctx, t0, fd);
9298 gen_set_label(l1);
9300 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
9301 tcg_gen_brcondi_i32(cond, t0, 0, l2);
9302 gen_load_fpr32h(ctx, t0, fs);
9303 gen_store_fpr32h(ctx, t0, fd);
9304 tcg_temp_free_i32(t0);
9305 gen_set_label(l2);
9308 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9309 int fs)
9311 TCGv_i32 t1 = tcg_const_i32(0);
9312 TCGv_i32 fp0 = tcg_temp_new_i32();
9313 TCGv_i32 fp1 = tcg_temp_new_i32();
9314 TCGv_i32 fp2 = tcg_temp_new_i32();
9315 gen_load_fpr32(ctx, fp0, fd);
9316 gen_load_fpr32(ctx, fp1, ft);
9317 gen_load_fpr32(ctx, fp2, fs);
9319 switch (op1) {
9320 case OPC_SEL_S:
9321 tcg_gen_andi_i32(fp0, fp0, 1);
9322 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9323 break;
9324 case OPC_SELEQZ_S:
9325 tcg_gen_andi_i32(fp1, fp1, 1);
9326 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9327 break;
9328 case OPC_SELNEZ_S:
9329 tcg_gen_andi_i32(fp1, fp1, 1);
9330 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9331 break;
9332 default:
9333 MIPS_INVAL("gen_sel_s");
9334 generate_exception_end(ctx, EXCP_RI);
9335 break;
9338 gen_store_fpr32(ctx, fp0, fd);
9339 tcg_temp_free_i32(fp2);
9340 tcg_temp_free_i32(fp1);
9341 tcg_temp_free_i32(fp0);
9342 tcg_temp_free_i32(t1);
9345 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9346 int fs)
9348 TCGv_i64 t1 = tcg_const_i64(0);
9349 TCGv_i64 fp0 = tcg_temp_new_i64();
9350 TCGv_i64 fp1 = tcg_temp_new_i64();
9351 TCGv_i64 fp2 = tcg_temp_new_i64();
9352 gen_load_fpr64(ctx, fp0, fd);
9353 gen_load_fpr64(ctx, fp1, ft);
9354 gen_load_fpr64(ctx, fp2, fs);
9356 switch (op1) {
9357 case OPC_SEL_D:
9358 tcg_gen_andi_i64(fp0, fp0, 1);
9359 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9360 break;
9361 case OPC_SELEQZ_D:
9362 tcg_gen_andi_i64(fp1, fp1, 1);
9363 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9364 break;
9365 case OPC_SELNEZ_D:
9366 tcg_gen_andi_i64(fp1, fp1, 1);
9367 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9368 break;
9369 default:
9370 MIPS_INVAL("gen_sel_d");
9371 generate_exception_end(ctx, EXCP_RI);
9372 break;
9375 gen_store_fpr64(ctx, fp0, fd);
9376 tcg_temp_free_i64(fp2);
9377 tcg_temp_free_i64(fp1);
9378 tcg_temp_free_i64(fp0);
9379 tcg_temp_free_i64(t1);
9382 static void gen_farith (DisasContext *ctx, enum fopcode op1,
9383 int ft, int fs, int fd, int cc)
9385 uint32_t func = ctx->opcode & 0x3f;
9386 switch (op1) {
9387 case OPC_ADD_S:
9389 TCGv_i32 fp0 = tcg_temp_new_i32();
9390 TCGv_i32 fp1 = tcg_temp_new_i32();
9392 gen_load_fpr32(ctx, fp0, fs);
9393 gen_load_fpr32(ctx, fp1, ft);
9394 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
9395 tcg_temp_free_i32(fp1);
9396 gen_store_fpr32(ctx, fp0, fd);
9397 tcg_temp_free_i32(fp0);
9399 break;
9400 case OPC_SUB_S:
9402 TCGv_i32 fp0 = tcg_temp_new_i32();
9403 TCGv_i32 fp1 = tcg_temp_new_i32();
9405 gen_load_fpr32(ctx, fp0, fs);
9406 gen_load_fpr32(ctx, fp1, ft);
9407 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
9408 tcg_temp_free_i32(fp1);
9409 gen_store_fpr32(ctx, fp0, fd);
9410 tcg_temp_free_i32(fp0);
9412 break;
9413 case OPC_MUL_S:
9415 TCGv_i32 fp0 = tcg_temp_new_i32();
9416 TCGv_i32 fp1 = tcg_temp_new_i32();
9418 gen_load_fpr32(ctx, fp0, fs);
9419 gen_load_fpr32(ctx, fp1, ft);
9420 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
9421 tcg_temp_free_i32(fp1);
9422 gen_store_fpr32(ctx, fp0, fd);
9423 tcg_temp_free_i32(fp0);
9425 break;
9426 case OPC_DIV_S:
9428 TCGv_i32 fp0 = tcg_temp_new_i32();
9429 TCGv_i32 fp1 = tcg_temp_new_i32();
9431 gen_load_fpr32(ctx, fp0, fs);
9432 gen_load_fpr32(ctx, fp1, ft);
9433 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
9434 tcg_temp_free_i32(fp1);
9435 gen_store_fpr32(ctx, fp0, fd);
9436 tcg_temp_free_i32(fp0);
9438 break;
9439 case OPC_SQRT_S:
9441 TCGv_i32 fp0 = tcg_temp_new_i32();
9443 gen_load_fpr32(ctx, fp0, fs);
9444 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
9445 gen_store_fpr32(ctx, fp0, fd);
9446 tcg_temp_free_i32(fp0);
9448 break;
9449 case OPC_ABS_S:
9451 TCGv_i32 fp0 = tcg_temp_new_i32();
9453 gen_load_fpr32(ctx, fp0, fs);
9454 if (ctx->abs2008) {
9455 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9456 } else {
9457 gen_helper_float_abs_s(fp0, fp0);
9459 gen_store_fpr32(ctx, fp0, fd);
9460 tcg_temp_free_i32(fp0);
9462 break;
9463 case OPC_MOV_S:
9465 TCGv_i32 fp0 = tcg_temp_new_i32();
9467 gen_load_fpr32(ctx, fp0, fs);
9468 gen_store_fpr32(ctx, fp0, fd);
9469 tcg_temp_free_i32(fp0);
9471 break;
9472 case OPC_NEG_S:
9474 TCGv_i32 fp0 = tcg_temp_new_i32();
9476 gen_load_fpr32(ctx, fp0, fs);
9477 if (ctx->abs2008) {
9478 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9479 } else {
9480 gen_helper_float_chs_s(fp0, fp0);
9482 gen_store_fpr32(ctx, fp0, fd);
9483 tcg_temp_free_i32(fp0);
9485 break;
9486 case OPC_ROUND_L_S:
9487 check_cp1_64bitmode(ctx);
9489 TCGv_i32 fp32 = tcg_temp_new_i32();
9490 TCGv_i64 fp64 = tcg_temp_new_i64();
9492 gen_load_fpr32(ctx, fp32, fs);
9493 if (ctx->nan2008) {
9494 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
9495 } else {
9496 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
9498 tcg_temp_free_i32(fp32);
9499 gen_store_fpr64(ctx, fp64, fd);
9500 tcg_temp_free_i64(fp64);
9502 break;
9503 case OPC_TRUNC_L_S:
9504 check_cp1_64bitmode(ctx);
9506 TCGv_i32 fp32 = tcg_temp_new_i32();
9507 TCGv_i64 fp64 = tcg_temp_new_i64();
9509 gen_load_fpr32(ctx, fp32, fs);
9510 if (ctx->nan2008) {
9511 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
9512 } else {
9513 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
9515 tcg_temp_free_i32(fp32);
9516 gen_store_fpr64(ctx, fp64, fd);
9517 tcg_temp_free_i64(fp64);
9519 break;
9520 case OPC_CEIL_L_S:
9521 check_cp1_64bitmode(ctx);
9523 TCGv_i32 fp32 = tcg_temp_new_i32();
9524 TCGv_i64 fp64 = tcg_temp_new_i64();
9526 gen_load_fpr32(ctx, fp32, fs);
9527 if (ctx->nan2008) {
9528 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
9529 } else {
9530 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
9532 tcg_temp_free_i32(fp32);
9533 gen_store_fpr64(ctx, fp64, fd);
9534 tcg_temp_free_i64(fp64);
9536 break;
9537 case OPC_FLOOR_L_S:
9538 check_cp1_64bitmode(ctx);
9540 TCGv_i32 fp32 = tcg_temp_new_i32();
9541 TCGv_i64 fp64 = tcg_temp_new_i64();
9543 gen_load_fpr32(ctx, fp32, fs);
9544 if (ctx->nan2008) {
9545 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
9546 } else {
9547 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
9549 tcg_temp_free_i32(fp32);
9550 gen_store_fpr64(ctx, fp64, fd);
9551 tcg_temp_free_i64(fp64);
9553 break;
9554 case OPC_ROUND_W_S:
9556 TCGv_i32 fp0 = tcg_temp_new_i32();
9558 gen_load_fpr32(ctx, fp0, fs);
9559 if (ctx->nan2008) {
9560 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
9561 } else {
9562 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
9564 gen_store_fpr32(ctx, fp0, fd);
9565 tcg_temp_free_i32(fp0);
9567 break;
9568 case OPC_TRUNC_W_S:
9570 TCGv_i32 fp0 = tcg_temp_new_i32();
9572 gen_load_fpr32(ctx, fp0, fs);
9573 if (ctx->nan2008) {
9574 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
9575 } else {
9576 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
9578 gen_store_fpr32(ctx, fp0, fd);
9579 tcg_temp_free_i32(fp0);
9581 break;
9582 case OPC_CEIL_W_S:
9584 TCGv_i32 fp0 = tcg_temp_new_i32();
9586 gen_load_fpr32(ctx, fp0, fs);
9587 if (ctx->nan2008) {
9588 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
9589 } else {
9590 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
9592 gen_store_fpr32(ctx, fp0, fd);
9593 tcg_temp_free_i32(fp0);
9595 break;
9596 case OPC_FLOOR_W_S:
9598 TCGv_i32 fp0 = tcg_temp_new_i32();
9600 gen_load_fpr32(ctx, fp0, fs);
9601 if (ctx->nan2008) {
9602 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
9603 } else {
9604 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
9606 gen_store_fpr32(ctx, fp0, fd);
9607 tcg_temp_free_i32(fp0);
9609 break;
9610 case OPC_SEL_S:
9611 check_insn(ctx, ISA_MIPS32R6);
9612 gen_sel_s(ctx, op1, fd, ft, fs);
9613 break;
9614 case OPC_SELEQZ_S:
9615 check_insn(ctx, ISA_MIPS32R6);
9616 gen_sel_s(ctx, op1, fd, ft, fs);
9617 break;
9618 case OPC_SELNEZ_S:
9619 check_insn(ctx, ISA_MIPS32R6);
9620 gen_sel_s(ctx, op1, fd, ft, fs);
9621 break;
9622 case OPC_MOVCF_S:
9623 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9624 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9625 break;
9626 case OPC_MOVZ_S:
9627 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9629 TCGLabel *l1 = gen_new_label();
9630 TCGv_i32 fp0;
9632 if (ft != 0) {
9633 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9635 fp0 = tcg_temp_new_i32();
9636 gen_load_fpr32(ctx, fp0, fs);
9637 gen_store_fpr32(ctx, fp0, fd);
9638 tcg_temp_free_i32(fp0);
9639 gen_set_label(l1);
9641 break;
9642 case OPC_MOVN_S:
9643 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9645 TCGLabel *l1 = gen_new_label();
9646 TCGv_i32 fp0;
9648 if (ft != 0) {
9649 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9650 fp0 = tcg_temp_new_i32();
9651 gen_load_fpr32(ctx, fp0, fs);
9652 gen_store_fpr32(ctx, fp0, fd);
9653 tcg_temp_free_i32(fp0);
9654 gen_set_label(l1);
9657 break;
9658 case OPC_RECIP_S:
9660 TCGv_i32 fp0 = tcg_temp_new_i32();
9662 gen_load_fpr32(ctx, fp0, fs);
9663 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9664 gen_store_fpr32(ctx, fp0, fd);
9665 tcg_temp_free_i32(fp0);
9667 break;
9668 case OPC_RSQRT_S:
9670 TCGv_i32 fp0 = tcg_temp_new_i32();
9672 gen_load_fpr32(ctx, fp0, fs);
9673 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9674 gen_store_fpr32(ctx, fp0, fd);
9675 tcg_temp_free_i32(fp0);
9677 break;
9678 case OPC_MADDF_S:
9679 check_insn(ctx, ISA_MIPS32R6);
9681 TCGv_i32 fp0 = tcg_temp_new_i32();
9682 TCGv_i32 fp1 = tcg_temp_new_i32();
9683 TCGv_i32 fp2 = tcg_temp_new_i32();
9684 gen_load_fpr32(ctx, fp0, fs);
9685 gen_load_fpr32(ctx, fp1, ft);
9686 gen_load_fpr32(ctx, fp2, fd);
9687 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9688 gen_store_fpr32(ctx, fp2, fd);
9689 tcg_temp_free_i32(fp2);
9690 tcg_temp_free_i32(fp1);
9691 tcg_temp_free_i32(fp0);
9693 break;
9694 case OPC_MSUBF_S:
9695 check_insn(ctx, ISA_MIPS32R6);
9697 TCGv_i32 fp0 = tcg_temp_new_i32();
9698 TCGv_i32 fp1 = tcg_temp_new_i32();
9699 TCGv_i32 fp2 = tcg_temp_new_i32();
9700 gen_load_fpr32(ctx, fp0, fs);
9701 gen_load_fpr32(ctx, fp1, ft);
9702 gen_load_fpr32(ctx, fp2, fd);
9703 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9704 gen_store_fpr32(ctx, fp2, fd);
9705 tcg_temp_free_i32(fp2);
9706 tcg_temp_free_i32(fp1);
9707 tcg_temp_free_i32(fp0);
9709 break;
9710 case OPC_RINT_S:
9711 check_insn(ctx, ISA_MIPS32R6);
9713 TCGv_i32 fp0 = tcg_temp_new_i32();
9714 gen_load_fpr32(ctx, fp0, fs);
9715 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9716 gen_store_fpr32(ctx, fp0, fd);
9717 tcg_temp_free_i32(fp0);
9719 break;
9720 case OPC_CLASS_S:
9721 check_insn(ctx, ISA_MIPS32R6);
9723 TCGv_i32 fp0 = tcg_temp_new_i32();
9724 gen_load_fpr32(ctx, fp0, fs);
9725 gen_helper_float_class_s(fp0, cpu_env, fp0);
9726 gen_store_fpr32(ctx, fp0, fd);
9727 tcg_temp_free_i32(fp0);
9729 break;
9730 case OPC_MIN_S: /* OPC_RECIP2_S */
9731 if (ctx->insn_flags & ISA_MIPS32R6) {
9732 /* OPC_MIN_S */
9733 TCGv_i32 fp0 = tcg_temp_new_i32();
9734 TCGv_i32 fp1 = tcg_temp_new_i32();
9735 TCGv_i32 fp2 = tcg_temp_new_i32();
9736 gen_load_fpr32(ctx, fp0, fs);
9737 gen_load_fpr32(ctx, fp1, ft);
9738 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9739 gen_store_fpr32(ctx, fp2, fd);
9740 tcg_temp_free_i32(fp2);
9741 tcg_temp_free_i32(fp1);
9742 tcg_temp_free_i32(fp0);
9743 } else {
9744 /* OPC_RECIP2_S */
9745 check_cp1_64bitmode(ctx);
9747 TCGv_i32 fp0 = tcg_temp_new_i32();
9748 TCGv_i32 fp1 = tcg_temp_new_i32();
9750 gen_load_fpr32(ctx, fp0, fs);
9751 gen_load_fpr32(ctx, fp1, ft);
9752 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9753 tcg_temp_free_i32(fp1);
9754 gen_store_fpr32(ctx, fp0, fd);
9755 tcg_temp_free_i32(fp0);
9758 break;
9759 case OPC_MINA_S: /* OPC_RECIP1_S */
9760 if (ctx->insn_flags & ISA_MIPS32R6) {
9761 /* OPC_MINA_S */
9762 TCGv_i32 fp0 = tcg_temp_new_i32();
9763 TCGv_i32 fp1 = tcg_temp_new_i32();
9764 TCGv_i32 fp2 = tcg_temp_new_i32();
9765 gen_load_fpr32(ctx, fp0, fs);
9766 gen_load_fpr32(ctx, fp1, ft);
9767 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9768 gen_store_fpr32(ctx, fp2, fd);
9769 tcg_temp_free_i32(fp2);
9770 tcg_temp_free_i32(fp1);
9771 tcg_temp_free_i32(fp0);
9772 } else {
9773 /* OPC_RECIP1_S */
9774 check_cp1_64bitmode(ctx);
9776 TCGv_i32 fp0 = tcg_temp_new_i32();
9778 gen_load_fpr32(ctx, fp0, fs);
9779 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9780 gen_store_fpr32(ctx, fp0, fd);
9781 tcg_temp_free_i32(fp0);
9784 break;
9785 case OPC_MAX_S: /* OPC_RSQRT1_S */
9786 if (ctx->insn_flags & ISA_MIPS32R6) {
9787 /* OPC_MAX_S */
9788 TCGv_i32 fp0 = tcg_temp_new_i32();
9789 TCGv_i32 fp1 = tcg_temp_new_i32();
9790 gen_load_fpr32(ctx, fp0, fs);
9791 gen_load_fpr32(ctx, fp1, ft);
9792 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9793 gen_store_fpr32(ctx, fp1, fd);
9794 tcg_temp_free_i32(fp1);
9795 tcg_temp_free_i32(fp0);
9796 } else {
9797 /* OPC_RSQRT1_S */
9798 check_cp1_64bitmode(ctx);
9800 TCGv_i32 fp0 = tcg_temp_new_i32();
9802 gen_load_fpr32(ctx, fp0, fs);
9803 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9804 gen_store_fpr32(ctx, fp0, fd);
9805 tcg_temp_free_i32(fp0);
9808 break;
9809 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9810 if (ctx->insn_flags & ISA_MIPS32R6) {
9811 /* OPC_MAXA_S */
9812 TCGv_i32 fp0 = tcg_temp_new_i32();
9813 TCGv_i32 fp1 = tcg_temp_new_i32();
9814 gen_load_fpr32(ctx, fp0, fs);
9815 gen_load_fpr32(ctx, fp1, ft);
9816 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9817 gen_store_fpr32(ctx, fp1, fd);
9818 tcg_temp_free_i32(fp1);
9819 tcg_temp_free_i32(fp0);
9820 } else {
9821 /* OPC_RSQRT2_S */
9822 check_cp1_64bitmode(ctx);
9824 TCGv_i32 fp0 = tcg_temp_new_i32();
9825 TCGv_i32 fp1 = tcg_temp_new_i32();
9827 gen_load_fpr32(ctx, fp0, fs);
9828 gen_load_fpr32(ctx, fp1, ft);
9829 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9830 tcg_temp_free_i32(fp1);
9831 gen_store_fpr32(ctx, fp0, fd);
9832 tcg_temp_free_i32(fp0);
9835 break;
9836 case OPC_CVT_D_S:
9837 check_cp1_registers(ctx, fd);
9839 TCGv_i32 fp32 = tcg_temp_new_i32();
9840 TCGv_i64 fp64 = tcg_temp_new_i64();
9842 gen_load_fpr32(ctx, fp32, fs);
9843 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9844 tcg_temp_free_i32(fp32);
9845 gen_store_fpr64(ctx, fp64, fd);
9846 tcg_temp_free_i64(fp64);
9848 break;
9849 case OPC_CVT_W_S:
9851 TCGv_i32 fp0 = tcg_temp_new_i32();
9853 gen_load_fpr32(ctx, fp0, fs);
9854 if (ctx->nan2008) {
9855 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
9856 } else {
9857 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
9859 gen_store_fpr32(ctx, fp0, fd);
9860 tcg_temp_free_i32(fp0);
9862 break;
9863 case OPC_CVT_L_S:
9864 check_cp1_64bitmode(ctx);
9866 TCGv_i32 fp32 = tcg_temp_new_i32();
9867 TCGv_i64 fp64 = tcg_temp_new_i64();
9869 gen_load_fpr32(ctx, fp32, fs);
9870 if (ctx->nan2008) {
9871 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
9872 } else {
9873 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
9875 tcg_temp_free_i32(fp32);
9876 gen_store_fpr64(ctx, fp64, fd);
9877 tcg_temp_free_i64(fp64);
9879 break;
9880 case OPC_CVT_PS_S:
9881 check_ps(ctx);
9883 TCGv_i64 fp64 = tcg_temp_new_i64();
9884 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9885 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9887 gen_load_fpr32(ctx, fp32_0, fs);
9888 gen_load_fpr32(ctx, fp32_1, ft);
9889 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9890 tcg_temp_free_i32(fp32_1);
9891 tcg_temp_free_i32(fp32_0);
9892 gen_store_fpr64(ctx, fp64, fd);
9893 tcg_temp_free_i64(fp64);
9895 break;
9896 case OPC_CMP_F_S:
9897 case OPC_CMP_UN_S:
9898 case OPC_CMP_EQ_S:
9899 case OPC_CMP_UEQ_S:
9900 case OPC_CMP_OLT_S:
9901 case OPC_CMP_ULT_S:
9902 case OPC_CMP_OLE_S:
9903 case OPC_CMP_ULE_S:
9904 case OPC_CMP_SF_S:
9905 case OPC_CMP_NGLE_S:
9906 case OPC_CMP_SEQ_S:
9907 case OPC_CMP_NGL_S:
9908 case OPC_CMP_LT_S:
9909 case OPC_CMP_NGE_S:
9910 case OPC_CMP_LE_S:
9911 case OPC_CMP_NGT_S:
9912 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9913 if (ctx->opcode & (1 << 6)) {
9914 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9915 } else {
9916 gen_cmp_s(ctx, func-48, ft, fs, cc);
9918 break;
9919 case OPC_ADD_D:
9920 check_cp1_registers(ctx, fs | ft | fd);
9922 TCGv_i64 fp0 = tcg_temp_new_i64();
9923 TCGv_i64 fp1 = tcg_temp_new_i64();
9925 gen_load_fpr64(ctx, fp0, fs);
9926 gen_load_fpr64(ctx, fp1, ft);
9927 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9928 tcg_temp_free_i64(fp1);
9929 gen_store_fpr64(ctx, fp0, fd);
9930 tcg_temp_free_i64(fp0);
9932 break;
9933 case OPC_SUB_D:
9934 check_cp1_registers(ctx, fs | ft | fd);
9936 TCGv_i64 fp0 = tcg_temp_new_i64();
9937 TCGv_i64 fp1 = tcg_temp_new_i64();
9939 gen_load_fpr64(ctx, fp0, fs);
9940 gen_load_fpr64(ctx, fp1, ft);
9941 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9942 tcg_temp_free_i64(fp1);
9943 gen_store_fpr64(ctx, fp0, fd);
9944 tcg_temp_free_i64(fp0);
9946 break;
9947 case OPC_MUL_D:
9948 check_cp1_registers(ctx, fs | ft | fd);
9950 TCGv_i64 fp0 = tcg_temp_new_i64();
9951 TCGv_i64 fp1 = tcg_temp_new_i64();
9953 gen_load_fpr64(ctx, fp0, fs);
9954 gen_load_fpr64(ctx, fp1, ft);
9955 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9956 tcg_temp_free_i64(fp1);
9957 gen_store_fpr64(ctx, fp0, fd);
9958 tcg_temp_free_i64(fp0);
9960 break;
9961 case OPC_DIV_D:
9962 check_cp1_registers(ctx, fs | ft | fd);
9964 TCGv_i64 fp0 = tcg_temp_new_i64();
9965 TCGv_i64 fp1 = tcg_temp_new_i64();
9967 gen_load_fpr64(ctx, fp0, fs);
9968 gen_load_fpr64(ctx, fp1, ft);
9969 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9970 tcg_temp_free_i64(fp1);
9971 gen_store_fpr64(ctx, fp0, fd);
9972 tcg_temp_free_i64(fp0);
9974 break;
9975 case OPC_SQRT_D:
9976 check_cp1_registers(ctx, fs | fd);
9978 TCGv_i64 fp0 = tcg_temp_new_i64();
9980 gen_load_fpr64(ctx, fp0, fs);
9981 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9982 gen_store_fpr64(ctx, fp0, fd);
9983 tcg_temp_free_i64(fp0);
9985 break;
9986 case OPC_ABS_D:
9987 check_cp1_registers(ctx, fs | fd);
9989 TCGv_i64 fp0 = tcg_temp_new_i64();
9991 gen_load_fpr64(ctx, fp0, fs);
9992 if (ctx->abs2008) {
9993 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9994 } else {
9995 gen_helper_float_abs_d(fp0, fp0);
9997 gen_store_fpr64(ctx, fp0, fd);
9998 tcg_temp_free_i64(fp0);
10000 break;
10001 case OPC_MOV_D:
10002 check_cp1_registers(ctx, fs | fd);
10004 TCGv_i64 fp0 = tcg_temp_new_i64();
10006 gen_load_fpr64(ctx, fp0, fs);
10007 gen_store_fpr64(ctx, fp0, fd);
10008 tcg_temp_free_i64(fp0);
10010 break;
10011 case OPC_NEG_D:
10012 check_cp1_registers(ctx, fs | fd);
10014 TCGv_i64 fp0 = tcg_temp_new_i64();
10016 gen_load_fpr64(ctx, fp0, fs);
10017 if (ctx->abs2008) {
10018 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10019 } else {
10020 gen_helper_float_chs_d(fp0, fp0);
10022 gen_store_fpr64(ctx, fp0, fd);
10023 tcg_temp_free_i64(fp0);
10025 break;
10026 case OPC_ROUND_L_D:
10027 check_cp1_64bitmode(ctx);
10029 TCGv_i64 fp0 = tcg_temp_new_i64();
10031 gen_load_fpr64(ctx, fp0, fs);
10032 if (ctx->nan2008) {
10033 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10034 } else {
10035 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10037 gen_store_fpr64(ctx, fp0, fd);
10038 tcg_temp_free_i64(fp0);
10040 break;
10041 case OPC_TRUNC_L_D:
10042 check_cp1_64bitmode(ctx);
10044 TCGv_i64 fp0 = tcg_temp_new_i64();
10046 gen_load_fpr64(ctx, fp0, fs);
10047 if (ctx->nan2008) {
10048 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10049 } else {
10050 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10052 gen_store_fpr64(ctx, fp0, fd);
10053 tcg_temp_free_i64(fp0);
10055 break;
10056 case OPC_CEIL_L_D:
10057 check_cp1_64bitmode(ctx);
10059 TCGv_i64 fp0 = tcg_temp_new_i64();
10061 gen_load_fpr64(ctx, fp0, fs);
10062 if (ctx->nan2008) {
10063 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10064 } else {
10065 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10067 gen_store_fpr64(ctx, fp0, fd);
10068 tcg_temp_free_i64(fp0);
10070 break;
10071 case OPC_FLOOR_L_D:
10072 check_cp1_64bitmode(ctx);
10074 TCGv_i64 fp0 = tcg_temp_new_i64();
10076 gen_load_fpr64(ctx, fp0, fs);
10077 if (ctx->nan2008) {
10078 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10079 } else {
10080 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10082 gen_store_fpr64(ctx, fp0, fd);
10083 tcg_temp_free_i64(fp0);
10085 break;
10086 case OPC_ROUND_W_D:
10087 check_cp1_registers(ctx, fs);
10089 TCGv_i32 fp32 = tcg_temp_new_i32();
10090 TCGv_i64 fp64 = tcg_temp_new_i64();
10092 gen_load_fpr64(ctx, fp64, fs);
10093 if (ctx->nan2008) {
10094 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10095 } else {
10096 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10098 tcg_temp_free_i64(fp64);
10099 gen_store_fpr32(ctx, fp32, fd);
10100 tcg_temp_free_i32(fp32);
10102 break;
10103 case OPC_TRUNC_W_D:
10104 check_cp1_registers(ctx, fs);
10106 TCGv_i32 fp32 = tcg_temp_new_i32();
10107 TCGv_i64 fp64 = tcg_temp_new_i64();
10109 gen_load_fpr64(ctx, fp64, fs);
10110 if (ctx->nan2008) {
10111 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10112 } else {
10113 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10115 tcg_temp_free_i64(fp64);
10116 gen_store_fpr32(ctx, fp32, fd);
10117 tcg_temp_free_i32(fp32);
10119 break;
10120 case OPC_CEIL_W_D:
10121 check_cp1_registers(ctx, fs);
10123 TCGv_i32 fp32 = tcg_temp_new_i32();
10124 TCGv_i64 fp64 = tcg_temp_new_i64();
10126 gen_load_fpr64(ctx, fp64, fs);
10127 if (ctx->nan2008) {
10128 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10129 } else {
10130 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10132 tcg_temp_free_i64(fp64);
10133 gen_store_fpr32(ctx, fp32, fd);
10134 tcg_temp_free_i32(fp32);
10136 break;
10137 case OPC_FLOOR_W_D:
10138 check_cp1_registers(ctx, fs);
10140 TCGv_i32 fp32 = tcg_temp_new_i32();
10141 TCGv_i64 fp64 = tcg_temp_new_i64();
10143 gen_load_fpr64(ctx, fp64, fs);
10144 if (ctx->nan2008) {
10145 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10146 } else {
10147 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10149 tcg_temp_free_i64(fp64);
10150 gen_store_fpr32(ctx, fp32, fd);
10151 tcg_temp_free_i32(fp32);
10153 break;
10154 case OPC_SEL_D:
10155 check_insn(ctx, ISA_MIPS32R6);
10156 gen_sel_d(ctx, op1, fd, ft, fs);
10157 break;
10158 case OPC_SELEQZ_D:
10159 check_insn(ctx, ISA_MIPS32R6);
10160 gen_sel_d(ctx, op1, fd, ft, fs);
10161 break;
10162 case OPC_SELNEZ_D:
10163 check_insn(ctx, ISA_MIPS32R6);
10164 gen_sel_d(ctx, op1, fd, ft, fs);
10165 break;
10166 case OPC_MOVCF_D:
10167 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10168 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10169 break;
10170 case OPC_MOVZ_D:
10171 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10173 TCGLabel *l1 = gen_new_label();
10174 TCGv_i64 fp0;
10176 if (ft != 0) {
10177 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10179 fp0 = tcg_temp_new_i64();
10180 gen_load_fpr64(ctx, fp0, fs);
10181 gen_store_fpr64(ctx, fp0, fd);
10182 tcg_temp_free_i64(fp0);
10183 gen_set_label(l1);
10185 break;
10186 case OPC_MOVN_D:
10187 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10189 TCGLabel *l1 = gen_new_label();
10190 TCGv_i64 fp0;
10192 if (ft != 0) {
10193 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10194 fp0 = tcg_temp_new_i64();
10195 gen_load_fpr64(ctx, fp0, fs);
10196 gen_store_fpr64(ctx, fp0, fd);
10197 tcg_temp_free_i64(fp0);
10198 gen_set_label(l1);
10201 break;
10202 case OPC_RECIP_D:
10203 check_cp1_registers(ctx, fs | fd);
10205 TCGv_i64 fp0 = tcg_temp_new_i64();
10207 gen_load_fpr64(ctx, fp0, fs);
10208 gen_helper_float_recip_d(fp0, cpu_env, fp0);
10209 gen_store_fpr64(ctx, fp0, fd);
10210 tcg_temp_free_i64(fp0);
10212 break;
10213 case OPC_RSQRT_D:
10214 check_cp1_registers(ctx, fs | fd);
10216 TCGv_i64 fp0 = tcg_temp_new_i64();
10218 gen_load_fpr64(ctx, fp0, fs);
10219 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
10220 gen_store_fpr64(ctx, fp0, fd);
10221 tcg_temp_free_i64(fp0);
10223 break;
10224 case OPC_MADDF_D:
10225 check_insn(ctx, ISA_MIPS32R6);
10227 TCGv_i64 fp0 = tcg_temp_new_i64();
10228 TCGv_i64 fp1 = tcg_temp_new_i64();
10229 TCGv_i64 fp2 = tcg_temp_new_i64();
10230 gen_load_fpr64(ctx, fp0, fs);
10231 gen_load_fpr64(ctx, fp1, ft);
10232 gen_load_fpr64(ctx, fp2, fd);
10233 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
10234 gen_store_fpr64(ctx, fp2, fd);
10235 tcg_temp_free_i64(fp2);
10236 tcg_temp_free_i64(fp1);
10237 tcg_temp_free_i64(fp0);
10239 break;
10240 case OPC_MSUBF_D:
10241 check_insn(ctx, ISA_MIPS32R6);
10243 TCGv_i64 fp0 = tcg_temp_new_i64();
10244 TCGv_i64 fp1 = tcg_temp_new_i64();
10245 TCGv_i64 fp2 = tcg_temp_new_i64();
10246 gen_load_fpr64(ctx, fp0, fs);
10247 gen_load_fpr64(ctx, fp1, ft);
10248 gen_load_fpr64(ctx, fp2, fd);
10249 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
10250 gen_store_fpr64(ctx, fp2, fd);
10251 tcg_temp_free_i64(fp2);
10252 tcg_temp_free_i64(fp1);
10253 tcg_temp_free_i64(fp0);
10255 break;
10256 case OPC_RINT_D:
10257 check_insn(ctx, ISA_MIPS32R6);
10259 TCGv_i64 fp0 = tcg_temp_new_i64();
10260 gen_load_fpr64(ctx, fp0, fs);
10261 gen_helper_float_rint_d(fp0, cpu_env, fp0);
10262 gen_store_fpr64(ctx, fp0, fd);
10263 tcg_temp_free_i64(fp0);
10265 break;
10266 case OPC_CLASS_D:
10267 check_insn(ctx, ISA_MIPS32R6);
10269 TCGv_i64 fp0 = tcg_temp_new_i64();
10270 gen_load_fpr64(ctx, fp0, fs);
10271 gen_helper_float_class_d(fp0, cpu_env, fp0);
10272 gen_store_fpr64(ctx, fp0, fd);
10273 tcg_temp_free_i64(fp0);
10275 break;
10276 case OPC_MIN_D: /* OPC_RECIP2_D */
10277 if (ctx->insn_flags & ISA_MIPS32R6) {
10278 /* OPC_MIN_D */
10279 TCGv_i64 fp0 = tcg_temp_new_i64();
10280 TCGv_i64 fp1 = tcg_temp_new_i64();
10281 gen_load_fpr64(ctx, fp0, fs);
10282 gen_load_fpr64(ctx, fp1, ft);
10283 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
10284 gen_store_fpr64(ctx, fp1, fd);
10285 tcg_temp_free_i64(fp1);
10286 tcg_temp_free_i64(fp0);
10287 } else {
10288 /* OPC_RECIP2_D */
10289 check_cp1_64bitmode(ctx);
10291 TCGv_i64 fp0 = tcg_temp_new_i64();
10292 TCGv_i64 fp1 = tcg_temp_new_i64();
10294 gen_load_fpr64(ctx, fp0, fs);
10295 gen_load_fpr64(ctx, fp1, ft);
10296 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
10297 tcg_temp_free_i64(fp1);
10298 gen_store_fpr64(ctx, fp0, fd);
10299 tcg_temp_free_i64(fp0);
10302 break;
10303 case OPC_MINA_D: /* OPC_RECIP1_D */
10304 if (ctx->insn_flags & ISA_MIPS32R6) {
10305 /* OPC_MINA_D */
10306 TCGv_i64 fp0 = tcg_temp_new_i64();
10307 TCGv_i64 fp1 = tcg_temp_new_i64();
10308 gen_load_fpr64(ctx, fp0, fs);
10309 gen_load_fpr64(ctx, fp1, ft);
10310 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
10311 gen_store_fpr64(ctx, fp1, fd);
10312 tcg_temp_free_i64(fp1);
10313 tcg_temp_free_i64(fp0);
10314 } else {
10315 /* OPC_RECIP1_D */
10316 check_cp1_64bitmode(ctx);
10318 TCGv_i64 fp0 = tcg_temp_new_i64();
10320 gen_load_fpr64(ctx, fp0, fs);
10321 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
10322 gen_store_fpr64(ctx, fp0, fd);
10323 tcg_temp_free_i64(fp0);
10326 break;
10327 case OPC_MAX_D: /* OPC_RSQRT1_D */
10328 if (ctx->insn_flags & ISA_MIPS32R6) {
10329 /* OPC_MAX_D */
10330 TCGv_i64 fp0 = tcg_temp_new_i64();
10331 TCGv_i64 fp1 = tcg_temp_new_i64();
10332 gen_load_fpr64(ctx, fp0, fs);
10333 gen_load_fpr64(ctx, fp1, ft);
10334 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
10335 gen_store_fpr64(ctx, fp1, fd);
10336 tcg_temp_free_i64(fp1);
10337 tcg_temp_free_i64(fp0);
10338 } else {
10339 /* OPC_RSQRT1_D */
10340 check_cp1_64bitmode(ctx);
10342 TCGv_i64 fp0 = tcg_temp_new_i64();
10344 gen_load_fpr64(ctx, fp0, fs);
10345 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
10346 gen_store_fpr64(ctx, fp0, fd);
10347 tcg_temp_free_i64(fp0);
10350 break;
10351 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10352 if (ctx->insn_flags & ISA_MIPS32R6) {
10353 /* OPC_MAXA_D */
10354 TCGv_i64 fp0 = tcg_temp_new_i64();
10355 TCGv_i64 fp1 = tcg_temp_new_i64();
10356 gen_load_fpr64(ctx, fp0, fs);
10357 gen_load_fpr64(ctx, fp1, ft);
10358 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
10359 gen_store_fpr64(ctx, fp1, fd);
10360 tcg_temp_free_i64(fp1);
10361 tcg_temp_free_i64(fp0);
10362 } else {
10363 /* OPC_RSQRT2_D */
10364 check_cp1_64bitmode(ctx);
10366 TCGv_i64 fp0 = tcg_temp_new_i64();
10367 TCGv_i64 fp1 = tcg_temp_new_i64();
10369 gen_load_fpr64(ctx, fp0, fs);
10370 gen_load_fpr64(ctx, fp1, ft);
10371 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
10372 tcg_temp_free_i64(fp1);
10373 gen_store_fpr64(ctx, fp0, fd);
10374 tcg_temp_free_i64(fp0);
10377 break;
10378 case OPC_CMP_F_D:
10379 case OPC_CMP_UN_D:
10380 case OPC_CMP_EQ_D:
10381 case OPC_CMP_UEQ_D:
10382 case OPC_CMP_OLT_D:
10383 case OPC_CMP_ULT_D:
10384 case OPC_CMP_OLE_D:
10385 case OPC_CMP_ULE_D:
10386 case OPC_CMP_SF_D:
10387 case OPC_CMP_NGLE_D:
10388 case OPC_CMP_SEQ_D:
10389 case OPC_CMP_NGL_D:
10390 case OPC_CMP_LT_D:
10391 case OPC_CMP_NGE_D:
10392 case OPC_CMP_LE_D:
10393 case OPC_CMP_NGT_D:
10394 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10395 if (ctx->opcode & (1 << 6)) {
10396 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
10397 } else {
10398 gen_cmp_d(ctx, func-48, ft, fs, cc);
10400 break;
10401 case OPC_CVT_S_D:
10402 check_cp1_registers(ctx, fs);
10404 TCGv_i32 fp32 = tcg_temp_new_i32();
10405 TCGv_i64 fp64 = tcg_temp_new_i64();
10407 gen_load_fpr64(ctx, fp64, fs);
10408 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
10409 tcg_temp_free_i64(fp64);
10410 gen_store_fpr32(ctx, fp32, fd);
10411 tcg_temp_free_i32(fp32);
10413 break;
10414 case OPC_CVT_W_D:
10415 check_cp1_registers(ctx, fs);
10417 TCGv_i32 fp32 = tcg_temp_new_i32();
10418 TCGv_i64 fp64 = tcg_temp_new_i64();
10420 gen_load_fpr64(ctx, fp64, fs);
10421 if (ctx->nan2008) {
10422 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
10423 } else {
10424 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
10426 tcg_temp_free_i64(fp64);
10427 gen_store_fpr32(ctx, fp32, fd);
10428 tcg_temp_free_i32(fp32);
10430 break;
10431 case OPC_CVT_L_D:
10432 check_cp1_64bitmode(ctx);
10434 TCGv_i64 fp0 = tcg_temp_new_i64();
10436 gen_load_fpr64(ctx, fp0, fs);
10437 if (ctx->nan2008) {
10438 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
10439 } else {
10440 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
10442 gen_store_fpr64(ctx, fp0, fd);
10443 tcg_temp_free_i64(fp0);
10445 break;
10446 case OPC_CVT_S_W:
10448 TCGv_i32 fp0 = tcg_temp_new_i32();
10450 gen_load_fpr32(ctx, fp0, fs);
10451 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
10452 gen_store_fpr32(ctx, fp0, fd);
10453 tcg_temp_free_i32(fp0);
10455 break;
10456 case OPC_CVT_D_W:
10457 check_cp1_registers(ctx, fd);
10459 TCGv_i32 fp32 = tcg_temp_new_i32();
10460 TCGv_i64 fp64 = tcg_temp_new_i64();
10462 gen_load_fpr32(ctx, fp32, fs);
10463 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
10464 tcg_temp_free_i32(fp32);
10465 gen_store_fpr64(ctx, fp64, fd);
10466 tcg_temp_free_i64(fp64);
10468 break;
10469 case OPC_CVT_S_L:
10470 check_cp1_64bitmode(ctx);
10472 TCGv_i32 fp32 = tcg_temp_new_i32();
10473 TCGv_i64 fp64 = tcg_temp_new_i64();
10475 gen_load_fpr64(ctx, fp64, fs);
10476 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10477 tcg_temp_free_i64(fp64);
10478 gen_store_fpr32(ctx, fp32, fd);
10479 tcg_temp_free_i32(fp32);
10481 break;
10482 case OPC_CVT_D_L:
10483 check_cp1_64bitmode(ctx);
10485 TCGv_i64 fp0 = tcg_temp_new_i64();
10487 gen_load_fpr64(ctx, fp0, fs);
10488 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10489 gen_store_fpr64(ctx, fp0, fd);
10490 tcg_temp_free_i64(fp0);
10492 break;
10493 case OPC_CVT_PS_PW:
10494 check_ps(ctx);
10496 TCGv_i64 fp0 = tcg_temp_new_i64();
10498 gen_load_fpr64(ctx, fp0, fs);
10499 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
10500 gen_store_fpr64(ctx, fp0, fd);
10501 tcg_temp_free_i64(fp0);
10503 break;
10504 case OPC_ADD_PS:
10505 check_ps(ctx);
10507 TCGv_i64 fp0 = tcg_temp_new_i64();
10508 TCGv_i64 fp1 = tcg_temp_new_i64();
10510 gen_load_fpr64(ctx, fp0, fs);
10511 gen_load_fpr64(ctx, fp1, ft);
10512 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
10513 tcg_temp_free_i64(fp1);
10514 gen_store_fpr64(ctx, fp0, fd);
10515 tcg_temp_free_i64(fp0);
10517 break;
10518 case OPC_SUB_PS:
10519 check_ps(ctx);
10521 TCGv_i64 fp0 = tcg_temp_new_i64();
10522 TCGv_i64 fp1 = tcg_temp_new_i64();
10524 gen_load_fpr64(ctx, fp0, fs);
10525 gen_load_fpr64(ctx, fp1, ft);
10526 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
10527 tcg_temp_free_i64(fp1);
10528 gen_store_fpr64(ctx, fp0, fd);
10529 tcg_temp_free_i64(fp0);
10531 break;
10532 case OPC_MUL_PS:
10533 check_ps(ctx);
10535 TCGv_i64 fp0 = tcg_temp_new_i64();
10536 TCGv_i64 fp1 = tcg_temp_new_i64();
10538 gen_load_fpr64(ctx, fp0, fs);
10539 gen_load_fpr64(ctx, fp1, ft);
10540 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
10541 tcg_temp_free_i64(fp1);
10542 gen_store_fpr64(ctx, fp0, fd);
10543 tcg_temp_free_i64(fp0);
10545 break;
10546 case OPC_ABS_PS:
10547 check_ps(ctx);
10549 TCGv_i64 fp0 = tcg_temp_new_i64();
10551 gen_load_fpr64(ctx, fp0, fs);
10552 gen_helper_float_abs_ps(fp0, fp0);
10553 gen_store_fpr64(ctx, fp0, fd);
10554 tcg_temp_free_i64(fp0);
10556 break;
10557 case OPC_MOV_PS:
10558 check_ps(ctx);
10560 TCGv_i64 fp0 = tcg_temp_new_i64();
10562 gen_load_fpr64(ctx, fp0, fs);
10563 gen_store_fpr64(ctx, fp0, fd);
10564 tcg_temp_free_i64(fp0);
10566 break;
10567 case OPC_NEG_PS:
10568 check_ps(ctx);
10570 TCGv_i64 fp0 = tcg_temp_new_i64();
10572 gen_load_fpr64(ctx, fp0, fs);
10573 gen_helper_float_chs_ps(fp0, fp0);
10574 gen_store_fpr64(ctx, fp0, fd);
10575 tcg_temp_free_i64(fp0);
10577 break;
10578 case OPC_MOVCF_PS:
10579 check_ps(ctx);
10580 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10581 break;
10582 case OPC_MOVZ_PS:
10583 check_ps(ctx);
10585 TCGLabel *l1 = gen_new_label();
10586 TCGv_i64 fp0;
10588 if (ft != 0)
10589 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10590 fp0 = tcg_temp_new_i64();
10591 gen_load_fpr64(ctx, fp0, fs);
10592 gen_store_fpr64(ctx, fp0, fd);
10593 tcg_temp_free_i64(fp0);
10594 gen_set_label(l1);
10596 break;
10597 case OPC_MOVN_PS:
10598 check_ps(ctx);
10600 TCGLabel *l1 = gen_new_label();
10601 TCGv_i64 fp0;
10603 if (ft != 0) {
10604 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10605 fp0 = tcg_temp_new_i64();
10606 gen_load_fpr64(ctx, fp0, fs);
10607 gen_store_fpr64(ctx, fp0, fd);
10608 tcg_temp_free_i64(fp0);
10609 gen_set_label(l1);
10612 break;
10613 case OPC_ADDR_PS:
10614 check_ps(ctx);
10616 TCGv_i64 fp0 = tcg_temp_new_i64();
10617 TCGv_i64 fp1 = tcg_temp_new_i64();
10619 gen_load_fpr64(ctx, fp0, ft);
10620 gen_load_fpr64(ctx, fp1, fs);
10621 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10622 tcg_temp_free_i64(fp1);
10623 gen_store_fpr64(ctx, fp0, fd);
10624 tcg_temp_free_i64(fp0);
10626 break;
10627 case OPC_MULR_PS:
10628 check_ps(ctx);
10630 TCGv_i64 fp0 = tcg_temp_new_i64();
10631 TCGv_i64 fp1 = tcg_temp_new_i64();
10633 gen_load_fpr64(ctx, fp0, ft);
10634 gen_load_fpr64(ctx, fp1, fs);
10635 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10636 tcg_temp_free_i64(fp1);
10637 gen_store_fpr64(ctx, fp0, fd);
10638 tcg_temp_free_i64(fp0);
10640 break;
10641 case OPC_RECIP2_PS:
10642 check_ps(ctx);
10644 TCGv_i64 fp0 = tcg_temp_new_i64();
10645 TCGv_i64 fp1 = tcg_temp_new_i64();
10647 gen_load_fpr64(ctx, fp0, fs);
10648 gen_load_fpr64(ctx, fp1, ft);
10649 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10650 tcg_temp_free_i64(fp1);
10651 gen_store_fpr64(ctx, fp0, fd);
10652 tcg_temp_free_i64(fp0);
10654 break;
10655 case OPC_RECIP1_PS:
10656 check_ps(ctx);
10658 TCGv_i64 fp0 = tcg_temp_new_i64();
10660 gen_load_fpr64(ctx, fp0, fs);
10661 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10662 gen_store_fpr64(ctx, fp0, fd);
10663 tcg_temp_free_i64(fp0);
10665 break;
10666 case OPC_RSQRT1_PS:
10667 check_ps(ctx);
10669 TCGv_i64 fp0 = tcg_temp_new_i64();
10671 gen_load_fpr64(ctx, fp0, fs);
10672 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10673 gen_store_fpr64(ctx, fp0, fd);
10674 tcg_temp_free_i64(fp0);
10676 break;
10677 case OPC_RSQRT2_PS:
10678 check_ps(ctx);
10680 TCGv_i64 fp0 = tcg_temp_new_i64();
10681 TCGv_i64 fp1 = tcg_temp_new_i64();
10683 gen_load_fpr64(ctx, fp0, fs);
10684 gen_load_fpr64(ctx, fp1, ft);
10685 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10686 tcg_temp_free_i64(fp1);
10687 gen_store_fpr64(ctx, fp0, fd);
10688 tcg_temp_free_i64(fp0);
10690 break;
10691 case OPC_CVT_S_PU:
10692 check_cp1_64bitmode(ctx);
10694 TCGv_i32 fp0 = tcg_temp_new_i32();
10696 gen_load_fpr32h(ctx, fp0, fs);
10697 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10698 gen_store_fpr32(ctx, fp0, fd);
10699 tcg_temp_free_i32(fp0);
10701 break;
10702 case OPC_CVT_PW_PS:
10703 check_ps(ctx);
10705 TCGv_i64 fp0 = tcg_temp_new_i64();
10707 gen_load_fpr64(ctx, fp0, fs);
10708 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10709 gen_store_fpr64(ctx, fp0, fd);
10710 tcg_temp_free_i64(fp0);
10712 break;
10713 case OPC_CVT_S_PL:
10714 check_cp1_64bitmode(ctx);
10716 TCGv_i32 fp0 = tcg_temp_new_i32();
10718 gen_load_fpr32(ctx, fp0, fs);
10719 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10720 gen_store_fpr32(ctx, fp0, fd);
10721 tcg_temp_free_i32(fp0);
10723 break;
10724 case OPC_PLL_PS:
10725 check_ps(ctx);
10727 TCGv_i32 fp0 = tcg_temp_new_i32();
10728 TCGv_i32 fp1 = tcg_temp_new_i32();
10730 gen_load_fpr32(ctx, fp0, fs);
10731 gen_load_fpr32(ctx, fp1, ft);
10732 gen_store_fpr32h(ctx, fp0, fd);
10733 gen_store_fpr32(ctx, fp1, fd);
10734 tcg_temp_free_i32(fp0);
10735 tcg_temp_free_i32(fp1);
10737 break;
10738 case OPC_PLU_PS:
10739 check_ps(ctx);
10741 TCGv_i32 fp0 = tcg_temp_new_i32();
10742 TCGv_i32 fp1 = tcg_temp_new_i32();
10744 gen_load_fpr32(ctx, fp0, fs);
10745 gen_load_fpr32h(ctx, fp1, ft);
10746 gen_store_fpr32(ctx, fp1, fd);
10747 gen_store_fpr32h(ctx, fp0, fd);
10748 tcg_temp_free_i32(fp0);
10749 tcg_temp_free_i32(fp1);
10751 break;
10752 case OPC_PUL_PS:
10753 check_ps(ctx);
10755 TCGv_i32 fp0 = tcg_temp_new_i32();
10756 TCGv_i32 fp1 = tcg_temp_new_i32();
10758 gen_load_fpr32h(ctx, fp0, fs);
10759 gen_load_fpr32(ctx, fp1, ft);
10760 gen_store_fpr32(ctx, fp1, fd);
10761 gen_store_fpr32h(ctx, fp0, fd);
10762 tcg_temp_free_i32(fp0);
10763 tcg_temp_free_i32(fp1);
10765 break;
10766 case OPC_PUU_PS:
10767 check_ps(ctx);
10769 TCGv_i32 fp0 = tcg_temp_new_i32();
10770 TCGv_i32 fp1 = tcg_temp_new_i32();
10772 gen_load_fpr32h(ctx, fp0, fs);
10773 gen_load_fpr32h(ctx, fp1, ft);
10774 gen_store_fpr32(ctx, fp1, fd);
10775 gen_store_fpr32h(ctx, fp0, fd);
10776 tcg_temp_free_i32(fp0);
10777 tcg_temp_free_i32(fp1);
10779 break;
10780 case OPC_CMP_F_PS:
10781 case OPC_CMP_UN_PS:
10782 case OPC_CMP_EQ_PS:
10783 case OPC_CMP_UEQ_PS:
10784 case OPC_CMP_OLT_PS:
10785 case OPC_CMP_ULT_PS:
10786 case OPC_CMP_OLE_PS:
10787 case OPC_CMP_ULE_PS:
10788 case OPC_CMP_SF_PS:
10789 case OPC_CMP_NGLE_PS:
10790 case OPC_CMP_SEQ_PS:
10791 case OPC_CMP_NGL_PS:
10792 case OPC_CMP_LT_PS:
10793 case OPC_CMP_NGE_PS:
10794 case OPC_CMP_LE_PS:
10795 case OPC_CMP_NGT_PS:
10796 if (ctx->opcode & (1 << 6)) {
10797 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10798 } else {
10799 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10801 break;
10802 default:
10803 MIPS_INVAL("farith");
10804 generate_exception_end(ctx, EXCP_RI);
10805 return;
10809 /* Coprocessor 3 (FPU) */
10810 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10811 int fd, int fs, int base, int index)
10813 TCGv t0 = tcg_temp_new();
10815 if (base == 0) {
10816 gen_load_gpr(t0, index);
10817 } else if (index == 0) {
10818 gen_load_gpr(t0, base);
10819 } else {
10820 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10822 /* Don't do NOP if destination is zero: we must perform the actual
10823 memory access. */
10824 switch (opc) {
10825 case OPC_LWXC1:
10826 check_cop1x(ctx);
10828 TCGv_i32 fp0 = tcg_temp_new_i32();
10830 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10831 tcg_gen_trunc_tl_i32(fp0, t0);
10832 gen_store_fpr32(ctx, fp0, fd);
10833 tcg_temp_free_i32(fp0);
10835 break;
10836 case OPC_LDXC1:
10837 check_cop1x(ctx);
10838 check_cp1_registers(ctx, fd);
10840 TCGv_i64 fp0 = tcg_temp_new_i64();
10841 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10842 gen_store_fpr64(ctx, fp0, fd);
10843 tcg_temp_free_i64(fp0);
10845 break;
10846 case OPC_LUXC1:
10847 check_cp1_64bitmode(ctx);
10848 tcg_gen_andi_tl(t0, t0, ~0x7);
10850 TCGv_i64 fp0 = tcg_temp_new_i64();
10852 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10853 gen_store_fpr64(ctx, fp0, fd);
10854 tcg_temp_free_i64(fp0);
10856 break;
10857 case OPC_SWXC1:
10858 check_cop1x(ctx);
10860 TCGv_i32 fp0 = tcg_temp_new_i32();
10861 gen_load_fpr32(ctx, fp0, fs);
10862 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10863 tcg_temp_free_i32(fp0);
10865 break;
10866 case OPC_SDXC1:
10867 check_cop1x(ctx);
10868 check_cp1_registers(ctx, fs);
10870 TCGv_i64 fp0 = tcg_temp_new_i64();
10871 gen_load_fpr64(ctx, fp0, fs);
10872 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10873 tcg_temp_free_i64(fp0);
10875 break;
10876 case OPC_SUXC1:
10877 check_cp1_64bitmode(ctx);
10878 tcg_gen_andi_tl(t0, t0, ~0x7);
10880 TCGv_i64 fp0 = tcg_temp_new_i64();
10881 gen_load_fpr64(ctx, fp0, fs);
10882 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10883 tcg_temp_free_i64(fp0);
10885 break;
10887 tcg_temp_free(t0);
10890 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10891 int fd, int fr, int fs, int ft)
10893 switch (opc) {
10894 case OPC_ALNV_PS:
10895 check_ps(ctx);
10897 TCGv t0 = tcg_temp_local_new();
10898 TCGv_i32 fp = tcg_temp_new_i32();
10899 TCGv_i32 fph = tcg_temp_new_i32();
10900 TCGLabel *l1 = gen_new_label();
10901 TCGLabel *l2 = gen_new_label();
10903 gen_load_gpr(t0, fr);
10904 tcg_gen_andi_tl(t0, t0, 0x7);
10906 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10907 gen_load_fpr32(ctx, fp, fs);
10908 gen_load_fpr32h(ctx, fph, fs);
10909 gen_store_fpr32(ctx, fp, fd);
10910 gen_store_fpr32h(ctx, fph, fd);
10911 tcg_gen_br(l2);
10912 gen_set_label(l1);
10913 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10914 tcg_temp_free(t0);
10915 #ifdef TARGET_WORDS_BIGENDIAN
10916 gen_load_fpr32(ctx, fp, fs);
10917 gen_load_fpr32h(ctx, fph, ft);
10918 gen_store_fpr32h(ctx, fp, fd);
10919 gen_store_fpr32(ctx, fph, fd);
10920 #else
10921 gen_load_fpr32h(ctx, fph, fs);
10922 gen_load_fpr32(ctx, fp, ft);
10923 gen_store_fpr32(ctx, fph, fd);
10924 gen_store_fpr32h(ctx, fp, fd);
10925 #endif
10926 gen_set_label(l2);
10927 tcg_temp_free_i32(fp);
10928 tcg_temp_free_i32(fph);
10930 break;
10931 case OPC_MADD_S:
10932 check_cop1x(ctx);
10934 TCGv_i32 fp0 = tcg_temp_new_i32();
10935 TCGv_i32 fp1 = tcg_temp_new_i32();
10936 TCGv_i32 fp2 = tcg_temp_new_i32();
10938 gen_load_fpr32(ctx, fp0, fs);
10939 gen_load_fpr32(ctx, fp1, ft);
10940 gen_load_fpr32(ctx, fp2, fr);
10941 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10942 tcg_temp_free_i32(fp0);
10943 tcg_temp_free_i32(fp1);
10944 gen_store_fpr32(ctx, fp2, fd);
10945 tcg_temp_free_i32(fp2);
10947 break;
10948 case OPC_MADD_D:
10949 check_cop1x(ctx);
10950 check_cp1_registers(ctx, fd | fs | ft | fr);
10952 TCGv_i64 fp0 = tcg_temp_new_i64();
10953 TCGv_i64 fp1 = tcg_temp_new_i64();
10954 TCGv_i64 fp2 = tcg_temp_new_i64();
10956 gen_load_fpr64(ctx, fp0, fs);
10957 gen_load_fpr64(ctx, fp1, ft);
10958 gen_load_fpr64(ctx, fp2, fr);
10959 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10960 tcg_temp_free_i64(fp0);
10961 tcg_temp_free_i64(fp1);
10962 gen_store_fpr64(ctx, fp2, fd);
10963 tcg_temp_free_i64(fp2);
10965 break;
10966 case OPC_MADD_PS:
10967 check_ps(ctx);
10969 TCGv_i64 fp0 = tcg_temp_new_i64();
10970 TCGv_i64 fp1 = tcg_temp_new_i64();
10971 TCGv_i64 fp2 = tcg_temp_new_i64();
10973 gen_load_fpr64(ctx, fp0, fs);
10974 gen_load_fpr64(ctx, fp1, ft);
10975 gen_load_fpr64(ctx, fp2, fr);
10976 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10977 tcg_temp_free_i64(fp0);
10978 tcg_temp_free_i64(fp1);
10979 gen_store_fpr64(ctx, fp2, fd);
10980 tcg_temp_free_i64(fp2);
10982 break;
10983 case OPC_MSUB_S:
10984 check_cop1x(ctx);
10986 TCGv_i32 fp0 = tcg_temp_new_i32();
10987 TCGv_i32 fp1 = tcg_temp_new_i32();
10988 TCGv_i32 fp2 = tcg_temp_new_i32();
10990 gen_load_fpr32(ctx, fp0, fs);
10991 gen_load_fpr32(ctx, fp1, ft);
10992 gen_load_fpr32(ctx, fp2, fr);
10993 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10994 tcg_temp_free_i32(fp0);
10995 tcg_temp_free_i32(fp1);
10996 gen_store_fpr32(ctx, fp2, fd);
10997 tcg_temp_free_i32(fp2);
10999 break;
11000 case OPC_MSUB_D:
11001 check_cop1x(ctx);
11002 check_cp1_registers(ctx, fd | fs | ft | fr);
11004 TCGv_i64 fp0 = tcg_temp_new_i64();
11005 TCGv_i64 fp1 = tcg_temp_new_i64();
11006 TCGv_i64 fp2 = tcg_temp_new_i64();
11008 gen_load_fpr64(ctx, fp0, fs);
11009 gen_load_fpr64(ctx, fp1, ft);
11010 gen_load_fpr64(ctx, fp2, fr);
11011 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11012 tcg_temp_free_i64(fp0);
11013 tcg_temp_free_i64(fp1);
11014 gen_store_fpr64(ctx, fp2, fd);
11015 tcg_temp_free_i64(fp2);
11017 break;
11018 case OPC_MSUB_PS:
11019 check_ps(ctx);
11021 TCGv_i64 fp0 = tcg_temp_new_i64();
11022 TCGv_i64 fp1 = tcg_temp_new_i64();
11023 TCGv_i64 fp2 = tcg_temp_new_i64();
11025 gen_load_fpr64(ctx, fp0, fs);
11026 gen_load_fpr64(ctx, fp1, ft);
11027 gen_load_fpr64(ctx, fp2, fr);
11028 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11029 tcg_temp_free_i64(fp0);
11030 tcg_temp_free_i64(fp1);
11031 gen_store_fpr64(ctx, fp2, fd);
11032 tcg_temp_free_i64(fp2);
11034 break;
11035 case OPC_NMADD_S:
11036 check_cop1x(ctx);
11038 TCGv_i32 fp0 = tcg_temp_new_i32();
11039 TCGv_i32 fp1 = tcg_temp_new_i32();
11040 TCGv_i32 fp2 = tcg_temp_new_i32();
11042 gen_load_fpr32(ctx, fp0, fs);
11043 gen_load_fpr32(ctx, fp1, ft);
11044 gen_load_fpr32(ctx, fp2, fr);
11045 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11046 tcg_temp_free_i32(fp0);
11047 tcg_temp_free_i32(fp1);
11048 gen_store_fpr32(ctx, fp2, fd);
11049 tcg_temp_free_i32(fp2);
11051 break;
11052 case OPC_NMADD_D:
11053 check_cop1x(ctx);
11054 check_cp1_registers(ctx, fd | fs | ft | fr);
11056 TCGv_i64 fp0 = tcg_temp_new_i64();
11057 TCGv_i64 fp1 = tcg_temp_new_i64();
11058 TCGv_i64 fp2 = tcg_temp_new_i64();
11060 gen_load_fpr64(ctx, fp0, fs);
11061 gen_load_fpr64(ctx, fp1, ft);
11062 gen_load_fpr64(ctx, fp2, fr);
11063 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11064 tcg_temp_free_i64(fp0);
11065 tcg_temp_free_i64(fp1);
11066 gen_store_fpr64(ctx, fp2, fd);
11067 tcg_temp_free_i64(fp2);
11069 break;
11070 case OPC_NMADD_PS:
11071 check_ps(ctx);
11073 TCGv_i64 fp0 = tcg_temp_new_i64();
11074 TCGv_i64 fp1 = tcg_temp_new_i64();
11075 TCGv_i64 fp2 = tcg_temp_new_i64();
11077 gen_load_fpr64(ctx, fp0, fs);
11078 gen_load_fpr64(ctx, fp1, ft);
11079 gen_load_fpr64(ctx, fp2, fr);
11080 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11081 tcg_temp_free_i64(fp0);
11082 tcg_temp_free_i64(fp1);
11083 gen_store_fpr64(ctx, fp2, fd);
11084 tcg_temp_free_i64(fp2);
11086 break;
11087 case OPC_NMSUB_S:
11088 check_cop1x(ctx);
11090 TCGv_i32 fp0 = tcg_temp_new_i32();
11091 TCGv_i32 fp1 = tcg_temp_new_i32();
11092 TCGv_i32 fp2 = tcg_temp_new_i32();
11094 gen_load_fpr32(ctx, fp0, fs);
11095 gen_load_fpr32(ctx, fp1, ft);
11096 gen_load_fpr32(ctx, fp2, fr);
11097 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11098 tcg_temp_free_i32(fp0);
11099 tcg_temp_free_i32(fp1);
11100 gen_store_fpr32(ctx, fp2, fd);
11101 tcg_temp_free_i32(fp2);
11103 break;
11104 case OPC_NMSUB_D:
11105 check_cop1x(ctx);
11106 check_cp1_registers(ctx, fd | fs | ft | fr);
11108 TCGv_i64 fp0 = tcg_temp_new_i64();
11109 TCGv_i64 fp1 = tcg_temp_new_i64();
11110 TCGv_i64 fp2 = tcg_temp_new_i64();
11112 gen_load_fpr64(ctx, fp0, fs);
11113 gen_load_fpr64(ctx, fp1, ft);
11114 gen_load_fpr64(ctx, fp2, fr);
11115 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11116 tcg_temp_free_i64(fp0);
11117 tcg_temp_free_i64(fp1);
11118 gen_store_fpr64(ctx, fp2, fd);
11119 tcg_temp_free_i64(fp2);
11121 break;
11122 case OPC_NMSUB_PS:
11123 check_ps(ctx);
11125 TCGv_i64 fp0 = tcg_temp_new_i64();
11126 TCGv_i64 fp1 = tcg_temp_new_i64();
11127 TCGv_i64 fp2 = tcg_temp_new_i64();
11129 gen_load_fpr64(ctx, fp0, fs);
11130 gen_load_fpr64(ctx, fp1, ft);
11131 gen_load_fpr64(ctx, fp2, fr);
11132 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11133 tcg_temp_free_i64(fp0);
11134 tcg_temp_free_i64(fp1);
11135 gen_store_fpr64(ctx, fp2, fd);
11136 tcg_temp_free_i64(fp2);
11138 break;
11139 default:
11140 MIPS_INVAL("flt3_arith");
11141 generate_exception_end(ctx, EXCP_RI);
11142 return;
11146 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11148 TCGv t0;
11150 #if !defined(CONFIG_USER_ONLY)
11151 /* The Linux kernel will emulate rdhwr if it's not supported natively.
11152 Therefore only check the ISA in system mode. */
11153 check_insn(ctx, ISA_MIPS32R2);
11154 #endif
11155 t0 = tcg_temp_new();
11157 switch (rd) {
11158 case 0:
11159 gen_helper_rdhwr_cpunum(t0, cpu_env);
11160 gen_store_gpr(t0, rt);
11161 break;
11162 case 1:
11163 gen_helper_rdhwr_synci_step(t0, cpu_env);
11164 gen_store_gpr(t0, rt);
11165 break;
11166 case 2:
11167 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11168 gen_io_start();
11170 gen_helper_rdhwr_cc(t0, cpu_env);
11171 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11172 gen_io_end();
11174 gen_store_gpr(t0, rt);
11175 /* Break the TB to be able to take timer interrupts immediately
11176 after reading count. DISAS_STOP isn't sufficient, we need to ensure
11177 we break completely out of translated code. */
11178 gen_save_pc(ctx->base.pc_next + 4);
11179 ctx->base.is_jmp = DISAS_EXIT;
11180 break;
11181 case 3:
11182 gen_helper_rdhwr_ccres(t0, cpu_env);
11183 gen_store_gpr(t0, rt);
11184 break;
11185 case 4:
11186 check_insn(ctx, ISA_MIPS32R6);
11187 if (sel != 0) {
11188 /* Performance counter registers are not implemented other than
11189 * control register 0.
11191 generate_exception(ctx, EXCP_RI);
11193 gen_helper_rdhwr_performance(t0, cpu_env);
11194 gen_store_gpr(t0, rt);
11195 break;
11196 case 5:
11197 check_insn(ctx, ISA_MIPS32R6);
11198 gen_helper_rdhwr_xnp(t0, cpu_env);
11199 gen_store_gpr(t0, rt);
11200 break;
11201 case 29:
11202 #if defined(CONFIG_USER_ONLY)
11203 tcg_gen_ld_tl(t0, cpu_env,
11204 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11205 gen_store_gpr(t0, rt);
11206 break;
11207 #else
11208 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11209 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
11210 tcg_gen_ld_tl(t0, cpu_env,
11211 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11212 gen_store_gpr(t0, rt);
11213 } else {
11214 generate_exception_end(ctx, EXCP_RI);
11216 break;
11217 #endif
11218 default: /* Invalid */
11219 MIPS_INVAL("rdhwr");
11220 generate_exception_end(ctx, EXCP_RI);
11221 break;
11223 tcg_temp_free(t0);
11226 static inline void clear_branch_hflags(DisasContext *ctx)
11228 ctx->hflags &= ~MIPS_HFLAG_BMASK;
11229 if (ctx->base.is_jmp == DISAS_NEXT) {
11230 save_cpu_state(ctx, 0);
11231 } else {
11232 /* it is not safe to save ctx->hflags as hflags may be changed
11233 in execution time by the instruction in delay / forbidden slot. */
11234 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11238 static void gen_branch(DisasContext *ctx, int insn_bytes)
11240 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11241 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
11242 /* Branches completion */
11243 clear_branch_hflags(ctx);
11244 ctx->base.is_jmp = DISAS_NORETURN;
11245 /* FIXME: Need to clear can_do_io. */
11246 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
11247 case MIPS_HFLAG_FBNSLOT:
11248 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
11249 break;
11250 case MIPS_HFLAG_B:
11251 /* unconditional branch */
11252 if (proc_hflags & MIPS_HFLAG_BX) {
11253 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11255 gen_goto_tb(ctx, 0, ctx->btarget);
11256 break;
11257 case MIPS_HFLAG_BL:
11258 /* blikely taken case */
11259 gen_goto_tb(ctx, 0, ctx->btarget);
11260 break;
11261 case MIPS_HFLAG_BC:
11262 /* Conditional branch */
11264 TCGLabel *l1 = gen_new_label();
11266 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11267 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
11268 gen_set_label(l1);
11269 gen_goto_tb(ctx, 0, ctx->btarget);
11271 break;
11272 case MIPS_HFLAG_BR:
11273 /* unconditional branch to register */
11274 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
11275 TCGv t0 = tcg_temp_new();
11276 TCGv_i32 t1 = tcg_temp_new_i32();
11278 tcg_gen_andi_tl(t0, btarget, 0x1);
11279 tcg_gen_trunc_tl_i32(t1, t0);
11280 tcg_temp_free(t0);
11281 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11282 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11283 tcg_gen_or_i32(hflags, hflags, t1);
11284 tcg_temp_free_i32(t1);
11286 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11287 } else {
11288 tcg_gen_mov_tl(cpu_PC, btarget);
11290 if (ctx->base.singlestep_enabled) {
11291 save_cpu_state(ctx, 0);
11292 gen_helper_raise_exception_debug(cpu_env);
11294 tcg_gen_lookup_and_goto_ptr();
11295 break;
11296 default:
11297 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11298 abort();
11303 /* Compact Branches */
11304 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11305 int rs, int rt, int32_t offset)
11307 int bcond_compute = 0;
11308 TCGv t0 = tcg_temp_new();
11309 TCGv t1 = tcg_temp_new();
11310 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11312 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11313 #ifdef MIPS_DEBUG_DISAS
11314 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11315 "\n", ctx->base.pc_next);
11316 #endif
11317 generate_exception_end(ctx, EXCP_RI);
11318 goto out;
11321 /* Load needed operands and calculate btarget */
11322 switch (opc) {
11323 /* compact branch */
11324 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11325 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11326 gen_load_gpr(t0, rs);
11327 gen_load_gpr(t1, rt);
11328 bcond_compute = 1;
11329 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11330 if (rs <= rt && rs == 0) {
11331 /* OPC_BEQZALC, OPC_BNEZALC */
11332 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11334 break;
11335 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11336 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11337 gen_load_gpr(t0, rs);
11338 gen_load_gpr(t1, rt);
11339 bcond_compute = 1;
11340 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11341 break;
11342 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11343 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11344 if (rs == 0 || rs == rt) {
11345 /* OPC_BLEZALC, OPC_BGEZALC */
11346 /* OPC_BGTZALC, OPC_BLTZALC */
11347 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11349 gen_load_gpr(t0, rs);
11350 gen_load_gpr(t1, rt);
11351 bcond_compute = 1;
11352 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11353 break;
11354 case OPC_BC:
11355 case OPC_BALC:
11356 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11357 break;
11358 case OPC_BEQZC:
11359 case OPC_BNEZC:
11360 if (rs != 0) {
11361 /* OPC_BEQZC, OPC_BNEZC */
11362 gen_load_gpr(t0, rs);
11363 bcond_compute = 1;
11364 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11365 } else {
11366 /* OPC_JIC, OPC_JIALC */
11367 TCGv tbase = tcg_temp_new();
11368 TCGv toffset = tcg_temp_new();
11370 gen_load_gpr(tbase, rt);
11371 tcg_gen_movi_tl(toffset, offset);
11372 gen_op_addr_add(ctx, btarget, tbase, toffset);
11373 tcg_temp_free(tbase);
11374 tcg_temp_free(toffset);
11376 break;
11377 default:
11378 MIPS_INVAL("Compact branch/jump");
11379 generate_exception_end(ctx, EXCP_RI);
11380 goto out;
11383 if (bcond_compute == 0) {
11384 /* Uncoditional compact branch */
11385 switch (opc) {
11386 case OPC_JIALC:
11387 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11388 /* Fallthrough */
11389 case OPC_JIC:
11390 ctx->hflags |= MIPS_HFLAG_BR;
11391 break;
11392 case OPC_BALC:
11393 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11394 /* Fallthrough */
11395 case OPC_BC:
11396 ctx->hflags |= MIPS_HFLAG_B;
11397 break;
11398 default:
11399 MIPS_INVAL("Compact branch/jump");
11400 generate_exception_end(ctx, EXCP_RI);
11401 goto out;
11404 /* Generating branch here as compact branches don't have delay slot */
11405 gen_branch(ctx, 4);
11406 } else {
11407 /* Conditional compact branch */
11408 TCGLabel *fs = gen_new_label();
11409 save_cpu_state(ctx, 0);
11411 switch (opc) {
11412 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11413 if (rs == 0 && rt != 0) {
11414 /* OPC_BLEZALC */
11415 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11416 } else if (rs != 0 && rt != 0 && rs == rt) {
11417 /* OPC_BGEZALC */
11418 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11419 } else {
11420 /* OPC_BGEUC */
11421 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11423 break;
11424 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11425 if (rs == 0 && rt != 0) {
11426 /* OPC_BGTZALC */
11427 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11428 } else if (rs != 0 && rt != 0 && rs == rt) {
11429 /* OPC_BLTZALC */
11430 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11431 } else {
11432 /* OPC_BLTUC */
11433 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11435 break;
11436 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11437 if (rs == 0 && rt != 0) {
11438 /* OPC_BLEZC */
11439 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11440 } else if (rs != 0 && rt != 0 && rs == rt) {
11441 /* OPC_BGEZC */
11442 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11443 } else {
11444 /* OPC_BGEC */
11445 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11447 break;
11448 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11449 if (rs == 0 && rt != 0) {
11450 /* OPC_BGTZC */
11451 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11452 } else if (rs != 0 && rt != 0 && rs == rt) {
11453 /* OPC_BLTZC */
11454 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11455 } else {
11456 /* OPC_BLTC */
11457 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11459 break;
11460 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11461 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11462 if (rs >= rt) {
11463 /* OPC_BOVC, OPC_BNVC */
11464 TCGv t2 = tcg_temp_new();
11465 TCGv t3 = tcg_temp_new();
11466 TCGv t4 = tcg_temp_new();
11467 TCGv input_overflow = tcg_temp_new();
11469 gen_load_gpr(t0, rs);
11470 gen_load_gpr(t1, rt);
11471 tcg_gen_ext32s_tl(t2, t0);
11472 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11473 tcg_gen_ext32s_tl(t3, t1);
11474 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11475 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11477 tcg_gen_add_tl(t4, t2, t3);
11478 tcg_gen_ext32s_tl(t4, t4);
11479 tcg_gen_xor_tl(t2, t2, t3);
11480 tcg_gen_xor_tl(t3, t4, t3);
11481 tcg_gen_andc_tl(t2, t3, t2);
11482 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11483 tcg_gen_or_tl(t4, t4, input_overflow);
11484 if (opc == OPC_BOVC) {
11485 /* OPC_BOVC */
11486 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11487 } else {
11488 /* OPC_BNVC */
11489 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11491 tcg_temp_free(input_overflow);
11492 tcg_temp_free(t4);
11493 tcg_temp_free(t3);
11494 tcg_temp_free(t2);
11495 } else if (rs < rt && rs == 0) {
11496 /* OPC_BEQZALC, OPC_BNEZALC */
11497 if (opc == OPC_BEQZALC) {
11498 /* OPC_BEQZALC */
11499 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11500 } else {
11501 /* OPC_BNEZALC */
11502 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11504 } else {
11505 /* OPC_BEQC, OPC_BNEC */
11506 if (opc == OPC_BEQC) {
11507 /* OPC_BEQC */
11508 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11509 } else {
11510 /* OPC_BNEC */
11511 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11514 break;
11515 case OPC_BEQZC:
11516 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11517 break;
11518 case OPC_BNEZC:
11519 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11520 break;
11521 default:
11522 MIPS_INVAL("Compact conditional branch/jump");
11523 generate_exception_end(ctx, EXCP_RI);
11524 goto out;
11527 /* Generating branch here as compact branches don't have delay slot */
11528 gen_goto_tb(ctx, 1, ctx->btarget);
11529 gen_set_label(fs);
11531 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11534 out:
11535 tcg_temp_free(t0);
11536 tcg_temp_free(t1);
11539 /* ISA extensions (ASEs) */
11540 /* MIPS16 extension to MIPS32 */
11542 /* MIPS16 major opcodes */
11543 enum {
11544 M16_OPC_ADDIUSP = 0x00,
11545 M16_OPC_ADDIUPC = 0x01,
11546 M16_OPC_B = 0x02,
11547 M16_OPC_JAL = 0x03,
11548 M16_OPC_BEQZ = 0x04,
11549 M16_OPC_BNEQZ = 0x05,
11550 M16_OPC_SHIFT = 0x06,
11551 M16_OPC_LD = 0x07,
11552 M16_OPC_RRIA = 0x08,
11553 M16_OPC_ADDIU8 = 0x09,
11554 M16_OPC_SLTI = 0x0a,
11555 M16_OPC_SLTIU = 0x0b,
11556 M16_OPC_I8 = 0x0c,
11557 M16_OPC_LI = 0x0d,
11558 M16_OPC_CMPI = 0x0e,
11559 M16_OPC_SD = 0x0f,
11560 M16_OPC_LB = 0x10,
11561 M16_OPC_LH = 0x11,
11562 M16_OPC_LWSP = 0x12,
11563 M16_OPC_LW = 0x13,
11564 M16_OPC_LBU = 0x14,
11565 M16_OPC_LHU = 0x15,
11566 M16_OPC_LWPC = 0x16,
11567 M16_OPC_LWU = 0x17,
11568 M16_OPC_SB = 0x18,
11569 M16_OPC_SH = 0x19,
11570 M16_OPC_SWSP = 0x1a,
11571 M16_OPC_SW = 0x1b,
11572 M16_OPC_RRR = 0x1c,
11573 M16_OPC_RR = 0x1d,
11574 M16_OPC_EXTEND = 0x1e,
11575 M16_OPC_I64 = 0x1f
11578 /* I8 funct field */
11579 enum {
11580 I8_BTEQZ = 0x0,
11581 I8_BTNEZ = 0x1,
11582 I8_SWRASP = 0x2,
11583 I8_ADJSP = 0x3,
11584 I8_SVRS = 0x4,
11585 I8_MOV32R = 0x5,
11586 I8_MOVR32 = 0x7
11589 /* RRR f field */
11590 enum {
11591 RRR_DADDU = 0x0,
11592 RRR_ADDU = 0x1,
11593 RRR_DSUBU = 0x2,
11594 RRR_SUBU = 0x3
11597 /* RR funct field */
11598 enum {
11599 RR_JR = 0x00,
11600 RR_SDBBP = 0x01,
11601 RR_SLT = 0x02,
11602 RR_SLTU = 0x03,
11603 RR_SLLV = 0x04,
11604 RR_BREAK = 0x05,
11605 RR_SRLV = 0x06,
11606 RR_SRAV = 0x07,
11607 RR_DSRL = 0x08,
11608 RR_CMP = 0x0a,
11609 RR_NEG = 0x0b,
11610 RR_AND = 0x0c,
11611 RR_OR = 0x0d,
11612 RR_XOR = 0x0e,
11613 RR_NOT = 0x0f,
11614 RR_MFHI = 0x10,
11615 RR_CNVT = 0x11,
11616 RR_MFLO = 0x12,
11617 RR_DSRA = 0x13,
11618 RR_DSLLV = 0x14,
11619 RR_DSRLV = 0x16,
11620 RR_DSRAV = 0x17,
11621 RR_MULT = 0x18,
11622 RR_MULTU = 0x19,
11623 RR_DIV = 0x1a,
11624 RR_DIVU = 0x1b,
11625 RR_DMULT = 0x1c,
11626 RR_DMULTU = 0x1d,
11627 RR_DDIV = 0x1e,
11628 RR_DDIVU = 0x1f
11631 /* I64 funct field */
11632 enum {
11633 I64_LDSP = 0x0,
11634 I64_SDSP = 0x1,
11635 I64_SDRASP = 0x2,
11636 I64_DADJSP = 0x3,
11637 I64_LDPC = 0x4,
11638 I64_DADDIU5 = 0x5,
11639 I64_DADDIUPC = 0x6,
11640 I64_DADDIUSP = 0x7
11643 /* RR ry field for CNVT */
11644 enum {
11645 RR_RY_CNVT_ZEB = 0x0,
11646 RR_RY_CNVT_ZEH = 0x1,
11647 RR_RY_CNVT_ZEW = 0x2,
11648 RR_RY_CNVT_SEB = 0x4,
11649 RR_RY_CNVT_SEH = 0x5,
11650 RR_RY_CNVT_SEW = 0x6,
11653 static int xlat (int r)
11655 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11657 return map[r];
11660 static void gen_mips16_save (DisasContext *ctx,
11661 int xsregs, int aregs,
11662 int do_ra, int do_s0, int do_s1,
11663 int framesize)
11665 TCGv t0 = tcg_temp_new();
11666 TCGv t1 = tcg_temp_new();
11667 TCGv t2 = tcg_temp_new();
11668 int args, astatic;
11670 switch (aregs) {
11671 case 0:
11672 case 1:
11673 case 2:
11674 case 3:
11675 case 11:
11676 args = 0;
11677 break;
11678 case 4:
11679 case 5:
11680 case 6:
11681 case 7:
11682 args = 1;
11683 break;
11684 case 8:
11685 case 9:
11686 case 10:
11687 args = 2;
11688 break;
11689 case 12:
11690 case 13:
11691 args = 3;
11692 break;
11693 case 14:
11694 args = 4;
11695 break;
11696 default:
11697 generate_exception_end(ctx, EXCP_RI);
11698 return;
11701 switch (args) {
11702 case 4:
11703 gen_base_offset_addr(ctx, t0, 29, 12);
11704 gen_load_gpr(t1, 7);
11705 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11706 /* Fall through */
11707 case 3:
11708 gen_base_offset_addr(ctx, t0, 29, 8);
11709 gen_load_gpr(t1, 6);
11710 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11711 /* Fall through */
11712 case 2:
11713 gen_base_offset_addr(ctx, t0, 29, 4);
11714 gen_load_gpr(t1, 5);
11715 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11716 /* Fall through */
11717 case 1:
11718 gen_base_offset_addr(ctx, t0, 29, 0);
11719 gen_load_gpr(t1, 4);
11720 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11723 gen_load_gpr(t0, 29);
11725 #define DECR_AND_STORE(reg) do { \
11726 tcg_gen_movi_tl(t2, -4); \
11727 gen_op_addr_add(ctx, t0, t0, t2); \
11728 gen_load_gpr(t1, reg); \
11729 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11730 } while (0)
11732 if (do_ra) {
11733 DECR_AND_STORE(31);
11736 switch (xsregs) {
11737 case 7:
11738 DECR_AND_STORE(30);
11739 /* Fall through */
11740 case 6:
11741 DECR_AND_STORE(23);
11742 /* Fall through */
11743 case 5:
11744 DECR_AND_STORE(22);
11745 /* Fall through */
11746 case 4:
11747 DECR_AND_STORE(21);
11748 /* Fall through */
11749 case 3:
11750 DECR_AND_STORE(20);
11751 /* Fall through */
11752 case 2:
11753 DECR_AND_STORE(19);
11754 /* Fall through */
11755 case 1:
11756 DECR_AND_STORE(18);
11759 if (do_s1) {
11760 DECR_AND_STORE(17);
11762 if (do_s0) {
11763 DECR_AND_STORE(16);
11766 switch (aregs) {
11767 case 0:
11768 case 4:
11769 case 8:
11770 case 12:
11771 case 14:
11772 astatic = 0;
11773 break;
11774 case 1:
11775 case 5:
11776 case 9:
11777 case 13:
11778 astatic = 1;
11779 break;
11780 case 2:
11781 case 6:
11782 case 10:
11783 astatic = 2;
11784 break;
11785 case 3:
11786 case 7:
11787 astatic = 3;
11788 break;
11789 case 11:
11790 astatic = 4;
11791 break;
11792 default:
11793 generate_exception_end(ctx, EXCP_RI);
11794 return;
11797 if (astatic > 0) {
11798 DECR_AND_STORE(7);
11799 if (astatic > 1) {
11800 DECR_AND_STORE(6);
11801 if (astatic > 2) {
11802 DECR_AND_STORE(5);
11803 if (astatic > 3) {
11804 DECR_AND_STORE(4);
11809 #undef DECR_AND_STORE
11811 tcg_gen_movi_tl(t2, -framesize);
11812 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11813 tcg_temp_free(t0);
11814 tcg_temp_free(t1);
11815 tcg_temp_free(t2);
11818 static void gen_mips16_restore (DisasContext *ctx,
11819 int xsregs, int aregs,
11820 int do_ra, int do_s0, int do_s1,
11821 int framesize)
11823 int astatic;
11824 TCGv t0 = tcg_temp_new();
11825 TCGv t1 = tcg_temp_new();
11826 TCGv t2 = tcg_temp_new();
11828 tcg_gen_movi_tl(t2, framesize);
11829 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11831 #define DECR_AND_LOAD(reg) do { \
11832 tcg_gen_movi_tl(t2, -4); \
11833 gen_op_addr_add(ctx, t0, t0, t2); \
11834 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11835 gen_store_gpr(t1, reg); \
11836 } while (0)
11838 if (do_ra) {
11839 DECR_AND_LOAD(31);
11842 switch (xsregs) {
11843 case 7:
11844 DECR_AND_LOAD(30);
11845 /* Fall through */
11846 case 6:
11847 DECR_AND_LOAD(23);
11848 /* Fall through */
11849 case 5:
11850 DECR_AND_LOAD(22);
11851 /* Fall through */
11852 case 4:
11853 DECR_AND_LOAD(21);
11854 /* Fall through */
11855 case 3:
11856 DECR_AND_LOAD(20);
11857 /* Fall through */
11858 case 2:
11859 DECR_AND_LOAD(19);
11860 /* Fall through */
11861 case 1:
11862 DECR_AND_LOAD(18);
11865 if (do_s1) {
11866 DECR_AND_LOAD(17);
11868 if (do_s0) {
11869 DECR_AND_LOAD(16);
11872 switch (aregs) {
11873 case 0:
11874 case 4:
11875 case 8:
11876 case 12:
11877 case 14:
11878 astatic = 0;
11879 break;
11880 case 1:
11881 case 5:
11882 case 9:
11883 case 13:
11884 astatic = 1;
11885 break;
11886 case 2:
11887 case 6:
11888 case 10:
11889 astatic = 2;
11890 break;
11891 case 3:
11892 case 7:
11893 astatic = 3;
11894 break;
11895 case 11:
11896 astatic = 4;
11897 break;
11898 default:
11899 generate_exception_end(ctx, EXCP_RI);
11900 return;
11903 if (astatic > 0) {
11904 DECR_AND_LOAD(7);
11905 if (astatic > 1) {
11906 DECR_AND_LOAD(6);
11907 if (astatic > 2) {
11908 DECR_AND_LOAD(5);
11909 if (astatic > 3) {
11910 DECR_AND_LOAD(4);
11915 #undef DECR_AND_LOAD
11917 tcg_gen_movi_tl(t2, framesize);
11918 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11919 tcg_temp_free(t0);
11920 tcg_temp_free(t1);
11921 tcg_temp_free(t2);
11924 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11925 int is_64_bit, int extended)
11927 TCGv t0;
11929 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11930 generate_exception_end(ctx, EXCP_RI);
11931 return;
11934 t0 = tcg_temp_new();
11936 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11937 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11938 if (!is_64_bit) {
11939 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11942 tcg_temp_free(t0);
11945 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11946 int16_t offset)
11948 TCGv_i32 t0 = tcg_const_i32(op);
11949 TCGv t1 = tcg_temp_new();
11950 gen_base_offset_addr(ctx, t1, base, offset);
11951 gen_helper_cache(cpu_env, t1, t0);
11954 #if defined(TARGET_MIPS64)
11955 static void decode_i64_mips16 (DisasContext *ctx,
11956 int ry, int funct, int16_t offset,
11957 int extended)
11959 switch (funct) {
11960 case I64_LDSP:
11961 check_insn(ctx, ISA_MIPS3);
11962 check_mips_64(ctx);
11963 offset = extended ? offset : offset << 3;
11964 gen_ld(ctx, OPC_LD, ry, 29, offset);
11965 break;
11966 case I64_SDSP:
11967 check_insn(ctx, ISA_MIPS3);
11968 check_mips_64(ctx);
11969 offset = extended ? offset : offset << 3;
11970 gen_st(ctx, OPC_SD, ry, 29, offset);
11971 break;
11972 case I64_SDRASP:
11973 check_insn(ctx, ISA_MIPS3);
11974 check_mips_64(ctx);
11975 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11976 gen_st(ctx, OPC_SD, 31, 29, offset);
11977 break;
11978 case I64_DADJSP:
11979 check_insn(ctx, ISA_MIPS3);
11980 check_mips_64(ctx);
11981 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11982 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11983 break;
11984 case I64_LDPC:
11985 check_insn(ctx, ISA_MIPS3);
11986 check_mips_64(ctx);
11987 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11988 generate_exception_end(ctx, EXCP_RI);
11989 } else {
11990 offset = extended ? offset : offset << 3;
11991 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11993 break;
11994 case I64_DADDIU5:
11995 check_insn(ctx, ISA_MIPS3);
11996 check_mips_64(ctx);
11997 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11998 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11999 break;
12000 case I64_DADDIUPC:
12001 check_insn(ctx, ISA_MIPS3);
12002 check_mips_64(ctx);
12003 offset = extended ? offset : offset << 2;
12004 gen_addiupc(ctx, ry, offset, 1, extended);
12005 break;
12006 case I64_DADDIUSP:
12007 check_insn(ctx, ISA_MIPS3);
12008 check_mips_64(ctx);
12009 offset = extended ? offset : offset << 2;
12010 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12011 break;
12014 #endif
12016 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12018 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
12019 int op, rx, ry, funct, sa;
12020 int16_t imm, offset;
12022 ctx->opcode = (ctx->opcode << 16) | extend;
12023 op = (ctx->opcode >> 11) & 0x1f;
12024 sa = (ctx->opcode >> 22) & 0x1f;
12025 funct = (ctx->opcode >> 8) & 0x7;
12026 rx = xlat((ctx->opcode >> 8) & 0x7);
12027 ry = xlat((ctx->opcode >> 5) & 0x7);
12028 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12029 | ((ctx->opcode >> 21) & 0x3f) << 5
12030 | (ctx->opcode & 0x1f));
12032 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
12033 counterparts. */
12034 switch (op) {
12035 case M16_OPC_ADDIUSP:
12036 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12037 break;
12038 case M16_OPC_ADDIUPC:
12039 gen_addiupc(ctx, rx, imm, 0, 1);
12040 break;
12041 case M16_OPC_B:
12042 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12043 /* No delay slot, so just process as a normal instruction */
12044 break;
12045 case M16_OPC_BEQZ:
12046 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12047 /* No delay slot, so just process as a normal instruction */
12048 break;
12049 case M16_OPC_BNEQZ:
12050 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12051 /* No delay slot, so just process as a normal instruction */
12052 break;
12053 case M16_OPC_SHIFT:
12054 switch (ctx->opcode & 0x3) {
12055 case 0x0:
12056 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12057 break;
12058 case 0x1:
12059 #if defined(TARGET_MIPS64)
12060 check_mips_64(ctx);
12061 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12062 #else
12063 generate_exception_end(ctx, EXCP_RI);
12064 #endif
12065 break;
12066 case 0x2:
12067 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12068 break;
12069 case 0x3:
12070 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12071 break;
12073 break;
12074 #if defined(TARGET_MIPS64)
12075 case M16_OPC_LD:
12076 check_insn(ctx, ISA_MIPS3);
12077 check_mips_64(ctx);
12078 gen_ld(ctx, OPC_LD, ry, rx, offset);
12079 break;
12080 #endif
12081 case M16_OPC_RRIA:
12082 imm = ctx->opcode & 0xf;
12083 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12084 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12085 imm = (int16_t) (imm << 1) >> 1;
12086 if ((ctx->opcode >> 4) & 0x1) {
12087 #if defined(TARGET_MIPS64)
12088 check_mips_64(ctx);
12089 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12090 #else
12091 generate_exception_end(ctx, EXCP_RI);
12092 #endif
12093 } else {
12094 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12096 break;
12097 case M16_OPC_ADDIU8:
12098 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12099 break;
12100 case M16_OPC_SLTI:
12101 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12102 break;
12103 case M16_OPC_SLTIU:
12104 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12105 break;
12106 case M16_OPC_I8:
12107 switch (funct) {
12108 case I8_BTEQZ:
12109 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
12110 break;
12111 case I8_BTNEZ:
12112 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
12113 break;
12114 case I8_SWRASP:
12115 gen_st(ctx, OPC_SW, 31, 29, imm);
12116 break;
12117 case I8_ADJSP:
12118 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
12119 break;
12120 case I8_SVRS:
12121 check_insn(ctx, ISA_MIPS32);
12123 int xsregs = (ctx->opcode >> 24) & 0x7;
12124 int aregs = (ctx->opcode >> 16) & 0xf;
12125 int do_ra = (ctx->opcode >> 6) & 0x1;
12126 int do_s0 = (ctx->opcode >> 5) & 0x1;
12127 int do_s1 = (ctx->opcode >> 4) & 0x1;
12128 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12129 | (ctx->opcode & 0xf)) << 3;
12131 if (ctx->opcode & (1 << 7)) {
12132 gen_mips16_save(ctx, xsregs, aregs,
12133 do_ra, do_s0, do_s1,
12134 framesize);
12135 } else {
12136 gen_mips16_restore(ctx, xsregs, aregs,
12137 do_ra, do_s0, do_s1,
12138 framesize);
12141 break;
12142 default:
12143 generate_exception_end(ctx, EXCP_RI);
12144 break;
12146 break;
12147 case M16_OPC_LI:
12148 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
12149 break;
12150 case M16_OPC_CMPI:
12151 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
12152 break;
12153 #if defined(TARGET_MIPS64)
12154 case M16_OPC_SD:
12155 check_insn(ctx, ISA_MIPS3);
12156 check_mips_64(ctx);
12157 gen_st(ctx, OPC_SD, ry, rx, offset);
12158 break;
12159 #endif
12160 case M16_OPC_LB:
12161 gen_ld(ctx, OPC_LB, ry, rx, offset);
12162 break;
12163 case M16_OPC_LH:
12164 gen_ld(ctx, OPC_LH, ry, rx, offset);
12165 break;
12166 case M16_OPC_LWSP:
12167 gen_ld(ctx, OPC_LW, rx, 29, offset);
12168 break;
12169 case M16_OPC_LW:
12170 gen_ld(ctx, OPC_LW, ry, rx, offset);
12171 break;
12172 case M16_OPC_LBU:
12173 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12174 break;
12175 case M16_OPC_LHU:
12176 gen_ld(ctx, OPC_LHU, ry, rx, offset);
12177 break;
12178 case M16_OPC_LWPC:
12179 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
12180 break;
12181 #if defined(TARGET_MIPS64)
12182 case M16_OPC_LWU:
12183 check_insn(ctx, ISA_MIPS3);
12184 check_mips_64(ctx);
12185 gen_ld(ctx, OPC_LWU, ry, rx, offset);
12186 break;
12187 #endif
12188 case M16_OPC_SB:
12189 gen_st(ctx, OPC_SB, ry, rx, offset);
12190 break;
12191 case M16_OPC_SH:
12192 gen_st(ctx, OPC_SH, ry, rx, offset);
12193 break;
12194 case M16_OPC_SWSP:
12195 gen_st(ctx, OPC_SW, rx, 29, offset);
12196 break;
12197 case M16_OPC_SW:
12198 gen_st(ctx, OPC_SW, ry, rx, offset);
12199 break;
12200 #if defined(TARGET_MIPS64)
12201 case M16_OPC_I64:
12202 decode_i64_mips16(ctx, ry, funct, offset, 1);
12203 break;
12204 #endif
12205 default:
12206 generate_exception_end(ctx, EXCP_RI);
12207 break;
12210 return 4;
12213 static inline bool is_uhi(int sdbbp_code)
12215 #ifdef CONFIG_USER_ONLY
12216 return false;
12217 #else
12218 return semihosting_enabled() && sdbbp_code == 1;
12219 #endif
12222 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12224 int rx, ry;
12225 int sa;
12226 int op, cnvt_op, op1, offset;
12227 int funct;
12228 int n_bytes;
12230 op = (ctx->opcode >> 11) & 0x1f;
12231 sa = (ctx->opcode >> 2) & 0x7;
12232 sa = sa == 0 ? 8 : sa;
12233 rx = xlat((ctx->opcode >> 8) & 0x7);
12234 cnvt_op = (ctx->opcode >> 5) & 0x7;
12235 ry = xlat((ctx->opcode >> 5) & 0x7);
12236 op1 = offset = ctx->opcode & 0x1f;
12238 n_bytes = 2;
12240 switch (op) {
12241 case M16_OPC_ADDIUSP:
12243 int16_t imm = ((uint8_t) ctx->opcode) << 2;
12245 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12247 break;
12248 case M16_OPC_ADDIUPC:
12249 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
12250 break;
12251 case M16_OPC_B:
12252 offset = (ctx->opcode & 0x7ff) << 1;
12253 offset = (int16_t)(offset << 4) >> 4;
12254 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
12255 /* No delay slot, so just process as a normal instruction */
12256 break;
12257 case M16_OPC_JAL:
12258 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
12259 offset = (((ctx->opcode & 0x1f) << 21)
12260 | ((ctx->opcode >> 5) & 0x1f) << 16
12261 | offset) << 2;
12262 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
12263 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
12264 n_bytes = 4;
12265 break;
12266 case M16_OPC_BEQZ:
12267 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
12268 ((int8_t)ctx->opcode) << 1, 0);
12269 /* No delay slot, so just process as a normal instruction */
12270 break;
12271 case M16_OPC_BNEQZ:
12272 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
12273 ((int8_t)ctx->opcode) << 1, 0);
12274 /* No delay slot, so just process as a normal instruction */
12275 break;
12276 case M16_OPC_SHIFT:
12277 switch (ctx->opcode & 0x3) {
12278 case 0x0:
12279 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12280 break;
12281 case 0x1:
12282 #if defined(TARGET_MIPS64)
12283 check_insn(ctx, ISA_MIPS3);
12284 check_mips_64(ctx);
12285 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12286 #else
12287 generate_exception_end(ctx, EXCP_RI);
12288 #endif
12289 break;
12290 case 0x2:
12291 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12292 break;
12293 case 0x3:
12294 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12295 break;
12297 break;
12298 #if defined(TARGET_MIPS64)
12299 case M16_OPC_LD:
12300 check_insn(ctx, ISA_MIPS3);
12301 check_mips_64(ctx);
12302 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
12303 break;
12304 #endif
12305 case M16_OPC_RRIA:
12307 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12309 if ((ctx->opcode >> 4) & 1) {
12310 #if defined(TARGET_MIPS64)
12311 check_insn(ctx, ISA_MIPS3);
12312 check_mips_64(ctx);
12313 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12314 #else
12315 generate_exception_end(ctx, EXCP_RI);
12316 #endif
12317 } else {
12318 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12321 break;
12322 case M16_OPC_ADDIU8:
12324 int16_t imm = (int8_t) ctx->opcode;
12326 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12328 break;
12329 case M16_OPC_SLTI:
12331 int16_t imm = (uint8_t) ctx->opcode;
12332 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12334 break;
12335 case M16_OPC_SLTIU:
12337 int16_t imm = (uint8_t) ctx->opcode;
12338 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12340 break;
12341 case M16_OPC_I8:
12343 int reg32;
12345 funct = (ctx->opcode >> 8) & 0x7;
12346 switch (funct) {
12347 case I8_BTEQZ:
12348 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
12349 ((int8_t)ctx->opcode) << 1, 0);
12350 break;
12351 case I8_BTNEZ:
12352 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
12353 ((int8_t)ctx->opcode) << 1, 0);
12354 break;
12355 case I8_SWRASP:
12356 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
12357 break;
12358 case I8_ADJSP:
12359 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
12360 ((int8_t)ctx->opcode) << 3);
12361 break;
12362 case I8_SVRS:
12363 check_insn(ctx, ISA_MIPS32);
12365 int do_ra = ctx->opcode & (1 << 6);
12366 int do_s0 = ctx->opcode & (1 << 5);
12367 int do_s1 = ctx->opcode & (1 << 4);
12368 int framesize = ctx->opcode & 0xf;
12370 if (framesize == 0) {
12371 framesize = 128;
12372 } else {
12373 framesize = framesize << 3;
12376 if (ctx->opcode & (1 << 7)) {
12377 gen_mips16_save(ctx, 0, 0,
12378 do_ra, do_s0, do_s1, framesize);
12379 } else {
12380 gen_mips16_restore(ctx, 0, 0,
12381 do_ra, do_s0, do_s1, framesize);
12384 break;
12385 case I8_MOV32R:
12387 int rz = xlat(ctx->opcode & 0x7);
12389 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
12390 ((ctx->opcode >> 5) & 0x7);
12391 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
12393 break;
12394 case I8_MOVR32:
12395 reg32 = ctx->opcode & 0x1f;
12396 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
12397 break;
12398 default:
12399 generate_exception_end(ctx, EXCP_RI);
12400 break;
12403 break;
12404 case M16_OPC_LI:
12406 int16_t imm = (uint8_t) ctx->opcode;
12408 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
12410 break;
12411 case M16_OPC_CMPI:
12413 int16_t imm = (uint8_t) ctx->opcode;
12414 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
12416 break;
12417 #if defined(TARGET_MIPS64)
12418 case M16_OPC_SD:
12419 check_insn(ctx, ISA_MIPS3);
12420 check_mips_64(ctx);
12421 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
12422 break;
12423 #endif
12424 case M16_OPC_LB:
12425 gen_ld(ctx, OPC_LB, ry, rx, offset);
12426 break;
12427 case M16_OPC_LH:
12428 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
12429 break;
12430 case M16_OPC_LWSP:
12431 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12432 break;
12433 case M16_OPC_LW:
12434 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
12435 break;
12436 case M16_OPC_LBU:
12437 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12438 break;
12439 case M16_OPC_LHU:
12440 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
12441 break;
12442 case M16_OPC_LWPC:
12443 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
12444 break;
12445 #if defined (TARGET_MIPS64)
12446 case M16_OPC_LWU:
12447 check_insn(ctx, ISA_MIPS3);
12448 check_mips_64(ctx);
12449 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
12450 break;
12451 #endif
12452 case M16_OPC_SB:
12453 gen_st(ctx, OPC_SB, ry, rx, offset);
12454 break;
12455 case M16_OPC_SH:
12456 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
12457 break;
12458 case M16_OPC_SWSP:
12459 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12460 break;
12461 case M16_OPC_SW:
12462 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
12463 break;
12464 case M16_OPC_RRR:
12466 int rz = xlat((ctx->opcode >> 2) & 0x7);
12467 int mips32_op;
12469 switch (ctx->opcode & 0x3) {
12470 case RRR_ADDU:
12471 mips32_op = OPC_ADDU;
12472 break;
12473 case RRR_SUBU:
12474 mips32_op = OPC_SUBU;
12475 break;
12476 #if defined(TARGET_MIPS64)
12477 case RRR_DADDU:
12478 mips32_op = OPC_DADDU;
12479 check_insn(ctx, ISA_MIPS3);
12480 check_mips_64(ctx);
12481 break;
12482 case RRR_DSUBU:
12483 mips32_op = OPC_DSUBU;
12484 check_insn(ctx, ISA_MIPS3);
12485 check_mips_64(ctx);
12486 break;
12487 #endif
12488 default:
12489 generate_exception_end(ctx, EXCP_RI);
12490 goto done;
12493 gen_arith(ctx, mips32_op, rz, rx, ry);
12494 done:
12497 break;
12498 case M16_OPC_RR:
12499 switch (op1) {
12500 case RR_JR:
12502 int nd = (ctx->opcode >> 7) & 0x1;
12503 int link = (ctx->opcode >> 6) & 0x1;
12504 int ra = (ctx->opcode >> 5) & 0x1;
12506 if (nd) {
12507 check_insn(ctx, ISA_MIPS32);
12510 if (link) {
12511 op = OPC_JALR;
12512 } else {
12513 op = OPC_JR;
12516 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12517 (nd ? 0 : 2));
12519 break;
12520 case RR_SDBBP:
12521 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12522 gen_helper_do_semihosting(cpu_env);
12523 } else {
12524 /* XXX: not clear which exception should be raised
12525 * when in debug mode...
12527 check_insn(ctx, ISA_MIPS32);
12528 generate_exception_end(ctx, EXCP_DBp);
12530 break;
12531 case RR_SLT:
12532 gen_slt(ctx, OPC_SLT, 24, rx, ry);
12533 break;
12534 case RR_SLTU:
12535 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
12536 break;
12537 case RR_BREAK:
12538 generate_exception_end(ctx, EXCP_BREAK);
12539 break;
12540 case RR_SLLV:
12541 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
12542 break;
12543 case RR_SRLV:
12544 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
12545 break;
12546 case RR_SRAV:
12547 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
12548 break;
12549 #if defined (TARGET_MIPS64)
12550 case RR_DSRL:
12551 check_insn(ctx, ISA_MIPS3);
12552 check_mips_64(ctx);
12553 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
12554 break;
12555 #endif
12556 case RR_CMP:
12557 gen_logic(ctx, OPC_XOR, 24, rx, ry);
12558 break;
12559 case RR_NEG:
12560 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
12561 break;
12562 case RR_AND:
12563 gen_logic(ctx, OPC_AND, rx, rx, ry);
12564 break;
12565 case RR_OR:
12566 gen_logic(ctx, OPC_OR, rx, rx, ry);
12567 break;
12568 case RR_XOR:
12569 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12570 break;
12571 case RR_NOT:
12572 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12573 break;
12574 case RR_MFHI:
12575 gen_HILO(ctx, OPC_MFHI, 0, rx);
12576 break;
12577 case RR_CNVT:
12578 check_insn(ctx, ISA_MIPS32);
12579 switch (cnvt_op) {
12580 case RR_RY_CNVT_ZEB:
12581 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12582 break;
12583 case RR_RY_CNVT_ZEH:
12584 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12585 break;
12586 case RR_RY_CNVT_SEB:
12587 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12588 break;
12589 case RR_RY_CNVT_SEH:
12590 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12591 break;
12592 #if defined (TARGET_MIPS64)
12593 case RR_RY_CNVT_ZEW:
12594 check_insn(ctx, ISA_MIPS64);
12595 check_mips_64(ctx);
12596 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12597 break;
12598 case RR_RY_CNVT_SEW:
12599 check_insn(ctx, ISA_MIPS64);
12600 check_mips_64(ctx);
12601 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12602 break;
12603 #endif
12604 default:
12605 generate_exception_end(ctx, EXCP_RI);
12606 break;
12608 break;
12609 case RR_MFLO:
12610 gen_HILO(ctx, OPC_MFLO, 0, rx);
12611 break;
12612 #if defined (TARGET_MIPS64)
12613 case RR_DSRA:
12614 check_insn(ctx, ISA_MIPS3);
12615 check_mips_64(ctx);
12616 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12617 break;
12618 case RR_DSLLV:
12619 check_insn(ctx, ISA_MIPS3);
12620 check_mips_64(ctx);
12621 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12622 break;
12623 case RR_DSRLV:
12624 check_insn(ctx, ISA_MIPS3);
12625 check_mips_64(ctx);
12626 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12627 break;
12628 case RR_DSRAV:
12629 check_insn(ctx, ISA_MIPS3);
12630 check_mips_64(ctx);
12631 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12632 break;
12633 #endif
12634 case RR_MULT:
12635 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12636 break;
12637 case RR_MULTU:
12638 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12639 break;
12640 case RR_DIV:
12641 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12642 break;
12643 case RR_DIVU:
12644 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12645 break;
12646 #if defined (TARGET_MIPS64)
12647 case RR_DMULT:
12648 check_insn(ctx, ISA_MIPS3);
12649 check_mips_64(ctx);
12650 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12651 break;
12652 case RR_DMULTU:
12653 check_insn(ctx, ISA_MIPS3);
12654 check_mips_64(ctx);
12655 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12656 break;
12657 case RR_DDIV:
12658 check_insn(ctx, ISA_MIPS3);
12659 check_mips_64(ctx);
12660 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12661 break;
12662 case RR_DDIVU:
12663 check_insn(ctx, ISA_MIPS3);
12664 check_mips_64(ctx);
12665 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12666 break;
12667 #endif
12668 default:
12669 generate_exception_end(ctx, EXCP_RI);
12670 break;
12672 break;
12673 case M16_OPC_EXTEND:
12674 decode_extended_mips16_opc(env, ctx);
12675 n_bytes = 4;
12676 break;
12677 #if defined(TARGET_MIPS64)
12678 case M16_OPC_I64:
12679 funct = (ctx->opcode >> 8) & 0x7;
12680 decode_i64_mips16(ctx, ry, funct, offset, 0);
12681 break;
12682 #endif
12683 default:
12684 generate_exception_end(ctx, EXCP_RI);
12685 break;
12688 return n_bytes;
12691 /* microMIPS extension to MIPS32/MIPS64 */
12694 * microMIPS32/microMIPS64 major opcodes
12696 * 1. MIPS Architecture for Programmers Volume II-B:
12697 * The microMIPS32 Instruction Set (Revision 3.05)
12699 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12701 * 2. MIPS Architecture For Programmers Volume II-A:
12702 * The MIPS64 Instruction Set (Revision 3.51)
12705 enum {
12706 POOL32A = 0x00,
12707 POOL16A = 0x01,
12708 LBU16 = 0x02,
12709 MOVE16 = 0x03,
12710 ADDI32 = 0x04,
12711 R6_LUI = 0x04,
12712 AUI = 0x04,
12713 LBU32 = 0x05,
12714 SB32 = 0x06,
12715 LB32 = 0x07,
12717 POOL32B = 0x08,
12718 POOL16B = 0x09,
12719 LHU16 = 0x0a,
12720 ANDI16 = 0x0b,
12721 ADDIU32 = 0x0c,
12722 LHU32 = 0x0d,
12723 SH32 = 0x0e,
12724 LH32 = 0x0f,
12726 POOL32I = 0x10,
12727 POOL16C = 0x11,
12728 LWSP16 = 0x12,
12729 POOL16D = 0x13,
12730 ORI32 = 0x14,
12731 POOL32F = 0x15,
12732 POOL32S = 0x16, /* MIPS64 */
12733 DADDIU32 = 0x17, /* MIPS64 */
12735 POOL32C = 0x18,
12736 LWGP16 = 0x19,
12737 LW16 = 0x1a,
12738 POOL16E = 0x1b,
12739 XORI32 = 0x1c,
12740 JALS32 = 0x1d,
12741 BOVC = 0x1d,
12742 BEQC = 0x1d,
12743 BEQZALC = 0x1d,
12744 ADDIUPC = 0x1e,
12745 PCREL = 0x1e,
12746 BNVC = 0x1f,
12747 BNEC = 0x1f,
12748 BNEZALC = 0x1f,
12750 R6_BEQZC = 0x20,
12751 JIC = 0x20,
12752 POOL16F = 0x21,
12753 SB16 = 0x22,
12754 BEQZ16 = 0x23,
12755 BEQZC16 = 0x23,
12756 SLTI32 = 0x24,
12757 BEQ32 = 0x25,
12758 BC = 0x25,
12759 SWC132 = 0x26,
12760 LWC132 = 0x27,
12762 /* 0x29 is reserved */
12763 RES_29 = 0x29,
12764 R6_BNEZC = 0x28,
12765 JIALC = 0x28,
12766 SH16 = 0x2a,
12767 BNEZ16 = 0x2b,
12768 BNEZC16 = 0x2b,
12769 SLTIU32 = 0x2c,
12770 BNE32 = 0x2d,
12771 BALC = 0x2d,
12772 SDC132 = 0x2e,
12773 LDC132 = 0x2f,
12775 /* 0x31 is reserved */
12776 RES_31 = 0x31,
12777 BLEZALC = 0x30,
12778 BGEZALC = 0x30,
12779 BGEUC = 0x30,
12780 SWSP16 = 0x32,
12781 B16 = 0x33,
12782 BC16 = 0x33,
12783 ANDI32 = 0x34,
12784 J32 = 0x35,
12785 BGTZC = 0x35,
12786 BLTZC = 0x35,
12787 BLTC = 0x35,
12788 SD32 = 0x36, /* MIPS64 */
12789 LD32 = 0x37, /* MIPS64 */
12791 /* 0x39 is reserved */
12792 RES_39 = 0x39,
12793 BGTZALC = 0x38,
12794 BLTZALC = 0x38,
12795 BLTUC = 0x38,
12796 SW16 = 0x3a,
12797 LI16 = 0x3b,
12798 JALX32 = 0x3c,
12799 JAL32 = 0x3d,
12800 BLEZC = 0x3d,
12801 BGEZC = 0x3d,
12802 BGEC = 0x3d,
12803 SW32 = 0x3e,
12804 LW32 = 0x3f
12807 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12808 enum {
12809 ADDIUPC_00 = 0x00,
12810 ADDIUPC_01 = 0x01,
12811 ADDIUPC_02 = 0x02,
12812 ADDIUPC_03 = 0x03,
12813 ADDIUPC_04 = 0x04,
12814 ADDIUPC_05 = 0x05,
12815 ADDIUPC_06 = 0x06,
12816 ADDIUPC_07 = 0x07,
12817 AUIPC = 0x1e,
12818 ALUIPC = 0x1f,
12819 LWPC_08 = 0x08,
12820 LWPC_09 = 0x09,
12821 LWPC_0A = 0x0A,
12822 LWPC_0B = 0x0B,
12823 LWPC_0C = 0x0C,
12824 LWPC_0D = 0x0D,
12825 LWPC_0E = 0x0E,
12826 LWPC_0F = 0x0F,
12829 /* POOL32A encoding of minor opcode field */
12831 enum {
12832 /* These opcodes are distinguished only by bits 9..6; those bits are
12833 * what are recorded below. */
12834 SLL32 = 0x0,
12835 SRL32 = 0x1,
12836 SRA = 0x2,
12837 ROTR = 0x3,
12838 SELEQZ = 0x5,
12839 SELNEZ = 0x6,
12840 R6_RDHWR = 0x7,
12842 SLLV = 0x0,
12843 SRLV = 0x1,
12844 SRAV = 0x2,
12845 ROTRV = 0x3,
12846 ADD = 0x4,
12847 ADDU32 = 0x5,
12848 SUB = 0x6,
12849 SUBU32 = 0x7,
12850 MUL = 0x8,
12851 AND = 0x9,
12852 OR32 = 0xa,
12853 NOR = 0xb,
12854 XOR32 = 0xc,
12855 SLT = 0xd,
12856 SLTU = 0xe,
12858 MOVN = 0x0,
12859 R6_MUL = 0x0,
12860 MOVZ = 0x1,
12861 MUH = 0x1,
12862 MULU = 0x2,
12863 MUHU = 0x3,
12864 LWXS = 0x4,
12865 R6_DIV = 0x4,
12866 MOD = 0x5,
12867 R6_DIVU = 0x6,
12868 MODU = 0x7,
12870 /* The following can be distinguished by their lower 6 bits. */
12871 BREAK32 = 0x07,
12872 INS = 0x0c,
12873 LSA = 0x0f,
12874 ALIGN = 0x1f,
12875 EXT = 0x2c,
12876 POOL32AXF = 0x3c,
12877 SIGRIE = 0x3f
12880 /* POOL32AXF encoding of minor opcode field extension */
12883 * 1. MIPS Architecture for Programmers Volume II-B:
12884 * The microMIPS32 Instruction Set (Revision 3.05)
12886 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12888 * 2. MIPS Architecture for Programmers VolumeIV-e:
12889 * The MIPS DSP Application-Specific Extension
12890 * to the microMIPS32 Architecture (Revision 2.34)
12892 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12895 enum {
12896 /* bits 11..6 */
12897 TEQ = 0x00,
12898 TGE = 0x08,
12899 TGEU = 0x10,
12900 TLT = 0x20,
12901 TLTU = 0x28,
12902 TNE = 0x30,
12904 MFC0 = 0x03,
12905 MTC0 = 0x0b,
12907 /* begin of microMIPS32 DSP */
12909 /* bits 13..12 for 0x01 */
12910 MFHI_ACC = 0x0,
12911 MFLO_ACC = 0x1,
12912 MTHI_ACC = 0x2,
12913 MTLO_ACC = 0x3,
12915 /* bits 13..12 for 0x2a */
12916 MADD_ACC = 0x0,
12917 MADDU_ACC = 0x1,
12918 MSUB_ACC = 0x2,
12919 MSUBU_ACC = 0x3,
12921 /* bits 13..12 for 0x32 */
12922 MULT_ACC = 0x0,
12923 MULTU_ACC = 0x1,
12925 /* end of microMIPS32 DSP */
12927 /* bits 15..12 for 0x2c */
12928 BITSWAP = 0x0,
12929 SEB = 0x2,
12930 SEH = 0x3,
12931 CLO = 0x4,
12932 CLZ = 0x5,
12933 RDHWR = 0x6,
12934 WSBH = 0x7,
12935 MULT = 0x8,
12936 MULTU = 0x9,
12937 DIV = 0xa,
12938 DIVU = 0xb,
12939 MADD = 0xc,
12940 MADDU = 0xd,
12941 MSUB = 0xe,
12942 MSUBU = 0xf,
12944 /* bits 15..12 for 0x34 */
12945 MFC2 = 0x4,
12946 MTC2 = 0x5,
12947 MFHC2 = 0x8,
12948 MTHC2 = 0x9,
12949 CFC2 = 0xc,
12950 CTC2 = 0xd,
12952 /* bits 15..12 for 0x3c */
12953 JALR = 0x0,
12954 JR = 0x0, /* alias */
12955 JALRC = 0x0,
12956 JRC = 0x0,
12957 JALR_HB = 0x1,
12958 JALRC_HB = 0x1,
12959 JALRS = 0x4,
12960 JALRS_HB = 0x5,
12962 /* bits 15..12 for 0x05 */
12963 RDPGPR = 0xe,
12964 WRPGPR = 0xf,
12966 /* bits 15..12 for 0x0d */
12967 TLBP = 0x0,
12968 TLBR = 0x1,
12969 TLBWI = 0x2,
12970 TLBWR = 0x3,
12971 TLBINV = 0x4,
12972 TLBINVF = 0x5,
12973 WAIT = 0x9,
12974 IRET = 0xd,
12975 DERET = 0xe,
12976 ERET = 0xf,
12978 /* bits 15..12 for 0x15 */
12979 DMT = 0x0,
12980 DVPE = 0x1,
12981 EMT = 0x2,
12982 EVPE = 0x3,
12984 /* bits 15..12 for 0x1d */
12985 DI = 0x4,
12986 EI = 0x5,
12988 /* bits 15..12 for 0x2d */
12989 SYNC = 0x6,
12990 SYSCALL = 0x8,
12991 SDBBP = 0xd,
12993 /* bits 15..12 for 0x35 */
12994 MFHI32 = 0x0,
12995 MFLO32 = 0x1,
12996 MTHI32 = 0x2,
12997 MTLO32 = 0x3,
13000 /* POOL32B encoding of minor opcode field (bits 15..12) */
13002 enum {
13003 LWC2 = 0x0,
13004 LWP = 0x1,
13005 LDP = 0x4,
13006 LWM32 = 0x5,
13007 CACHE = 0x6,
13008 LDM = 0x7,
13009 SWC2 = 0x8,
13010 SWP = 0x9,
13011 SDP = 0xc,
13012 SWM32 = 0xd,
13013 SDM = 0xf
13016 /* POOL32C encoding of minor opcode field (bits 15..12) */
13018 enum {
13019 LWL = 0x0,
13020 SWL = 0x8,
13021 LWR = 0x1,
13022 SWR = 0x9,
13023 PREF = 0x2,
13024 ST_EVA = 0xa,
13025 LL = 0x3,
13026 SC = 0xb,
13027 LDL = 0x4,
13028 SDL = 0xc,
13029 LDR = 0x5,
13030 SDR = 0xd,
13031 LD_EVA = 0x6,
13032 LWU = 0xe,
13033 LLD = 0x7,
13034 SCD = 0xf
13037 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13039 enum {
13040 LBUE = 0x0,
13041 LHUE = 0x1,
13042 LWLE = 0x2,
13043 LWRE = 0x3,
13044 LBE = 0x4,
13045 LHE = 0x5,
13046 LLE = 0x6,
13047 LWE = 0x7,
13050 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13052 enum {
13053 SWLE = 0x0,
13054 SWRE = 0x1,
13055 PREFE = 0x2,
13056 CACHEE = 0x3,
13057 SBE = 0x4,
13058 SHE = 0x5,
13059 SCE = 0x6,
13060 SWE = 0x7,
13063 /* POOL32F encoding of minor opcode field (bits 5..0) */
13065 enum {
13066 /* These are the bit 7..6 values */
13067 ADD_FMT = 0x0,
13069 SUB_FMT = 0x1,
13071 MUL_FMT = 0x2,
13073 DIV_FMT = 0x3,
13075 /* These are the bit 8..6 values */
13076 MOVN_FMT = 0x0,
13077 RSQRT2_FMT = 0x0,
13078 MOVF_FMT = 0x0,
13079 RINT_FMT = 0x0,
13080 SELNEZ_FMT = 0x0,
13082 MOVZ_FMT = 0x1,
13083 LWXC1 = 0x1,
13084 MOVT_FMT = 0x1,
13085 CLASS_FMT = 0x1,
13086 SELEQZ_FMT = 0x1,
13088 PLL_PS = 0x2,
13089 SWXC1 = 0x2,
13090 SEL_FMT = 0x2,
13092 PLU_PS = 0x3,
13093 LDXC1 = 0x3,
13095 MOVN_FMT_04 = 0x4,
13096 PUL_PS = 0x4,
13097 SDXC1 = 0x4,
13098 RECIP2_FMT = 0x4,
13100 MOVZ_FMT_05 = 0x05,
13101 PUU_PS = 0x5,
13102 LUXC1 = 0x5,
13104 CVT_PS_S = 0x6,
13105 SUXC1 = 0x6,
13106 ADDR_PS = 0x6,
13107 PREFX = 0x6,
13108 MADDF_FMT = 0x6,
13110 MULR_PS = 0x7,
13111 MSUBF_FMT = 0x7,
13113 MADD_S = 0x01,
13114 MADD_D = 0x09,
13115 MADD_PS = 0x11,
13116 ALNV_PS = 0x19,
13117 MSUB_S = 0x21,
13118 MSUB_D = 0x29,
13119 MSUB_PS = 0x31,
13121 NMADD_S = 0x02,
13122 NMADD_D = 0x0a,
13123 NMADD_PS = 0x12,
13124 NMSUB_S = 0x22,
13125 NMSUB_D = 0x2a,
13126 NMSUB_PS = 0x32,
13128 MIN_FMT = 0x3,
13129 MAX_FMT = 0xb,
13130 MINA_FMT = 0x23,
13131 MAXA_FMT = 0x2b,
13132 POOL32FXF = 0x3b,
13134 CABS_COND_FMT = 0x1c, /* MIPS3D */
13135 C_COND_FMT = 0x3c,
13137 CMP_CONDN_S = 0x5,
13138 CMP_CONDN_D = 0x15
13141 /* POOL32Fxf encoding of minor opcode extension field */
13143 enum {
13144 CVT_L = 0x04,
13145 RSQRT_FMT = 0x08,
13146 FLOOR_L = 0x0c,
13147 CVT_PW_PS = 0x1c,
13148 CVT_W = 0x24,
13149 SQRT_FMT = 0x28,
13150 FLOOR_W = 0x2c,
13151 CVT_PS_PW = 0x3c,
13152 CFC1 = 0x40,
13153 RECIP_FMT = 0x48,
13154 CEIL_L = 0x4c,
13155 CTC1 = 0x60,
13156 CEIL_W = 0x6c,
13157 MFC1 = 0x80,
13158 CVT_S_PL = 0x84,
13159 TRUNC_L = 0x8c,
13160 MTC1 = 0xa0,
13161 CVT_S_PU = 0xa4,
13162 TRUNC_W = 0xac,
13163 MFHC1 = 0xc0,
13164 ROUND_L = 0xcc,
13165 MTHC1 = 0xe0,
13166 ROUND_W = 0xec,
13168 MOV_FMT = 0x01,
13169 MOVF = 0x05,
13170 ABS_FMT = 0x0d,
13171 RSQRT1_FMT = 0x1d,
13172 MOVT = 0x25,
13173 NEG_FMT = 0x2d,
13174 CVT_D = 0x4d,
13175 RECIP1_FMT = 0x5d,
13176 CVT_S = 0x6d
13179 /* POOL32I encoding of minor opcode field (bits 25..21) */
13181 enum {
13182 BLTZ = 0x00,
13183 BLTZAL = 0x01,
13184 BGEZ = 0x02,
13185 BGEZAL = 0x03,
13186 BLEZ = 0x04,
13187 BNEZC = 0x05,
13188 BGTZ = 0x06,
13189 BEQZC = 0x07,
13190 TLTI = 0x08,
13191 BC1EQZC = 0x08,
13192 TGEI = 0x09,
13193 BC1NEZC = 0x09,
13194 TLTIU = 0x0a,
13195 BC2EQZC = 0x0a,
13196 TGEIU = 0x0b,
13197 BC2NEZC = 0x0a,
13198 TNEI = 0x0c,
13199 R6_SYNCI = 0x0c,
13200 LUI = 0x0d,
13201 TEQI = 0x0e,
13202 SYNCI = 0x10,
13203 BLTZALS = 0x11,
13204 BGEZALS = 0x13,
13205 BC2F = 0x14,
13206 BC2T = 0x15,
13207 BPOSGE64 = 0x1a,
13208 BPOSGE32 = 0x1b,
13209 /* These overlap and are distinguished by bit16 of the instruction */
13210 BC1F = 0x1c,
13211 BC1T = 0x1d,
13212 BC1ANY2F = 0x1c,
13213 BC1ANY2T = 0x1d,
13214 BC1ANY4F = 0x1e,
13215 BC1ANY4T = 0x1f
13218 /* POOL16A encoding of minor opcode field */
13220 enum {
13221 ADDU16 = 0x0,
13222 SUBU16 = 0x1
13225 /* POOL16B encoding of minor opcode field */
13227 enum {
13228 SLL16 = 0x0,
13229 SRL16 = 0x1
13232 /* POOL16C encoding of minor opcode field */
13234 enum {
13235 NOT16 = 0x00,
13236 XOR16 = 0x04,
13237 AND16 = 0x08,
13238 OR16 = 0x0c,
13239 LWM16 = 0x10,
13240 SWM16 = 0x14,
13241 JR16 = 0x18,
13242 JRC16 = 0x1a,
13243 JALR16 = 0x1c,
13244 JALR16S = 0x1e,
13245 MFHI16 = 0x20,
13246 MFLO16 = 0x24,
13247 BREAK16 = 0x28,
13248 SDBBP16 = 0x2c,
13249 JRADDIUSP = 0x30
13252 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
13254 enum {
13255 R6_NOT16 = 0x00,
13256 R6_AND16 = 0x01,
13257 R6_LWM16 = 0x02,
13258 R6_JRC16 = 0x03,
13259 MOVEP = 0x04,
13260 MOVEP_05 = 0x05,
13261 MOVEP_06 = 0x06,
13262 MOVEP_07 = 0x07,
13263 R6_XOR16 = 0x08,
13264 R6_OR16 = 0x09,
13265 R6_SWM16 = 0x0a,
13266 JALRC16 = 0x0b,
13267 MOVEP_0C = 0x0c,
13268 MOVEP_0D = 0x0d,
13269 MOVEP_0E = 0x0e,
13270 MOVEP_0F = 0x0f,
13271 JRCADDIUSP = 0x13,
13272 R6_BREAK16 = 0x1b,
13273 R6_SDBBP16 = 0x3b
13276 /* POOL16D encoding of minor opcode field */
13278 enum {
13279 ADDIUS5 = 0x0,
13280 ADDIUSP = 0x1
13283 /* POOL16E encoding of minor opcode field */
13285 enum {
13286 ADDIUR2 = 0x0,
13287 ADDIUR1SP = 0x1
13290 static int mmreg (int r)
13292 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13294 return map[r];
13297 /* Used for 16-bit store instructions. */
13298 static int mmreg2 (int r)
13300 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
13302 return map[r];
13305 #define uMIPS_RD(op) ((op >> 7) & 0x7)
13306 #define uMIPS_RS(op) ((op >> 4) & 0x7)
13307 #define uMIPS_RS2(op) uMIPS_RS(op)
13308 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
13309 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
13310 #define uMIPS_RS5(op) (op & 0x1f)
13312 /* Signed immediate */
13313 #define SIMM(op, start, width) \
13314 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
13315 << (32-width)) \
13316 >> (32-width))
13317 /* Zero-extended immediate */
13318 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
13320 static void gen_addiur1sp(DisasContext *ctx)
13322 int rd = mmreg(uMIPS_RD(ctx->opcode));
13324 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
13327 static void gen_addiur2(DisasContext *ctx)
13329 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
13330 int rd = mmreg(uMIPS_RD(ctx->opcode));
13331 int rs = mmreg(uMIPS_RS(ctx->opcode));
13333 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
13336 static void gen_addiusp(DisasContext *ctx)
13338 int encoded = ZIMM(ctx->opcode, 1, 9);
13339 int decoded;
13341 if (encoded <= 1) {
13342 decoded = 256 + encoded;
13343 } else if (encoded <= 255) {
13344 decoded = encoded;
13345 } else if (encoded <= 509) {
13346 decoded = encoded - 512;
13347 } else {
13348 decoded = encoded - 768;
13351 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
13354 static void gen_addius5(DisasContext *ctx)
13356 int imm = SIMM(ctx->opcode, 1, 4);
13357 int rd = (ctx->opcode >> 5) & 0x1f;
13359 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
13362 static void gen_andi16(DisasContext *ctx)
13364 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
13365 31, 32, 63, 64, 255, 32768, 65535 };
13366 int rd = mmreg(uMIPS_RD(ctx->opcode));
13367 int rs = mmreg(uMIPS_RS(ctx->opcode));
13368 int encoded = ZIMM(ctx->opcode, 0, 4);
13370 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
13373 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
13374 int base, int16_t offset)
13376 TCGv t0, t1;
13377 TCGv_i32 t2;
13379 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13380 generate_exception_end(ctx, EXCP_RI);
13381 return;
13384 t0 = tcg_temp_new();
13386 gen_base_offset_addr(ctx, t0, base, offset);
13388 t1 = tcg_const_tl(reglist);
13389 t2 = tcg_const_i32(ctx->mem_idx);
13391 save_cpu_state(ctx, 1);
13392 switch (opc) {
13393 case LWM32:
13394 gen_helper_lwm(cpu_env, t0, t1, t2);
13395 break;
13396 case SWM32:
13397 gen_helper_swm(cpu_env, t0, t1, t2);
13398 break;
13399 #ifdef TARGET_MIPS64
13400 case LDM:
13401 gen_helper_ldm(cpu_env, t0, t1, t2);
13402 break;
13403 case SDM:
13404 gen_helper_sdm(cpu_env, t0, t1, t2);
13405 break;
13406 #endif
13408 tcg_temp_free(t0);
13409 tcg_temp_free(t1);
13410 tcg_temp_free_i32(t2);
13414 static void gen_pool16c_insn(DisasContext *ctx)
13416 int rd = mmreg((ctx->opcode >> 3) & 0x7);
13417 int rs = mmreg(ctx->opcode & 0x7);
13419 switch (((ctx->opcode) >> 4) & 0x3f) {
13420 case NOT16 + 0:
13421 case NOT16 + 1:
13422 case NOT16 + 2:
13423 case NOT16 + 3:
13424 gen_logic(ctx, OPC_NOR, rd, rs, 0);
13425 break;
13426 case XOR16 + 0:
13427 case XOR16 + 1:
13428 case XOR16 + 2:
13429 case XOR16 + 3:
13430 gen_logic(ctx, OPC_XOR, rd, rd, rs);
13431 break;
13432 case AND16 + 0:
13433 case AND16 + 1:
13434 case AND16 + 2:
13435 case AND16 + 3:
13436 gen_logic(ctx, OPC_AND, rd, rd, rs);
13437 break;
13438 case OR16 + 0:
13439 case OR16 + 1:
13440 case OR16 + 2:
13441 case OR16 + 3:
13442 gen_logic(ctx, OPC_OR, rd, rd, rs);
13443 break;
13444 case LWM16 + 0:
13445 case LWM16 + 1:
13446 case LWM16 + 2:
13447 case LWM16 + 3:
13449 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13450 int offset = ZIMM(ctx->opcode, 0, 4);
13452 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13453 29, offset << 2);
13455 break;
13456 case SWM16 + 0:
13457 case SWM16 + 1:
13458 case SWM16 + 2:
13459 case SWM16 + 3:
13461 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13462 int offset = ZIMM(ctx->opcode, 0, 4);
13464 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13465 29, offset << 2);
13467 break;
13468 case JR16 + 0:
13469 case JR16 + 1:
13471 int reg = ctx->opcode & 0x1f;
13473 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
13475 break;
13476 case JRC16 + 0:
13477 case JRC16 + 1:
13479 int reg = ctx->opcode & 0x1f;
13480 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
13481 /* Let normal delay slot handling in our caller take us
13482 to the branch target. */
13484 break;
13485 case JALR16 + 0:
13486 case JALR16 + 1:
13487 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13488 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13489 break;
13490 case JALR16S + 0:
13491 case JALR16S + 1:
13492 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13493 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13494 break;
13495 case MFHI16 + 0:
13496 case MFHI16 + 1:
13497 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
13498 break;
13499 case MFLO16 + 0:
13500 case MFLO16 + 1:
13501 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
13502 break;
13503 case BREAK16:
13504 generate_exception_end(ctx, EXCP_BREAK);
13505 break;
13506 case SDBBP16:
13507 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13508 gen_helper_do_semihosting(cpu_env);
13509 } else {
13510 /* XXX: not clear which exception should be raised
13511 * when in debug mode...
13513 check_insn(ctx, ISA_MIPS32);
13514 generate_exception_end(ctx, EXCP_DBp);
13516 break;
13517 case JRADDIUSP + 0:
13518 case JRADDIUSP + 1:
13520 int imm = ZIMM(ctx->opcode, 0, 5);
13521 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13522 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13523 /* Let normal delay slot handling in our caller take us
13524 to the branch target. */
13526 break;
13527 default:
13528 generate_exception_end(ctx, EXCP_RI);
13529 break;
13533 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13534 int enc_rs)
13536 int rd, rs, re, rt;
13537 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13538 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13539 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13540 rd = rd_enc[enc_dest];
13541 re = re_enc[enc_dest];
13542 rs = rs_rt_enc[enc_rs];
13543 rt = rs_rt_enc[enc_rt];
13544 if (rs) {
13545 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13546 } else {
13547 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13549 if (rt) {
13550 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13551 } else {
13552 tcg_gen_movi_tl(cpu_gpr[re], 0);
13556 static void gen_pool16c_r6_insn(DisasContext *ctx)
13558 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13559 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13561 switch (ctx->opcode & 0xf) {
13562 case R6_NOT16:
13563 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13564 break;
13565 case R6_AND16:
13566 gen_logic(ctx, OPC_AND, rt, rt, rs);
13567 break;
13568 case R6_LWM16:
13570 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13571 int offset = extract32(ctx->opcode, 4, 4);
13572 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13574 break;
13575 case R6_JRC16: /* JRCADDIUSP */
13576 if ((ctx->opcode >> 4) & 1) {
13577 /* JRCADDIUSP */
13578 int imm = extract32(ctx->opcode, 5, 5);
13579 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13580 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13581 } else {
13582 /* JRC16 */
13583 rs = extract32(ctx->opcode, 5, 5);
13584 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13586 break;
13587 case MOVEP:
13588 case MOVEP_05:
13589 case MOVEP_06:
13590 case MOVEP_07:
13591 case MOVEP_0C:
13592 case MOVEP_0D:
13593 case MOVEP_0E:
13594 case MOVEP_0F:
13596 int enc_dest = uMIPS_RD(ctx->opcode);
13597 int enc_rt = uMIPS_RS2(ctx->opcode);
13598 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13599 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13601 break;
13602 case R6_XOR16:
13603 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13604 break;
13605 case R6_OR16:
13606 gen_logic(ctx, OPC_OR, rt, rt, rs);
13607 break;
13608 case R6_SWM16:
13610 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13611 int offset = extract32(ctx->opcode, 4, 4);
13612 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13614 break;
13615 case JALRC16: /* BREAK16, SDBBP16 */
13616 switch (ctx->opcode & 0x3f) {
13617 case JALRC16:
13618 case JALRC16 + 0x20:
13619 /* JALRC16 */
13620 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13621 31, 0, 0);
13622 break;
13623 case R6_BREAK16:
13624 /* BREAK16 */
13625 generate_exception(ctx, EXCP_BREAK);
13626 break;
13627 case R6_SDBBP16:
13628 /* SDBBP16 */
13629 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13630 gen_helper_do_semihosting(cpu_env);
13631 } else {
13632 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13633 generate_exception(ctx, EXCP_RI);
13634 } else {
13635 generate_exception(ctx, EXCP_DBp);
13638 break;
13640 break;
13641 default:
13642 generate_exception(ctx, EXCP_RI);
13643 break;
13647 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13649 TCGv t0 = tcg_temp_new();
13650 TCGv t1 = tcg_temp_new();
13652 gen_load_gpr(t0, base);
13654 if (index != 0) {
13655 gen_load_gpr(t1, index);
13656 tcg_gen_shli_tl(t1, t1, 2);
13657 gen_op_addr_add(ctx, t0, t1, t0);
13660 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13661 gen_store_gpr(t1, rd);
13663 tcg_temp_free(t0);
13664 tcg_temp_free(t1);
13667 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13668 int base, int16_t offset)
13670 TCGv t0, t1;
13672 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13673 generate_exception_end(ctx, EXCP_RI);
13674 return;
13677 t0 = tcg_temp_new();
13678 t1 = tcg_temp_new();
13680 gen_base_offset_addr(ctx, t0, base, offset);
13682 switch (opc) {
13683 case LWP:
13684 if (rd == base) {
13685 generate_exception_end(ctx, EXCP_RI);
13686 return;
13688 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13689 gen_store_gpr(t1, rd);
13690 tcg_gen_movi_tl(t1, 4);
13691 gen_op_addr_add(ctx, t0, t0, t1);
13692 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13693 gen_store_gpr(t1, rd+1);
13694 break;
13695 case SWP:
13696 gen_load_gpr(t1, rd);
13697 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13698 tcg_gen_movi_tl(t1, 4);
13699 gen_op_addr_add(ctx, t0, t0, t1);
13700 gen_load_gpr(t1, rd+1);
13701 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13702 break;
13703 #ifdef TARGET_MIPS64
13704 case LDP:
13705 if (rd == base) {
13706 generate_exception_end(ctx, EXCP_RI);
13707 return;
13709 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13710 gen_store_gpr(t1, rd);
13711 tcg_gen_movi_tl(t1, 8);
13712 gen_op_addr_add(ctx, t0, t0, t1);
13713 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13714 gen_store_gpr(t1, rd+1);
13715 break;
13716 case SDP:
13717 gen_load_gpr(t1, rd);
13718 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13719 tcg_gen_movi_tl(t1, 8);
13720 gen_op_addr_add(ctx, t0, t0, t1);
13721 gen_load_gpr(t1, rd+1);
13722 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13723 break;
13724 #endif
13726 tcg_temp_free(t0);
13727 tcg_temp_free(t1);
13730 static void gen_sync(int stype)
13732 TCGBar tcg_mo = TCG_BAR_SC;
13734 switch (stype) {
13735 case 0x4: /* SYNC_WMB */
13736 tcg_mo |= TCG_MO_ST_ST;
13737 break;
13738 case 0x10: /* SYNC_MB */
13739 tcg_mo |= TCG_MO_ALL;
13740 break;
13741 case 0x11: /* SYNC_ACQUIRE */
13742 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
13743 break;
13744 case 0x12: /* SYNC_RELEASE */
13745 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
13746 break;
13747 case 0x13: /* SYNC_RMB */
13748 tcg_mo |= TCG_MO_LD_LD;
13749 break;
13750 default:
13751 tcg_mo |= TCG_MO_ALL;
13752 break;
13755 tcg_gen_mb(tcg_mo);
13758 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13760 int extension = (ctx->opcode >> 6) & 0x3f;
13761 int minor = (ctx->opcode >> 12) & 0xf;
13762 uint32_t mips32_op;
13764 switch (extension) {
13765 case TEQ:
13766 mips32_op = OPC_TEQ;
13767 goto do_trap;
13768 case TGE:
13769 mips32_op = OPC_TGE;
13770 goto do_trap;
13771 case TGEU:
13772 mips32_op = OPC_TGEU;
13773 goto do_trap;
13774 case TLT:
13775 mips32_op = OPC_TLT;
13776 goto do_trap;
13777 case TLTU:
13778 mips32_op = OPC_TLTU;
13779 goto do_trap;
13780 case TNE:
13781 mips32_op = OPC_TNE;
13782 do_trap:
13783 gen_trap(ctx, mips32_op, rs, rt, -1);
13784 break;
13785 #ifndef CONFIG_USER_ONLY
13786 case MFC0:
13787 case MFC0 + 32:
13788 check_cp0_enabled(ctx);
13789 if (rt == 0) {
13790 /* Treat as NOP. */
13791 break;
13793 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13794 break;
13795 case MTC0:
13796 case MTC0 + 32:
13797 check_cp0_enabled(ctx);
13799 TCGv t0 = tcg_temp_new();
13801 gen_load_gpr(t0, rt);
13802 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13803 tcg_temp_free(t0);
13805 break;
13806 #endif
13807 case 0x2a:
13808 switch (minor & 3) {
13809 case MADD_ACC:
13810 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13811 break;
13812 case MADDU_ACC:
13813 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13814 break;
13815 case MSUB_ACC:
13816 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13817 break;
13818 case MSUBU_ACC:
13819 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13820 break;
13821 default:
13822 goto pool32axf_invalid;
13824 break;
13825 case 0x32:
13826 switch (minor & 3) {
13827 case MULT_ACC:
13828 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13829 break;
13830 case MULTU_ACC:
13831 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13832 break;
13833 default:
13834 goto pool32axf_invalid;
13836 break;
13837 case 0x2c:
13838 switch (minor) {
13839 case BITSWAP:
13840 check_insn(ctx, ISA_MIPS32R6);
13841 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13842 break;
13843 case SEB:
13844 gen_bshfl(ctx, OPC_SEB, rs, rt);
13845 break;
13846 case SEH:
13847 gen_bshfl(ctx, OPC_SEH, rs, rt);
13848 break;
13849 case CLO:
13850 mips32_op = OPC_CLO;
13851 goto do_cl;
13852 case CLZ:
13853 mips32_op = OPC_CLZ;
13854 do_cl:
13855 check_insn(ctx, ISA_MIPS32);
13856 gen_cl(ctx, mips32_op, rt, rs);
13857 break;
13858 case RDHWR:
13859 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13860 gen_rdhwr(ctx, rt, rs, 0);
13861 break;
13862 case WSBH:
13863 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13864 break;
13865 case MULT:
13866 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13867 mips32_op = OPC_MULT;
13868 goto do_mul;
13869 case MULTU:
13870 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13871 mips32_op = OPC_MULTU;
13872 goto do_mul;
13873 case DIV:
13874 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13875 mips32_op = OPC_DIV;
13876 goto do_div;
13877 case DIVU:
13878 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13879 mips32_op = OPC_DIVU;
13880 goto do_div;
13881 do_div:
13882 check_insn(ctx, ISA_MIPS32);
13883 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13884 break;
13885 case MADD:
13886 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13887 mips32_op = OPC_MADD;
13888 goto do_mul;
13889 case MADDU:
13890 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13891 mips32_op = OPC_MADDU;
13892 goto do_mul;
13893 case MSUB:
13894 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13895 mips32_op = OPC_MSUB;
13896 goto do_mul;
13897 case MSUBU:
13898 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13899 mips32_op = OPC_MSUBU;
13900 do_mul:
13901 check_insn(ctx, ISA_MIPS32);
13902 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13903 break;
13904 default:
13905 goto pool32axf_invalid;
13907 break;
13908 case 0x34:
13909 switch (minor) {
13910 case MFC2:
13911 case MTC2:
13912 case MFHC2:
13913 case MTHC2:
13914 case CFC2:
13915 case CTC2:
13916 generate_exception_err(ctx, EXCP_CpU, 2);
13917 break;
13918 default:
13919 goto pool32axf_invalid;
13921 break;
13922 case 0x3c:
13923 switch (minor) {
13924 case JALR: /* JALRC */
13925 case JALR_HB: /* JALRC_HB */
13926 if (ctx->insn_flags & ISA_MIPS32R6) {
13927 /* JALRC, JALRC_HB */
13928 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13929 } else {
13930 /* JALR, JALR_HB */
13931 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13932 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13934 break;
13935 case JALRS:
13936 case JALRS_HB:
13937 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13938 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13939 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13940 break;
13941 default:
13942 goto pool32axf_invalid;
13944 break;
13945 case 0x05:
13946 switch (minor) {
13947 case RDPGPR:
13948 check_cp0_enabled(ctx);
13949 check_insn(ctx, ISA_MIPS32R2);
13950 gen_load_srsgpr(rs, rt);
13951 break;
13952 case WRPGPR:
13953 check_cp0_enabled(ctx);
13954 check_insn(ctx, ISA_MIPS32R2);
13955 gen_store_srsgpr(rs, rt);
13956 break;
13957 default:
13958 goto pool32axf_invalid;
13960 break;
13961 #ifndef CONFIG_USER_ONLY
13962 case 0x0d:
13963 switch (minor) {
13964 case TLBP:
13965 mips32_op = OPC_TLBP;
13966 goto do_cp0;
13967 case TLBR:
13968 mips32_op = OPC_TLBR;
13969 goto do_cp0;
13970 case TLBWI:
13971 mips32_op = OPC_TLBWI;
13972 goto do_cp0;
13973 case TLBWR:
13974 mips32_op = OPC_TLBWR;
13975 goto do_cp0;
13976 case TLBINV:
13977 mips32_op = OPC_TLBINV;
13978 goto do_cp0;
13979 case TLBINVF:
13980 mips32_op = OPC_TLBINVF;
13981 goto do_cp0;
13982 case WAIT:
13983 mips32_op = OPC_WAIT;
13984 goto do_cp0;
13985 case DERET:
13986 mips32_op = OPC_DERET;
13987 goto do_cp0;
13988 case ERET:
13989 mips32_op = OPC_ERET;
13990 do_cp0:
13991 gen_cp0(env, ctx, mips32_op, rt, rs);
13992 break;
13993 default:
13994 goto pool32axf_invalid;
13996 break;
13997 case 0x1d:
13998 switch (minor) {
13999 case DI:
14000 check_cp0_enabled(ctx);
14002 TCGv t0 = tcg_temp_new();
14004 save_cpu_state(ctx, 1);
14005 gen_helper_di(t0, cpu_env);
14006 gen_store_gpr(t0, rs);
14007 /* Stop translation as we may have switched the execution mode */
14008 ctx->base.is_jmp = DISAS_STOP;
14009 tcg_temp_free(t0);
14011 break;
14012 case EI:
14013 check_cp0_enabled(ctx);
14015 TCGv t0 = tcg_temp_new();
14017 save_cpu_state(ctx, 1);
14018 gen_helper_ei(t0, cpu_env);
14019 gen_store_gpr(t0, rs);
14020 /* DISAS_STOP isn't sufficient, we need to ensure we break out
14021 of translated code to check for pending interrupts. */
14022 gen_save_pc(ctx->base.pc_next + 4);
14023 ctx->base.is_jmp = DISAS_EXIT;
14024 tcg_temp_free(t0);
14026 break;
14027 default:
14028 goto pool32axf_invalid;
14030 break;
14031 #endif
14032 case 0x2d:
14033 switch (minor) {
14034 case SYNC:
14035 gen_sync(extract32(ctx->opcode, 16, 5));
14036 break;
14037 case SYSCALL:
14038 generate_exception_end(ctx, EXCP_SYSCALL);
14039 break;
14040 case SDBBP:
14041 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14042 gen_helper_do_semihosting(cpu_env);
14043 } else {
14044 check_insn(ctx, ISA_MIPS32);
14045 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14046 generate_exception_end(ctx, EXCP_RI);
14047 } else {
14048 generate_exception_end(ctx, EXCP_DBp);
14051 break;
14052 default:
14053 goto pool32axf_invalid;
14055 break;
14056 case 0x01:
14057 switch (minor & 3) {
14058 case MFHI_ACC:
14059 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14060 break;
14061 case MFLO_ACC:
14062 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14063 break;
14064 case MTHI_ACC:
14065 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14066 break;
14067 case MTLO_ACC:
14068 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14069 break;
14070 default:
14071 goto pool32axf_invalid;
14073 break;
14074 case 0x35:
14075 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14076 switch (minor) {
14077 case MFHI32:
14078 gen_HILO(ctx, OPC_MFHI, 0, rs);
14079 break;
14080 case MFLO32:
14081 gen_HILO(ctx, OPC_MFLO, 0, rs);
14082 break;
14083 case MTHI32:
14084 gen_HILO(ctx, OPC_MTHI, 0, rs);
14085 break;
14086 case MTLO32:
14087 gen_HILO(ctx, OPC_MTLO, 0, rs);
14088 break;
14089 default:
14090 goto pool32axf_invalid;
14092 break;
14093 default:
14094 pool32axf_invalid:
14095 MIPS_INVAL("pool32axf");
14096 generate_exception_end(ctx, EXCP_RI);
14097 break;
14101 /* Values for microMIPS fmt field. Variable-width, depending on which
14102 formats the instruction supports. */
14104 enum {
14105 FMT_SD_S = 0,
14106 FMT_SD_D = 1,
14108 FMT_SDPS_S = 0,
14109 FMT_SDPS_D = 1,
14110 FMT_SDPS_PS = 2,
14112 FMT_SWL_S = 0,
14113 FMT_SWL_W = 1,
14114 FMT_SWL_L = 2,
14116 FMT_DWL_D = 0,
14117 FMT_DWL_W = 1,
14118 FMT_DWL_L = 2
14121 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
14123 int extension = (ctx->opcode >> 6) & 0x3ff;
14124 uint32_t mips32_op;
14126 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
14127 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
14128 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
14130 switch (extension) {
14131 case FLOAT_1BIT_FMT(CFC1, 0):
14132 mips32_op = OPC_CFC1;
14133 goto do_cp1;
14134 case FLOAT_1BIT_FMT(CTC1, 0):
14135 mips32_op = OPC_CTC1;
14136 goto do_cp1;
14137 case FLOAT_1BIT_FMT(MFC1, 0):
14138 mips32_op = OPC_MFC1;
14139 goto do_cp1;
14140 case FLOAT_1BIT_FMT(MTC1, 0):
14141 mips32_op = OPC_MTC1;
14142 goto do_cp1;
14143 case FLOAT_1BIT_FMT(MFHC1, 0):
14144 mips32_op = OPC_MFHC1;
14145 goto do_cp1;
14146 case FLOAT_1BIT_FMT(MTHC1, 0):
14147 mips32_op = OPC_MTHC1;
14148 do_cp1:
14149 gen_cp1(ctx, mips32_op, rt, rs);
14150 break;
14152 /* Reciprocal square root */
14153 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
14154 mips32_op = OPC_RSQRT_S;
14155 goto do_unaryfp;
14156 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
14157 mips32_op = OPC_RSQRT_D;
14158 goto do_unaryfp;
14160 /* Square root */
14161 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
14162 mips32_op = OPC_SQRT_S;
14163 goto do_unaryfp;
14164 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
14165 mips32_op = OPC_SQRT_D;
14166 goto do_unaryfp;
14168 /* Reciprocal */
14169 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
14170 mips32_op = OPC_RECIP_S;
14171 goto do_unaryfp;
14172 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
14173 mips32_op = OPC_RECIP_D;
14174 goto do_unaryfp;
14176 /* Floor */
14177 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
14178 mips32_op = OPC_FLOOR_L_S;
14179 goto do_unaryfp;
14180 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
14181 mips32_op = OPC_FLOOR_L_D;
14182 goto do_unaryfp;
14183 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
14184 mips32_op = OPC_FLOOR_W_S;
14185 goto do_unaryfp;
14186 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
14187 mips32_op = OPC_FLOOR_W_D;
14188 goto do_unaryfp;
14190 /* Ceiling */
14191 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
14192 mips32_op = OPC_CEIL_L_S;
14193 goto do_unaryfp;
14194 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
14195 mips32_op = OPC_CEIL_L_D;
14196 goto do_unaryfp;
14197 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
14198 mips32_op = OPC_CEIL_W_S;
14199 goto do_unaryfp;
14200 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
14201 mips32_op = OPC_CEIL_W_D;
14202 goto do_unaryfp;
14204 /* Truncation */
14205 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
14206 mips32_op = OPC_TRUNC_L_S;
14207 goto do_unaryfp;
14208 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
14209 mips32_op = OPC_TRUNC_L_D;
14210 goto do_unaryfp;
14211 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
14212 mips32_op = OPC_TRUNC_W_S;
14213 goto do_unaryfp;
14214 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
14215 mips32_op = OPC_TRUNC_W_D;
14216 goto do_unaryfp;
14218 /* Round */
14219 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
14220 mips32_op = OPC_ROUND_L_S;
14221 goto do_unaryfp;
14222 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
14223 mips32_op = OPC_ROUND_L_D;
14224 goto do_unaryfp;
14225 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
14226 mips32_op = OPC_ROUND_W_S;
14227 goto do_unaryfp;
14228 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
14229 mips32_op = OPC_ROUND_W_D;
14230 goto do_unaryfp;
14232 /* Integer to floating-point conversion */
14233 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
14234 mips32_op = OPC_CVT_L_S;
14235 goto do_unaryfp;
14236 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
14237 mips32_op = OPC_CVT_L_D;
14238 goto do_unaryfp;
14239 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
14240 mips32_op = OPC_CVT_W_S;
14241 goto do_unaryfp;
14242 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
14243 mips32_op = OPC_CVT_W_D;
14244 goto do_unaryfp;
14246 /* Paired-foo conversions */
14247 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
14248 mips32_op = OPC_CVT_S_PL;
14249 goto do_unaryfp;
14250 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
14251 mips32_op = OPC_CVT_S_PU;
14252 goto do_unaryfp;
14253 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
14254 mips32_op = OPC_CVT_PW_PS;
14255 goto do_unaryfp;
14256 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
14257 mips32_op = OPC_CVT_PS_PW;
14258 goto do_unaryfp;
14260 /* Floating-point moves */
14261 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
14262 mips32_op = OPC_MOV_S;
14263 goto do_unaryfp;
14264 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
14265 mips32_op = OPC_MOV_D;
14266 goto do_unaryfp;
14267 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
14268 mips32_op = OPC_MOV_PS;
14269 goto do_unaryfp;
14271 /* Absolute value */
14272 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
14273 mips32_op = OPC_ABS_S;
14274 goto do_unaryfp;
14275 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
14276 mips32_op = OPC_ABS_D;
14277 goto do_unaryfp;
14278 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
14279 mips32_op = OPC_ABS_PS;
14280 goto do_unaryfp;
14282 /* Negation */
14283 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
14284 mips32_op = OPC_NEG_S;
14285 goto do_unaryfp;
14286 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
14287 mips32_op = OPC_NEG_D;
14288 goto do_unaryfp;
14289 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
14290 mips32_op = OPC_NEG_PS;
14291 goto do_unaryfp;
14293 /* Reciprocal square root step */
14294 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
14295 mips32_op = OPC_RSQRT1_S;
14296 goto do_unaryfp;
14297 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
14298 mips32_op = OPC_RSQRT1_D;
14299 goto do_unaryfp;
14300 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
14301 mips32_op = OPC_RSQRT1_PS;
14302 goto do_unaryfp;
14304 /* Reciprocal step */
14305 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
14306 mips32_op = OPC_RECIP1_S;
14307 goto do_unaryfp;
14308 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
14309 mips32_op = OPC_RECIP1_S;
14310 goto do_unaryfp;
14311 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
14312 mips32_op = OPC_RECIP1_PS;
14313 goto do_unaryfp;
14315 /* Conversions from double */
14316 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
14317 mips32_op = OPC_CVT_D_S;
14318 goto do_unaryfp;
14319 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
14320 mips32_op = OPC_CVT_D_W;
14321 goto do_unaryfp;
14322 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
14323 mips32_op = OPC_CVT_D_L;
14324 goto do_unaryfp;
14326 /* Conversions from single */
14327 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
14328 mips32_op = OPC_CVT_S_D;
14329 goto do_unaryfp;
14330 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
14331 mips32_op = OPC_CVT_S_W;
14332 goto do_unaryfp;
14333 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
14334 mips32_op = OPC_CVT_S_L;
14335 do_unaryfp:
14336 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
14337 break;
14339 /* Conditional moves on floating-point codes */
14340 case COND_FLOAT_MOV(MOVT, 0):
14341 case COND_FLOAT_MOV(MOVT, 1):
14342 case COND_FLOAT_MOV(MOVT, 2):
14343 case COND_FLOAT_MOV(MOVT, 3):
14344 case COND_FLOAT_MOV(MOVT, 4):
14345 case COND_FLOAT_MOV(MOVT, 5):
14346 case COND_FLOAT_MOV(MOVT, 6):
14347 case COND_FLOAT_MOV(MOVT, 7):
14348 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14349 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
14350 break;
14351 case COND_FLOAT_MOV(MOVF, 0):
14352 case COND_FLOAT_MOV(MOVF, 1):
14353 case COND_FLOAT_MOV(MOVF, 2):
14354 case COND_FLOAT_MOV(MOVF, 3):
14355 case COND_FLOAT_MOV(MOVF, 4):
14356 case COND_FLOAT_MOV(MOVF, 5):
14357 case COND_FLOAT_MOV(MOVF, 6):
14358 case COND_FLOAT_MOV(MOVF, 7):
14359 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14360 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
14361 break;
14362 default:
14363 MIPS_INVAL("pool32fxf");
14364 generate_exception_end(ctx, EXCP_RI);
14365 break;
14369 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
14371 int32_t offset;
14372 uint16_t insn;
14373 int rt, rs, rd, rr;
14374 int16_t imm;
14375 uint32_t op, minor, minor2, mips32_op;
14376 uint32_t cond, fmt, cc;
14378 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
14379 ctx->opcode = (ctx->opcode << 16) | insn;
14381 rt = (ctx->opcode >> 21) & 0x1f;
14382 rs = (ctx->opcode >> 16) & 0x1f;
14383 rd = (ctx->opcode >> 11) & 0x1f;
14384 rr = (ctx->opcode >> 6) & 0x1f;
14385 imm = (int16_t) ctx->opcode;
14387 op = (ctx->opcode >> 26) & 0x3f;
14388 switch (op) {
14389 case POOL32A:
14390 minor = ctx->opcode & 0x3f;
14391 switch (minor) {
14392 case 0x00:
14393 minor = (ctx->opcode >> 6) & 0xf;
14394 switch (minor) {
14395 case SLL32:
14396 mips32_op = OPC_SLL;
14397 goto do_shifti;
14398 case SRA:
14399 mips32_op = OPC_SRA;
14400 goto do_shifti;
14401 case SRL32:
14402 mips32_op = OPC_SRL;
14403 goto do_shifti;
14404 case ROTR:
14405 mips32_op = OPC_ROTR;
14406 do_shifti:
14407 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
14408 break;
14409 case SELEQZ:
14410 check_insn(ctx, ISA_MIPS32R6);
14411 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
14412 break;
14413 case SELNEZ:
14414 check_insn(ctx, ISA_MIPS32R6);
14415 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
14416 break;
14417 case R6_RDHWR:
14418 check_insn(ctx, ISA_MIPS32R6);
14419 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
14420 break;
14421 default:
14422 goto pool32a_invalid;
14424 break;
14425 case 0x10:
14426 minor = (ctx->opcode >> 6) & 0xf;
14427 switch (minor) {
14428 /* Arithmetic */
14429 case ADD:
14430 mips32_op = OPC_ADD;
14431 goto do_arith;
14432 case ADDU32:
14433 mips32_op = OPC_ADDU;
14434 goto do_arith;
14435 case SUB:
14436 mips32_op = OPC_SUB;
14437 goto do_arith;
14438 case SUBU32:
14439 mips32_op = OPC_SUBU;
14440 goto do_arith;
14441 case MUL:
14442 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14443 mips32_op = OPC_MUL;
14444 do_arith:
14445 gen_arith(ctx, mips32_op, rd, rs, rt);
14446 break;
14447 /* Shifts */
14448 case SLLV:
14449 mips32_op = OPC_SLLV;
14450 goto do_shift;
14451 case SRLV:
14452 mips32_op = OPC_SRLV;
14453 goto do_shift;
14454 case SRAV:
14455 mips32_op = OPC_SRAV;
14456 goto do_shift;
14457 case ROTRV:
14458 mips32_op = OPC_ROTRV;
14459 do_shift:
14460 gen_shift(ctx, mips32_op, rd, rs, rt);
14461 break;
14462 /* Logical operations */
14463 case AND:
14464 mips32_op = OPC_AND;
14465 goto do_logic;
14466 case OR32:
14467 mips32_op = OPC_OR;
14468 goto do_logic;
14469 case NOR:
14470 mips32_op = OPC_NOR;
14471 goto do_logic;
14472 case XOR32:
14473 mips32_op = OPC_XOR;
14474 do_logic:
14475 gen_logic(ctx, mips32_op, rd, rs, rt);
14476 break;
14477 /* Set less than */
14478 case SLT:
14479 mips32_op = OPC_SLT;
14480 goto do_slt;
14481 case SLTU:
14482 mips32_op = OPC_SLTU;
14483 do_slt:
14484 gen_slt(ctx, mips32_op, rd, rs, rt);
14485 break;
14486 default:
14487 goto pool32a_invalid;
14489 break;
14490 case 0x18:
14491 minor = (ctx->opcode >> 6) & 0xf;
14492 switch (minor) {
14493 /* Conditional moves */
14494 case MOVN: /* MUL */
14495 if (ctx->insn_flags & ISA_MIPS32R6) {
14496 /* MUL */
14497 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14498 } else {
14499 /* MOVN */
14500 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14502 break;
14503 case MOVZ: /* MUH */
14504 if (ctx->insn_flags & ISA_MIPS32R6) {
14505 /* MUH */
14506 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14507 } else {
14508 /* MOVZ */
14509 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14511 break;
14512 case MULU:
14513 check_insn(ctx, ISA_MIPS32R6);
14514 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14515 break;
14516 case MUHU:
14517 check_insn(ctx, ISA_MIPS32R6);
14518 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14519 break;
14520 case LWXS: /* DIV */
14521 if (ctx->insn_flags & ISA_MIPS32R6) {
14522 /* DIV */
14523 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14524 } else {
14525 /* LWXS */
14526 gen_ldxs(ctx, rs, rt, rd);
14528 break;
14529 case MOD:
14530 check_insn(ctx, ISA_MIPS32R6);
14531 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14532 break;
14533 case R6_DIVU:
14534 check_insn(ctx, ISA_MIPS32R6);
14535 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
14536 break;
14537 case MODU:
14538 check_insn(ctx, ISA_MIPS32R6);
14539 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
14540 break;
14541 default:
14542 goto pool32a_invalid;
14544 break;
14545 case INS:
14546 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14547 return;
14548 case LSA:
14549 check_insn(ctx, ISA_MIPS32R6);
14550 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14551 extract32(ctx->opcode, 9, 2));
14552 break;
14553 case ALIGN:
14554 check_insn(ctx, ISA_MIPS32R6);
14555 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
14556 break;
14557 case EXT:
14558 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14559 return;
14560 case POOL32AXF:
14561 gen_pool32axf(env, ctx, rt, rs);
14562 break;
14563 case BREAK32:
14564 generate_exception_end(ctx, EXCP_BREAK);
14565 break;
14566 case SIGRIE:
14567 check_insn(ctx, ISA_MIPS32R6);
14568 generate_exception_end(ctx, EXCP_RI);
14569 break;
14570 default:
14571 pool32a_invalid:
14572 MIPS_INVAL("pool32a");
14573 generate_exception_end(ctx, EXCP_RI);
14574 break;
14576 break;
14577 case POOL32B:
14578 minor = (ctx->opcode >> 12) & 0xf;
14579 switch (minor) {
14580 case CACHE:
14581 check_cp0_enabled(ctx);
14582 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14583 gen_cache_operation(ctx, rt, rs, imm);
14585 break;
14586 case LWC2:
14587 case SWC2:
14588 /* COP2: Not implemented. */
14589 generate_exception_err(ctx, EXCP_CpU, 2);
14590 break;
14591 #ifdef TARGET_MIPS64
14592 case LDP:
14593 case SDP:
14594 check_insn(ctx, ISA_MIPS3);
14595 check_mips_64(ctx);
14596 #endif
14597 /* fall through */
14598 case LWP:
14599 case SWP:
14600 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14601 break;
14602 #ifdef TARGET_MIPS64
14603 case LDM:
14604 case SDM:
14605 check_insn(ctx, ISA_MIPS3);
14606 check_mips_64(ctx);
14607 #endif
14608 /* fall through */
14609 case LWM32:
14610 case SWM32:
14611 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14612 break;
14613 default:
14614 MIPS_INVAL("pool32b");
14615 generate_exception_end(ctx, EXCP_RI);
14616 break;
14618 break;
14619 case POOL32F:
14620 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14621 minor = ctx->opcode & 0x3f;
14622 check_cp1_enabled(ctx);
14623 switch (minor) {
14624 case ALNV_PS:
14625 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14626 mips32_op = OPC_ALNV_PS;
14627 goto do_madd;
14628 case MADD_S:
14629 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14630 mips32_op = OPC_MADD_S;
14631 goto do_madd;
14632 case MADD_D:
14633 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14634 mips32_op = OPC_MADD_D;
14635 goto do_madd;
14636 case MADD_PS:
14637 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14638 mips32_op = OPC_MADD_PS;
14639 goto do_madd;
14640 case MSUB_S:
14641 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14642 mips32_op = OPC_MSUB_S;
14643 goto do_madd;
14644 case MSUB_D:
14645 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14646 mips32_op = OPC_MSUB_D;
14647 goto do_madd;
14648 case MSUB_PS:
14649 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14650 mips32_op = OPC_MSUB_PS;
14651 goto do_madd;
14652 case NMADD_S:
14653 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14654 mips32_op = OPC_NMADD_S;
14655 goto do_madd;
14656 case NMADD_D:
14657 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14658 mips32_op = OPC_NMADD_D;
14659 goto do_madd;
14660 case NMADD_PS:
14661 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14662 mips32_op = OPC_NMADD_PS;
14663 goto do_madd;
14664 case NMSUB_S:
14665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14666 mips32_op = OPC_NMSUB_S;
14667 goto do_madd;
14668 case NMSUB_D:
14669 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14670 mips32_op = OPC_NMSUB_D;
14671 goto do_madd;
14672 case NMSUB_PS:
14673 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14674 mips32_op = OPC_NMSUB_PS;
14675 do_madd:
14676 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14677 break;
14678 case CABS_COND_FMT:
14679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14680 cond = (ctx->opcode >> 6) & 0xf;
14681 cc = (ctx->opcode >> 13) & 0x7;
14682 fmt = (ctx->opcode >> 10) & 0x3;
14683 switch (fmt) {
14684 case 0x0:
14685 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14686 break;
14687 case 0x1:
14688 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14689 break;
14690 case 0x2:
14691 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14692 break;
14693 default:
14694 goto pool32f_invalid;
14696 break;
14697 case C_COND_FMT:
14698 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14699 cond = (ctx->opcode >> 6) & 0xf;
14700 cc = (ctx->opcode >> 13) & 0x7;
14701 fmt = (ctx->opcode >> 10) & 0x3;
14702 switch (fmt) {
14703 case 0x0:
14704 gen_cmp_s(ctx, cond, rt, rs, cc);
14705 break;
14706 case 0x1:
14707 gen_cmp_d(ctx, cond, rt, rs, cc);
14708 break;
14709 case 0x2:
14710 gen_cmp_ps(ctx, cond, rt, rs, cc);
14711 break;
14712 default:
14713 goto pool32f_invalid;
14715 break;
14716 case CMP_CONDN_S:
14717 check_insn(ctx, ISA_MIPS32R6);
14718 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14719 break;
14720 case CMP_CONDN_D:
14721 check_insn(ctx, ISA_MIPS32R6);
14722 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14723 break;
14724 case POOL32FXF:
14725 gen_pool32fxf(ctx, rt, rs);
14726 break;
14727 case 0x00:
14728 /* PLL foo */
14729 switch ((ctx->opcode >> 6) & 0x7) {
14730 case PLL_PS:
14731 mips32_op = OPC_PLL_PS;
14732 goto do_ps;
14733 case PLU_PS:
14734 mips32_op = OPC_PLU_PS;
14735 goto do_ps;
14736 case PUL_PS:
14737 mips32_op = OPC_PUL_PS;
14738 goto do_ps;
14739 case PUU_PS:
14740 mips32_op = OPC_PUU_PS;
14741 goto do_ps;
14742 case CVT_PS_S:
14743 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14744 mips32_op = OPC_CVT_PS_S;
14745 do_ps:
14746 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14747 break;
14748 default:
14749 goto pool32f_invalid;
14751 break;
14752 case MIN_FMT:
14753 check_insn(ctx, ISA_MIPS32R6);
14754 switch ((ctx->opcode >> 9) & 0x3) {
14755 case FMT_SDPS_S:
14756 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14757 break;
14758 case FMT_SDPS_D:
14759 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14760 break;
14761 default:
14762 goto pool32f_invalid;
14764 break;
14765 case 0x08:
14766 /* [LS][WDU]XC1 */
14767 switch ((ctx->opcode >> 6) & 0x7) {
14768 case LWXC1:
14769 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14770 mips32_op = OPC_LWXC1;
14771 goto do_ldst_cp1;
14772 case SWXC1:
14773 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14774 mips32_op = OPC_SWXC1;
14775 goto do_ldst_cp1;
14776 case LDXC1:
14777 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14778 mips32_op = OPC_LDXC1;
14779 goto do_ldst_cp1;
14780 case SDXC1:
14781 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14782 mips32_op = OPC_SDXC1;
14783 goto do_ldst_cp1;
14784 case LUXC1:
14785 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14786 mips32_op = OPC_LUXC1;
14787 goto do_ldst_cp1;
14788 case SUXC1:
14789 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14790 mips32_op = OPC_SUXC1;
14791 do_ldst_cp1:
14792 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14793 break;
14794 default:
14795 goto pool32f_invalid;
14797 break;
14798 case MAX_FMT:
14799 check_insn(ctx, ISA_MIPS32R6);
14800 switch ((ctx->opcode >> 9) & 0x3) {
14801 case FMT_SDPS_S:
14802 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14803 break;
14804 case FMT_SDPS_D:
14805 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14806 break;
14807 default:
14808 goto pool32f_invalid;
14810 break;
14811 case 0x18:
14812 /* 3D insns */
14813 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14814 fmt = (ctx->opcode >> 9) & 0x3;
14815 switch ((ctx->opcode >> 6) & 0x7) {
14816 case RSQRT2_FMT:
14817 switch (fmt) {
14818 case FMT_SDPS_S:
14819 mips32_op = OPC_RSQRT2_S;
14820 goto do_3d;
14821 case FMT_SDPS_D:
14822 mips32_op = OPC_RSQRT2_D;
14823 goto do_3d;
14824 case FMT_SDPS_PS:
14825 mips32_op = OPC_RSQRT2_PS;
14826 goto do_3d;
14827 default:
14828 goto pool32f_invalid;
14830 break;
14831 case RECIP2_FMT:
14832 switch (fmt) {
14833 case FMT_SDPS_S:
14834 mips32_op = OPC_RECIP2_S;
14835 goto do_3d;
14836 case FMT_SDPS_D:
14837 mips32_op = OPC_RECIP2_D;
14838 goto do_3d;
14839 case FMT_SDPS_PS:
14840 mips32_op = OPC_RECIP2_PS;
14841 goto do_3d;
14842 default:
14843 goto pool32f_invalid;
14845 break;
14846 case ADDR_PS:
14847 mips32_op = OPC_ADDR_PS;
14848 goto do_3d;
14849 case MULR_PS:
14850 mips32_op = OPC_MULR_PS;
14851 do_3d:
14852 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14853 break;
14854 default:
14855 goto pool32f_invalid;
14857 break;
14858 case 0x20:
14859 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14860 cc = (ctx->opcode >> 13) & 0x7;
14861 fmt = (ctx->opcode >> 9) & 0x3;
14862 switch ((ctx->opcode >> 6) & 0x7) {
14863 case MOVF_FMT: /* RINT_FMT */
14864 if (ctx->insn_flags & ISA_MIPS32R6) {
14865 /* RINT_FMT */
14866 switch (fmt) {
14867 case FMT_SDPS_S:
14868 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14869 break;
14870 case FMT_SDPS_D:
14871 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14872 break;
14873 default:
14874 goto pool32f_invalid;
14876 } else {
14877 /* MOVF_FMT */
14878 switch (fmt) {
14879 case FMT_SDPS_S:
14880 gen_movcf_s(ctx, rs, rt, cc, 0);
14881 break;
14882 case FMT_SDPS_D:
14883 gen_movcf_d(ctx, rs, rt, cc, 0);
14884 break;
14885 case FMT_SDPS_PS:
14886 check_ps(ctx);
14887 gen_movcf_ps(ctx, rs, rt, cc, 0);
14888 break;
14889 default:
14890 goto pool32f_invalid;
14893 break;
14894 case MOVT_FMT: /* CLASS_FMT */
14895 if (ctx->insn_flags & ISA_MIPS32R6) {
14896 /* CLASS_FMT */
14897 switch (fmt) {
14898 case FMT_SDPS_S:
14899 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14900 break;
14901 case FMT_SDPS_D:
14902 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14903 break;
14904 default:
14905 goto pool32f_invalid;
14907 } else {
14908 /* MOVT_FMT */
14909 switch (fmt) {
14910 case FMT_SDPS_S:
14911 gen_movcf_s(ctx, rs, rt, cc, 1);
14912 break;
14913 case FMT_SDPS_D:
14914 gen_movcf_d(ctx, rs, rt, cc, 1);
14915 break;
14916 case FMT_SDPS_PS:
14917 check_ps(ctx);
14918 gen_movcf_ps(ctx, rs, rt, cc, 1);
14919 break;
14920 default:
14921 goto pool32f_invalid;
14924 break;
14925 case PREFX:
14926 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14927 break;
14928 default:
14929 goto pool32f_invalid;
14931 break;
14932 #define FINSN_3ARG_SDPS(prfx) \
14933 switch ((ctx->opcode >> 8) & 0x3) { \
14934 case FMT_SDPS_S: \
14935 mips32_op = OPC_##prfx##_S; \
14936 goto do_fpop; \
14937 case FMT_SDPS_D: \
14938 mips32_op = OPC_##prfx##_D; \
14939 goto do_fpop; \
14940 case FMT_SDPS_PS: \
14941 check_ps(ctx); \
14942 mips32_op = OPC_##prfx##_PS; \
14943 goto do_fpop; \
14944 default: \
14945 goto pool32f_invalid; \
14947 case MINA_FMT:
14948 check_insn(ctx, ISA_MIPS32R6);
14949 switch ((ctx->opcode >> 9) & 0x3) {
14950 case FMT_SDPS_S:
14951 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14952 break;
14953 case FMT_SDPS_D:
14954 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14955 break;
14956 default:
14957 goto pool32f_invalid;
14959 break;
14960 case MAXA_FMT:
14961 check_insn(ctx, ISA_MIPS32R6);
14962 switch ((ctx->opcode >> 9) & 0x3) {
14963 case FMT_SDPS_S:
14964 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14965 break;
14966 case FMT_SDPS_D:
14967 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14968 break;
14969 default:
14970 goto pool32f_invalid;
14972 break;
14973 case 0x30:
14974 /* regular FP ops */
14975 switch ((ctx->opcode >> 6) & 0x3) {
14976 case ADD_FMT:
14977 FINSN_3ARG_SDPS(ADD);
14978 break;
14979 case SUB_FMT:
14980 FINSN_3ARG_SDPS(SUB);
14981 break;
14982 case MUL_FMT:
14983 FINSN_3ARG_SDPS(MUL);
14984 break;
14985 case DIV_FMT:
14986 fmt = (ctx->opcode >> 8) & 0x3;
14987 if (fmt == 1) {
14988 mips32_op = OPC_DIV_D;
14989 } else if (fmt == 0) {
14990 mips32_op = OPC_DIV_S;
14991 } else {
14992 goto pool32f_invalid;
14994 goto do_fpop;
14995 default:
14996 goto pool32f_invalid;
14998 break;
14999 case 0x38:
15000 /* cmovs */
15001 switch ((ctx->opcode >> 6) & 0x7) {
15002 case MOVN_FMT: /* SELNEZ_FMT */
15003 if (ctx->insn_flags & ISA_MIPS32R6) {
15004 /* SELNEZ_FMT */
15005 switch ((ctx->opcode >> 9) & 0x3) {
15006 case FMT_SDPS_S:
15007 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15008 break;
15009 case FMT_SDPS_D:
15010 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15011 break;
15012 default:
15013 goto pool32f_invalid;
15015 } else {
15016 /* MOVN_FMT */
15017 FINSN_3ARG_SDPS(MOVN);
15019 break;
15020 case MOVN_FMT_04:
15021 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15022 FINSN_3ARG_SDPS(MOVN);
15023 break;
15024 case MOVZ_FMT: /* SELEQZ_FMT */
15025 if (ctx->insn_flags & ISA_MIPS32R6) {
15026 /* SELEQZ_FMT */
15027 switch ((ctx->opcode >> 9) & 0x3) {
15028 case FMT_SDPS_S:
15029 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15030 break;
15031 case FMT_SDPS_D:
15032 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15033 break;
15034 default:
15035 goto pool32f_invalid;
15037 } else {
15038 /* MOVZ_FMT */
15039 FINSN_3ARG_SDPS(MOVZ);
15041 break;
15042 case MOVZ_FMT_05:
15043 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15044 FINSN_3ARG_SDPS(MOVZ);
15045 break;
15046 case SEL_FMT:
15047 check_insn(ctx, ISA_MIPS32R6);
15048 switch ((ctx->opcode >> 9) & 0x3) {
15049 case FMT_SDPS_S:
15050 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15051 break;
15052 case FMT_SDPS_D:
15053 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15054 break;
15055 default:
15056 goto pool32f_invalid;
15058 break;
15059 case MADDF_FMT:
15060 check_insn(ctx, ISA_MIPS32R6);
15061 switch ((ctx->opcode >> 9) & 0x3) {
15062 case FMT_SDPS_S:
15063 mips32_op = OPC_MADDF_S;
15064 goto do_fpop;
15065 case FMT_SDPS_D:
15066 mips32_op = OPC_MADDF_D;
15067 goto do_fpop;
15068 default:
15069 goto pool32f_invalid;
15071 break;
15072 case MSUBF_FMT:
15073 check_insn(ctx, ISA_MIPS32R6);
15074 switch ((ctx->opcode >> 9) & 0x3) {
15075 case FMT_SDPS_S:
15076 mips32_op = OPC_MSUBF_S;
15077 goto do_fpop;
15078 case FMT_SDPS_D:
15079 mips32_op = OPC_MSUBF_D;
15080 goto do_fpop;
15081 default:
15082 goto pool32f_invalid;
15084 break;
15085 default:
15086 goto pool32f_invalid;
15088 break;
15089 do_fpop:
15090 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15091 break;
15092 default:
15093 pool32f_invalid:
15094 MIPS_INVAL("pool32f");
15095 generate_exception_end(ctx, EXCP_RI);
15096 break;
15098 } else {
15099 generate_exception_err(ctx, EXCP_CpU, 1);
15101 break;
15102 case POOL32I:
15103 minor = (ctx->opcode >> 21) & 0x1f;
15104 switch (minor) {
15105 case BLTZ:
15106 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15107 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15108 break;
15109 case BLTZAL:
15110 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15111 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15112 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15113 break;
15114 case BLTZALS:
15115 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15116 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15117 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15118 break;
15119 case BGEZ:
15120 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15121 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15122 break;
15123 case BGEZAL:
15124 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15125 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15126 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15127 break;
15128 case BGEZALS:
15129 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15130 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
15131 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15132 break;
15133 case BLEZ:
15134 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15135 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
15136 break;
15137 case BGTZ:
15138 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15139 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
15140 break;
15142 /* Traps */
15143 case TLTI: /* BC1EQZC */
15144 if (ctx->insn_flags & ISA_MIPS32R6) {
15145 /* BC1EQZC */
15146 check_cp1_enabled(ctx);
15147 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
15148 } else {
15149 /* TLTI */
15150 mips32_op = OPC_TLTI;
15151 goto do_trapi;
15153 break;
15154 case TGEI: /* BC1NEZC */
15155 if (ctx->insn_flags & ISA_MIPS32R6) {
15156 /* BC1NEZC */
15157 check_cp1_enabled(ctx);
15158 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
15159 } else {
15160 /* TGEI */
15161 mips32_op = OPC_TGEI;
15162 goto do_trapi;
15164 break;
15165 case TLTIU:
15166 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15167 mips32_op = OPC_TLTIU;
15168 goto do_trapi;
15169 case TGEIU:
15170 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15171 mips32_op = OPC_TGEIU;
15172 goto do_trapi;
15173 case TNEI: /* SYNCI */
15174 if (ctx->insn_flags & ISA_MIPS32R6) {
15175 /* SYNCI */
15176 /* Break the TB to be able to sync copied instructions
15177 immediately */
15178 ctx->base.is_jmp = DISAS_STOP;
15179 } else {
15180 /* TNEI */
15181 mips32_op = OPC_TNEI;
15182 goto do_trapi;
15184 break;
15185 case TEQI:
15186 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15187 mips32_op = OPC_TEQI;
15188 do_trapi:
15189 gen_trap(ctx, mips32_op, rs, -1, imm);
15190 break;
15192 case BNEZC:
15193 case BEQZC:
15194 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15195 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
15196 4, rs, 0, imm << 1, 0);
15197 /* Compact branches don't have a delay slot, so just let
15198 the normal delay slot handling take us to the branch
15199 target. */
15200 break;
15201 case LUI:
15202 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15203 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
15204 break;
15205 case SYNCI:
15206 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15207 /* Break the TB to be able to sync copied instructions
15208 immediately */
15209 ctx->base.is_jmp = DISAS_STOP;
15210 break;
15211 case BC2F:
15212 case BC2T:
15213 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15214 /* COP2: Not implemented. */
15215 generate_exception_err(ctx, EXCP_CpU, 2);
15216 break;
15217 case BC1F:
15218 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15219 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
15220 goto do_cp1branch;
15221 case BC1T:
15222 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15223 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
15224 goto do_cp1branch;
15225 case BC1ANY4F:
15226 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15227 mips32_op = OPC_BC1FANY4;
15228 goto do_cp1mips3d;
15229 case BC1ANY4T:
15230 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15231 mips32_op = OPC_BC1TANY4;
15232 do_cp1mips3d:
15233 check_cop1x(ctx);
15234 check_insn(ctx, ASE_MIPS3D);
15235 /* Fall through */
15236 do_cp1branch:
15237 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15238 check_cp1_enabled(ctx);
15239 gen_compute_branch1(ctx, mips32_op,
15240 (ctx->opcode >> 18) & 0x7, imm << 1);
15241 } else {
15242 generate_exception_err(ctx, EXCP_CpU, 1);
15244 break;
15245 case BPOSGE64:
15246 case BPOSGE32:
15247 /* MIPS DSP: not implemented */
15248 /* Fall through */
15249 default:
15250 MIPS_INVAL("pool32i");
15251 generate_exception_end(ctx, EXCP_RI);
15252 break;
15254 break;
15255 case POOL32C:
15256 minor = (ctx->opcode >> 12) & 0xf;
15257 offset = sextract32(ctx->opcode, 0,
15258 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
15259 switch (minor) {
15260 case LWL:
15261 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15262 mips32_op = OPC_LWL;
15263 goto do_ld_lr;
15264 case SWL:
15265 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15266 mips32_op = OPC_SWL;
15267 goto do_st_lr;
15268 case LWR:
15269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15270 mips32_op = OPC_LWR;
15271 goto do_ld_lr;
15272 case SWR:
15273 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15274 mips32_op = OPC_SWR;
15275 goto do_st_lr;
15276 #if defined(TARGET_MIPS64)
15277 case LDL:
15278 check_insn(ctx, ISA_MIPS3);
15279 check_mips_64(ctx);
15280 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15281 mips32_op = OPC_LDL;
15282 goto do_ld_lr;
15283 case SDL:
15284 check_insn(ctx, ISA_MIPS3);
15285 check_mips_64(ctx);
15286 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15287 mips32_op = OPC_SDL;
15288 goto do_st_lr;
15289 case LDR:
15290 check_insn(ctx, ISA_MIPS3);
15291 check_mips_64(ctx);
15292 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15293 mips32_op = OPC_LDR;
15294 goto do_ld_lr;
15295 case SDR:
15296 check_insn(ctx, ISA_MIPS3);
15297 check_mips_64(ctx);
15298 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15299 mips32_op = OPC_SDR;
15300 goto do_st_lr;
15301 case LWU:
15302 check_insn(ctx, ISA_MIPS3);
15303 check_mips_64(ctx);
15304 mips32_op = OPC_LWU;
15305 goto do_ld_lr;
15306 case LLD:
15307 check_insn(ctx, ISA_MIPS3);
15308 check_mips_64(ctx);
15309 mips32_op = OPC_LLD;
15310 goto do_ld_lr;
15311 #endif
15312 case LL:
15313 mips32_op = OPC_LL;
15314 goto do_ld_lr;
15315 do_ld_lr:
15316 gen_ld(ctx, mips32_op, rt, rs, offset);
15317 break;
15318 do_st_lr:
15319 gen_st(ctx, mips32_op, rt, rs, offset);
15320 break;
15321 case SC:
15322 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
15323 break;
15324 #if defined(TARGET_MIPS64)
15325 case SCD:
15326 check_insn(ctx, ISA_MIPS3);
15327 check_mips_64(ctx);
15328 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
15329 break;
15330 #endif
15331 case LD_EVA:
15332 if (!ctx->eva) {
15333 MIPS_INVAL("pool32c ld-eva");
15334 generate_exception_end(ctx, EXCP_RI);
15335 break;
15337 check_cp0_enabled(ctx);
15339 minor2 = (ctx->opcode >> 9) & 0x7;
15340 offset = sextract32(ctx->opcode, 0, 9);
15341 switch (minor2) {
15342 case LBUE:
15343 mips32_op = OPC_LBUE;
15344 goto do_ld_lr;
15345 case LHUE:
15346 mips32_op = OPC_LHUE;
15347 goto do_ld_lr;
15348 case LWLE:
15349 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15350 mips32_op = OPC_LWLE;
15351 goto do_ld_lr;
15352 case LWRE:
15353 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15354 mips32_op = OPC_LWRE;
15355 goto do_ld_lr;
15356 case LBE:
15357 mips32_op = OPC_LBE;
15358 goto do_ld_lr;
15359 case LHE:
15360 mips32_op = OPC_LHE;
15361 goto do_ld_lr;
15362 case LLE:
15363 mips32_op = OPC_LLE;
15364 goto do_ld_lr;
15365 case LWE:
15366 mips32_op = OPC_LWE;
15367 goto do_ld_lr;
15369 break;
15370 case ST_EVA:
15371 if (!ctx->eva) {
15372 MIPS_INVAL("pool32c st-eva");
15373 generate_exception_end(ctx, EXCP_RI);
15374 break;
15376 check_cp0_enabled(ctx);
15378 minor2 = (ctx->opcode >> 9) & 0x7;
15379 offset = sextract32(ctx->opcode, 0, 9);
15380 switch (minor2) {
15381 case SWLE:
15382 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15383 mips32_op = OPC_SWLE;
15384 goto do_st_lr;
15385 case SWRE:
15386 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15387 mips32_op = OPC_SWRE;
15388 goto do_st_lr;
15389 case PREFE:
15390 /* Treat as no-op */
15391 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
15392 /* hint codes 24-31 are reserved and signal RI */
15393 generate_exception(ctx, EXCP_RI);
15395 break;
15396 case CACHEE:
15397 /* Treat as no-op */
15398 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15399 gen_cache_operation(ctx, rt, rs, offset);
15401 break;
15402 case SBE:
15403 mips32_op = OPC_SBE;
15404 goto do_st_lr;
15405 case SHE:
15406 mips32_op = OPC_SHE;
15407 goto do_st_lr;
15408 case SCE:
15409 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
15410 break;
15411 case SWE:
15412 mips32_op = OPC_SWE;
15413 goto do_st_lr;
15415 break;
15416 case PREF:
15417 /* Treat as no-op */
15418 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
15419 /* hint codes 24-31 are reserved and signal RI */
15420 generate_exception(ctx, EXCP_RI);
15422 break;
15423 default:
15424 MIPS_INVAL("pool32c");
15425 generate_exception_end(ctx, EXCP_RI);
15426 break;
15428 break;
15429 case ADDI32: /* AUI, LUI */
15430 if (ctx->insn_flags & ISA_MIPS32R6) {
15431 /* AUI, LUI */
15432 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
15433 } else {
15434 /* ADDI32 */
15435 mips32_op = OPC_ADDI;
15436 goto do_addi;
15438 break;
15439 case ADDIU32:
15440 mips32_op = OPC_ADDIU;
15441 do_addi:
15442 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
15443 break;
15445 /* Logical operations */
15446 case ORI32:
15447 mips32_op = OPC_ORI;
15448 goto do_logici;
15449 case XORI32:
15450 mips32_op = OPC_XORI;
15451 goto do_logici;
15452 case ANDI32:
15453 mips32_op = OPC_ANDI;
15454 do_logici:
15455 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
15456 break;
15458 /* Set less than immediate */
15459 case SLTI32:
15460 mips32_op = OPC_SLTI;
15461 goto do_slti;
15462 case SLTIU32:
15463 mips32_op = OPC_SLTIU;
15464 do_slti:
15465 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
15466 break;
15467 case JALX32:
15468 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15469 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15470 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
15471 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15472 break;
15473 case JALS32: /* BOVC, BEQC, BEQZALC */
15474 if (ctx->insn_flags & ISA_MIPS32R6) {
15475 if (rs >= rt) {
15476 /* BOVC */
15477 mips32_op = OPC_BOVC;
15478 } else if (rs < rt && rs == 0) {
15479 /* BEQZALC */
15480 mips32_op = OPC_BEQZALC;
15481 } else {
15482 /* BEQC */
15483 mips32_op = OPC_BEQC;
15485 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15486 } else {
15487 /* JALS32 */
15488 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15489 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15490 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15492 break;
15493 case BEQ32: /* BC */
15494 if (ctx->insn_flags & ISA_MIPS32R6) {
15495 /* BC */
15496 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15497 sextract32(ctx->opcode << 1, 0, 27));
15498 } else {
15499 /* BEQ32 */
15500 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15502 break;
15503 case BNE32: /* BALC */
15504 if (ctx->insn_flags & ISA_MIPS32R6) {
15505 /* BALC */
15506 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15507 sextract32(ctx->opcode << 1, 0, 27));
15508 } else {
15509 /* BNE32 */
15510 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15512 break;
15513 case J32: /* BGTZC, BLTZC, BLTC */
15514 if (ctx->insn_flags & ISA_MIPS32R6) {
15515 if (rs == 0 && rt != 0) {
15516 /* BGTZC */
15517 mips32_op = OPC_BGTZC;
15518 } else if (rs != 0 && rt != 0 && rs == rt) {
15519 /* BLTZC */
15520 mips32_op = OPC_BLTZC;
15521 } else {
15522 /* BLTC */
15523 mips32_op = OPC_BLTC;
15525 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15526 } else {
15527 /* J32 */
15528 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15529 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15531 break;
15532 case JAL32: /* BLEZC, BGEZC, BGEC */
15533 if (ctx->insn_flags & ISA_MIPS32R6) {
15534 if (rs == 0 && rt != 0) {
15535 /* BLEZC */
15536 mips32_op = OPC_BLEZC;
15537 } else if (rs != 0 && rt != 0 && rs == rt) {
15538 /* BGEZC */
15539 mips32_op = OPC_BGEZC;
15540 } else {
15541 /* BGEC */
15542 mips32_op = OPC_BGEC;
15544 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15545 } else {
15546 /* JAL32 */
15547 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15548 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15549 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15551 break;
15552 /* Floating point (COP1) */
15553 case LWC132:
15554 mips32_op = OPC_LWC1;
15555 goto do_cop1;
15556 case LDC132:
15557 mips32_op = OPC_LDC1;
15558 goto do_cop1;
15559 case SWC132:
15560 mips32_op = OPC_SWC1;
15561 goto do_cop1;
15562 case SDC132:
15563 mips32_op = OPC_SDC1;
15564 do_cop1:
15565 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
15566 break;
15567 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15568 if (ctx->insn_flags & ISA_MIPS32R6) {
15569 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15570 switch ((ctx->opcode >> 16) & 0x1f) {
15571 case ADDIUPC_00:
15572 case ADDIUPC_01:
15573 case ADDIUPC_02:
15574 case ADDIUPC_03:
15575 case ADDIUPC_04:
15576 case ADDIUPC_05:
15577 case ADDIUPC_06:
15578 case ADDIUPC_07:
15579 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
15580 break;
15581 case AUIPC:
15582 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
15583 break;
15584 case ALUIPC:
15585 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
15586 break;
15587 case LWPC_08:
15588 case LWPC_09:
15589 case LWPC_0A:
15590 case LWPC_0B:
15591 case LWPC_0C:
15592 case LWPC_0D:
15593 case LWPC_0E:
15594 case LWPC_0F:
15595 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
15596 break;
15597 default:
15598 generate_exception(ctx, EXCP_RI);
15599 break;
15601 } else {
15602 /* ADDIUPC */
15603 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
15604 offset = SIMM(ctx->opcode, 0, 23) << 2;
15606 gen_addiupc(ctx, reg, offset, 0, 0);
15608 break;
15609 case BNVC: /* BNEC, BNEZALC */
15610 check_insn(ctx, ISA_MIPS32R6);
15611 if (rs >= rt) {
15612 /* BNVC */
15613 mips32_op = OPC_BNVC;
15614 } else if (rs < rt && rs == 0) {
15615 /* BNEZALC */
15616 mips32_op = OPC_BNEZALC;
15617 } else {
15618 /* BNEC */
15619 mips32_op = OPC_BNEC;
15621 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15622 break;
15623 case R6_BNEZC: /* JIALC */
15624 check_insn(ctx, ISA_MIPS32R6);
15625 if (rt != 0) {
15626 /* BNEZC */
15627 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15628 sextract32(ctx->opcode << 1, 0, 22));
15629 } else {
15630 /* JIALC */
15631 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15633 break;
15634 case R6_BEQZC: /* JIC */
15635 check_insn(ctx, ISA_MIPS32R6);
15636 if (rt != 0) {
15637 /* BEQZC */
15638 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15639 sextract32(ctx->opcode << 1, 0, 22));
15640 } else {
15641 /* JIC */
15642 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15644 break;
15645 case BLEZALC: /* BGEZALC, BGEUC */
15646 check_insn(ctx, ISA_MIPS32R6);
15647 if (rs == 0 && rt != 0) {
15648 /* BLEZALC */
15649 mips32_op = OPC_BLEZALC;
15650 } else if (rs != 0 && rt != 0 && rs == rt) {
15651 /* BGEZALC */
15652 mips32_op = OPC_BGEZALC;
15653 } else {
15654 /* BGEUC */
15655 mips32_op = OPC_BGEUC;
15657 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15658 break;
15659 case BGTZALC: /* BLTZALC, BLTUC */
15660 check_insn(ctx, ISA_MIPS32R6);
15661 if (rs == 0 && rt != 0) {
15662 /* BGTZALC */
15663 mips32_op = OPC_BGTZALC;
15664 } else if (rs != 0 && rt != 0 && rs == rt) {
15665 /* BLTZALC */
15666 mips32_op = OPC_BLTZALC;
15667 } else {
15668 /* BLTUC */
15669 mips32_op = OPC_BLTUC;
15671 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15672 break;
15673 /* Loads and stores */
15674 case LB32:
15675 mips32_op = OPC_LB;
15676 goto do_ld;
15677 case LBU32:
15678 mips32_op = OPC_LBU;
15679 goto do_ld;
15680 case LH32:
15681 mips32_op = OPC_LH;
15682 goto do_ld;
15683 case LHU32:
15684 mips32_op = OPC_LHU;
15685 goto do_ld;
15686 case LW32:
15687 mips32_op = OPC_LW;
15688 goto do_ld;
15689 #ifdef TARGET_MIPS64
15690 case LD32:
15691 check_insn(ctx, ISA_MIPS3);
15692 check_mips_64(ctx);
15693 mips32_op = OPC_LD;
15694 goto do_ld;
15695 case SD32:
15696 check_insn(ctx, ISA_MIPS3);
15697 check_mips_64(ctx);
15698 mips32_op = OPC_SD;
15699 goto do_st;
15700 #endif
15701 case SB32:
15702 mips32_op = OPC_SB;
15703 goto do_st;
15704 case SH32:
15705 mips32_op = OPC_SH;
15706 goto do_st;
15707 case SW32:
15708 mips32_op = OPC_SW;
15709 goto do_st;
15710 do_ld:
15711 gen_ld(ctx, mips32_op, rt, rs, imm);
15712 break;
15713 do_st:
15714 gen_st(ctx, mips32_op, rt, rs, imm);
15715 break;
15716 default:
15717 generate_exception_end(ctx, EXCP_RI);
15718 break;
15722 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15724 uint32_t op;
15726 /* make sure instructions are on a halfword boundary */
15727 if (ctx->base.pc_next & 0x1) {
15728 env->CP0_BadVAddr = ctx->base.pc_next;
15729 generate_exception_end(ctx, EXCP_AdEL);
15730 return 2;
15733 op = (ctx->opcode >> 10) & 0x3f;
15734 /* Enforce properly-sized instructions in a delay slot */
15735 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15736 switch (op & 0x7) { /* MSB-3..MSB-5 */
15737 case 0:
15738 /* POOL32A, POOL32B, POOL32I, POOL32C */
15739 case 4:
15740 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15741 case 5:
15742 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15743 case 6:
15744 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15745 case 7:
15746 /* LB32, LH32, LWC132, LDC132, LW32 */
15747 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15748 generate_exception_end(ctx, EXCP_RI);
15749 return 2;
15751 break;
15752 case 1:
15753 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15754 case 2:
15755 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15756 case 3:
15757 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15758 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15759 generate_exception_end(ctx, EXCP_RI);
15760 return 2;
15762 break;
15766 switch (op) {
15767 case POOL16A:
15769 int rd = mmreg(uMIPS_RD(ctx->opcode));
15770 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15771 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15772 uint32_t opc = 0;
15774 switch (ctx->opcode & 0x1) {
15775 case ADDU16:
15776 opc = OPC_ADDU;
15777 break;
15778 case SUBU16:
15779 opc = OPC_SUBU;
15780 break;
15782 if (ctx->insn_flags & ISA_MIPS32R6) {
15783 /* In the Release 6 the register number location in
15784 * the instruction encoding has changed.
15786 gen_arith(ctx, opc, rs1, rd, rs2);
15787 } else {
15788 gen_arith(ctx, opc, rd, rs1, rs2);
15791 break;
15792 case POOL16B:
15794 int rd = mmreg(uMIPS_RD(ctx->opcode));
15795 int rs = mmreg(uMIPS_RS(ctx->opcode));
15796 int amount = (ctx->opcode >> 1) & 0x7;
15797 uint32_t opc = 0;
15798 amount = amount == 0 ? 8 : amount;
15800 switch (ctx->opcode & 0x1) {
15801 case SLL16:
15802 opc = OPC_SLL;
15803 break;
15804 case SRL16:
15805 opc = OPC_SRL;
15806 break;
15809 gen_shift_imm(ctx, opc, rd, rs, amount);
15811 break;
15812 case POOL16C:
15813 if (ctx->insn_flags & ISA_MIPS32R6) {
15814 gen_pool16c_r6_insn(ctx);
15815 } else {
15816 gen_pool16c_insn(ctx);
15818 break;
15819 case LWGP16:
15821 int rd = mmreg(uMIPS_RD(ctx->opcode));
15822 int rb = 28; /* GP */
15823 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15825 gen_ld(ctx, OPC_LW, rd, rb, offset);
15827 break;
15828 case POOL16F:
15829 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15830 if (ctx->opcode & 1) {
15831 generate_exception_end(ctx, EXCP_RI);
15832 } else {
15833 /* MOVEP */
15834 int enc_dest = uMIPS_RD(ctx->opcode);
15835 int enc_rt = uMIPS_RS2(ctx->opcode);
15836 int enc_rs = uMIPS_RS1(ctx->opcode);
15837 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15839 break;
15840 case LBU16:
15842 int rd = mmreg(uMIPS_RD(ctx->opcode));
15843 int rb = mmreg(uMIPS_RS(ctx->opcode));
15844 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15845 offset = (offset == 0xf ? -1 : offset);
15847 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15849 break;
15850 case LHU16:
15852 int rd = mmreg(uMIPS_RD(ctx->opcode));
15853 int rb = mmreg(uMIPS_RS(ctx->opcode));
15854 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15856 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15858 break;
15859 case LWSP16:
15861 int rd = (ctx->opcode >> 5) & 0x1f;
15862 int rb = 29; /* SP */
15863 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15865 gen_ld(ctx, OPC_LW, rd, rb, offset);
15867 break;
15868 case LW16:
15870 int rd = mmreg(uMIPS_RD(ctx->opcode));
15871 int rb = mmreg(uMIPS_RS(ctx->opcode));
15872 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15874 gen_ld(ctx, OPC_LW, rd, rb, offset);
15876 break;
15877 case SB16:
15879 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15880 int rb = mmreg(uMIPS_RS(ctx->opcode));
15881 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15883 gen_st(ctx, OPC_SB, rd, rb, offset);
15885 break;
15886 case SH16:
15888 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15889 int rb = mmreg(uMIPS_RS(ctx->opcode));
15890 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15892 gen_st(ctx, OPC_SH, rd, rb, offset);
15894 break;
15895 case SWSP16:
15897 int rd = (ctx->opcode >> 5) & 0x1f;
15898 int rb = 29; /* SP */
15899 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15901 gen_st(ctx, OPC_SW, rd, rb, offset);
15903 break;
15904 case SW16:
15906 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15907 int rb = mmreg(uMIPS_RS(ctx->opcode));
15908 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15910 gen_st(ctx, OPC_SW, rd, rb, offset);
15912 break;
15913 case MOVE16:
15915 int rd = uMIPS_RD5(ctx->opcode);
15916 int rs = uMIPS_RS5(ctx->opcode);
15918 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15920 break;
15921 case ANDI16:
15922 gen_andi16(ctx);
15923 break;
15924 case POOL16D:
15925 switch (ctx->opcode & 0x1) {
15926 case ADDIUS5:
15927 gen_addius5(ctx);
15928 break;
15929 case ADDIUSP:
15930 gen_addiusp(ctx);
15931 break;
15933 break;
15934 case POOL16E:
15935 switch (ctx->opcode & 0x1) {
15936 case ADDIUR2:
15937 gen_addiur2(ctx);
15938 break;
15939 case ADDIUR1SP:
15940 gen_addiur1sp(ctx);
15941 break;
15943 break;
15944 case B16: /* BC16 */
15945 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15946 sextract32(ctx->opcode, 0, 10) << 1,
15947 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15948 break;
15949 case BNEZ16: /* BNEZC16 */
15950 case BEQZ16: /* BEQZC16 */
15951 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15952 mmreg(uMIPS_RD(ctx->opcode)),
15953 0, sextract32(ctx->opcode, 0, 7) << 1,
15954 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15956 break;
15957 case LI16:
15959 int reg = mmreg(uMIPS_RD(ctx->opcode));
15960 int imm = ZIMM(ctx->opcode, 0, 7);
15962 imm = (imm == 0x7f ? -1 : imm);
15963 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15965 break;
15966 case RES_29:
15967 case RES_31:
15968 case RES_39:
15969 generate_exception_end(ctx, EXCP_RI);
15970 break;
15971 default:
15972 decode_micromips32_opc(env, ctx);
15973 return 4;
15976 return 2;
15981 * nanoMIPS opcodes
15985 /* MAJOR, P16, and P32 pools opcodes */
15986 enum {
15987 NM_P_ADDIU = 0x00,
15988 NM_ADDIUPC = 0x01,
15989 NM_MOVE_BALC = 0x02,
15990 NM_P16_MV = 0x04,
15991 NM_LW16 = 0x05,
15992 NM_BC16 = 0x06,
15993 NM_P16_SR = 0x07,
15995 NM_POOL32A = 0x08,
15996 NM_P_BAL = 0x0a,
15997 NM_P16_SHIFT = 0x0c,
15998 NM_LWSP16 = 0x0d,
15999 NM_BALC16 = 0x0e,
16000 NM_P16_4X4 = 0x0f,
16002 NM_P_GP_W = 0x10,
16003 NM_P_GP_BH = 0x11,
16004 NM_P_J = 0x12,
16005 NM_P16C = 0x14,
16006 NM_LWGP16 = 0x15,
16007 NM_P16_LB = 0x17,
16009 NM_P48I = 0x18,
16010 NM_P16_A1 = 0x1c,
16011 NM_LW4X4 = 0x1d,
16012 NM_P16_LH = 0x1f,
16014 NM_P_U12 = 0x20,
16015 NM_P_LS_U12 = 0x21,
16016 NM_P_BR1 = 0x22,
16017 NM_P16_A2 = 0x24,
16018 NM_SW16 = 0x25,
16019 NM_BEQZC16 = 0x26,
16021 NM_POOL32F = 0x28,
16022 NM_P_LS_S9 = 0x29,
16023 NM_P_BR2 = 0x2a,
16025 NM_P16_ADDU = 0x2c,
16026 NM_SWSP16 = 0x2d,
16027 NM_BNEZC16 = 0x2e,
16028 NM_MOVEP = 0x2f,
16030 NM_POOL32S = 0x30,
16031 NM_P_BRI = 0x32,
16032 NM_LI16 = 0x34,
16033 NM_SWGP16 = 0x35,
16034 NM_P16_BR = 0x36,
16036 NM_P_LUI = 0x38,
16037 NM_ANDI16 = 0x3c,
16038 NM_SW4X4 = 0x3d,
16039 NM_MOVEPREV = 0x3f,
16042 /* POOL32A instruction pool */
16043 enum {
16044 NM_POOL32A0 = 0x00,
16045 NM_SPECIAL2 = 0x01,
16046 NM_COP2_1 = 0x02,
16047 NM_UDI = 0x03,
16048 NM_POOL32A5 = 0x05,
16049 NM_POOL32A7 = 0x07,
16052 /* P.GP.W instruction pool */
16053 enum {
16054 NM_ADDIUGP_W = 0x00,
16055 NM_LWGP = 0x02,
16056 NM_SWGP = 0x03,
16059 /* P48I instruction pool */
16060 enum {
16061 NM_LI48 = 0x00,
16062 NM_ADDIU48 = 0x01,
16063 NM_ADDIUGP48 = 0x02,
16064 NM_ADDIUPC48 = 0x03,
16065 NM_LWPC48 = 0x0b,
16066 NM_SWPC48 = 0x0f,
16069 /* P.U12 instruction pool */
16070 enum {
16071 NM_ORI = 0x00,
16072 NM_XORI = 0x01,
16073 NM_ANDI = 0x02,
16074 NM_P_SR = 0x03,
16075 NM_SLTI = 0x04,
16076 NM_SLTIU = 0x05,
16077 NM_SEQI = 0x06,
16078 NM_ADDIUNEG = 0x08,
16079 NM_P_SHIFT = 0x0c,
16080 NM_P_ROTX = 0x0d,
16081 NM_P_INS = 0x0e,
16082 NM_P_EXT = 0x0f,
16085 /* POOL32F instruction pool */
16086 enum {
16087 NM_POOL32F_0 = 0x00,
16088 NM_POOL32F_3 = 0x03,
16089 NM_POOL32F_5 = 0x05,
16092 /* POOL32S instruction pool */
16093 enum {
16094 NM_POOL32S_0 = 0x00,
16095 NM_POOL32S_4 = 0x04,
16098 /* P.LUI instruction pool */
16099 enum {
16100 NM_LUI = 0x00,
16101 NM_ALUIPC = 0x01,
16104 /* P.GP.BH instruction pool */
16105 enum {
16106 NM_LBGP = 0x00,
16107 NM_SBGP = 0x01,
16108 NM_LBUGP = 0x02,
16109 NM_ADDIUGP_B = 0x03,
16110 NM_P_GP_LH = 0x04,
16111 NM_P_GP_SH = 0x05,
16112 NM_P_GP_CP1 = 0x06,
16115 /* P.LS.U12 instruction pool */
16116 enum {
16117 NM_LB = 0x00,
16118 NM_SB = 0x01,
16119 NM_LBU = 0x02,
16120 NM_P_PREFU12 = 0x03,
16121 NM_LH = 0x04,
16122 NM_SH = 0x05,
16123 NM_LHU = 0x06,
16124 NM_LWU = 0x07,
16125 NM_LW = 0x08,
16126 NM_SW = 0x09,
16127 NM_LWC1 = 0x0a,
16128 NM_SWC1 = 0x0b,
16129 NM_LDC1 = 0x0e,
16130 NM_SDC1 = 0x0f,
16133 /* P.LS.S9 instruction pool */
16134 enum {
16135 NM_P_LS_S0 = 0x00,
16136 NM_P_LS_S1 = 0x01,
16137 NM_P_LS_E0 = 0x02,
16138 NM_P_LS_WM = 0x04,
16139 NM_P_LS_UAWM = 0x05,
16142 /* P.BAL instruction pool */
16143 enum {
16144 NM_BC = 0x00,
16145 NM_BALC = 0x01,
16148 /* P.J instruction pool */
16149 enum {
16150 NM_JALRC = 0x00,
16151 NM_JALRC_HB = 0x01,
16152 NM_P_BALRSC = 0x08,
16155 /* P.BR1 instruction pool */
16156 enum {
16157 NM_BEQC = 0x00,
16158 NM_P_BR3A = 0x01,
16159 NM_BGEC = 0x02,
16160 NM_BGEUC = 0x03,
16163 /* P.BR2 instruction pool */
16164 enum {
16165 NM_BNEC = 0x00,
16166 NM_BLTC = 0x02,
16167 NM_BLTUC = 0x03,
16170 /* P.BRI instruction pool */
16171 enum {
16172 NM_BEQIC = 0x00,
16173 NM_BBEQZC = 0x01,
16174 NM_BGEIC = 0x02,
16175 NM_BGEIUC = 0x03,
16176 NM_BNEIC = 0x04,
16177 NM_BBNEZC = 0x05,
16178 NM_BLTIC = 0x06,
16179 NM_BLTIUC = 0x07,
16182 /* P16.SHIFT instruction pool */
16183 enum {
16184 NM_SLL16 = 0x00,
16185 NM_SRL16 = 0x01,
16188 /* POOL16C instruction pool */
16189 enum {
16190 NM_POOL16C_0 = 0x00,
16191 NM_LWXS16 = 0x01,
16194 /* P16.A1 instruction pool */
16195 enum {
16196 NM_ADDIUR1SP = 0x01,
16199 /* P16.A2 instruction pool */
16200 enum {
16201 NM_ADDIUR2 = 0x00,
16202 NM_P_ADDIURS5 = 0x01,
16205 /* P16.ADDU instruction pool */
16206 enum {
16207 NM_ADDU16 = 0x00,
16208 NM_SUBU16 = 0x01,
16211 /* P16.SR instruction pool */
16212 enum {
16213 NM_SAVE16 = 0x00,
16214 NM_RESTORE_JRC16 = 0x01,
16217 /* P16.4X4 instruction pool */
16218 enum {
16219 NM_ADDU4X4 = 0x00,
16220 NM_MUL4X4 = 0x01,
16223 /* P16.LB instruction pool */
16224 enum {
16225 NM_LB16 = 0x00,
16226 NM_SB16 = 0x01,
16227 NM_LBU16 = 0x02,
16230 /* P16.LH instruction pool */
16231 enum {
16232 NM_LH16 = 0x00,
16233 NM_SH16 = 0x01,
16234 NM_LHU16 = 0x02,
16237 /* P.RI instruction pool */
16238 enum {
16239 NM_SIGRIE = 0x00,
16240 NM_P_SYSCALL = 0x01,
16241 NM_BREAK = 0x02,
16242 NM_SDBBP = 0x03,
16245 /* POOL32A0 instruction pool */
16246 enum {
16247 NM_P_TRAP = 0x00,
16248 NM_SEB = 0x01,
16249 NM_SLLV = 0x02,
16250 NM_MUL = 0x03,
16251 NM_MFC0 = 0x06,
16252 NM_MFHC0 = 0x07,
16253 NM_SEH = 0x09,
16254 NM_SRLV = 0x0a,
16255 NM_MUH = 0x0b,
16256 NM_MTC0 = 0x0e,
16257 NM_MTHC0 = 0x0f,
16258 NM_SRAV = 0x12,
16259 NM_MULU = 0x13,
16260 NM_ROTRV = 0x1a,
16261 NM_MUHU = 0x1b,
16262 NM_ADD = 0x22,
16263 NM_DIV = 0x23,
16264 NM_ADDU = 0x2a,
16265 NM_MOD = 0x2b,
16266 NM_SUB = 0x32,
16267 NM_DIVU = 0x33,
16268 NM_RDHWR = 0x38,
16269 NM_SUBU = 0x3a,
16270 NM_MODU = 0x3b,
16271 NM_P_CMOVE = 0x42,
16272 NM_FORK = 0x45,
16273 NM_MFTR = 0x46,
16274 NM_MFHTR = 0x47,
16275 NM_AND = 0x4a,
16276 NM_YIELD = 0x4d,
16277 NM_MTTR = 0x4e,
16278 NM_MTHTR = 0x4f,
16279 NM_OR = 0x52,
16280 NM_D_E_MT_VPE = 0x56,
16281 NM_NOR = 0x5a,
16282 NM_XOR = 0x62,
16283 NM_SLT = 0x6a,
16284 NM_P_SLTU = 0x72,
16285 NM_SOV = 0x7a,
16288 /* POOL32A5 instruction pool */
16289 enum {
16290 NM_CMP_EQ_PH = 0x00,
16291 NM_CMP_LT_PH = 0x08,
16292 NM_CMP_LE_PH = 0x10,
16293 NM_CMPGU_EQ_QB = 0x18,
16294 NM_CMPGU_LT_QB = 0x20,
16295 NM_CMPGU_LE_QB = 0x28,
16296 NM_CMPGDU_EQ_QB = 0x30,
16297 NM_CMPGDU_LT_QB = 0x38,
16298 NM_CMPGDU_LE_QB = 0x40,
16299 NM_CMPU_EQ_QB = 0x48,
16300 NM_CMPU_LT_QB = 0x50,
16301 NM_CMPU_LE_QB = 0x58,
16302 NM_ADDQ_S_W = 0x60,
16303 NM_SUBQ_S_W = 0x68,
16304 NM_ADDSC = 0x70,
16305 NM_ADDWC = 0x78,
16307 NM_ADDQ_S_PH = 0x01,
16308 NM_ADDQH_R_PH = 0x09,
16309 NM_ADDQH_R_W = 0x11,
16310 NM_ADDU_S_QB = 0x19,
16311 NM_ADDU_S_PH = 0x21,
16312 NM_ADDUH_R_QB = 0x29,
16313 NM_SHRAV_R_PH = 0x31,
16314 NM_SHRAV_R_QB = 0x39,
16315 NM_SUBQ_S_PH = 0x41,
16316 NM_SUBQH_R_PH = 0x49,
16317 NM_SUBQH_R_W = 0x51,
16318 NM_SUBU_S_QB = 0x59,
16319 NM_SUBU_S_PH = 0x61,
16320 NM_SUBUH_R_QB = 0x69,
16321 NM_SHLLV_S_PH = 0x71,
16322 NM_PRECR_SRA_R_PH_W = 0x79,
16324 NM_MULEU_S_PH_QBL = 0x12,
16325 NM_MULEU_S_PH_QBR = 0x1a,
16326 NM_MULQ_RS_PH = 0x22,
16327 NM_MULQ_S_PH = 0x2a,
16328 NM_MULQ_RS_W = 0x32,
16329 NM_MULQ_S_W = 0x3a,
16330 NM_APPEND = 0x42,
16331 NM_MODSUB = 0x52,
16332 NM_SHRAV_R_W = 0x5a,
16333 NM_SHRLV_PH = 0x62,
16334 NM_SHRLV_QB = 0x6a,
16335 NM_SHLLV_QB = 0x72,
16336 NM_SHLLV_S_W = 0x7a,
16338 NM_SHILO = 0x03,
16340 NM_MULEQ_S_W_PHL = 0x04,
16341 NM_MULEQ_S_W_PHR = 0x0c,
16343 NM_MUL_S_PH = 0x05,
16344 NM_PRECR_QB_PH = 0x0d,
16345 NM_PRECRQ_QB_PH = 0x15,
16346 NM_PRECRQ_PH_W = 0x1d,
16347 NM_PRECRQ_RS_PH_W = 0x25,
16348 NM_PRECRQU_S_QB_PH = 0x2d,
16349 NM_PACKRL_PH = 0x35,
16350 NM_PICK_QB = 0x3d,
16351 NM_PICK_PH = 0x45,
16353 NM_SHRA_R_W = 0x5e,
16354 NM_SHRA_R_PH = 0x66,
16355 NM_SHLL_S_PH = 0x76,
16356 NM_SHLL_S_W = 0x7e,
16358 NM_REPL_PH = 0x07
16361 /* POOL32A7 instruction pool */
16362 enum {
16363 NM_P_LSX = 0x00,
16364 NM_LSA = 0x01,
16365 NM_EXTW = 0x03,
16366 NM_POOL32AXF = 0x07,
16369 /* P.SR instruction pool */
16370 enum {
16371 NM_PP_SR = 0x00,
16372 NM_P_SR_F = 0x01,
16375 /* P.SHIFT instruction pool */
16376 enum {
16377 NM_P_SLL = 0x00,
16378 NM_SRL = 0x02,
16379 NM_SRA = 0x04,
16380 NM_ROTR = 0x06,
16383 /* P.ROTX instruction pool */
16384 enum {
16385 NM_ROTX = 0x00,
16388 /* P.INS instruction pool */
16389 enum {
16390 NM_INS = 0x00,
16393 /* P.EXT instruction pool */
16394 enum {
16395 NM_EXT = 0x00,
16398 /* POOL32F_0 (fmt) instruction pool */
16399 enum {
16400 NM_RINT_S = 0x04,
16401 NM_RINT_D = 0x44,
16402 NM_ADD_S = 0x06,
16403 NM_SELEQZ_S = 0x07,
16404 NM_SELEQZ_D = 0x47,
16405 NM_CLASS_S = 0x0c,
16406 NM_CLASS_D = 0x4c,
16407 NM_SUB_S = 0x0e,
16408 NM_SELNEZ_S = 0x0f,
16409 NM_SELNEZ_D = 0x4f,
16410 NM_MUL_S = 0x16,
16411 NM_SEL_S = 0x17,
16412 NM_SEL_D = 0x57,
16413 NM_DIV_S = 0x1e,
16414 NM_ADD_D = 0x26,
16415 NM_SUB_D = 0x2e,
16416 NM_MUL_D = 0x36,
16417 NM_MADDF_S = 0x37,
16418 NM_MADDF_D = 0x77,
16419 NM_DIV_D = 0x3e,
16420 NM_MSUBF_S = 0x3f,
16421 NM_MSUBF_D = 0x7f,
16424 /* POOL32F_3 instruction pool */
16425 enum {
16426 NM_MIN_FMT = 0x00,
16427 NM_MAX_FMT = 0x01,
16428 NM_MINA_FMT = 0x04,
16429 NM_MAXA_FMT = 0x05,
16430 NM_POOL32FXF = 0x07,
16433 /* POOL32F_5 instruction pool */
16434 enum {
16435 NM_CMP_CONDN_S = 0x00,
16436 NM_CMP_CONDN_D = 0x02,
16439 /* P.GP.LH instruction pool */
16440 enum {
16441 NM_LHGP = 0x00,
16442 NM_LHUGP = 0x01,
16445 /* P.GP.SH instruction pool */
16446 enum {
16447 NM_SHGP = 0x00,
16450 /* P.GP.CP1 instruction pool */
16451 enum {
16452 NM_LWC1GP = 0x00,
16453 NM_SWC1GP = 0x01,
16454 NM_LDC1GP = 0x02,
16455 NM_SDC1GP = 0x03,
16458 /* P.LS.S0 instruction pool */
16459 enum {
16460 NM_LBS9 = 0x00,
16461 NM_LHS9 = 0x04,
16462 NM_LWS9 = 0x08,
16463 NM_LDS9 = 0x0c,
16465 NM_SBS9 = 0x01,
16466 NM_SHS9 = 0x05,
16467 NM_SWS9 = 0x09,
16468 NM_SDS9 = 0x0d,
16470 NM_LBUS9 = 0x02,
16471 NM_LHUS9 = 0x06,
16472 NM_LWC1S9 = 0x0a,
16473 NM_LDC1S9 = 0x0e,
16475 NM_P_PREFS9 = 0x03,
16476 NM_LWUS9 = 0x07,
16477 NM_SWC1S9 = 0x0b,
16478 NM_SDC1S9 = 0x0f,
16481 /* P.LS.S1 instruction pool */
16482 enum {
16483 NM_ASET_ACLR = 0x02,
16484 NM_UALH = 0x04,
16485 NM_UASH = 0x05,
16486 NM_CACHE = 0x07,
16487 NM_P_LL = 0x0a,
16488 NM_P_SC = 0x0b,
16491 /* P.LS.WM instruction pool */
16492 enum {
16493 NM_LWM = 0x00,
16494 NM_SWM = 0x01,
16497 /* P.LS.UAWM instruction pool */
16498 enum {
16499 NM_UALWM = 0x00,
16500 NM_UASWM = 0x01,
16503 /* P.BR3A instruction pool */
16504 enum {
16505 NM_BC1EQZC = 0x00,
16506 NM_BC1NEZC = 0x01,
16507 NM_BC2EQZC = 0x02,
16508 NM_BC2NEZC = 0x03,
16509 NM_BPOSGE32C = 0x04,
16512 /* P16.RI instruction pool */
16513 enum {
16514 NM_P16_SYSCALL = 0x01,
16515 NM_BREAK16 = 0x02,
16516 NM_SDBBP16 = 0x03,
16519 /* POOL16C_0 instruction pool */
16520 enum {
16521 NM_POOL16C_00 = 0x00,
16524 /* P16.JRC instruction pool */
16525 enum {
16526 NM_JRC = 0x00,
16527 NM_JALRC16 = 0x01,
16530 /* P.SYSCALL instruction pool */
16531 enum {
16532 NM_SYSCALL = 0x00,
16533 NM_HYPCALL = 0x01,
16536 /* P.TRAP instruction pool */
16537 enum {
16538 NM_TEQ = 0x00,
16539 NM_TNE = 0x01,
16542 /* P.CMOVE instruction pool */
16543 enum {
16544 NM_MOVZ = 0x00,
16545 NM_MOVN = 0x01,
16548 /* POOL32Axf instruction pool */
16549 enum {
16550 NM_POOL32AXF_1 = 0x01,
16551 NM_POOL32AXF_2 = 0x02,
16552 NM_POOL32AXF_4 = 0x04,
16553 NM_POOL32AXF_5 = 0x05,
16554 NM_POOL32AXF_7 = 0x07,
16557 /* POOL32Axf_1 instruction pool */
16558 enum {
16559 NM_POOL32AXF_1_0 = 0x00,
16560 NM_POOL32AXF_1_1 = 0x01,
16561 NM_POOL32AXF_1_3 = 0x03,
16562 NM_POOL32AXF_1_4 = 0x04,
16563 NM_POOL32AXF_1_5 = 0x05,
16564 NM_POOL32AXF_1_7 = 0x07,
16567 /* POOL32Axf_2 instruction pool */
16568 enum {
16569 NM_POOL32AXF_2_0_7 = 0x00,
16570 NM_POOL32AXF_2_8_15 = 0x01,
16571 NM_POOL32AXF_2_16_23 = 0x02,
16572 NM_POOL32AXF_2_24_31 = 0x03,
16575 /* POOL32Axf_7 instruction pool */
16576 enum {
16577 NM_SHRA_R_QB = 0x0,
16578 NM_SHRL_PH = 0x1,
16579 NM_REPL_QB = 0x2,
16582 /* POOL32Axf_1_0 instruction pool */
16583 enum {
16584 NM_MFHI = 0x0,
16585 NM_MFLO = 0x1,
16586 NM_MTHI = 0x2,
16587 NM_MTLO = 0x3,
16590 /* POOL32Axf_1_1 instruction pool */
16591 enum {
16592 NM_MTHLIP = 0x0,
16593 NM_SHILOV = 0x1,
16596 /* POOL32Axf_1_3 instruction pool */
16597 enum {
16598 NM_RDDSP = 0x0,
16599 NM_WRDSP = 0x1,
16600 NM_EXTP = 0x2,
16601 NM_EXTPDP = 0x3,
16604 /* POOL32Axf_1_4 instruction pool */
16605 enum {
16606 NM_SHLL_QB = 0x0,
16607 NM_SHRL_QB = 0x1,
16610 /* POOL32Axf_1_5 instruction pool */
16611 enum {
16612 NM_MAQ_S_W_PHR = 0x0,
16613 NM_MAQ_S_W_PHL = 0x1,
16614 NM_MAQ_SA_W_PHR = 0x2,
16615 NM_MAQ_SA_W_PHL = 0x3,
16618 /* POOL32Axf_1_7 instruction pool */
16619 enum {
16620 NM_EXTR_W = 0x0,
16621 NM_EXTR_R_W = 0x1,
16622 NM_EXTR_RS_W = 0x2,
16623 NM_EXTR_S_H = 0x3,
16626 /* POOL32Axf_2_0_7 instruction pool */
16627 enum {
16628 NM_DPA_W_PH = 0x0,
16629 NM_DPAQ_S_W_PH = 0x1,
16630 NM_DPS_W_PH = 0x2,
16631 NM_DPSQ_S_W_PH = 0x3,
16632 NM_BALIGN = 0x4,
16633 NM_MADD = 0x5,
16634 NM_MULT = 0x6,
16635 NM_EXTRV_W = 0x7,
16638 /* POOL32Axf_2_8_15 instruction pool */
16639 enum {
16640 NM_DPAX_W_PH = 0x0,
16641 NM_DPAQ_SA_L_W = 0x1,
16642 NM_DPSX_W_PH = 0x2,
16643 NM_DPSQ_SA_L_W = 0x3,
16644 NM_MADDU = 0x5,
16645 NM_MULTU = 0x6,
16646 NM_EXTRV_R_W = 0x7,
16649 /* POOL32Axf_2_16_23 instruction pool */
16650 enum {
16651 NM_DPAU_H_QBL = 0x0,
16652 NM_DPAQX_S_W_PH = 0x1,
16653 NM_DPSU_H_QBL = 0x2,
16654 NM_DPSQX_S_W_PH = 0x3,
16655 NM_EXTPV = 0x4,
16656 NM_MSUB = 0x5,
16657 NM_MULSA_W_PH = 0x6,
16658 NM_EXTRV_RS_W = 0x7,
16661 /* POOL32Axf_2_24_31 instruction pool */
16662 enum {
16663 NM_DPAU_H_QBR = 0x0,
16664 NM_DPAQX_SA_W_PH = 0x1,
16665 NM_DPSU_H_QBR = 0x2,
16666 NM_DPSQX_SA_W_PH = 0x3,
16667 NM_EXTPDPV = 0x4,
16668 NM_MSUBU = 0x5,
16669 NM_MULSAQ_S_W_PH = 0x6,
16670 NM_EXTRV_S_H = 0x7,
16673 /* POOL32Axf_{4, 5} instruction pool */
16674 enum {
16675 NM_CLO = 0x25,
16676 NM_CLZ = 0x2d,
16678 NM_TLBP = 0x01,
16679 NM_TLBR = 0x09,
16680 NM_TLBWI = 0x11,
16681 NM_TLBWR = 0x19,
16682 NM_TLBINV = 0x03,
16683 NM_TLBINVF = 0x0b,
16684 NM_DI = 0x23,
16685 NM_EI = 0x2b,
16686 NM_RDPGPR = 0x70,
16687 NM_WRPGPR = 0x78,
16688 NM_WAIT = 0x61,
16689 NM_DERET = 0x71,
16690 NM_ERETX = 0x79,
16692 /* nanoMIPS DSP instructions */
16693 NM_ABSQ_S_QB = 0x00,
16694 NM_ABSQ_S_PH = 0x08,
16695 NM_ABSQ_S_W = 0x10,
16696 NM_PRECEQ_W_PHL = 0x28,
16697 NM_PRECEQ_W_PHR = 0x30,
16698 NM_PRECEQU_PH_QBL = 0x38,
16699 NM_PRECEQU_PH_QBR = 0x48,
16700 NM_PRECEU_PH_QBL = 0x58,
16701 NM_PRECEU_PH_QBR = 0x68,
16702 NM_PRECEQU_PH_QBLA = 0x39,
16703 NM_PRECEQU_PH_QBRA = 0x49,
16704 NM_PRECEU_PH_QBLA = 0x59,
16705 NM_PRECEU_PH_QBRA = 0x69,
16706 NM_REPLV_PH = 0x01,
16707 NM_REPLV_QB = 0x09,
16708 NM_BITREV = 0x18,
16709 NM_INSV = 0x20,
16710 NM_RADDU_W_QB = 0x78,
16712 NM_BITSWAP = 0x05,
16713 NM_WSBH = 0x3d,
16716 /* PP.SR instruction pool */
16717 enum {
16718 NM_SAVE = 0x00,
16719 NM_RESTORE = 0x02,
16720 NM_RESTORE_JRC = 0x03,
16723 /* P.SR.F instruction pool */
16724 enum {
16725 NM_SAVEF = 0x00,
16726 NM_RESTOREF = 0x01,
16729 /* P16.SYSCALL instruction pool */
16730 enum {
16731 NM_SYSCALL16 = 0x00,
16732 NM_HYPCALL16 = 0x01,
16735 /* POOL16C_00 instruction pool */
16736 enum {
16737 NM_NOT16 = 0x00,
16738 NM_XOR16 = 0x01,
16739 NM_AND16 = 0x02,
16740 NM_OR16 = 0x03,
16743 /* PP.LSX and PP.LSXS instruction pool */
16744 enum {
16745 NM_LBX = 0x00,
16746 NM_LHX = 0x04,
16747 NM_LWX = 0x08,
16748 NM_LDX = 0x0c,
16750 NM_SBX = 0x01,
16751 NM_SHX = 0x05,
16752 NM_SWX = 0x09,
16753 NM_SDX = 0x0d,
16755 NM_LBUX = 0x02,
16756 NM_LHUX = 0x06,
16757 NM_LWC1X = 0x0a,
16758 NM_LDC1X = 0x0e,
16760 NM_LWUX = 0x07,
16761 NM_SWC1X = 0x0b,
16762 NM_SDC1X = 0x0f,
16764 NM_LHXS = 0x04,
16765 NM_LWXS = 0x08,
16766 NM_LDXS = 0x0c,
16768 NM_SHXS = 0x05,
16769 NM_SWXS = 0x09,
16770 NM_SDXS = 0x0d,
16772 NM_LHUXS = 0x06,
16773 NM_LWC1XS = 0x0a,
16774 NM_LDC1XS = 0x0e,
16776 NM_LWUXS = 0x07,
16777 NM_SWC1XS = 0x0b,
16778 NM_SDC1XS = 0x0f,
16781 /* ERETx instruction pool */
16782 enum {
16783 NM_ERET = 0x00,
16784 NM_ERETNC = 0x01,
16787 /* POOL32FxF_{0, 1} insturction pool */
16788 enum {
16789 NM_CFC1 = 0x40,
16790 NM_CTC1 = 0x60,
16791 NM_MFC1 = 0x80,
16792 NM_MTC1 = 0xa0,
16793 NM_MFHC1 = 0xc0,
16794 NM_MTHC1 = 0xe0,
16796 NM_CVT_S_PL = 0x84,
16797 NM_CVT_S_PU = 0xa4,
16799 NM_CVT_L_S = 0x004,
16800 NM_CVT_L_D = 0x104,
16801 NM_CVT_W_S = 0x024,
16802 NM_CVT_W_D = 0x124,
16804 NM_RSQRT_S = 0x008,
16805 NM_RSQRT_D = 0x108,
16807 NM_SQRT_S = 0x028,
16808 NM_SQRT_D = 0x128,
16810 NM_RECIP_S = 0x048,
16811 NM_RECIP_D = 0x148,
16813 NM_FLOOR_L_S = 0x00c,
16814 NM_FLOOR_L_D = 0x10c,
16816 NM_FLOOR_W_S = 0x02c,
16817 NM_FLOOR_W_D = 0x12c,
16819 NM_CEIL_L_S = 0x04c,
16820 NM_CEIL_L_D = 0x14c,
16821 NM_CEIL_W_S = 0x06c,
16822 NM_CEIL_W_D = 0x16c,
16823 NM_TRUNC_L_S = 0x08c,
16824 NM_TRUNC_L_D = 0x18c,
16825 NM_TRUNC_W_S = 0x0ac,
16826 NM_TRUNC_W_D = 0x1ac,
16827 NM_ROUND_L_S = 0x0cc,
16828 NM_ROUND_L_D = 0x1cc,
16829 NM_ROUND_W_S = 0x0ec,
16830 NM_ROUND_W_D = 0x1ec,
16832 NM_MOV_S = 0x01,
16833 NM_MOV_D = 0x81,
16834 NM_ABS_S = 0x0d,
16835 NM_ABS_D = 0x8d,
16836 NM_NEG_S = 0x2d,
16837 NM_NEG_D = 0xad,
16838 NM_CVT_D_S = 0x04d,
16839 NM_CVT_D_W = 0x0cd,
16840 NM_CVT_D_L = 0x14d,
16841 NM_CVT_S_D = 0x06d,
16842 NM_CVT_S_W = 0x0ed,
16843 NM_CVT_S_L = 0x16d,
16846 /* P.LL instruction pool */
16847 enum {
16848 NM_LL = 0x00,
16849 NM_LLWP = 0x01,
16852 /* P.SC instruction pool */
16853 enum {
16854 NM_SC = 0x00,
16855 NM_SCWP = 0x01,
16858 /* P.DVP instruction pool */
16859 enum {
16860 NM_DVP = 0x00,
16861 NM_EVP = 0x01,
16867 * nanoMIPS decoding engine
16872 /* extraction utilities */
16874 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
16875 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
16876 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
16877 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
16878 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
16879 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
16881 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
16882 static inline int decode_gpr_gpr3(int r)
16884 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
16886 return map[r & 0x7];
16889 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
16890 static inline int decode_gpr_gpr3_src_store(int r)
16892 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
16894 return map[r & 0x7];
16897 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
16898 static inline int decode_gpr_gpr4(int r)
16900 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
16901 16, 17, 18, 19, 20, 21, 22, 23 };
16903 return map[r & 0xf];
16906 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
16907 static inline int decode_gpr_gpr4_zero(int r)
16909 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
16910 16, 17, 18, 19, 20, 21, 22, 23 };
16912 return map[r & 0xf];
16916 /* extraction utilities */
16918 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
16919 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
16920 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
16921 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
16922 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
16923 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
16926 static void gen_adjust_sp(DisasContext *ctx, int u)
16928 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
16931 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
16932 uint8_t gp, uint16_t u)
16934 int counter = 0;
16935 TCGv va = tcg_temp_new();
16936 TCGv t0 = tcg_temp_new();
16938 while (counter != count) {
16939 bool use_gp = gp && (counter == count - 1);
16940 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
16941 int this_offset = -((counter + 1) << 2);
16942 gen_base_offset_addr(ctx, va, 29, this_offset);
16943 gen_load_gpr(t0, this_rt);
16944 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
16945 (MO_TEUL | ctx->default_tcg_memop_mask));
16946 counter++;
16949 /* adjust stack pointer */
16950 gen_adjust_sp(ctx, -u);
16952 tcg_temp_free(t0);
16953 tcg_temp_free(va);
16956 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
16957 uint8_t gp, uint16_t u)
16959 int counter = 0;
16960 TCGv va = tcg_temp_new();
16961 TCGv t0 = tcg_temp_new();
16963 while (counter != count) {
16964 bool use_gp = gp && (counter == count - 1);
16965 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
16966 int this_offset = u - ((counter + 1) << 2);
16967 gen_base_offset_addr(ctx, va, 29, this_offset);
16968 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
16969 ctx->default_tcg_memop_mask);
16970 tcg_gen_ext32s_tl(t0, t0);
16971 gen_store_gpr(t0, this_rt);
16972 counter++;
16975 /* adjust stack pointer */
16976 gen_adjust_sp(ctx, u);
16978 tcg_temp_free(t0);
16979 tcg_temp_free(va);
16982 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
16984 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
16985 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
16987 switch (extract32(ctx->opcode, 2, 2)) {
16988 case NM_NOT16:
16989 gen_logic(ctx, OPC_NOR, rt, rs, 0);
16990 break;
16991 case NM_AND16:
16992 gen_logic(ctx, OPC_AND, rt, rt, rs);
16993 break;
16994 case NM_XOR16:
16995 gen_logic(ctx, OPC_XOR, rt, rt, rs);
16996 break;
16997 case NM_OR16:
16998 gen_logic(ctx, OPC_OR, rt, rt, rs);
16999 break;
17003 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17005 int rt = extract32(ctx->opcode, 21, 5);
17006 int rs = extract32(ctx->opcode, 16, 5);
17007 int rd = extract32(ctx->opcode, 11, 5);
17009 switch (extract32(ctx->opcode, 3, 7)) {
17010 case NM_P_TRAP:
17011 switch (extract32(ctx->opcode, 10, 1)) {
17012 case NM_TEQ:
17013 check_nms(ctx);
17014 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17015 break;
17016 case NM_TNE:
17017 check_nms(ctx);
17018 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17019 break;
17021 break;
17022 case NM_RDHWR:
17023 check_nms(ctx);
17024 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17025 break;
17026 case NM_SEB:
17027 check_nms(ctx);
17028 gen_bshfl(ctx, OPC_SEB, rs, rt);
17029 break;
17030 case NM_SEH:
17031 gen_bshfl(ctx, OPC_SEH, rs, rt);
17032 break;
17033 case NM_SLLV:
17034 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17035 break;
17036 case NM_SRLV:
17037 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17038 break;
17039 case NM_SRAV:
17040 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17041 break;
17042 case NM_ROTRV:
17043 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17044 break;
17045 case NM_ADD:
17046 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17047 break;
17048 case NM_ADDU:
17049 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17050 break;
17051 case NM_SUB:
17052 check_nms(ctx);
17053 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17054 break;
17055 case NM_SUBU:
17056 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17057 break;
17058 case NM_P_CMOVE:
17059 switch (extract32(ctx->opcode, 10, 1)) {
17060 case NM_MOVZ:
17061 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17062 break;
17063 case NM_MOVN:
17064 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17065 break;
17067 break;
17068 case NM_AND:
17069 gen_logic(ctx, OPC_AND, rd, rs, rt);
17070 break;
17071 case NM_OR:
17072 gen_logic(ctx, OPC_OR, rd, rs, rt);
17073 break;
17074 case NM_NOR:
17075 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17076 break;
17077 case NM_XOR:
17078 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17079 break;
17080 case NM_SLT:
17081 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17082 break;
17083 case NM_P_SLTU:
17084 if (rd == 0) {
17085 /* P_DVP */
17086 #ifndef CONFIG_USER_ONLY
17087 TCGv t0 = tcg_temp_new();
17088 switch (extract32(ctx->opcode, 10, 1)) {
17089 case NM_DVP:
17090 if (ctx->vp) {
17091 check_cp0_enabled(ctx);
17092 gen_helper_dvp(t0, cpu_env);
17093 gen_store_gpr(t0, rt);
17095 break;
17096 case NM_EVP:
17097 if (ctx->vp) {
17098 check_cp0_enabled(ctx);
17099 gen_helper_evp(t0, cpu_env);
17100 gen_store_gpr(t0, rt);
17102 break;
17104 tcg_temp_free(t0);
17105 #endif
17106 } else {
17107 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
17109 break;
17110 case NM_SOV:
17112 TCGv t0 = tcg_temp_new();
17113 TCGv t1 = tcg_temp_new();
17114 TCGv t2 = tcg_temp_new();
17116 gen_load_gpr(t1, rs);
17117 gen_load_gpr(t2, rt);
17118 tcg_gen_add_tl(t0, t1, t2);
17119 tcg_gen_ext32s_tl(t0, t0);
17120 tcg_gen_xor_tl(t1, t1, t2);
17121 tcg_gen_xor_tl(t2, t0, t2);
17122 tcg_gen_andc_tl(t1, t2, t1);
17124 /* operands of same sign, result different sign */
17125 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
17126 gen_store_gpr(t0, rd);
17128 tcg_temp_free(t0);
17129 tcg_temp_free(t1);
17130 tcg_temp_free(t2);
17132 break;
17133 case NM_MUL:
17134 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
17135 break;
17136 case NM_MUH:
17137 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
17138 break;
17139 case NM_MULU:
17140 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
17141 break;
17142 case NM_MUHU:
17143 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
17144 break;
17145 case NM_DIV:
17146 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
17147 break;
17148 case NM_MOD:
17149 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
17150 break;
17151 case NM_DIVU:
17152 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
17153 break;
17154 case NM_MODU:
17155 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
17156 break;
17157 #ifndef CONFIG_USER_ONLY
17158 case NM_MFC0:
17159 check_cp0_enabled(ctx);
17160 if (rt == 0) {
17161 /* Treat as NOP. */
17162 break;
17164 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
17165 break;
17166 case NM_MTC0:
17167 check_cp0_enabled(ctx);
17169 TCGv t0 = tcg_temp_new();
17171 gen_load_gpr(t0, rt);
17172 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
17173 tcg_temp_free(t0);
17175 break;
17176 case NM_D_E_MT_VPE:
17178 uint8_t sc = extract32(ctx->opcode, 10, 1);
17179 TCGv t0 = tcg_temp_new();
17181 switch (sc) {
17182 case 0:
17183 if (rs == 1) {
17184 /* DMT */
17185 check_cp0_mt(ctx);
17186 gen_helper_dmt(t0);
17187 gen_store_gpr(t0, rt);
17188 } else if (rs == 0) {
17189 /* DVPE */
17190 check_cp0_mt(ctx);
17191 gen_helper_dvpe(t0, cpu_env);
17192 gen_store_gpr(t0, rt);
17193 } else {
17194 generate_exception_end(ctx, EXCP_RI);
17196 break;
17197 case 1:
17198 if (rs == 1) {
17199 /* EMT */
17200 check_cp0_mt(ctx);
17201 gen_helper_emt(t0);
17202 gen_store_gpr(t0, rt);
17203 } else if (rs == 0) {
17204 /* EVPE */
17205 check_cp0_mt(ctx);
17206 gen_helper_evpe(t0, cpu_env);
17207 gen_store_gpr(t0, rt);
17208 } else {
17209 generate_exception_end(ctx, EXCP_RI);
17211 break;
17214 tcg_temp_free(t0);
17216 break;
17217 case NM_FORK:
17218 check_mt(ctx);
17220 TCGv t0 = tcg_temp_new();
17221 TCGv t1 = tcg_temp_new();
17223 gen_load_gpr(t0, rt);
17224 gen_load_gpr(t1, rs);
17225 gen_helper_fork(t0, t1);
17226 tcg_temp_free(t0);
17227 tcg_temp_free(t1);
17229 break;
17230 case NM_MFTR:
17231 case NM_MFHTR:
17232 check_cp0_enabled(ctx);
17233 if (rd == 0) {
17234 /* Treat as NOP. */
17235 return;
17237 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17238 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17239 break;
17240 case NM_MTTR:
17241 case NM_MTHTR:
17242 check_cp0_enabled(ctx);
17243 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17244 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17245 break;
17246 case NM_YIELD:
17247 check_mt(ctx);
17249 TCGv t0 = tcg_temp_new();
17251 gen_load_gpr(t0, rs);
17252 gen_helper_yield(t0, cpu_env, t0);
17253 gen_store_gpr(t0, rt);
17254 tcg_temp_free(t0);
17256 break;
17257 #endif
17258 default:
17259 generate_exception_end(ctx, EXCP_RI);
17260 break;
17264 /* dsp */
17265 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
17266 int ret, int v1, int v2)
17268 TCGv_i32 t0;
17269 TCGv v0_t;
17270 TCGv v1_t;
17272 t0 = tcg_temp_new_i32();
17274 v0_t = tcg_temp_new();
17275 v1_t = tcg_temp_new();
17277 tcg_gen_movi_i32(t0, v2 >> 3);
17279 gen_load_gpr(v0_t, ret);
17280 gen_load_gpr(v1_t, v1);
17282 switch (opc) {
17283 case NM_MAQ_S_W_PHR:
17284 check_dsp(ctx);
17285 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
17286 break;
17287 case NM_MAQ_S_W_PHL:
17288 check_dsp(ctx);
17289 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
17290 break;
17291 case NM_MAQ_SA_W_PHR:
17292 check_dsp(ctx);
17293 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
17294 break;
17295 case NM_MAQ_SA_W_PHL:
17296 check_dsp(ctx);
17297 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
17298 break;
17299 default:
17300 generate_exception_end(ctx, EXCP_RI);
17301 break;
17304 tcg_temp_free_i32(t0);
17306 tcg_temp_free(v0_t);
17307 tcg_temp_free(v1_t);
17311 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
17312 int ret, int v1, int v2)
17314 int16_t imm;
17315 TCGv t0 = tcg_temp_new();
17316 TCGv t1 = tcg_temp_new();
17317 TCGv v0_t = tcg_temp_new();
17319 gen_load_gpr(v0_t, v1);
17321 switch (opc) {
17322 case NM_POOL32AXF_1_0:
17323 check_dsp(ctx);
17324 switch (extract32(ctx->opcode, 12, 2)) {
17325 case NM_MFHI:
17326 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
17327 break;
17328 case NM_MFLO:
17329 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
17330 break;
17331 case NM_MTHI:
17332 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
17333 break;
17334 case NM_MTLO:
17335 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
17336 break;
17338 break;
17339 case NM_POOL32AXF_1_1:
17340 check_dsp(ctx);
17341 switch (extract32(ctx->opcode, 12, 2)) {
17342 case NM_MTHLIP:
17343 tcg_gen_movi_tl(t0, v2);
17344 gen_helper_mthlip(t0, v0_t, cpu_env);
17345 break;
17346 case NM_SHILOV:
17347 tcg_gen_movi_tl(t0, v2 >> 3);
17348 gen_helper_shilo(t0, v0_t, cpu_env);
17349 break;
17350 default:
17351 generate_exception_end(ctx, EXCP_RI);
17352 break;
17354 break;
17355 case NM_POOL32AXF_1_3:
17356 check_dsp(ctx);
17357 imm = extract32(ctx->opcode, 14, 7);
17358 switch (extract32(ctx->opcode, 12, 2)) {
17359 case NM_RDDSP:
17360 tcg_gen_movi_tl(t0, imm);
17361 gen_helper_rddsp(t0, t0, cpu_env);
17362 gen_store_gpr(t0, ret);
17363 break;
17364 case NM_WRDSP:
17365 gen_load_gpr(t0, ret);
17366 tcg_gen_movi_tl(t1, imm);
17367 gen_helper_wrdsp(t0, t1, cpu_env);
17368 break;
17369 case NM_EXTP:
17370 tcg_gen_movi_tl(t0, v2 >> 3);
17371 tcg_gen_movi_tl(t1, v1);
17372 gen_helper_extp(t0, t0, t1, cpu_env);
17373 gen_store_gpr(t0, ret);
17374 break;
17375 case NM_EXTPDP:
17376 tcg_gen_movi_tl(t0, v2 >> 3);
17377 tcg_gen_movi_tl(t1, v1);
17378 gen_helper_extpdp(t0, t0, t1, cpu_env);
17379 gen_store_gpr(t0, ret);
17380 break;
17382 break;
17383 case NM_POOL32AXF_1_4:
17384 check_dsp(ctx);
17385 tcg_gen_movi_tl(t0, v2 >> 2);
17386 switch (extract32(ctx->opcode, 12, 1)) {
17387 case NM_SHLL_QB:
17388 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
17389 gen_store_gpr(t0, ret);
17390 break;
17391 case NM_SHRL_QB:
17392 gen_helper_shrl_qb(t0, t0, v0_t);
17393 gen_store_gpr(t0, ret);
17394 break;
17396 break;
17397 case NM_POOL32AXF_1_5:
17398 opc = extract32(ctx->opcode, 12, 2);
17399 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
17400 break;
17401 case NM_POOL32AXF_1_7:
17402 check_dsp(ctx);
17403 tcg_gen_movi_tl(t0, v2 >> 3);
17404 tcg_gen_movi_tl(t1, v1);
17405 switch (extract32(ctx->opcode, 12, 2)) {
17406 case NM_EXTR_W:
17407 gen_helper_extr_w(t0, t0, t1, cpu_env);
17408 gen_store_gpr(t0, ret);
17409 break;
17410 case NM_EXTR_R_W:
17411 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
17412 gen_store_gpr(t0, ret);
17413 break;
17414 case NM_EXTR_RS_W:
17415 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
17416 gen_store_gpr(t0, ret);
17417 break;
17418 case NM_EXTR_S_H:
17419 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
17420 gen_store_gpr(t0, ret);
17421 break;
17423 break;
17424 default:
17425 generate_exception_end(ctx, EXCP_RI);
17426 break;
17429 tcg_temp_free(t0);
17430 tcg_temp_free(t1);
17431 tcg_temp_free(v0_t);
17434 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
17435 TCGv v0, TCGv v1, int rd)
17437 TCGv_i32 t0;
17439 t0 = tcg_temp_new_i32();
17441 tcg_gen_movi_i32(t0, rd >> 3);
17443 switch (opc) {
17444 case NM_POOL32AXF_2_0_7:
17445 switch (extract32(ctx->opcode, 9, 3)) {
17446 case NM_DPA_W_PH:
17447 check_dspr2(ctx);
17448 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
17449 break;
17450 case NM_DPAQ_S_W_PH:
17451 check_dsp(ctx);
17452 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
17453 break;
17454 case NM_DPS_W_PH:
17455 check_dspr2(ctx);
17456 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
17457 break;
17458 case NM_DPSQ_S_W_PH:
17459 check_dsp(ctx);
17460 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
17461 break;
17462 default:
17463 generate_exception_end(ctx, EXCP_RI);
17464 break;
17466 break;
17467 case NM_POOL32AXF_2_8_15:
17468 switch (extract32(ctx->opcode, 9, 3)) {
17469 case NM_DPAX_W_PH:
17470 check_dspr2(ctx);
17471 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
17472 break;
17473 case NM_DPAQ_SA_L_W:
17474 check_dsp(ctx);
17475 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
17476 break;
17477 case NM_DPSX_W_PH:
17478 check_dspr2(ctx);
17479 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
17480 break;
17481 case NM_DPSQ_SA_L_W:
17482 check_dsp(ctx);
17483 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
17484 break;
17485 default:
17486 generate_exception_end(ctx, EXCP_RI);
17487 break;
17489 break;
17490 case NM_POOL32AXF_2_16_23:
17491 switch (extract32(ctx->opcode, 9, 3)) {
17492 case NM_DPAU_H_QBL:
17493 check_dsp(ctx);
17494 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
17495 break;
17496 case NM_DPAQX_S_W_PH:
17497 check_dspr2(ctx);
17498 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
17499 break;
17500 case NM_DPSU_H_QBL:
17501 check_dsp(ctx);
17502 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
17503 break;
17504 case NM_DPSQX_S_W_PH:
17505 check_dspr2(ctx);
17506 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
17507 break;
17508 case NM_MULSA_W_PH:
17509 check_dspr2(ctx);
17510 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
17511 break;
17512 default:
17513 generate_exception_end(ctx, EXCP_RI);
17514 break;
17516 break;
17517 case NM_POOL32AXF_2_24_31:
17518 switch (extract32(ctx->opcode, 9, 3)) {
17519 case NM_DPAU_H_QBR:
17520 check_dsp(ctx);
17521 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
17522 break;
17523 case NM_DPAQX_SA_W_PH:
17524 check_dspr2(ctx);
17525 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
17526 break;
17527 case NM_DPSU_H_QBR:
17528 check_dsp(ctx);
17529 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
17530 break;
17531 case NM_DPSQX_SA_W_PH:
17532 check_dspr2(ctx);
17533 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
17534 break;
17535 case NM_MULSAQ_S_W_PH:
17536 check_dsp(ctx);
17537 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
17538 break;
17539 default:
17540 generate_exception_end(ctx, EXCP_RI);
17541 break;
17543 break;
17544 default:
17545 generate_exception_end(ctx, EXCP_RI);
17546 break;
17549 tcg_temp_free_i32(t0);
17552 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
17553 int rt, int rs, int rd)
17555 int ret = rt;
17556 TCGv t0 = tcg_temp_new();
17557 TCGv t1 = tcg_temp_new();
17558 TCGv v0_t = tcg_temp_new();
17559 TCGv v1_t = tcg_temp_new();
17561 gen_load_gpr(v0_t, rt);
17562 gen_load_gpr(v1_t, rs);
17564 switch (opc) {
17565 case NM_POOL32AXF_2_0_7:
17566 switch (extract32(ctx->opcode, 9, 3)) {
17567 case NM_DPA_W_PH:
17568 case NM_DPAQ_S_W_PH:
17569 case NM_DPS_W_PH:
17570 case NM_DPSQ_S_W_PH:
17571 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17572 break;
17573 case NM_BALIGN:
17574 check_dspr2(ctx);
17575 if (rt != 0) {
17576 gen_load_gpr(t0, rs);
17577 rd &= 3;
17578 if (rd != 0 && rd != 2) {
17579 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
17580 tcg_gen_ext32u_tl(t0, t0);
17581 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
17582 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
17584 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
17586 break;
17587 case NM_MADD:
17588 check_dsp(ctx);
17590 int acc = extract32(ctx->opcode, 14, 2);
17591 TCGv_i64 t2 = tcg_temp_new_i64();
17592 TCGv_i64 t3 = tcg_temp_new_i64();
17594 gen_load_gpr(t0, rt);
17595 gen_load_gpr(t1, rs);
17596 tcg_gen_ext_tl_i64(t2, t0);
17597 tcg_gen_ext_tl_i64(t3, t1);
17598 tcg_gen_mul_i64(t2, t2, t3);
17599 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17600 tcg_gen_add_i64(t2, t2, t3);
17601 tcg_temp_free_i64(t3);
17602 gen_move_low32(cpu_LO[acc], t2);
17603 gen_move_high32(cpu_HI[acc], t2);
17604 tcg_temp_free_i64(t2);
17606 break;
17607 case NM_MULT:
17608 check_dsp(ctx);
17610 int acc = extract32(ctx->opcode, 14, 2);
17611 TCGv_i32 t2 = tcg_temp_new_i32();
17612 TCGv_i32 t3 = tcg_temp_new_i32();
17614 gen_load_gpr(t0, rs);
17615 gen_load_gpr(t1, rt);
17616 tcg_gen_trunc_tl_i32(t2, t0);
17617 tcg_gen_trunc_tl_i32(t3, t1);
17618 tcg_gen_muls2_i32(t2, t3, t2, t3);
17619 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
17620 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
17621 tcg_temp_free_i32(t2);
17622 tcg_temp_free_i32(t3);
17624 break;
17625 case NM_EXTRV_W:
17626 check_dsp(ctx);
17627 gen_load_gpr(v1_t, rs);
17628 tcg_gen_movi_tl(t0, rd >> 3);
17629 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
17630 gen_store_gpr(t0, ret);
17631 break;
17633 break;
17634 case NM_POOL32AXF_2_8_15:
17635 switch (extract32(ctx->opcode, 9, 3)) {
17636 case NM_DPAX_W_PH:
17637 case NM_DPAQ_SA_L_W:
17638 case NM_DPSX_W_PH:
17639 case NM_DPSQ_SA_L_W:
17640 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17641 break;
17642 case NM_MADDU:
17643 check_dsp(ctx);
17645 int acc = extract32(ctx->opcode, 14, 2);
17646 TCGv_i64 t2 = tcg_temp_new_i64();
17647 TCGv_i64 t3 = tcg_temp_new_i64();
17649 gen_load_gpr(t0, rs);
17650 gen_load_gpr(t1, rt);
17651 tcg_gen_ext32u_tl(t0, t0);
17652 tcg_gen_ext32u_tl(t1, t1);
17653 tcg_gen_extu_tl_i64(t2, t0);
17654 tcg_gen_extu_tl_i64(t3, t1);
17655 tcg_gen_mul_i64(t2, t2, t3);
17656 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17657 tcg_gen_add_i64(t2, t2, t3);
17658 tcg_temp_free_i64(t3);
17659 gen_move_low32(cpu_LO[acc], t2);
17660 gen_move_high32(cpu_HI[acc], t2);
17661 tcg_temp_free_i64(t2);
17663 break;
17664 case NM_MULTU:
17665 check_dsp(ctx);
17667 int acc = extract32(ctx->opcode, 14, 2);
17668 TCGv_i32 t2 = tcg_temp_new_i32();
17669 TCGv_i32 t3 = tcg_temp_new_i32();
17671 gen_load_gpr(t0, rs);
17672 gen_load_gpr(t1, rt);
17673 tcg_gen_trunc_tl_i32(t2, t0);
17674 tcg_gen_trunc_tl_i32(t3, t1);
17675 tcg_gen_mulu2_i32(t2, t3, t2, t3);
17676 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
17677 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
17678 tcg_temp_free_i32(t2);
17679 tcg_temp_free_i32(t3);
17681 break;
17682 case NM_EXTRV_R_W:
17683 check_dsp(ctx);
17684 tcg_gen_movi_tl(t0, rd >> 3);
17685 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
17686 gen_store_gpr(t0, ret);
17687 break;
17688 default:
17689 generate_exception_end(ctx, EXCP_RI);
17690 break;
17692 break;
17693 case NM_POOL32AXF_2_16_23:
17694 switch (extract32(ctx->opcode, 9, 3)) {
17695 case NM_DPAU_H_QBL:
17696 case NM_DPAQX_S_W_PH:
17697 case NM_DPSU_H_QBL:
17698 case NM_DPSQX_S_W_PH:
17699 case NM_MULSA_W_PH:
17700 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17701 break;
17702 case NM_EXTPV:
17703 check_dsp(ctx);
17704 tcg_gen_movi_tl(t0, rd >> 3);
17705 gen_helper_extp(t0, t0, v1_t, cpu_env);
17706 gen_store_gpr(t0, ret);
17707 break;
17708 case NM_MSUB:
17709 check_dsp(ctx);
17711 int acc = extract32(ctx->opcode, 14, 2);
17712 TCGv_i64 t2 = tcg_temp_new_i64();
17713 TCGv_i64 t3 = tcg_temp_new_i64();
17715 gen_load_gpr(t0, rs);
17716 gen_load_gpr(t1, rt);
17717 tcg_gen_ext_tl_i64(t2, t0);
17718 tcg_gen_ext_tl_i64(t3, t1);
17719 tcg_gen_mul_i64(t2, t2, t3);
17720 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17721 tcg_gen_sub_i64(t2, t3, t2);
17722 tcg_temp_free_i64(t3);
17723 gen_move_low32(cpu_LO[acc], t2);
17724 gen_move_high32(cpu_HI[acc], t2);
17725 tcg_temp_free_i64(t2);
17727 break;
17728 case NM_EXTRV_RS_W:
17729 check_dsp(ctx);
17730 tcg_gen_movi_tl(t0, rd >> 3);
17731 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
17732 gen_store_gpr(t0, ret);
17733 break;
17735 break;
17736 case NM_POOL32AXF_2_24_31:
17737 switch (extract32(ctx->opcode, 9, 3)) {
17738 case NM_DPAU_H_QBR:
17739 case NM_DPAQX_SA_W_PH:
17740 case NM_DPSU_H_QBR:
17741 case NM_DPSQX_SA_W_PH:
17742 case NM_MULSAQ_S_W_PH:
17743 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
17744 break;
17745 case NM_EXTPDPV:
17746 check_dsp(ctx);
17747 tcg_gen_movi_tl(t0, rd >> 3);
17748 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
17749 gen_store_gpr(t0, ret);
17750 break;
17751 case NM_MSUBU:
17752 check_dsp(ctx);
17754 int acc = extract32(ctx->opcode, 14, 2);
17755 TCGv_i64 t2 = tcg_temp_new_i64();
17756 TCGv_i64 t3 = tcg_temp_new_i64();
17758 gen_load_gpr(t0, rs);
17759 gen_load_gpr(t1, rt);
17760 tcg_gen_ext32u_tl(t0, t0);
17761 tcg_gen_ext32u_tl(t1, t1);
17762 tcg_gen_extu_tl_i64(t2, t0);
17763 tcg_gen_extu_tl_i64(t3, t1);
17764 tcg_gen_mul_i64(t2, t2, t3);
17765 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
17766 tcg_gen_sub_i64(t2, t3, t2);
17767 tcg_temp_free_i64(t3);
17768 gen_move_low32(cpu_LO[acc], t2);
17769 gen_move_high32(cpu_HI[acc], t2);
17770 tcg_temp_free_i64(t2);
17772 break;
17773 case NM_EXTRV_S_H:
17774 check_dsp(ctx);
17775 tcg_gen_movi_tl(t0, rd >> 3);
17776 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
17777 gen_store_gpr(t0, ret);
17778 break;
17780 break;
17781 default:
17782 generate_exception_end(ctx, EXCP_RI);
17783 break;
17786 tcg_temp_free(t0);
17787 tcg_temp_free(t1);
17789 tcg_temp_free(v0_t);
17790 tcg_temp_free(v1_t);
17793 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
17794 int rt, int rs)
17796 int ret = rt;
17797 TCGv t0 = tcg_temp_new();
17798 TCGv v0_t = tcg_temp_new();
17800 gen_load_gpr(v0_t, rs);
17802 switch (opc) {
17803 case NM_ABSQ_S_QB:
17804 check_dspr2(ctx);
17805 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
17806 gen_store_gpr(v0_t, ret);
17807 break;
17808 case NM_ABSQ_S_PH:
17809 check_dsp(ctx);
17810 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
17811 gen_store_gpr(v0_t, ret);
17812 break;
17813 case NM_ABSQ_S_W:
17814 check_dsp(ctx);
17815 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
17816 gen_store_gpr(v0_t, ret);
17817 break;
17818 case NM_PRECEQ_W_PHL:
17819 check_dsp(ctx);
17820 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
17821 tcg_gen_ext32s_tl(v0_t, v0_t);
17822 gen_store_gpr(v0_t, ret);
17823 break;
17824 case NM_PRECEQ_W_PHR:
17825 check_dsp(ctx);
17826 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
17827 tcg_gen_shli_tl(v0_t, v0_t, 16);
17828 tcg_gen_ext32s_tl(v0_t, v0_t);
17829 gen_store_gpr(v0_t, ret);
17830 break;
17831 case NM_PRECEQU_PH_QBL:
17832 check_dsp(ctx);
17833 gen_helper_precequ_ph_qbl(v0_t, v0_t);
17834 gen_store_gpr(v0_t, ret);
17835 break;
17836 case NM_PRECEQU_PH_QBR:
17837 check_dsp(ctx);
17838 gen_helper_precequ_ph_qbr(v0_t, v0_t);
17839 gen_store_gpr(v0_t, ret);
17840 break;
17841 case NM_PRECEQU_PH_QBLA:
17842 check_dsp(ctx);
17843 gen_helper_precequ_ph_qbla(v0_t, v0_t);
17844 gen_store_gpr(v0_t, ret);
17845 break;
17846 case NM_PRECEQU_PH_QBRA:
17847 check_dsp(ctx);
17848 gen_helper_precequ_ph_qbra(v0_t, v0_t);
17849 gen_store_gpr(v0_t, ret);
17850 break;
17851 case NM_PRECEU_PH_QBL:
17852 check_dsp(ctx);
17853 gen_helper_preceu_ph_qbl(v0_t, v0_t);
17854 gen_store_gpr(v0_t, ret);
17855 break;
17856 case NM_PRECEU_PH_QBR:
17857 check_dsp(ctx);
17858 gen_helper_preceu_ph_qbr(v0_t, v0_t);
17859 gen_store_gpr(v0_t, ret);
17860 break;
17861 case NM_PRECEU_PH_QBLA:
17862 check_dsp(ctx);
17863 gen_helper_preceu_ph_qbla(v0_t, v0_t);
17864 gen_store_gpr(v0_t, ret);
17865 break;
17866 case NM_PRECEU_PH_QBRA:
17867 check_dsp(ctx);
17868 gen_helper_preceu_ph_qbra(v0_t, v0_t);
17869 gen_store_gpr(v0_t, ret);
17870 break;
17871 case NM_REPLV_PH:
17872 check_dsp(ctx);
17873 tcg_gen_ext16u_tl(v0_t, v0_t);
17874 tcg_gen_shli_tl(t0, v0_t, 16);
17875 tcg_gen_or_tl(v0_t, v0_t, t0);
17876 tcg_gen_ext32s_tl(v0_t, v0_t);
17877 gen_store_gpr(v0_t, ret);
17878 break;
17879 case NM_REPLV_QB:
17880 check_dsp(ctx);
17881 tcg_gen_ext8u_tl(v0_t, v0_t);
17882 tcg_gen_shli_tl(t0, v0_t, 8);
17883 tcg_gen_or_tl(v0_t, v0_t, t0);
17884 tcg_gen_shli_tl(t0, v0_t, 16);
17885 tcg_gen_or_tl(v0_t, v0_t, t0);
17886 tcg_gen_ext32s_tl(v0_t, v0_t);
17887 gen_store_gpr(v0_t, ret);
17888 break;
17889 case NM_BITREV:
17890 check_dsp(ctx);
17891 gen_helper_bitrev(v0_t, v0_t);
17892 gen_store_gpr(v0_t, ret);
17893 break;
17894 case NM_INSV:
17895 check_dsp(ctx);
17897 TCGv tv0 = tcg_temp_new();
17899 gen_load_gpr(tv0, rt);
17900 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
17901 gen_store_gpr(v0_t, ret);
17902 tcg_temp_free(tv0);
17904 break;
17905 case NM_RADDU_W_QB:
17906 check_dsp(ctx);
17907 gen_helper_raddu_w_qb(v0_t, v0_t);
17908 gen_store_gpr(v0_t, ret);
17909 break;
17910 case NM_BITSWAP:
17911 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
17912 break;
17913 case NM_CLO:
17914 check_nms(ctx);
17915 gen_cl(ctx, OPC_CLO, ret, rs);
17916 break;
17917 case NM_CLZ:
17918 check_nms(ctx);
17919 gen_cl(ctx, OPC_CLZ, ret, rs);
17920 break;
17921 case NM_WSBH:
17922 gen_bshfl(ctx, OPC_WSBH, ret, rs);
17923 break;
17924 default:
17925 generate_exception_end(ctx, EXCP_RI);
17926 break;
17929 tcg_temp_free(v0_t);
17930 tcg_temp_free(t0);
17933 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
17934 int rt, int rs, int rd)
17936 TCGv t0 = tcg_temp_new();
17937 TCGv rs_t = tcg_temp_new();
17939 gen_load_gpr(rs_t, rs);
17941 switch (opc) {
17942 case NM_SHRA_R_QB:
17943 check_dspr2(ctx);
17944 tcg_gen_movi_tl(t0, rd >> 2);
17945 switch (extract32(ctx->opcode, 12, 1)) {
17946 case 0:
17947 /* NM_SHRA_QB */
17948 gen_helper_shra_qb(t0, t0, rs_t);
17949 gen_store_gpr(t0, rt);
17950 break;
17951 case 1:
17952 /* NM_SHRA_R_QB */
17953 gen_helper_shra_r_qb(t0, t0, rs_t);
17954 gen_store_gpr(t0, rt);
17955 break;
17957 break;
17958 case NM_SHRL_PH:
17959 check_dspr2(ctx);
17960 tcg_gen_movi_tl(t0, rd >> 1);
17961 gen_helper_shrl_ph(t0, t0, rs_t);
17962 gen_store_gpr(t0, rt);
17963 break;
17964 case NM_REPL_QB:
17965 check_dsp(ctx);
17967 int16_t imm;
17968 target_long result;
17969 imm = extract32(ctx->opcode, 13, 8);
17970 result = (uint32_t)imm << 24 |
17971 (uint32_t)imm << 16 |
17972 (uint32_t)imm << 8 |
17973 (uint32_t)imm;
17974 result = (int32_t)result;
17975 tcg_gen_movi_tl(t0, result);
17976 gen_store_gpr(t0, rt);
17978 break;
17979 default:
17980 generate_exception_end(ctx, EXCP_RI);
17981 break;
17983 tcg_temp_free(t0);
17984 tcg_temp_free(rs_t);
17988 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17990 int rt = extract32(ctx->opcode, 21, 5);
17991 int rs = extract32(ctx->opcode, 16, 5);
17992 int rd = extract32(ctx->opcode, 11, 5);
17994 switch (extract32(ctx->opcode, 6, 3)) {
17995 case NM_POOL32AXF_1:
17997 int32_t op1 = extract32(ctx->opcode, 9, 3);
17998 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18000 break;
18001 case NM_POOL32AXF_2:
18003 int32_t op1 = extract32(ctx->opcode, 12, 2);
18004 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18006 break;
18007 case NM_POOL32AXF_4:
18009 int32_t op1 = extract32(ctx->opcode, 9, 7);
18010 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18012 break;
18013 case NM_POOL32AXF_5:
18014 switch (extract32(ctx->opcode, 9, 7)) {
18015 #ifndef CONFIG_USER_ONLY
18016 case NM_TLBP:
18017 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18018 break;
18019 case NM_TLBR:
18020 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18021 break;
18022 case NM_TLBWI:
18023 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18024 break;
18025 case NM_TLBWR:
18026 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18027 break;
18028 case NM_TLBINV:
18029 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18030 break;
18031 case NM_TLBINVF:
18032 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18033 break;
18034 case NM_DI:
18035 check_cp0_enabled(ctx);
18037 TCGv t0 = tcg_temp_new();
18039 save_cpu_state(ctx, 1);
18040 gen_helper_di(t0, cpu_env);
18041 gen_store_gpr(t0, rt);
18042 /* Stop translation as we may have switched the execution mode */
18043 ctx->base.is_jmp = DISAS_STOP;
18044 tcg_temp_free(t0);
18046 break;
18047 case NM_EI:
18048 check_cp0_enabled(ctx);
18050 TCGv t0 = tcg_temp_new();
18052 save_cpu_state(ctx, 1);
18053 gen_helper_ei(t0, cpu_env);
18054 gen_store_gpr(t0, rt);
18055 /* Stop translation as we may have switched the execution mode */
18056 ctx->base.is_jmp = DISAS_STOP;
18057 tcg_temp_free(t0);
18059 break;
18060 case NM_RDPGPR:
18061 gen_load_srsgpr(rs, rt);
18062 break;
18063 case NM_WRPGPR:
18064 gen_store_srsgpr(rs, rt);
18065 break;
18066 case NM_WAIT:
18067 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18068 break;
18069 case NM_DERET:
18070 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18071 break;
18072 case NM_ERETX:
18073 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18074 break;
18075 #endif
18076 default:
18077 generate_exception_end(ctx, EXCP_RI);
18078 break;
18080 break;
18081 case NM_POOL32AXF_7:
18083 int32_t op1 = extract32(ctx->opcode, 9, 3);
18084 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18086 break;
18087 default:
18088 generate_exception_end(ctx, EXCP_RI);
18089 break;
18093 /* Immediate Value Compact Branches */
18094 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
18095 int rt, int32_t imm, int32_t offset)
18097 TCGCond cond;
18098 int bcond_compute = 0;
18099 TCGv t0 = tcg_temp_new();
18100 TCGv t1 = tcg_temp_new();
18102 gen_load_gpr(t0, rt);
18103 tcg_gen_movi_tl(t1, imm);
18104 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18106 /* Load needed operands and calculate btarget */
18107 switch (opc) {
18108 case NM_BEQIC:
18109 if (rt == 0 && imm == 0) {
18110 /* Unconditional branch */
18111 } else if (rt == 0 && imm != 0) {
18112 /* Treat as NOP */
18113 goto out;
18114 } else {
18115 bcond_compute = 1;
18116 cond = TCG_COND_EQ;
18118 break;
18119 case NM_BBEQZC:
18120 case NM_BBNEZC:
18121 check_nms(ctx);
18122 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
18123 generate_exception_end(ctx, EXCP_RI);
18124 goto out;
18125 } else if (rt == 0 && opc == NM_BBEQZC) {
18126 /* Unconditional branch */
18127 } else if (rt == 0 && opc == NM_BBNEZC) {
18128 /* Treat as NOP */
18129 goto out;
18130 } else {
18131 tcg_gen_shri_tl(t0, t0, imm);
18132 tcg_gen_andi_tl(t0, t0, 1);
18133 tcg_gen_movi_tl(t1, 0);
18134 bcond_compute = 1;
18135 if (opc == NM_BBEQZC) {
18136 cond = TCG_COND_EQ;
18137 } else {
18138 cond = TCG_COND_NE;
18141 break;
18142 case NM_BNEIC:
18143 if (rt == 0 && imm == 0) {
18144 /* Treat as NOP */
18145 goto out;
18146 } else if (rt == 0 && imm != 0) {
18147 /* Unconditional branch */
18148 } else {
18149 bcond_compute = 1;
18150 cond = TCG_COND_NE;
18152 break;
18153 case NM_BGEIC:
18154 if (rt == 0 && imm == 0) {
18155 /* Unconditional branch */
18156 } else {
18157 bcond_compute = 1;
18158 cond = TCG_COND_GE;
18160 break;
18161 case NM_BLTIC:
18162 bcond_compute = 1;
18163 cond = TCG_COND_LT;
18164 break;
18165 case NM_BGEIUC:
18166 if (rt == 0 && imm == 0) {
18167 /* Unconditional branch */
18168 } else {
18169 bcond_compute = 1;
18170 cond = TCG_COND_GEU;
18172 break;
18173 case NM_BLTIUC:
18174 bcond_compute = 1;
18175 cond = TCG_COND_LTU;
18176 break;
18177 default:
18178 MIPS_INVAL("Immediate Value Compact branch");
18179 generate_exception_end(ctx, EXCP_RI);
18180 goto out;
18183 if (bcond_compute == 0) {
18184 /* Uncoditional compact branch */
18185 gen_goto_tb(ctx, 0, ctx->btarget);
18186 } else {
18187 /* Conditional compact branch */
18188 TCGLabel *fs = gen_new_label();
18190 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
18192 gen_goto_tb(ctx, 1, ctx->btarget);
18193 gen_set_label(fs);
18195 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
18198 out:
18199 tcg_temp_free(t0);
18200 tcg_temp_free(t1);
18203 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
18204 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
18205 int rt)
18207 TCGv t0 = tcg_temp_new();
18208 TCGv t1 = tcg_temp_new();
18210 /* load rs */
18211 gen_load_gpr(t0, rs);
18213 /* link */
18214 if (rt != 0) {
18215 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
18218 /* calculate btarget */
18219 tcg_gen_shli_tl(t0, t0, 1);
18220 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
18221 gen_op_addr_add(ctx, btarget, t1, t0);
18223 /* unconditional branch to register */
18224 tcg_gen_mov_tl(cpu_PC, btarget);
18225 tcg_gen_lookup_and_goto_ptr();
18227 tcg_temp_free(t0);
18228 tcg_temp_free(t1);
18231 /* nanoMIPS Branches */
18232 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
18233 int rs, int rt, int32_t offset)
18235 int bcond_compute = 0;
18236 TCGv t0 = tcg_temp_new();
18237 TCGv t1 = tcg_temp_new();
18239 /* Load needed operands and calculate btarget */
18240 switch (opc) {
18241 /* compact branch */
18242 case OPC_BGEC:
18243 case OPC_BLTC:
18244 gen_load_gpr(t0, rs);
18245 gen_load_gpr(t1, rt);
18246 bcond_compute = 1;
18247 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18248 break;
18249 case OPC_BGEUC:
18250 case OPC_BLTUC:
18251 if (rs == 0 || rs == rt) {
18252 /* OPC_BLEZALC, OPC_BGEZALC */
18253 /* OPC_BGTZALC, OPC_BLTZALC */
18254 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
18256 gen_load_gpr(t0, rs);
18257 gen_load_gpr(t1, rt);
18258 bcond_compute = 1;
18259 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18260 break;
18261 case OPC_BC:
18262 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18263 break;
18264 case OPC_BEQZC:
18265 if (rs != 0) {
18266 /* OPC_BEQZC, OPC_BNEZC */
18267 gen_load_gpr(t0, rs);
18268 bcond_compute = 1;
18269 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18270 } else {
18271 /* OPC_JIC, OPC_JIALC */
18272 TCGv tbase = tcg_temp_new();
18273 TCGv toffset = tcg_temp_new();
18275 gen_load_gpr(tbase, rt);
18276 tcg_gen_movi_tl(toffset, offset);
18277 gen_op_addr_add(ctx, btarget, tbase, toffset);
18278 tcg_temp_free(tbase);
18279 tcg_temp_free(toffset);
18281 break;
18282 default:
18283 MIPS_INVAL("Compact branch/jump");
18284 generate_exception_end(ctx, EXCP_RI);
18285 goto out;
18288 if (bcond_compute == 0) {
18289 /* Uncoditional compact branch */
18290 switch (opc) {
18291 case OPC_BC:
18292 gen_goto_tb(ctx, 0, ctx->btarget);
18293 break;
18294 default:
18295 MIPS_INVAL("Compact branch/jump");
18296 generate_exception_end(ctx, EXCP_RI);
18297 goto out;
18299 } else {
18300 /* Conditional compact branch */
18301 TCGLabel *fs = gen_new_label();
18303 switch (opc) {
18304 case OPC_BGEUC:
18305 if (rs == 0 && rt != 0) {
18306 /* OPC_BLEZALC */
18307 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18308 } else if (rs != 0 && rt != 0 && rs == rt) {
18309 /* OPC_BGEZALC */
18310 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18311 } else {
18312 /* OPC_BGEUC */
18313 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
18315 break;
18316 case OPC_BLTUC:
18317 if (rs == 0 && rt != 0) {
18318 /* OPC_BGTZALC */
18319 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18320 } else if (rs != 0 && rt != 0 && rs == rt) {
18321 /* OPC_BLTZALC */
18322 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
18323 } else {
18324 /* OPC_BLTUC */
18325 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
18327 break;
18328 case OPC_BGEC:
18329 if (rs == 0 && rt != 0) {
18330 /* OPC_BLEZC */
18331 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18332 } else if (rs != 0 && rt != 0 && rs == rt) {
18333 /* OPC_BGEZC */
18334 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18335 } else {
18336 /* OPC_BGEC */
18337 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
18339 break;
18340 case OPC_BLTC:
18341 if (rs == 0 && rt != 0) {
18342 /* OPC_BGTZC */
18343 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18344 } else if (rs != 0 && rt != 0 && rs == rt) {
18345 /* OPC_BLTZC */
18346 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
18347 } else {
18348 /* OPC_BLTC */
18349 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
18351 break;
18352 case OPC_BEQZC:
18353 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
18354 break;
18355 default:
18356 MIPS_INVAL("Compact conditional branch/jump");
18357 generate_exception_end(ctx, EXCP_RI);
18358 goto out;
18361 /* Generating branch here as compact branches don't have delay slot */
18362 gen_goto_tb(ctx, 1, ctx->btarget);
18363 gen_set_label(fs);
18365 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
18368 out:
18369 tcg_temp_free(t0);
18370 tcg_temp_free(t1);
18374 /* nanoMIPS CP1 Branches */
18375 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
18376 int32_t ft, int32_t offset)
18378 target_ulong btarget;
18379 TCGv_i64 t0 = tcg_temp_new_i64();
18381 gen_load_fpr64(ctx, t0, ft);
18382 tcg_gen_andi_i64(t0, t0, 1);
18384 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18386 switch (op) {
18387 case NM_BC1EQZC:
18388 tcg_gen_xori_i64(t0, t0, 1);
18389 ctx->hflags |= MIPS_HFLAG_BC;
18390 break;
18391 case NM_BC1NEZC:
18392 /* t0 already set */
18393 ctx->hflags |= MIPS_HFLAG_BC;
18394 break;
18395 default:
18396 MIPS_INVAL("cp1 cond branch");
18397 generate_exception_end(ctx, EXCP_RI);
18398 goto out;
18401 tcg_gen_trunc_i64_tl(bcond, t0);
18403 ctx->btarget = btarget;
18405 out:
18406 tcg_temp_free_i64(t0);
18410 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
18412 TCGv t0, t1;
18413 t0 = tcg_temp_new();
18414 t1 = tcg_temp_new();
18416 gen_load_gpr(t0, rs);
18417 gen_load_gpr(t1, rt);
18419 if ((extract32(ctx->opcode, 6, 1)) == 1) {
18420 /* PP.LSXS instructions require shifting */
18421 switch (extract32(ctx->opcode, 7, 4)) {
18422 case NM_SHXS:
18423 check_nms(ctx);
18424 case NM_LHXS:
18425 case NM_LHUXS:
18426 tcg_gen_shli_tl(t0, t0, 1);
18427 break;
18428 case NM_SWXS:
18429 check_nms(ctx);
18430 case NM_LWXS:
18431 case NM_LWC1XS:
18432 case NM_SWC1XS:
18433 tcg_gen_shli_tl(t0, t0, 2);
18434 break;
18435 case NM_LDC1XS:
18436 case NM_SDC1XS:
18437 tcg_gen_shli_tl(t0, t0, 3);
18438 break;
18441 gen_op_addr_add(ctx, t0, t0, t1);
18443 switch (extract32(ctx->opcode, 7, 4)) {
18444 case NM_LBX:
18445 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18446 MO_SB);
18447 gen_store_gpr(t0, rd);
18448 break;
18449 case NM_LHX:
18450 /*case NM_LHXS:*/
18451 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18452 MO_TESW);
18453 gen_store_gpr(t0, rd);
18454 break;
18455 case NM_LWX:
18456 /*case NM_LWXS:*/
18457 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18458 MO_TESL);
18459 gen_store_gpr(t0, rd);
18460 break;
18461 case NM_LBUX:
18462 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18463 MO_UB);
18464 gen_store_gpr(t0, rd);
18465 break;
18466 case NM_LHUX:
18467 /*case NM_LHUXS:*/
18468 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
18469 MO_TEUW);
18470 gen_store_gpr(t0, rd);
18471 break;
18472 case NM_SBX:
18473 check_nms(ctx);
18474 gen_load_gpr(t1, rd);
18475 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18476 MO_8);
18477 break;
18478 case NM_SHX:
18479 /*case NM_SHXS:*/
18480 check_nms(ctx);
18481 gen_load_gpr(t1, rd);
18482 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18483 MO_TEUW);
18484 break;
18485 case NM_SWX:
18486 /*case NM_SWXS:*/
18487 check_nms(ctx);
18488 gen_load_gpr(t1, rd);
18489 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
18490 MO_TEUL);
18491 break;
18492 case NM_LWC1X:
18493 /*case NM_LWC1XS:*/
18494 case NM_LDC1X:
18495 /*case NM_LDC1XS:*/
18496 case NM_SWC1X:
18497 /*case NM_SWC1XS:*/
18498 case NM_SDC1X:
18499 /*case NM_SDC1XS:*/
18500 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
18501 check_cp1_enabled(ctx);
18502 switch (extract32(ctx->opcode, 7, 4)) {
18503 case NM_LWC1X:
18504 /*case NM_LWC1XS:*/
18505 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
18506 break;
18507 case NM_LDC1X:
18508 /*case NM_LDC1XS:*/
18509 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
18510 break;
18511 case NM_SWC1X:
18512 /*case NM_SWC1XS:*/
18513 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
18514 break;
18515 case NM_SDC1X:
18516 /*case NM_SDC1XS:*/
18517 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
18518 break;
18520 } else {
18521 generate_exception_err(ctx, EXCP_CpU, 1);
18523 break;
18524 default:
18525 generate_exception_end(ctx, EXCP_RI);
18526 break;
18529 tcg_temp_free(t0);
18530 tcg_temp_free(t1);
18533 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
18535 int rt, rs, rd;
18537 rt = extract32(ctx->opcode, 21, 5);
18538 rs = extract32(ctx->opcode, 16, 5);
18539 rd = extract32(ctx->opcode, 11, 5);
18541 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
18542 generate_exception_end(ctx, EXCP_RI);
18543 return;
18545 check_cp1_enabled(ctx);
18546 switch (extract32(ctx->opcode, 0, 3)) {
18547 case NM_POOL32F_0:
18548 switch (extract32(ctx->opcode, 3, 7)) {
18549 case NM_RINT_S:
18550 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
18551 break;
18552 case NM_RINT_D:
18553 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
18554 break;
18555 case NM_CLASS_S:
18556 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
18557 break;
18558 case NM_CLASS_D:
18559 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
18560 break;
18561 case NM_ADD_S:
18562 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
18563 break;
18564 case NM_ADD_D:
18565 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
18566 break;
18567 case NM_SUB_S:
18568 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
18569 break;
18570 case NM_SUB_D:
18571 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
18572 break;
18573 case NM_MUL_S:
18574 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
18575 break;
18576 case NM_MUL_D:
18577 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
18578 break;
18579 case NM_DIV_S:
18580 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
18581 break;
18582 case NM_DIV_D:
18583 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
18584 break;
18585 case NM_SELEQZ_S:
18586 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
18587 break;
18588 case NM_SELEQZ_D:
18589 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
18590 break;
18591 case NM_SELNEZ_S:
18592 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
18593 break;
18594 case NM_SELNEZ_D:
18595 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
18596 break;
18597 case NM_SEL_S:
18598 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
18599 break;
18600 case NM_SEL_D:
18601 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
18602 break;
18603 case NM_MADDF_S:
18604 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
18605 break;
18606 case NM_MADDF_D:
18607 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
18608 break;
18609 case NM_MSUBF_S:
18610 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
18611 break;
18612 case NM_MSUBF_D:
18613 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
18614 break;
18615 default:
18616 generate_exception_end(ctx, EXCP_RI);
18617 break;
18619 break;
18620 case NM_POOL32F_3:
18621 switch (extract32(ctx->opcode, 3, 3)) {
18622 case NM_MIN_FMT:
18623 switch (extract32(ctx->opcode, 9, 1)) {
18624 case FMT_SDPS_S:
18625 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
18626 break;
18627 case FMT_SDPS_D:
18628 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
18629 break;
18631 break;
18632 case NM_MAX_FMT:
18633 switch (extract32(ctx->opcode, 9, 1)) {
18634 case FMT_SDPS_S:
18635 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
18636 break;
18637 case FMT_SDPS_D:
18638 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
18639 break;
18641 break;
18642 case NM_MINA_FMT:
18643 switch (extract32(ctx->opcode, 9, 1)) {
18644 case FMT_SDPS_S:
18645 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
18646 break;
18647 case FMT_SDPS_D:
18648 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
18649 break;
18651 break;
18652 case NM_MAXA_FMT:
18653 switch (extract32(ctx->opcode, 9, 1)) {
18654 case FMT_SDPS_S:
18655 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
18656 break;
18657 case FMT_SDPS_D:
18658 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
18659 break;
18661 break;
18662 case NM_POOL32FXF:
18663 switch (extract32(ctx->opcode, 6, 8)) {
18664 case NM_CFC1:
18665 gen_cp1(ctx, OPC_CFC1, rt, rs);
18666 break;
18667 case NM_CTC1:
18668 gen_cp1(ctx, OPC_CTC1, rt, rs);
18669 break;
18670 case NM_MFC1:
18671 gen_cp1(ctx, OPC_MFC1, rt, rs);
18672 break;
18673 case NM_MTC1:
18674 gen_cp1(ctx, OPC_MTC1, rt, rs);
18675 break;
18676 case NM_MFHC1:
18677 gen_cp1(ctx, OPC_MFHC1, rt, rs);
18678 break;
18679 case NM_MTHC1:
18680 gen_cp1(ctx, OPC_MTHC1, rt, rs);
18681 break;
18682 case NM_CVT_S_PL:
18683 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
18684 break;
18685 case NM_CVT_S_PU:
18686 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
18687 break;
18688 default:
18689 switch (extract32(ctx->opcode, 6, 9)) {
18690 case NM_CVT_L_S:
18691 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
18692 break;
18693 case NM_CVT_L_D:
18694 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
18695 break;
18696 case NM_CVT_W_S:
18697 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
18698 break;
18699 case NM_CVT_W_D:
18700 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
18701 break;
18702 case NM_RSQRT_S:
18703 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
18704 break;
18705 case NM_RSQRT_D:
18706 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
18707 break;
18708 case NM_SQRT_S:
18709 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
18710 break;
18711 case NM_SQRT_D:
18712 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
18713 break;
18714 case NM_RECIP_S:
18715 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
18716 break;
18717 case NM_RECIP_D:
18718 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
18719 break;
18720 case NM_FLOOR_L_S:
18721 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
18722 break;
18723 case NM_FLOOR_L_D:
18724 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
18725 break;
18726 case NM_FLOOR_W_S:
18727 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
18728 break;
18729 case NM_FLOOR_W_D:
18730 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
18731 break;
18732 case NM_CEIL_L_S:
18733 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
18734 break;
18735 case NM_CEIL_L_D:
18736 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
18737 break;
18738 case NM_CEIL_W_S:
18739 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
18740 break;
18741 case NM_CEIL_W_D:
18742 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
18743 break;
18744 case NM_TRUNC_L_S:
18745 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
18746 break;
18747 case NM_TRUNC_L_D:
18748 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
18749 break;
18750 case NM_TRUNC_W_S:
18751 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
18752 break;
18753 case NM_TRUNC_W_D:
18754 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
18755 break;
18756 case NM_ROUND_L_S:
18757 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
18758 break;
18759 case NM_ROUND_L_D:
18760 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
18761 break;
18762 case NM_ROUND_W_S:
18763 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
18764 break;
18765 case NM_ROUND_W_D:
18766 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
18767 break;
18768 case NM_MOV_S:
18769 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
18770 break;
18771 case NM_MOV_D:
18772 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
18773 break;
18774 case NM_ABS_S:
18775 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
18776 break;
18777 case NM_ABS_D:
18778 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
18779 break;
18780 case NM_NEG_S:
18781 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
18782 break;
18783 case NM_NEG_D:
18784 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
18785 break;
18786 case NM_CVT_D_S:
18787 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
18788 break;
18789 case NM_CVT_D_W:
18790 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
18791 break;
18792 case NM_CVT_D_L:
18793 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
18794 break;
18795 case NM_CVT_S_D:
18796 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
18797 break;
18798 case NM_CVT_S_W:
18799 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
18800 break;
18801 case NM_CVT_S_L:
18802 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
18803 break;
18804 default:
18805 generate_exception_end(ctx, EXCP_RI);
18806 break;
18808 break;
18810 break;
18812 break;
18813 case NM_POOL32F_5:
18814 switch (extract32(ctx->opcode, 3, 3)) {
18815 case NM_CMP_CONDN_S:
18816 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
18817 break;
18818 case NM_CMP_CONDN_D:
18819 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
18820 break;
18821 default:
18822 generate_exception_end(ctx, EXCP_RI);
18823 break;
18825 break;
18826 default:
18827 generate_exception_end(ctx, EXCP_RI);
18828 break;
18832 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
18833 int rd, int rs, int rt)
18835 int ret = rd;
18836 TCGv t0 = tcg_temp_new();
18837 TCGv v1_t = tcg_temp_new();
18838 TCGv v2_t = tcg_temp_new();
18840 gen_load_gpr(v1_t, rs);
18841 gen_load_gpr(v2_t, rt);
18843 switch (opc) {
18844 case NM_CMP_EQ_PH:
18845 check_dsp(ctx);
18846 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
18847 break;
18848 case NM_CMP_LT_PH:
18849 check_dsp(ctx);
18850 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
18851 break;
18852 case NM_CMP_LE_PH:
18853 check_dsp(ctx);
18854 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
18855 break;
18856 case NM_CMPU_EQ_QB:
18857 check_dsp(ctx);
18858 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
18859 break;
18860 case NM_CMPU_LT_QB:
18861 check_dsp(ctx);
18862 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
18863 break;
18864 case NM_CMPU_LE_QB:
18865 check_dsp(ctx);
18866 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
18867 break;
18868 case NM_CMPGU_EQ_QB:
18869 check_dsp(ctx);
18870 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
18871 gen_store_gpr(v1_t, ret);
18872 break;
18873 case NM_CMPGU_LT_QB:
18874 check_dsp(ctx);
18875 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
18876 gen_store_gpr(v1_t, ret);
18877 break;
18878 case NM_CMPGU_LE_QB:
18879 check_dsp(ctx);
18880 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
18881 gen_store_gpr(v1_t, ret);
18882 break;
18883 case NM_CMPGDU_EQ_QB:
18884 check_dspr2(ctx);
18885 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
18886 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
18887 gen_store_gpr(v1_t, ret);
18888 break;
18889 case NM_CMPGDU_LT_QB:
18890 check_dspr2(ctx);
18891 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
18892 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
18893 gen_store_gpr(v1_t, ret);
18894 break;
18895 case NM_CMPGDU_LE_QB:
18896 check_dspr2(ctx);
18897 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
18898 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
18899 gen_store_gpr(v1_t, ret);
18900 break;
18901 case NM_PACKRL_PH:
18902 check_dsp(ctx);
18903 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
18904 gen_store_gpr(v1_t, ret);
18905 break;
18906 case NM_PICK_QB:
18907 check_dsp(ctx);
18908 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
18909 gen_store_gpr(v1_t, ret);
18910 break;
18911 case NM_PICK_PH:
18912 check_dsp(ctx);
18913 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
18914 gen_store_gpr(v1_t, ret);
18915 break;
18916 case NM_ADDQ_S_W:
18917 check_dsp(ctx);
18918 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
18919 gen_store_gpr(v1_t, ret);
18920 break;
18921 case NM_SUBQ_S_W:
18922 check_dsp(ctx);
18923 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
18924 gen_store_gpr(v1_t, ret);
18925 break;
18926 case NM_ADDSC:
18927 check_dsp(ctx);
18928 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
18929 gen_store_gpr(v1_t, ret);
18930 break;
18931 case NM_ADDWC:
18932 check_dsp(ctx);
18933 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
18934 gen_store_gpr(v1_t, ret);
18935 break;
18936 case NM_ADDQ_S_PH:
18937 check_dsp(ctx);
18938 switch (extract32(ctx->opcode, 10, 1)) {
18939 case 0:
18940 /* ADDQ_PH */
18941 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
18942 gen_store_gpr(v1_t, ret);
18943 break;
18944 case 1:
18945 /* ADDQ_S_PH */
18946 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
18947 gen_store_gpr(v1_t, ret);
18948 break;
18950 break;
18951 case NM_ADDQH_R_PH:
18952 check_dspr2(ctx);
18953 switch (extract32(ctx->opcode, 10, 1)) {
18954 case 0:
18955 /* ADDQH_PH */
18956 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
18957 gen_store_gpr(v1_t, ret);
18958 break;
18959 case 1:
18960 /* ADDQH_R_PH */
18961 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
18962 gen_store_gpr(v1_t, ret);
18963 break;
18965 break;
18966 case NM_ADDQH_R_W:
18967 check_dspr2(ctx);
18968 switch (extract32(ctx->opcode, 10, 1)) {
18969 case 0:
18970 /* ADDQH_W */
18971 gen_helper_addqh_w(v1_t, v1_t, v2_t);
18972 gen_store_gpr(v1_t, ret);
18973 break;
18974 case 1:
18975 /* ADDQH_R_W */
18976 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
18977 gen_store_gpr(v1_t, ret);
18978 break;
18980 break;
18981 case NM_ADDU_S_QB:
18982 check_dsp(ctx);
18983 switch (extract32(ctx->opcode, 10, 1)) {
18984 case 0:
18985 /* ADDU_QB */
18986 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
18987 gen_store_gpr(v1_t, ret);
18988 break;
18989 case 1:
18990 /* ADDU_S_QB */
18991 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
18992 gen_store_gpr(v1_t, ret);
18993 break;
18995 break;
18996 case NM_ADDU_S_PH:
18997 check_dspr2(ctx);
18998 switch (extract32(ctx->opcode, 10, 1)) {
18999 case 0:
19000 /* ADDU_PH */
19001 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19002 gen_store_gpr(v1_t, ret);
19003 break;
19004 case 1:
19005 /* ADDU_S_PH */
19006 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19007 gen_store_gpr(v1_t, ret);
19008 break;
19010 break;
19011 case NM_ADDUH_R_QB:
19012 check_dspr2(ctx);
19013 switch (extract32(ctx->opcode, 10, 1)) {
19014 case 0:
19015 /* ADDUH_QB */
19016 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19017 gen_store_gpr(v1_t, ret);
19018 break;
19019 case 1:
19020 /* ADDUH_R_QB */
19021 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19022 gen_store_gpr(v1_t, ret);
19023 break;
19025 break;
19026 case NM_SHRAV_R_PH:
19027 check_dsp(ctx);
19028 switch (extract32(ctx->opcode, 10, 1)) {
19029 case 0:
19030 /* SHRAV_PH */
19031 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19032 gen_store_gpr(v1_t, ret);
19033 break;
19034 case 1:
19035 /* SHRAV_R_PH */
19036 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19037 gen_store_gpr(v1_t, ret);
19038 break;
19040 break;
19041 case NM_SHRAV_R_QB:
19042 check_dspr2(ctx);
19043 switch (extract32(ctx->opcode, 10, 1)) {
19044 case 0:
19045 /* SHRAV_QB */
19046 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19047 gen_store_gpr(v1_t, ret);
19048 break;
19049 case 1:
19050 /* SHRAV_R_QB */
19051 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19052 gen_store_gpr(v1_t, ret);
19053 break;
19055 break;
19056 case NM_SUBQ_S_PH:
19057 check_dsp(ctx);
19058 switch (extract32(ctx->opcode, 10, 1)) {
19059 case 0:
19060 /* SUBQ_PH */
19061 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19062 gen_store_gpr(v1_t, ret);
19063 break;
19064 case 1:
19065 /* SUBQ_S_PH */
19066 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19067 gen_store_gpr(v1_t, ret);
19068 break;
19070 break;
19071 case NM_SUBQH_R_PH:
19072 check_dspr2(ctx);
19073 switch (extract32(ctx->opcode, 10, 1)) {
19074 case 0:
19075 /* SUBQH_PH */
19076 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19077 gen_store_gpr(v1_t, ret);
19078 break;
19079 case 1:
19080 /* SUBQH_R_PH */
19081 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19082 gen_store_gpr(v1_t, ret);
19083 break;
19085 break;
19086 case NM_SUBQH_R_W:
19087 check_dspr2(ctx);
19088 switch (extract32(ctx->opcode, 10, 1)) {
19089 case 0:
19090 /* SUBQH_W */
19091 gen_helper_subqh_w(v1_t, v1_t, v2_t);
19092 gen_store_gpr(v1_t, ret);
19093 break;
19094 case 1:
19095 /* SUBQH_R_W */
19096 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
19097 gen_store_gpr(v1_t, ret);
19098 break;
19100 break;
19101 case NM_SUBU_S_QB:
19102 check_dsp(ctx);
19103 switch (extract32(ctx->opcode, 10, 1)) {
19104 case 0:
19105 /* SUBU_QB */
19106 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
19107 gen_store_gpr(v1_t, ret);
19108 break;
19109 case 1:
19110 /* SUBU_S_QB */
19111 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19112 gen_store_gpr(v1_t, ret);
19113 break;
19115 break;
19116 case NM_SUBU_S_PH:
19117 check_dspr2(ctx);
19118 switch (extract32(ctx->opcode, 10, 1)) {
19119 case 0:
19120 /* SUBU_PH */
19121 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
19122 gen_store_gpr(v1_t, ret);
19123 break;
19124 case 1:
19125 /* SUBU_S_PH */
19126 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19127 gen_store_gpr(v1_t, ret);
19128 break;
19130 break;
19131 case NM_SUBUH_R_QB:
19132 check_dspr2(ctx);
19133 switch (extract32(ctx->opcode, 10, 1)) {
19134 case 0:
19135 /* SUBUH_QB */
19136 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
19137 gen_store_gpr(v1_t, ret);
19138 break;
19139 case 1:
19140 /* SUBUH_R_QB */
19141 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
19142 gen_store_gpr(v1_t, ret);
19143 break;
19145 break;
19146 case NM_SHLLV_S_PH:
19147 check_dsp(ctx);
19148 switch (extract32(ctx->opcode, 10, 1)) {
19149 case 0:
19150 /* SHLLV_PH */
19151 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
19152 gen_store_gpr(v1_t, ret);
19153 break;
19154 case 1:
19155 /* SHLLV_S_PH */
19156 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
19157 gen_store_gpr(v1_t, ret);
19158 break;
19160 break;
19161 case NM_PRECR_SRA_R_PH_W:
19162 check_dspr2(ctx);
19163 switch (extract32(ctx->opcode, 10, 1)) {
19164 case 0:
19165 /* PRECR_SRA_PH_W */
19167 TCGv_i32 sa_t = tcg_const_i32(rd);
19168 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
19169 cpu_gpr[rt]);
19170 gen_store_gpr(v1_t, rt);
19171 tcg_temp_free_i32(sa_t);
19173 break;
19174 case 1:
19175 /* PRECR_SRA_R_PH_W */
19177 TCGv_i32 sa_t = tcg_const_i32(rd);
19178 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
19179 cpu_gpr[rt]);
19180 gen_store_gpr(v1_t, rt);
19181 tcg_temp_free_i32(sa_t);
19183 break;
19185 break;
19186 case NM_MULEU_S_PH_QBL:
19187 check_dsp(ctx);
19188 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
19189 gen_store_gpr(v1_t, ret);
19190 break;
19191 case NM_MULEU_S_PH_QBR:
19192 check_dsp(ctx);
19193 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
19194 gen_store_gpr(v1_t, ret);
19195 break;
19196 case NM_MULQ_RS_PH:
19197 check_dsp(ctx);
19198 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
19199 gen_store_gpr(v1_t, ret);
19200 break;
19201 case NM_MULQ_S_PH:
19202 check_dspr2(ctx);
19203 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19204 gen_store_gpr(v1_t, ret);
19205 break;
19206 case NM_MULQ_RS_W:
19207 check_dspr2(ctx);
19208 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
19209 gen_store_gpr(v1_t, ret);
19210 break;
19211 case NM_MULQ_S_W:
19212 check_dspr2(ctx);
19213 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
19214 gen_store_gpr(v1_t, ret);
19215 break;
19216 case NM_APPEND:
19217 check_dspr2(ctx);
19218 gen_load_gpr(t0, rs);
19219 if (rd != 0) {
19220 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
19222 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19223 break;
19224 case NM_MODSUB:
19225 check_dsp(ctx);
19226 gen_helper_modsub(v1_t, v1_t, v2_t);
19227 gen_store_gpr(v1_t, ret);
19228 break;
19229 case NM_SHRAV_R_W:
19230 check_dsp(ctx);
19231 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
19232 gen_store_gpr(v1_t, ret);
19233 break;
19234 case NM_SHRLV_PH:
19235 check_dspr2(ctx);
19236 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
19237 gen_store_gpr(v1_t, ret);
19238 break;
19239 case NM_SHRLV_QB:
19240 check_dsp(ctx);
19241 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
19242 gen_store_gpr(v1_t, ret);
19243 break;
19244 case NM_SHLLV_QB:
19245 check_dsp(ctx);
19246 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
19247 gen_store_gpr(v1_t, ret);
19248 break;
19249 case NM_SHLLV_S_W:
19250 check_dsp(ctx);
19251 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
19252 gen_store_gpr(v1_t, ret);
19253 break;
19254 case NM_SHILO:
19255 check_dsp(ctx);
19257 TCGv tv0 = tcg_temp_new();
19258 TCGv tv1 = tcg_temp_new();
19259 int16_t imm = extract32(ctx->opcode, 16, 7);
19261 tcg_gen_movi_tl(tv0, rd >> 3);
19262 tcg_gen_movi_tl(tv1, imm);
19263 gen_helper_shilo(tv0, tv1, cpu_env);
19265 break;
19266 case NM_MULEQ_S_W_PHL:
19267 check_dsp(ctx);
19268 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
19269 gen_store_gpr(v1_t, ret);
19270 break;
19271 case NM_MULEQ_S_W_PHR:
19272 check_dsp(ctx);
19273 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
19274 gen_store_gpr(v1_t, ret);
19275 break;
19276 case NM_MUL_S_PH:
19277 check_dspr2(ctx);
19278 switch (extract32(ctx->opcode, 10, 1)) {
19279 case 0:
19280 /* MUL_PH */
19281 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
19282 gen_store_gpr(v1_t, ret);
19283 break;
19284 case 1:
19285 /* MUL_S_PH */
19286 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
19287 gen_store_gpr(v1_t, ret);
19288 break;
19290 break;
19291 case NM_PRECR_QB_PH:
19292 check_dspr2(ctx);
19293 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
19294 gen_store_gpr(v1_t, ret);
19295 break;
19296 case NM_PRECRQ_QB_PH:
19297 check_dsp(ctx);
19298 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
19299 gen_store_gpr(v1_t, ret);
19300 break;
19301 case NM_PRECRQ_PH_W:
19302 check_dsp(ctx);
19303 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
19304 gen_store_gpr(v1_t, ret);
19305 break;
19306 case NM_PRECRQ_RS_PH_W:
19307 check_dsp(ctx);
19308 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
19309 gen_store_gpr(v1_t, ret);
19310 break;
19311 case NM_PRECRQU_S_QB_PH:
19312 check_dsp(ctx);
19313 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
19314 gen_store_gpr(v1_t, ret);
19315 break;
19316 case NM_SHRA_R_W:
19317 check_dsp(ctx);
19318 tcg_gen_movi_tl(t0, rd);
19319 gen_helper_shra_r_w(v1_t, t0, v1_t);
19320 gen_store_gpr(v1_t, rt);
19321 break;
19322 case NM_SHRA_R_PH:
19323 check_dsp(ctx);
19324 tcg_gen_movi_tl(t0, rd >> 1);
19325 switch (extract32(ctx->opcode, 10, 1)) {
19326 case 0:
19327 /* SHRA_PH */
19328 gen_helper_shra_ph(v1_t, t0, v1_t);
19329 break;
19330 gen_store_gpr(v1_t, rt);
19331 case 1:
19332 /* SHRA_R_PH */
19333 gen_helper_shra_r_ph(v1_t, t0, v1_t);
19334 gen_store_gpr(v1_t, rt);
19335 break;
19337 break;
19338 case NM_SHLL_S_PH:
19339 check_dsp(ctx);
19340 tcg_gen_movi_tl(t0, rd >> 1);
19341 switch (extract32(ctx->opcode, 10, 2)) {
19342 case 0:
19343 /* SHLL_PH */
19344 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
19345 gen_store_gpr(v1_t, rt);
19346 break;
19347 case 2:
19348 /* SHLL_S_PH */
19349 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
19350 gen_store_gpr(v1_t, rt);
19351 break;
19352 default:
19353 generate_exception_end(ctx, EXCP_RI);
19354 break;
19356 break;
19357 case NM_SHLL_S_W:
19358 check_dsp(ctx);
19359 tcg_gen_movi_tl(t0, rd);
19360 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
19361 gen_store_gpr(v1_t, rt);
19362 break;
19363 case NM_REPL_PH:
19364 check_dsp(ctx);
19366 int16_t imm;
19367 imm = sextract32(ctx->opcode, 11, 11);
19368 imm = (int16_t)(imm << 6) >> 6;
19369 if (rt != 0) {
19370 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
19373 break;
19374 default:
19375 generate_exception_end(ctx, EXCP_RI);
19376 break;
19380 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
19382 uint16_t insn;
19383 uint32_t op;
19384 int rt, rs, rd;
19385 int offset;
19386 int imm;
19388 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
19389 ctx->opcode = (ctx->opcode << 16) | insn;
19391 rt = extract32(ctx->opcode, 21, 5);
19392 rs = extract32(ctx->opcode, 16, 5);
19393 rd = extract32(ctx->opcode, 11, 5);
19395 op = extract32(ctx->opcode, 26, 6);
19396 switch (op) {
19397 case NM_P_ADDIU:
19398 if (rt == 0) {
19399 /* P.RI */
19400 switch (extract32(ctx->opcode, 19, 2)) {
19401 case NM_SIGRIE:
19402 default:
19403 generate_exception_end(ctx, EXCP_RI);
19404 break;
19405 case NM_P_SYSCALL:
19406 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
19407 generate_exception_end(ctx, EXCP_SYSCALL);
19408 } else {
19409 generate_exception_end(ctx, EXCP_RI);
19411 break;
19412 case NM_BREAK:
19413 generate_exception_end(ctx, EXCP_BREAK);
19414 break;
19415 case NM_SDBBP:
19416 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
19417 gen_helper_do_semihosting(cpu_env);
19418 } else {
19419 if (ctx->hflags & MIPS_HFLAG_SBRI) {
19420 generate_exception_end(ctx, EXCP_RI);
19421 } else {
19422 generate_exception_end(ctx, EXCP_DBp);
19425 break;
19427 } else {
19428 /* NM_ADDIU */
19429 imm = extract32(ctx->opcode, 0, 16);
19430 if (rs != 0) {
19431 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
19432 } else {
19433 tcg_gen_movi_tl(cpu_gpr[rt], imm);
19435 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19437 break;
19438 case NM_ADDIUPC:
19439 if (rt != 0) {
19440 offset = sextract32(ctx->opcode, 0, 1) << 21 |
19441 extract32(ctx->opcode, 1, 20) << 1;
19442 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
19443 tcg_gen_movi_tl(cpu_gpr[rt], addr);
19445 break;
19446 case NM_POOL32A:
19447 switch (ctx->opcode & 0x07) {
19448 case NM_POOL32A0:
19449 gen_pool32a0_nanomips_insn(env, ctx);
19450 break;
19451 case NM_POOL32A5:
19453 int32_t op1 = extract32(ctx->opcode, 3, 7);
19454 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
19456 break;
19457 case NM_POOL32A7:
19458 switch (extract32(ctx->opcode, 3, 3)) {
19459 case NM_P_LSX:
19460 gen_p_lsx(ctx, rd, rs, rt);
19461 break;
19462 case NM_LSA:
19463 /* In nanoMIPS, the shift field directly encodes the shift
19464 * amount, meaning that the supported shift values are in
19465 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
19466 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
19467 extract32(ctx->opcode, 9, 2) - 1);
19468 break;
19469 case NM_EXTW:
19470 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
19471 break;
19472 case NM_POOL32AXF:
19473 gen_pool32axf_nanomips_insn(env, ctx);
19474 break;
19475 default:
19476 generate_exception_end(ctx, EXCP_RI);
19477 break;
19479 break;
19480 default:
19481 generate_exception_end(ctx, EXCP_RI);
19482 break;
19484 break;
19485 case NM_P_GP_W:
19486 switch (ctx->opcode & 0x03) {
19487 case NM_ADDIUGP_W:
19488 if (rt != 0) {
19489 offset = extract32(ctx->opcode, 0, 21);
19490 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
19492 break;
19493 case NM_LWGP:
19494 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
19495 break;
19496 case NM_SWGP:
19497 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
19498 break;
19499 default:
19500 generate_exception_end(ctx, EXCP_RI);
19501 break;
19503 break;
19504 case NM_P48I:
19506 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
19507 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
19508 switch (extract32(ctx->opcode, 16, 5)) {
19509 case NM_LI48:
19510 check_nms(ctx);
19511 if (rt != 0) {
19512 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
19514 break;
19515 case NM_ADDIU48:
19516 check_nms(ctx);
19517 if (rt != 0) {
19518 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
19519 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19521 break;
19522 case NM_ADDIUGP48:
19523 check_nms(ctx);
19524 if (rt != 0) {
19525 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
19527 break;
19528 case NM_ADDIUPC48:
19529 check_nms(ctx);
19530 if (rt != 0) {
19531 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19532 addr_off);
19534 tcg_gen_movi_tl(cpu_gpr[rt], addr);
19536 break;
19537 case NM_LWPC48:
19538 check_nms(ctx);
19539 if (rt != 0) {
19540 TCGv t0;
19541 t0 = tcg_temp_new();
19543 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19544 addr_off);
19546 tcg_gen_movi_tl(t0, addr);
19547 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
19548 tcg_temp_free(t0);
19550 break;
19551 case NM_SWPC48:
19552 check_nms(ctx);
19554 TCGv t0, t1;
19555 t0 = tcg_temp_new();
19556 t1 = tcg_temp_new();
19558 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
19559 addr_off);
19561 tcg_gen_movi_tl(t0, addr);
19562 gen_load_gpr(t1, rt);
19564 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
19566 tcg_temp_free(t0);
19567 tcg_temp_free(t1);
19569 break;
19570 default:
19571 generate_exception_end(ctx, EXCP_RI);
19572 break;
19574 return 6;
19576 case NM_P_U12:
19577 switch (extract32(ctx->opcode, 12, 4)) {
19578 case NM_ORI:
19579 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
19580 break;
19581 case NM_XORI:
19582 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
19583 break;
19584 case NM_ANDI:
19585 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
19586 break;
19587 case NM_P_SR:
19588 switch (extract32(ctx->opcode, 20, 1)) {
19589 case NM_PP_SR:
19590 switch (ctx->opcode & 3) {
19591 case NM_SAVE:
19592 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
19593 extract32(ctx->opcode, 2, 1),
19594 extract32(ctx->opcode, 3, 9) << 3);
19595 break;
19596 case NM_RESTORE:
19597 case NM_RESTORE_JRC:
19598 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
19599 extract32(ctx->opcode, 2, 1),
19600 extract32(ctx->opcode, 3, 9) << 3);
19601 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
19602 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
19604 break;
19605 default:
19606 generate_exception_end(ctx, EXCP_RI);
19607 break;
19609 break;
19610 case NM_P_SR_F:
19611 generate_exception_end(ctx, EXCP_RI);
19612 break;
19614 break;
19615 case NM_SLTI:
19616 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
19617 break;
19618 case NM_SLTIU:
19619 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
19620 break;
19621 case NM_SEQI:
19623 TCGv t0 = tcg_temp_new();
19625 imm = extract32(ctx->opcode, 0, 12);
19626 gen_load_gpr(t0, rs);
19627 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
19628 gen_store_gpr(t0, rt);
19630 tcg_temp_free(t0);
19632 break;
19633 case NM_ADDIUNEG:
19634 imm = (int16_t) extract32(ctx->opcode, 0, 12);
19635 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
19636 break;
19637 case NM_P_SHIFT:
19639 int shift = extract32(ctx->opcode, 0, 5);
19640 switch (extract32(ctx->opcode, 5, 4)) {
19641 case NM_P_SLL:
19642 if (rt == 0 && shift == 0) {
19643 /* NOP */
19644 } else if (rt == 0 && shift == 3) {
19645 /* EHB - treat as NOP */
19646 } else if (rt == 0 && shift == 5) {
19647 /* PAUSE - treat as NOP */
19648 } else if (rt == 0 && shift == 6) {
19649 /* SYNC */
19650 gen_sync(extract32(ctx->opcode, 16, 5));
19651 } else {
19652 /* SLL */
19653 gen_shift_imm(ctx, OPC_SLL, rt, rs,
19654 extract32(ctx->opcode, 0, 5));
19656 break;
19657 case NM_SRL:
19658 gen_shift_imm(ctx, OPC_SRL, rt, rs,
19659 extract32(ctx->opcode, 0, 5));
19660 break;
19661 case NM_SRA:
19662 gen_shift_imm(ctx, OPC_SRA, rt, rs,
19663 extract32(ctx->opcode, 0, 5));
19664 break;
19665 case NM_ROTR:
19666 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
19667 extract32(ctx->opcode, 0, 5));
19668 break;
19671 break;
19672 case NM_P_ROTX:
19673 check_nms(ctx);
19674 if (rt != 0) {
19675 TCGv t0 = tcg_temp_new();
19676 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
19677 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
19678 << 1);
19679 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
19681 gen_load_gpr(t0, rs);
19682 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
19683 tcg_temp_free(t0);
19685 tcg_temp_free_i32(shift);
19686 tcg_temp_free_i32(shiftx);
19687 tcg_temp_free_i32(stripe);
19689 break;
19690 case NM_P_INS:
19691 switch (((ctx->opcode >> 10) & 2) |
19692 (extract32(ctx->opcode, 5, 1))) {
19693 case NM_INS:
19694 check_nms(ctx);
19695 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
19696 extract32(ctx->opcode, 6, 5));
19697 break;
19698 default:
19699 generate_exception_end(ctx, EXCP_RI);
19700 break;
19702 break;
19703 case NM_P_EXT:
19704 switch (((ctx->opcode >> 10) & 2) |
19705 (extract32(ctx->opcode, 5, 1))) {
19706 case NM_EXT:
19707 check_nms(ctx);
19708 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
19709 extract32(ctx->opcode, 6, 5));
19710 break;
19711 default:
19712 generate_exception_end(ctx, EXCP_RI);
19713 break;
19715 break;
19716 default:
19717 generate_exception_end(ctx, EXCP_RI);
19718 break;
19720 break;
19721 case NM_POOL32F:
19722 gen_pool32f_nanomips_insn(ctx);
19723 break;
19724 case NM_POOL32S:
19725 break;
19726 case NM_P_LUI:
19727 switch (extract32(ctx->opcode, 1, 1)) {
19728 case NM_LUI:
19729 if (rt != 0) {
19730 tcg_gen_movi_tl(cpu_gpr[rt],
19731 sextract32(ctx->opcode, 0, 1) << 31 |
19732 extract32(ctx->opcode, 2, 10) << 21 |
19733 extract32(ctx->opcode, 12, 9) << 12);
19735 break;
19736 case NM_ALUIPC:
19737 if (rt != 0) {
19738 offset = sextract32(ctx->opcode, 0, 1) << 31 |
19739 extract32(ctx->opcode, 2, 10) << 21 |
19740 extract32(ctx->opcode, 12, 9) << 12;
19741 target_long addr;
19742 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
19743 tcg_gen_movi_tl(cpu_gpr[rt], addr);
19745 break;
19747 break;
19748 case NM_P_GP_BH:
19750 uint32_t u = extract32(ctx->opcode, 0, 18);
19752 switch (extract32(ctx->opcode, 18, 3)) {
19753 case NM_LBGP:
19754 gen_ld(ctx, OPC_LB, rt, 28, u);
19755 break;
19756 case NM_SBGP:
19757 gen_st(ctx, OPC_SB, rt, 28, u);
19758 break;
19759 case NM_LBUGP:
19760 gen_ld(ctx, OPC_LBU, rt, 28, u);
19761 break;
19762 case NM_ADDIUGP_B:
19763 if (rt != 0) {
19764 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
19766 break;
19767 case NM_P_GP_LH:
19768 u &= ~1;
19769 switch (ctx->opcode & 1) {
19770 case NM_LHGP:
19771 gen_ld(ctx, OPC_LH, rt, 28, u);
19772 break;
19773 case NM_LHUGP:
19774 gen_ld(ctx, OPC_LHU, rt, 28, u);
19775 break;
19777 break;
19778 case NM_P_GP_SH:
19779 u &= ~1;
19780 switch (ctx->opcode & 1) {
19781 case NM_SHGP:
19782 gen_st(ctx, OPC_SH, rt, 28, u);
19783 break;
19784 default:
19785 generate_exception_end(ctx, EXCP_RI);
19786 break;
19788 break;
19789 case NM_P_GP_CP1:
19790 u &= ~0x3;
19791 switch (ctx->opcode & 0x3) {
19792 case NM_LWC1GP:
19793 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
19794 break;
19795 case NM_LDC1GP:
19796 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
19797 break;
19798 case NM_SWC1GP:
19799 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
19800 break;
19801 case NM_SDC1GP:
19802 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
19803 break;
19805 break;
19806 default:
19807 generate_exception_end(ctx, EXCP_RI);
19808 break;
19811 break;
19812 case NM_P_LS_U12:
19814 uint32_t u = extract32(ctx->opcode, 0, 12);
19816 switch (extract32(ctx->opcode, 12, 4)) {
19817 case NM_P_PREFU12:
19818 if (rt == 31) {
19819 /* SYNCI */
19820 /* Break the TB to be able to sync copied instructions
19821 immediately */
19822 ctx->base.is_jmp = DISAS_STOP;
19823 } else {
19824 /* PREF */
19825 /* Treat as NOP. */
19827 break;
19828 case NM_LB:
19829 gen_ld(ctx, OPC_LB, rt, rs, u);
19830 break;
19831 case NM_LH:
19832 gen_ld(ctx, OPC_LH, rt, rs, u);
19833 break;
19834 case NM_LW:
19835 gen_ld(ctx, OPC_LW, rt, rs, u);
19836 break;
19837 case NM_LBU:
19838 gen_ld(ctx, OPC_LBU, rt, rs, u);
19839 break;
19840 case NM_LHU:
19841 gen_ld(ctx, OPC_LHU, rt, rs, u);
19842 break;
19843 case NM_SB:
19844 gen_st(ctx, OPC_SB, rt, rs, u);
19845 break;
19846 case NM_SH:
19847 gen_st(ctx, OPC_SH, rt, rs, u);
19848 break;
19849 case NM_SW:
19850 gen_st(ctx, OPC_SW, rt, rs, u);
19851 break;
19852 case NM_LWC1:
19853 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
19854 break;
19855 case NM_LDC1:
19856 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
19857 break;
19858 case NM_SWC1:
19859 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
19860 break;
19861 case NM_SDC1:
19862 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
19863 break;
19864 default:
19865 generate_exception_end(ctx, EXCP_RI);
19866 break;
19869 break;
19870 case NM_P_LS_S9:
19872 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
19873 extract32(ctx->opcode, 0, 8);
19875 switch (extract32(ctx->opcode, 8, 3)) {
19876 case NM_P_LS_S0:
19877 switch (extract32(ctx->opcode, 11, 4)) {
19878 case NM_LBS9:
19879 gen_ld(ctx, OPC_LB, rt, rs, s);
19880 break;
19881 case NM_LHS9:
19882 gen_ld(ctx, OPC_LH, rt, rs, s);
19883 break;
19884 case NM_LWS9:
19885 gen_ld(ctx, OPC_LW, rt, rs, s);
19886 break;
19887 case NM_LBUS9:
19888 gen_ld(ctx, OPC_LBU, rt, rs, s);
19889 break;
19890 case NM_LHUS9:
19891 gen_ld(ctx, OPC_LHU, rt, rs, s);
19892 break;
19893 case NM_SBS9:
19894 gen_st(ctx, OPC_SB, rt, rs, s);
19895 break;
19896 case NM_SHS9:
19897 gen_st(ctx, OPC_SH, rt, rs, s);
19898 break;
19899 case NM_SWS9:
19900 gen_st(ctx, OPC_SW, rt, rs, s);
19901 break;
19902 case NM_LWC1S9:
19903 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
19904 break;
19905 case NM_LDC1S9:
19906 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
19907 break;
19908 case NM_SWC1S9:
19909 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
19910 break;
19911 case NM_SDC1S9:
19912 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
19913 break;
19914 case NM_P_PREFS9:
19915 if (rt == 31) {
19916 /* SYNCI */
19917 /* Break the TB to be able to sync copied instructions
19918 immediately */
19919 ctx->base.is_jmp = DISAS_STOP;
19920 } else {
19921 /* PREF */
19922 /* Treat as NOP. */
19924 break;
19925 default:
19926 generate_exception_end(ctx, EXCP_RI);
19927 break;
19929 break;
19930 case NM_P_LS_S1:
19931 switch (extract32(ctx->opcode, 11, 4)) {
19932 case NM_UALH:
19933 case NM_UASH:
19934 check_nms(ctx);
19936 TCGv t0 = tcg_temp_new();
19937 TCGv t1 = tcg_temp_new();
19939 gen_base_offset_addr(ctx, t0, rs, s);
19941 switch (extract32(ctx->opcode, 11, 4)) {
19942 case NM_UALH:
19943 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
19944 MO_UNALN);
19945 gen_store_gpr(t0, rt);
19946 break;
19947 case NM_UASH:
19948 gen_load_gpr(t1, rt);
19949 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
19950 MO_UNALN);
19951 break;
19953 tcg_temp_free(t0);
19954 tcg_temp_free(t1);
19956 break;
19957 case NM_P_LL:
19958 switch (ctx->opcode & 0x03) {
19959 case NM_LL:
19960 gen_ld(ctx, OPC_LL, rt, rs, s);
19961 break;
19962 case NM_LLWP:
19963 check_xnp(ctx);
19964 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
19965 break;
19967 break;
19968 case NM_P_SC:
19969 switch (ctx->opcode & 0x03) {
19970 case NM_SC:
19971 gen_st_cond(ctx, OPC_SC, rt, rs, s);
19972 break;
19973 case NM_SCWP:
19974 check_xnp(ctx);
19975 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
19976 break;
19978 break;
19979 case NM_CACHE:
19980 check_cp0_enabled(ctx);
19981 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
19982 gen_cache_operation(ctx, rt, rs, s);
19984 break;
19986 break;
19987 case NM_P_LS_WM:
19988 case NM_P_LS_UAWM:
19989 check_nms(ctx);
19991 int count = extract32(ctx->opcode, 12, 3);
19992 int counter = 0;
19994 offset = sextract32(ctx->opcode, 15, 1) << 8 |
19995 extract32(ctx->opcode, 0, 8);
19996 TCGv va = tcg_temp_new();
19997 TCGv t1 = tcg_temp_new();
19998 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
19999 NM_P_LS_UAWM ? MO_UNALN : 0;
20001 count = (count == 0) ? 8 : count;
20002 while (counter != count) {
20003 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
20004 int this_offset = offset + (counter << 2);
20006 gen_base_offset_addr(ctx, va, rs, this_offset);
20008 switch (extract32(ctx->opcode, 11, 1)) {
20009 case NM_LWM:
20010 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
20011 memop | MO_TESL);
20012 gen_store_gpr(t1, this_rt);
20013 if ((this_rt == rs) &&
20014 (counter != (count - 1))) {
20015 /* UNPREDICTABLE */
20017 break;
20018 case NM_SWM:
20019 this_rt = (rt == 0) ? 0 : this_rt;
20020 gen_load_gpr(t1, this_rt);
20021 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
20022 memop | MO_TEUL);
20023 break;
20025 counter++;
20027 tcg_temp_free(va);
20028 tcg_temp_free(t1);
20030 break;
20031 default:
20032 generate_exception_end(ctx, EXCP_RI);
20033 break;
20036 break;
20037 case NM_MOVE_BALC:
20038 check_nms(ctx);
20040 TCGv t0 = tcg_temp_new();
20041 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
20042 extract32(ctx->opcode, 1, 20) << 1;
20043 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
20044 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
20045 extract32(ctx->opcode, 21, 3));
20046 gen_load_gpr(t0, rt);
20047 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20048 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20049 tcg_temp_free(t0);
20051 break;
20052 case NM_P_BAL:
20054 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
20055 extract32(ctx->opcode, 1, 24) << 1;
20057 if ((extract32(ctx->opcode, 25, 1)) == 0) {
20058 /* BC */
20059 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
20060 } else {
20061 /* BALC */
20062 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20065 break;
20066 case NM_P_J:
20067 switch (extract32(ctx->opcode, 12, 4)) {
20068 case NM_JALRC:
20069 case NM_JALRC_HB:
20070 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
20071 break;
20072 case NM_P_BALRSC:
20073 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
20074 break;
20075 default:
20076 generate_exception_end(ctx, EXCP_RI);
20077 break;
20079 break;
20080 case NM_P_BR1:
20082 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20083 extract32(ctx->opcode, 1, 13) << 1;
20084 switch (extract32(ctx->opcode, 14, 2)) {
20085 case NM_BEQC:
20086 check_nms(ctx);
20087 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
20088 break;
20089 case NM_P_BR3A:
20090 s = sextract32(ctx->opcode, 0, 1) << 14 |
20091 extract32(ctx->opcode, 1, 13) << 1;
20092 check_cp1_enabled(ctx);
20093 switch (extract32(ctx->opcode, 16, 5)) {
20094 case NM_BC1EQZC:
20095 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
20096 break;
20097 case NM_BC1NEZC:
20098 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
20099 break;
20100 case NM_BPOSGE32C:
20101 check_dspr2(ctx);
20103 int32_t imm = extract32(ctx->opcode, 1, 13) |
20104 extract32(ctx->opcode, 0, 1) << 13;
20106 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
20107 imm);
20109 break;
20110 default:
20111 generate_exception_end(ctx, EXCP_RI);
20112 break;
20114 break;
20115 case NM_BGEC:
20116 if (rs == rt) {
20117 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
20118 } else {
20119 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
20121 break;
20122 case NM_BGEUC:
20123 if (rs == rt || rt == 0) {
20124 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
20125 } else if (rs == 0) {
20126 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
20127 } else {
20128 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
20130 break;
20133 break;
20134 case NM_P_BR2:
20136 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20137 extract32(ctx->opcode, 1, 13) << 1;
20138 switch (extract32(ctx->opcode, 14, 2)) {
20139 case NM_BNEC:
20140 check_nms(ctx);
20141 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
20142 break;
20143 case NM_BLTC:
20144 if (rs != 0 && rt != 0 && rs == rt) {
20145 /* NOP */
20146 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
20147 } else {
20148 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
20150 break;
20151 case NM_BLTUC:
20152 if (rs == 0 || rs == rt) {
20153 /* NOP */
20154 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
20155 } else {
20156 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
20158 break;
20159 default:
20160 generate_exception_end(ctx, EXCP_RI);
20161 break;
20164 break;
20165 case NM_P_BRI:
20167 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
20168 extract32(ctx->opcode, 1, 10) << 1;
20169 uint32_t u = extract32(ctx->opcode, 11, 7);
20171 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
20172 rt, u, s);
20174 break;
20175 default:
20176 generate_exception_end(ctx, EXCP_RI);
20177 break;
20179 return 4;
20182 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
20184 uint32_t op;
20185 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
20186 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
20187 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
20188 int offset;
20189 int imm;
20191 /* make sure instructions are on a halfword boundary */
20192 if (ctx->base.pc_next & 0x1) {
20193 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
20194 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
20195 tcg_temp_free(tmp);
20196 generate_exception_end(ctx, EXCP_AdEL);
20197 return 2;
20200 op = extract32(ctx->opcode, 10, 6);
20201 switch (op) {
20202 case NM_P16_MV:
20203 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20204 if (rt != 0) {
20205 /* MOVE */
20206 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
20207 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
20208 } else {
20209 /* P16.RI */
20210 switch (extract32(ctx->opcode, 3, 2)) {
20211 case NM_P16_SYSCALL:
20212 if (extract32(ctx->opcode, 2, 1) == 0) {
20213 generate_exception_end(ctx, EXCP_SYSCALL);
20214 } else {
20215 generate_exception_end(ctx, EXCP_RI);
20217 break;
20218 case NM_BREAK16:
20219 generate_exception_end(ctx, EXCP_BREAK);
20220 break;
20221 case NM_SDBBP16:
20222 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
20223 gen_helper_do_semihosting(cpu_env);
20224 } else {
20225 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20226 generate_exception_end(ctx, EXCP_RI);
20227 } else {
20228 generate_exception_end(ctx, EXCP_DBp);
20231 break;
20232 default:
20233 generate_exception_end(ctx, EXCP_RI);
20234 break;
20237 break;
20238 case NM_P16_SHIFT:
20240 int shift = extract32(ctx->opcode, 0, 3);
20241 uint32_t opc = 0;
20242 shift = (shift == 0) ? 8 : shift;
20244 switch (extract32(ctx->opcode, 3, 1)) {
20245 case NM_SLL16:
20246 opc = OPC_SLL;
20247 break;
20248 case NM_SRL16:
20249 opc = OPC_SRL;
20250 break;
20252 gen_shift_imm(ctx, opc, rt, rs, shift);
20254 break;
20255 case NM_P16C:
20256 switch (ctx->opcode & 1) {
20257 case NM_POOL16C_0:
20258 gen_pool16c_nanomips_insn(ctx);
20259 break;
20260 case NM_LWXS16:
20261 gen_ldxs(ctx, rt, rs, rd);
20262 break;
20264 break;
20265 case NM_P16_A1:
20266 switch (extract32(ctx->opcode, 6, 1)) {
20267 case NM_ADDIUR1SP:
20268 imm = extract32(ctx->opcode, 0, 6) << 2;
20269 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
20270 break;
20271 default:
20272 generate_exception_end(ctx, EXCP_RI);
20273 break;
20275 break;
20276 case NM_P16_A2:
20277 switch (extract32(ctx->opcode, 3, 1)) {
20278 case NM_ADDIUR2:
20279 imm = extract32(ctx->opcode, 0, 3) << 2;
20280 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
20281 break;
20282 case NM_P_ADDIURS5:
20283 rt = extract32(ctx->opcode, 5, 5);
20284 if (rt != 0) {
20285 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
20286 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
20287 (extract32(ctx->opcode, 0, 3));
20288 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
20290 break;
20292 break;
20293 case NM_P16_ADDU:
20294 switch (ctx->opcode & 0x1) {
20295 case NM_ADDU16:
20296 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
20297 break;
20298 case NM_SUBU16:
20299 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
20300 break;
20302 break;
20303 case NM_P16_4X4:
20304 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20305 extract32(ctx->opcode, 5, 3);
20306 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20307 extract32(ctx->opcode, 0, 3);
20308 rt = decode_gpr_gpr4(rt);
20309 rs = decode_gpr_gpr4(rs);
20310 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
20311 (extract32(ctx->opcode, 3, 1))) {
20312 case NM_ADDU4X4:
20313 check_nms(ctx);
20314 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
20315 break;
20316 case NM_MUL4X4:
20317 check_nms(ctx);
20318 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
20319 break;
20320 default:
20321 generate_exception_end(ctx, EXCP_RI);
20322 break;
20324 break;
20325 case NM_LI16:
20327 int imm = extract32(ctx->opcode, 0, 7);
20328 imm = (imm == 0x7f ? -1 : imm);
20329 if (rt != 0) {
20330 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20333 break;
20334 case NM_ANDI16:
20336 uint32_t u = extract32(ctx->opcode, 0, 4);
20337 u = (u == 12) ? 0xff :
20338 (u == 13) ? 0xffff : u;
20339 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
20341 break;
20342 case NM_P16_LB:
20343 offset = extract32(ctx->opcode, 0, 2);
20344 switch (extract32(ctx->opcode, 2, 2)) {
20345 case NM_LB16:
20346 gen_ld(ctx, OPC_LB, rt, rs, offset);
20347 break;
20348 case NM_SB16:
20349 rt = decode_gpr_gpr3_src_store(
20350 NANOMIPS_EXTRACT_RD(ctx->opcode));
20351 gen_st(ctx, OPC_SB, rt, rs, offset);
20352 break;
20353 case NM_LBU16:
20354 gen_ld(ctx, OPC_LBU, rt, rs, offset);
20355 break;
20356 default:
20357 generate_exception_end(ctx, EXCP_RI);
20358 break;
20360 break;
20361 case NM_P16_LH:
20362 offset = extract32(ctx->opcode, 1, 2) << 1;
20363 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
20364 case NM_LH16:
20365 gen_ld(ctx, OPC_LH, rt, rs, offset);
20366 break;
20367 case NM_SH16:
20368 rt = decode_gpr_gpr3_src_store(
20369 NANOMIPS_EXTRACT_RD(ctx->opcode));
20370 gen_st(ctx, OPC_SH, rt, rs, offset);
20371 break;
20372 case NM_LHU16:
20373 gen_ld(ctx, OPC_LHU, rt, rs, offset);
20374 break;
20375 default:
20376 generate_exception_end(ctx, EXCP_RI);
20377 break;
20379 break;
20380 case NM_LW16:
20381 offset = extract32(ctx->opcode, 0, 4) << 2;
20382 gen_ld(ctx, OPC_LW, rt, rs, offset);
20383 break;
20384 case NM_LWSP16:
20385 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20386 offset = extract32(ctx->opcode, 0, 5) << 2;
20387 gen_ld(ctx, OPC_LW, rt, 29, offset);
20388 break;
20389 case NM_LW4X4:
20390 check_nms(ctx);
20391 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20392 extract32(ctx->opcode, 5, 3);
20393 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20394 extract32(ctx->opcode, 0, 3);
20395 offset = (extract32(ctx->opcode, 3, 1) << 3) |
20396 (extract32(ctx->opcode, 8, 1) << 2);
20397 rt = decode_gpr_gpr4(rt);
20398 rs = decode_gpr_gpr4(rs);
20399 gen_ld(ctx, OPC_LW, rt, rs, offset);
20400 break;
20401 case NM_SW4X4:
20402 check_nms(ctx);
20403 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20404 extract32(ctx->opcode, 5, 3);
20405 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20406 extract32(ctx->opcode, 0, 3);
20407 offset = (extract32(ctx->opcode, 3, 1) << 3) |
20408 (extract32(ctx->opcode, 8, 1) << 2);
20409 rt = decode_gpr_gpr4_zero(rt);
20410 rs = decode_gpr_gpr4(rs);
20411 gen_st(ctx, OPC_SW, rt, rs, offset);
20412 break;
20413 case NM_LWGP16:
20414 offset = extract32(ctx->opcode, 0, 7) << 2;
20415 gen_ld(ctx, OPC_LW, rt, 28, offset);
20416 break;
20417 case NM_SWSP16:
20418 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20419 offset = extract32(ctx->opcode, 0, 5) << 2;
20420 gen_st(ctx, OPC_SW, rt, 29, offset);
20421 break;
20422 case NM_SW16:
20423 rt = decode_gpr_gpr3_src_store(
20424 NANOMIPS_EXTRACT_RD(ctx->opcode));
20425 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
20426 offset = extract32(ctx->opcode, 0, 4) << 2;
20427 gen_st(ctx, OPC_SW, rt, rs, offset);
20428 break;
20429 case NM_SWGP16:
20430 rt = decode_gpr_gpr3_src_store(
20431 NANOMIPS_EXTRACT_RD(ctx->opcode));
20432 offset = extract32(ctx->opcode, 0, 7) << 2;
20433 gen_st(ctx, OPC_SW, rt, 28, offset);
20434 break;
20435 case NM_BC16:
20436 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
20437 (sextract32(ctx->opcode, 0, 1) << 10) |
20438 (extract32(ctx->opcode, 1, 9) << 1));
20439 break;
20440 case NM_BALC16:
20441 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
20442 (sextract32(ctx->opcode, 0, 1) << 10) |
20443 (extract32(ctx->opcode, 1, 9) << 1));
20444 break;
20445 case NM_BEQZC16:
20446 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
20447 (sextract32(ctx->opcode, 0, 1) << 7) |
20448 (extract32(ctx->opcode, 1, 6) << 1));
20449 break;
20450 case NM_BNEZC16:
20451 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
20452 (sextract32(ctx->opcode, 0, 1) << 7) |
20453 (extract32(ctx->opcode, 1, 6) << 1));
20454 break;
20455 case NM_P16_BR:
20456 switch (ctx->opcode & 0xf) {
20457 case 0:
20458 /* P16.JRC */
20459 switch (extract32(ctx->opcode, 4, 1)) {
20460 case NM_JRC:
20461 gen_compute_branch_nm(ctx, OPC_JR, 2,
20462 extract32(ctx->opcode, 5, 5), 0, 0);
20463 break;
20464 case NM_JALRC16:
20465 gen_compute_branch_nm(ctx, OPC_JALR, 2,
20466 extract32(ctx->opcode, 5, 5), 31, 0);
20467 break;
20469 break;
20470 default:
20472 /* P16.BRI */
20473 uint32_t opc = extract32(ctx->opcode, 4, 3) <
20474 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
20475 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
20476 extract32(ctx->opcode, 0, 4) << 1);
20478 break;
20480 break;
20481 case NM_P16_SR:
20483 int count = extract32(ctx->opcode, 0, 4);
20484 int u = extract32(ctx->opcode, 4, 4) << 4;
20486 rt = 30 + extract32(ctx->opcode, 9, 1);
20487 switch (extract32(ctx->opcode, 8, 1)) {
20488 case NM_SAVE16:
20489 gen_save(ctx, rt, count, 0, u);
20490 break;
20491 case NM_RESTORE_JRC16:
20492 gen_restore(ctx, rt, count, 0, u);
20493 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20494 break;
20497 break;
20498 case NM_MOVEP:
20499 case NM_MOVEPREV:
20500 check_nms(ctx);
20502 static const int gpr2reg1[] = {4, 5, 6, 7};
20503 static const int gpr2reg2[] = {5, 6, 7, 8};
20504 int re;
20505 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
20506 extract32(ctx->opcode, 8, 1);
20507 int r1 = gpr2reg1[rd2];
20508 int r2 = gpr2reg2[rd2];
20509 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
20510 extract32(ctx->opcode, 0, 3);
20511 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
20512 extract32(ctx->opcode, 5, 3);
20513 TCGv t0 = tcg_temp_new();
20514 TCGv t1 = tcg_temp_new();
20515 if (op == NM_MOVEP) {
20516 rd = r1;
20517 re = r2;
20518 rs = decode_gpr_gpr4_zero(r3);
20519 rt = decode_gpr_gpr4_zero(r4);
20520 } else {
20521 rd = decode_gpr_gpr4(r3);
20522 re = decode_gpr_gpr4(r4);
20523 rs = r1;
20524 rt = r2;
20526 gen_load_gpr(t0, rs);
20527 gen_load_gpr(t1, rt);
20528 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20529 tcg_gen_mov_tl(cpu_gpr[re], t1);
20530 tcg_temp_free(t0);
20531 tcg_temp_free(t1);
20533 break;
20534 default:
20535 return decode_nanomips_32_48_opc(env, ctx);
20538 return 2;
20542 /* SmartMIPS extension to MIPS32 */
20544 #if defined(TARGET_MIPS64)
20546 /* MDMX extension to MIPS64 */
20548 #endif
20550 /* MIPSDSP functions. */
20551 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
20552 int rd, int base, int offset)
20554 TCGv t0;
20556 check_dsp(ctx);
20557 t0 = tcg_temp_new();
20559 if (base == 0) {
20560 gen_load_gpr(t0, offset);
20561 } else if (offset == 0) {
20562 gen_load_gpr(t0, base);
20563 } else {
20564 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
20567 switch (opc) {
20568 case OPC_LBUX:
20569 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
20570 gen_store_gpr(t0, rd);
20571 break;
20572 case OPC_LHX:
20573 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
20574 gen_store_gpr(t0, rd);
20575 break;
20576 case OPC_LWX:
20577 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
20578 gen_store_gpr(t0, rd);
20579 break;
20580 #if defined(TARGET_MIPS64)
20581 case OPC_LDX:
20582 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
20583 gen_store_gpr(t0, rd);
20584 break;
20585 #endif
20587 tcg_temp_free(t0);
20590 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
20591 int ret, int v1, int v2)
20593 TCGv v1_t;
20594 TCGv v2_t;
20596 if (ret == 0) {
20597 /* Treat as NOP. */
20598 return;
20601 v1_t = tcg_temp_new();
20602 v2_t = tcg_temp_new();
20604 gen_load_gpr(v1_t, v1);
20605 gen_load_gpr(v2_t, v2);
20607 switch (op1) {
20608 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
20609 case OPC_MULT_G_2E:
20610 check_dspr2(ctx);
20611 switch (op2) {
20612 case OPC_ADDUH_QB:
20613 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
20614 break;
20615 case OPC_ADDUH_R_QB:
20616 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
20617 break;
20618 case OPC_ADDQH_PH:
20619 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
20620 break;
20621 case OPC_ADDQH_R_PH:
20622 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
20623 break;
20624 case OPC_ADDQH_W:
20625 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
20626 break;
20627 case OPC_ADDQH_R_W:
20628 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
20629 break;
20630 case OPC_SUBUH_QB:
20631 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
20632 break;
20633 case OPC_SUBUH_R_QB:
20634 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
20635 break;
20636 case OPC_SUBQH_PH:
20637 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
20638 break;
20639 case OPC_SUBQH_R_PH:
20640 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
20641 break;
20642 case OPC_SUBQH_W:
20643 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
20644 break;
20645 case OPC_SUBQH_R_W:
20646 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
20647 break;
20649 break;
20650 case OPC_ABSQ_S_PH_DSP:
20651 switch (op2) {
20652 case OPC_ABSQ_S_QB:
20653 check_dspr2(ctx);
20654 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
20655 break;
20656 case OPC_ABSQ_S_PH:
20657 check_dsp(ctx);
20658 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
20659 break;
20660 case OPC_ABSQ_S_W:
20661 check_dsp(ctx);
20662 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
20663 break;
20664 case OPC_PRECEQ_W_PHL:
20665 check_dsp(ctx);
20666 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
20667 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
20668 break;
20669 case OPC_PRECEQ_W_PHR:
20670 check_dsp(ctx);
20671 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
20672 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
20673 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
20674 break;
20675 case OPC_PRECEQU_PH_QBL:
20676 check_dsp(ctx);
20677 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
20678 break;
20679 case OPC_PRECEQU_PH_QBR:
20680 check_dsp(ctx);
20681 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
20682 break;
20683 case OPC_PRECEQU_PH_QBLA:
20684 check_dsp(ctx);
20685 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
20686 break;
20687 case OPC_PRECEQU_PH_QBRA:
20688 check_dsp(ctx);
20689 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
20690 break;
20691 case OPC_PRECEU_PH_QBL:
20692 check_dsp(ctx);
20693 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
20694 break;
20695 case OPC_PRECEU_PH_QBR:
20696 check_dsp(ctx);
20697 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
20698 break;
20699 case OPC_PRECEU_PH_QBLA:
20700 check_dsp(ctx);
20701 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
20702 break;
20703 case OPC_PRECEU_PH_QBRA:
20704 check_dsp(ctx);
20705 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
20706 break;
20708 break;
20709 case OPC_ADDU_QB_DSP:
20710 switch (op2) {
20711 case OPC_ADDQ_PH:
20712 check_dsp(ctx);
20713 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20714 break;
20715 case OPC_ADDQ_S_PH:
20716 check_dsp(ctx);
20717 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20718 break;
20719 case OPC_ADDQ_S_W:
20720 check_dsp(ctx);
20721 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20722 break;
20723 case OPC_ADDU_QB:
20724 check_dsp(ctx);
20725 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20726 break;
20727 case OPC_ADDU_S_QB:
20728 check_dsp(ctx);
20729 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20730 break;
20731 case OPC_ADDU_PH:
20732 check_dspr2(ctx);
20733 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20734 break;
20735 case OPC_ADDU_S_PH:
20736 check_dspr2(ctx);
20737 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20738 break;
20739 case OPC_SUBQ_PH:
20740 check_dsp(ctx);
20741 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20742 break;
20743 case OPC_SUBQ_S_PH:
20744 check_dsp(ctx);
20745 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20746 break;
20747 case OPC_SUBQ_S_W:
20748 check_dsp(ctx);
20749 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20750 break;
20751 case OPC_SUBU_QB:
20752 check_dsp(ctx);
20753 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20754 break;
20755 case OPC_SUBU_S_QB:
20756 check_dsp(ctx);
20757 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20758 break;
20759 case OPC_SUBU_PH:
20760 check_dspr2(ctx);
20761 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20762 break;
20763 case OPC_SUBU_S_PH:
20764 check_dspr2(ctx);
20765 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20766 break;
20767 case OPC_ADDSC:
20768 check_dsp(ctx);
20769 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20770 break;
20771 case OPC_ADDWC:
20772 check_dsp(ctx);
20773 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20774 break;
20775 case OPC_MODSUB:
20776 check_dsp(ctx);
20777 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
20778 break;
20779 case OPC_RADDU_W_QB:
20780 check_dsp(ctx);
20781 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
20782 break;
20784 break;
20785 case OPC_CMPU_EQ_QB_DSP:
20786 switch (op2) {
20787 case OPC_PRECR_QB_PH:
20788 check_dspr2(ctx);
20789 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
20790 break;
20791 case OPC_PRECRQ_QB_PH:
20792 check_dsp(ctx);
20793 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
20794 break;
20795 case OPC_PRECR_SRA_PH_W:
20796 check_dspr2(ctx);
20798 TCGv_i32 sa_t = tcg_const_i32(v2);
20799 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
20800 cpu_gpr[ret]);
20801 tcg_temp_free_i32(sa_t);
20802 break;
20804 case OPC_PRECR_SRA_R_PH_W:
20805 check_dspr2(ctx);
20807 TCGv_i32 sa_t = tcg_const_i32(v2);
20808 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
20809 cpu_gpr[ret]);
20810 tcg_temp_free_i32(sa_t);
20811 break;
20813 case OPC_PRECRQ_PH_W:
20814 check_dsp(ctx);
20815 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
20816 break;
20817 case OPC_PRECRQ_RS_PH_W:
20818 check_dsp(ctx);
20819 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20820 break;
20821 case OPC_PRECRQU_S_QB_PH:
20822 check_dsp(ctx);
20823 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20824 break;
20826 break;
20827 #ifdef TARGET_MIPS64
20828 case OPC_ABSQ_S_QH_DSP:
20829 switch (op2) {
20830 case OPC_PRECEQ_L_PWL:
20831 check_dsp(ctx);
20832 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
20833 break;
20834 case OPC_PRECEQ_L_PWR:
20835 check_dsp(ctx);
20836 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
20837 break;
20838 case OPC_PRECEQ_PW_QHL:
20839 check_dsp(ctx);
20840 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
20841 break;
20842 case OPC_PRECEQ_PW_QHR:
20843 check_dsp(ctx);
20844 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
20845 break;
20846 case OPC_PRECEQ_PW_QHLA:
20847 check_dsp(ctx);
20848 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
20849 break;
20850 case OPC_PRECEQ_PW_QHRA:
20851 check_dsp(ctx);
20852 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
20853 break;
20854 case OPC_PRECEQU_QH_OBL:
20855 check_dsp(ctx);
20856 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
20857 break;
20858 case OPC_PRECEQU_QH_OBR:
20859 check_dsp(ctx);
20860 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
20861 break;
20862 case OPC_PRECEQU_QH_OBLA:
20863 check_dsp(ctx);
20864 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
20865 break;
20866 case OPC_PRECEQU_QH_OBRA:
20867 check_dsp(ctx);
20868 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
20869 break;
20870 case OPC_PRECEU_QH_OBL:
20871 check_dsp(ctx);
20872 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
20873 break;
20874 case OPC_PRECEU_QH_OBR:
20875 check_dsp(ctx);
20876 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
20877 break;
20878 case OPC_PRECEU_QH_OBLA:
20879 check_dsp(ctx);
20880 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
20881 break;
20882 case OPC_PRECEU_QH_OBRA:
20883 check_dsp(ctx);
20884 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
20885 break;
20886 case OPC_ABSQ_S_OB:
20887 check_dspr2(ctx);
20888 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
20889 break;
20890 case OPC_ABSQ_S_PW:
20891 check_dsp(ctx);
20892 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
20893 break;
20894 case OPC_ABSQ_S_QH:
20895 check_dsp(ctx);
20896 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
20897 break;
20899 break;
20900 case OPC_ADDU_OB_DSP:
20901 switch (op2) {
20902 case OPC_RADDU_L_OB:
20903 check_dsp(ctx);
20904 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
20905 break;
20906 case OPC_SUBQ_PW:
20907 check_dsp(ctx);
20908 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20909 break;
20910 case OPC_SUBQ_S_PW:
20911 check_dsp(ctx);
20912 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20913 break;
20914 case OPC_SUBQ_QH:
20915 check_dsp(ctx);
20916 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20917 break;
20918 case OPC_SUBQ_S_QH:
20919 check_dsp(ctx);
20920 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20921 break;
20922 case OPC_SUBU_OB:
20923 check_dsp(ctx);
20924 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20925 break;
20926 case OPC_SUBU_S_OB:
20927 check_dsp(ctx);
20928 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20929 break;
20930 case OPC_SUBU_QH:
20931 check_dspr2(ctx);
20932 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20933 break;
20934 case OPC_SUBU_S_QH:
20935 check_dspr2(ctx);
20936 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20937 break;
20938 case OPC_SUBUH_OB:
20939 check_dspr2(ctx);
20940 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
20941 break;
20942 case OPC_SUBUH_R_OB:
20943 check_dspr2(ctx);
20944 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
20945 break;
20946 case OPC_ADDQ_PW:
20947 check_dsp(ctx);
20948 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20949 break;
20950 case OPC_ADDQ_S_PW:
20951 check_dsp(ctx);
20952 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20953 break;
20954 case OPC_ADDQ_QH:
20955 check_dsp(ctx);
20956 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20957 break;
20958 case OPC_ADDQ_S_QH:
20959 check_dsp(ctx);
20960 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20961 break;
20962 case OPC_ADDU_OB:
20963 check_dsp(ctx);
20964 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20965 break;
20966 case OPC_ADDU_S_OB:
20967 check_dsp(ctx);
20968 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20969 break;
20970 case OPC_ADDU_QH:
20971 check_dspr2(ctx);
20972 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20973 break;
20974 case OPC_ADDU_S_QH:
20975 check_dspr2(ctx);
20976 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
20977 break;
20978 case OPC_ADDUH_OB:
20979 check_dspr2(ctx);
20980 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
20981 break;
20982 case OPC_ADDUH_R_OB:
20983 check_dspr2(ctx);
20984 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
20985 break;
20987 break;
20988 case OPC_CMPU_EQ_OB_DSP:
20989 switch (op2) {
20990 case OPC_PRECR_OB_QH:
20991 check_dspr2(ctx);
20992 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
20993 break;
20994 case OPC_PRECR_SRA_QH_PW:
20995 check_dspr2(ctx);
20997 TCGv_i32 ret_t = tcg_const_i32(ret);
20998 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
20999 tcg_temp_free_i32(ret_t);
21000 break;
21002 case OPC_PRECR_SRA_R_QH_PW:
21003 check_dspr2(ctx);
21005 TCGv_i32 sa_v = tcg_const_i32(ret);
21006 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
21007 tcg_temp_free_i32(sa_v);
21008 break;
21010 case OPC_PRECRQ_OB_QH:
21011 check_dsp(ctx);
21012 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21013 break;
21014 case OPC_PRECRQ_PW_L:
21015 check_dsp(ctx);
21016 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
21017 break;
21018 case OPC_PRECRQ_QH_PW:
21019 check_dsp(ctx);
21020 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
21021 break;
21022 case OPC_PRECRQ_RS_QH_PW:
21023 check_dsp(ctx);
21024 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21025 break;
21026 case OPC_PRECRQU_S_OB_QH:
21027 check_dsp(ctx);
21028 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21029 break;
21031 break;
21032 #endif
21035 tcg_temp_free(v1_t);
21036 tcg_temp_free(v2_t);
21039 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
21040 int ret, int v1, int v2)
21042 uint32_t op2;
21043 TCGv t0;
21044 TCGv v1_t;
21045 TCGv v2_t;
21047 if (ret == 0) {
21048 /* Treat as NOP. */
21049 return;
21052 t0 = tcg_temp_new();
21053 v1_t = tcg_temp_new();
21054 v2_t = tcg_temp_new();
21056 tcg_gen_movi_tl(t0, v1);
21057 gen_load_gpr(v1_t, v1);
21058 gen_load_gpr(v2_t, v2);
21060 switch (opc) {
21061 case OPC_SHLL_QB_DSP:
21063 op2 = MASK_SHLL_QB(ctx->opcode);
21064 switch (op2) {
21065 case OPC_SHLL_QB:
21066 check_dsp(ctx);
21067 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
21068 break;
21069 case OPC_SHLLV_QB:
21070 check_dsp(ctx);
21071 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21072 break;
21073 case OPC_SHLL_PH:
21074 check_dsp(ctx);
21075 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21076 break;
21077 case OPC_SHLLV_PH:
21078 check_dsp(ctx);
21079 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21080 break;
21081 case OPC_SHLL_S_PH:
21082 check_dsp(ctx);
21083 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21084 break;
21085 case OPC_SHLLV_S_PH:
21086 check_dsp(ctx);
21087 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21088 break;
21089 case OPC_SHLL_S_W:
21090 check_dsp(ctx);
21091 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
21092 break;
21093 case OPC_SHLLV_S_W:
21094 check_dsp(ctx);
21095 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21096 break;
21097 case OPC_SHRL_QB:
21098 check_dsp(ctx);
21099 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
21100 break;
21101 case OPC_SHRLV_QB:
21102 check_dsp(ctx);
21103 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
21104 break;
21105 case OPC_SHRL_PH:
21106 check_dspr2(ctx);
21107 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
21108 break;
21109 case OPC_SHRLV_PH:
21110 check_dspr2(ctx);
21111 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
21112 break;
21113 case OPC_SHRA_QB:
21114 check_dspr2(ctx);
21115 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
21116 break;
21117 case OPC_SHRA_R_QB:
21118 check_dspr2(ctx);
21119 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
21120 break;
21121 case OPC_SHRAV_QB:
21122 check_dspr2(ctx);
21123 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
21124 break;
21125 case OPC_SHRAV_R_QB:
21126 check_dspr2(ctx);
21127 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
21128 break;
21129 case OPC_SHRA_PH:
21130 check_dsp(ctx);
21131 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
21132 break;
21133 case OPC_SHRA_R_PH:
21134 check_dsp(ctx);
21135 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
21136 break;
21137 case OPC_SHRAV_PH:
21138 check_dsp(ctx);
21139 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
21140 break;
21141 case OPC_SHRAV_R_PH:
21142 check_dsp(ctx);
21143 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
21144 break;
21145 case OPC_SHRA_R_W:
21146 check_dsp(ctx);
21147 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
21148 break;
21149 case OPC_SHRAV_R_W:
21150 check_dsp(ctx);
21151 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
21152 break;
21153 default: /* Invalid */
21154 MIPS_INVAL("MASK SHLL.QB");
21155 generate_exception_end(ctx, EXCP_RI);
21156 break;
21158 break;
21160 #ifdef TARGET_MIPS64
21161 case OPC_SHLL_OB_DSP:
21162 op2 = MASK_SHLL_OB(ctx->opcode);
21163 switch (op2) {
21164 case OPC_SHLL_PW:
21165 check_dsp(ctx);
21166 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
21167 break;
21168 case OPC_SHLLV_PW:
21169 check_dsp(ctx);
21170 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21171 break;
21172 case OPC_SHLL_S_PW:
21173 check_dsp(ctx);
21174 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
21175 break;
21176 case OPC_SHLLV_S_PW:
21177 check_dsp(ctx);
21178 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21179 break;
21180 case OPC_SHLL_OB:
21181 check_dsp(ctx);
21182 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
21183 break;
21184 case OPC_SHLLV_OB:
21185 check_dsp(ctx);
21186 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21187 break;
21188 case OPC_SHLL_QH:
21189 check_dsp(ctx);
21190 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
21191 break;
21192 case OPC_SHLLV_QH:
21193 check_dsp(ctx);
21194 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21195 break;
21196 case OPC_SHLL_S_QH:
21197 check_dsp(ctx);
21198 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
21199 break;
21200 case OPC_SHLLV_S_QH:
21201 check_dsp(ctx);
21202 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21203 break;
21204 case OPC_SHRA_OB:
21205 check_dspr2(ctx);
21206 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
21207 break;
21208 case OPC_SHRAV_OB:
21209 check_dspr2(ctx);
21210 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
21211 break;
21212 case OPC_SHRA_R_OB:
21213 check_dspr2(ctx);
21214 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
21215 break;
21216 case OPC_SHRAV_R_OB:
21217 check_dspr2(ctx);
21218 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
21219 break;
21220 case OPC_SHRA_PW:
21221 check_dsp(ctx);
21222 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
21223 break;
21224 case OPC_SHRAV_PW:
21225 check_dsp(ctx);
21226 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
21227 break;
21228 case OPC_SHRA_R_PW:
21229 check_dsp(ctx);
21230 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
21231 break;
21232 case OPC_SHRAV_R_PW:
21233 check_dsp(ctx);
21234 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
21235 break;
21236 case OPC_SHRA_QH:
21237 check_dsp(ctx);
21238 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
21239 break;
21240 case OPC_SHRAV_QH:
21241 check_dsp(ctx);
21242 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
21243 break;
21244 case OPC_SHRA_R_QH:
21245 check_dsp(ctx);
21246 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
21247 break;
21248 case OPC_SHRAV_R_QH:
21249 check_dsp(ctx);
21250 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
21251 break;
21252 case OPC_SHRL_OB:
21253 check_dsp(ctx);
21254 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
21255 break;
21256 case OPC_SHRLV_OB:
21257 check_dsp(ctx);
21258 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
21259 break;
21260 case OPC_SHRL_QH:
21261 check_dspr2(ctx);
21262 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
21263 break;
21264 case OPC_SHRLV_QH:
21265 check_dspr2(ctx);
21266 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
21267 break;
21268 default: /* Invalid */
21269 MIPS_INVAL("MASK SHLL.OB");
21270 generate_exception_end(ctx, EXCP_RI);
21271 break;
21273 break;
21274 #endif
21277 tcg_temp_free(t0);
21278 tcg_temp_free(v1_t);
21279 tcg_temp_free(v2_t);
21282 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
21283 int ret, int v1, int v2, int check_ret)
21285 TCGv_i32 t0;
21286 TCGv v1_t;
21287 TCGv v2_t;
21289 if ((ret == 0) && (check_ret == 1)) {
21290 /* Treat as NOP. */
21291 return;
21294 t0 = tcg_temp_new_i32();
21295 v1_t = tcg_temp_new();
21296 v2_t = tcg_temp_new();
21298 tcg_gen_movi_i32(t0, ret);
21299 gen_load_gpr(v1_t, v1);
21300 gen_load_gpr(v2_t, v2);
21302 switch (op1) {
21303 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
21304 * the same mask and op1. */
21305 case OPC_MULT_G_2E:
21306 check_dspr2(ctx);
21307 switch (op2) {
21308 case OPC_MUL_PH:
21309 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21310 break;
21311 case OPC_MUL_S_PH:
21312 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21313 break;
21314 case OPC_MULQ_S_W:
21315 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21316 break;
21317 case OPC_MULQ_RS_W:
21318 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21319 break;
21321 break;
21322 case OPC_DPA_W_PH_DSP:
21323 switch (op2) {
21324 case OPC_DPAU_H_QBL:
21325 check_dsp(ctx);
21326 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
21327 break;
21328 case OPC_DPAU_H_QBR:
21329 check_dsp(ctx);
21330 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
21331 break;
21332 case OPC_DPSU_H_QBL:
21333 check_dsp(ctx);
21334 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
21335 break;
21336 case OPC_DPSU_H_QBR:
21337 check_dsp(ctx);
21338 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
21339 break;
21340 case OPC_DPA_W_PH:
21341 check_dspr2(ctx);
21342 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
21343 break;
21344 case OPC_DPAX_W_PH:
21345 check_dspr2(ctx);
21346 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
21347 break;
21348 case OPC_DPAQ_S_W_PH:
21349 check_dsp(ctx);
21350 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21351 break;
21352 case OPC_DPAQX_S_W_PH:
21353 check_dspr2(ctx);
21354 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
21355 break;
21356 case OPC_DPAQX_SA_W_PH:
21357 check_dspr2(ctx);
21358 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
21359 break;
21360 case OPC_DPS_W_PH:
21361 check_dspr2(ctx);
21362 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
21363 break;
21364 case OPC_DPSX_W_PH:
21365 check_dspr2(ctx);
21366 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
21367 break;
21368 case OPC_DPSQ_S_W_PH:
21369 check_dsp(ctx);
21370 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21371 break;
21372 case OPC_DPSQX_S_W_PH:
21373 check_dspr2(ctx);
21374 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
21375 break;
21376 case OPC_DPSQX_SA_W_PH:
21377 check_dspr2(ctx);
21378 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
21379 break;
21380 case OPC_MULSAQ_S_W_PH:
21381 check_dsp(ctx);
21382 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
21383 break;
21384 case OPC_DPAQ_SA_L_W:
21385 check_dsp(ctx);
21386 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
21387 break;
21388 case OPC_DPSQ_SA_L_W:
21389 check_dsp(ctx);
21390 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
21391 break;
21392 case OPC_MAQ_S_W_PHL:
21393 check_dsp(ctx);
21394 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
21395 break;
21396 case OPC_MAQ_S_W_PHR:
21397 check_dsp(ctx);
21398 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
21399 break;
21400 case OPC_MAQ_SA_W_PHL:
21401 check_dsp(ctx);
21402 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
21403 break;
21404 case OPC_MAQ_SA_W_PHR:
21405 check_dsp(ctx);
21406 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
21407 break;
21408 case OPC_MULSA_W_PH:
21409 check_dspr2(ctx);
21410 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
21411 break;
21413 break;
21414 #ifdef TARGET_MIPS64
21415 case OPC_DPAQ_W_QH_DSP:
21417 int ac = ret & 0x03;
21418 tcg_gen_movi_i32(t0, ac);
21420 switch (op2) {
21421 case OPC_DMADD:
21422 check_dsp(ctx);
21423 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
21424 break;
21425 case OPC_DMADDU:
21426 check_dsp(ctx);
21427 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
21428 break;
21429 case OPC_DMSUB:
21430 check_dsp(ctx);
21431 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
21432 break;
21433 case OPC_DMSUBU:
21434 check_dsp(ctx);
21435 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
21436 break;
21437 case OPC_DPA_W_QH:
21438 check_dspr2(ctx);
21439 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
21440 break;
21441 case OPC_DPAQ_S_W_QH:
21442 check_dsp(ctx);
21443 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21444 break;
21445 case OPC_DPAQ_SA_L_PW:
21446 check_dsp(ctx);
21447 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
21448 break;
21449 case OPC_DPAU_H_OBL:
21450 check_dsp(ctx);
21451 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
21452 break;
21453 case OPC_DPAU_H_OBR:
21454 check_dsp(ctx);
21455 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
21456 break;
21457 case OPC_DPS_W_QH:
21458 check_dspr2(ctx);
21459 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
21460 break;
21461 case OPC_DPSQ_S_W_QH:
21462 check_dsp(ctx);
21463 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21464 break;
21465 case OPC_DPSQ_SA_L_PW:
21466 check_dsp(ctx);
21467 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
21468 break;
21469 case OPC_DPSU_H_OBL:
21470 check_dsp(ctx);
21471 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
21472 break;
21473 case OPC_DPSU_H_OBR:
21474 check_dsp(ctx);
21475 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
21476 break;
21477 case OPC_MAQ_S_L_PWL:
21478 check_dsp(ctx);
21479 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
21480 break;
21481 case OPC_MAQ_S_L_PWR:
21482 check_dsp(ctx);
21483 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
21484 break;
21485 case OPC_MAQ_S_W_QHLL:
21486 check_dsp(ctx);
21487 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
21488 break;
21489 case OPC_MAQ_SA_W_QHLL:
21490 check_dsp(ctx);
21491 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
21492 break;
21493 case OPC_MAQ_S_W_QHLR:
21494 check_dsp(ctx);
21495 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
21496 break;
21497 case OPC_MAQ_SA_W_QHLR:
21498 check_dsp(ctx);
21499 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
21500 break;
21501 case OPC_MAQ_S_W_QHRL:
21502 check_dsp(ctx);
21503 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
21504 break;
21505 case OPC_MAQ_SA_W_QHRL:
21506 check_dsp(ctx);
21507 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
21508 break;
21509 case OPC_MAQ_S_W_QHRR:
21510 check_dsp(ctx);
21511 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
21512 break;
21513 case OPC_MAQ_SA_W_QHRR:
21514 check_dsp(ctx);
21515 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
21516 break;
21517 case OPC_MULSAQ_S_L_PW:
21518 check_dsp(ctx);
21519 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
21520 break;
21521 case OPC_MULSAQ_S_W_QH:
21522 check_dsp(ctx);
21523 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
21524 break;
21527 break;
21528 #endif
21529 case OPC_ADDU_QB_DSP:
21530 switch (op2) {
21531 case OPC_MULEU_S_PH_QBL:
21532 check_dsp(ctx);
21533 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21534 break;
21535 case OPC_MULEU_S_PH_QBR:
21536 check_dsp(ctx);
21537 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21538 break;
21539 case OPC_MULQ_RS_PH:
21540 check_dsp(ctx);
21541 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21542 break;
21543 case OPC_MULEQ_S_W_PHL:
21544 check_dsp(ctx);
21545 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21546 break;
21547 case OPC_MULEQ_S_W_PHR:
21548 check_dsp(ctx);
21549 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21550 break;
21551 case OPC_MULQ_S_PH:
21552 check_dspr2(ctx);
21553 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21554 break;
21556 break;
21557 #ifdef TARGET_MIPS64
21558 case OPC_ADDU_OB_DSP:
21559 switch (op2) {
21560 case OPC_MULEQ_S_PW_QHL:
21561 check_dsp(ctx);
21562 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21563 break;
21564 case OPC_MULEQ_S_PW_QHR:
21565 check_dsp(ctx);
21566 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21567 break;
21568 case OPC_MULEU_S_QH_OBL:
21569 check_dsp(ctx);
21570 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21571 break;
21572 case OPC_MULEU_S_QH_OBR:
21573 check_dsp(ctx);
21574 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21575 break;
21576 case OPC_MULQ_RS_QH:
21577 check_dsp(ctx);
21578 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21579 break;
21581 break;
21582 #endif
21585 tcg_temp_free_i32(t0);
21586 tcg_temp_free(v1_t);
21587 tcg_temp_free(v2_t);
21590 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
21591 int ret, int val)
21593 int16_t imm;
21594 TCGv t0;
21595 TCGv val_t;
21597 if (ret == 0) {
21598 /* Treat as NOP. */
21599 return;
21602 t0 = tcg_temp_new();
21603 val_t = tcg_temp_new();
21604 gen_load_gpr(val_t, val);
21606 switch (op1) {
21607 case OPC_ABSQ_S_PH_DSP:
21608 switch (op2) {
21609 case OPC_BITREV:
21610 check_dsp(ctx);
21611 gen_helper_bitrev(cpu_gpr[ret], val_t);
21612 break;
21613 case OPC_REPL_QB:
21614 check_dsp(ctx);
21616 target_long result;
21617 imm = (ctx->opcode >> 16) & 0xFF;
21618 result = (uint32_t)imm << 24 |
21619 (uint32_t)imm << 16 |
21620 (uint32_t)imm << 8 |
21621 (uint32_t)imm;
21622 result = (int32_t)result;
21623 tcg_gen_movi_tl(cpu_gpr[ret], result);
21625 break;
21626 case OPC_REPLV_QB:
21627 check_dsp(ctx);
21628 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
21629 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
21630 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21631 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21632 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21633 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21634 break;
21635 case OPC_REPL_PH:
21636 check_dsp(ctx);
21638 imm = (ctx->opcode >> 16) & 0x03FF;
21639 imm = (int16_t)(imm << 6) >> 6;
21640 tcg_gen_movi_tl(cpu_gpr[ret], \
21641 (target_long)((int32_t)imm << 16 | \
21642 (uint16_t)imm));
21644 break;
21645 case OPC_REPLV_PH:
21646 check_dsp(ctx);
21647 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
21648 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21649 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21650 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21651 break;
21653 break;
21654 #ifdef TARGET_MIPS64
21655 case OPC_ABSQ_S_QH_DSP:
21656 switch (op2) {
21657 case OPC_REPL_OB:
21658 check_dsp(ctx);
21660 target_long temp;
21662 imm = (ctx->opcode >> 16) & 0xFF;
21663 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
21664 temp = (temp << 16) | temp;
21665 temp = (temp << 32) | temp;
21666 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21667 break;
21669 case OPC_REPL_PW:
21670 check_dsp(ctx);
21672 target_long temp;
21674 imm = (ctx->opcode >> 16) & 0x03FF;
21675 imm = (int16_t)(imm << 6) >> 6;
21676 temp = ((target_long)imm << 32) \
21677 | ((target_long)imm & 0xFFFFFFFF);
21678 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21679 break;
21681 case OPC_REPL_QH:
21682 check_dsp(ctx);
21684 target_long temp;
21686 imm = (ctx->opcode >> 16) & 0x03FF;
21687 imm = (int16_t)(imm << 6) >> 6;
21689 temp = ((uint64_t)(uint16_t)imm << 48) |
21690 ((uint64_t)(uint16_t)imm << 32) |
21691 ((uint64_t)(uint16_t)imm << 16) |
21692 (uint64_t)(uint16_t)imm;
21693 tcg_gen_movi_tl(cpu_gpr[ret], temp);
21694 break;
21696 case OPC_REPLV_OB:
21697 check_dsp(ctx);
21698 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
21699 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
21700 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21701 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21702 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21703 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21704 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21705 break;
21706 case OPC_REPLV_PW:
21707 check_dsp(ctx);
21708 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
21709 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21710 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21711 break;
21712 case OPC_REPLV_QH:
21713 check_dsp(ctx);
21714 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
21715 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
21716 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21717 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
21718 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
21719 break;
21721 break;
21722 #endif
21724 tcg_temp_free(t0);
21725 tcg_temp_free(val_t);
21728 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
21729 uint32_t op1, uint32_t op2,
21730 int ret, int v1, int v2, int check_ret)
21732 TCGv t1;
21733 TCGv v1_t;
21734 TCGv v2_t;
21736 if ((ret == 0) && (check_ret == 1)) {
21737 /* Treat as NOP. */
21738 return;
21741 t1 = tcg_temp_new();
21742 v1_t = tcg_temp_new();
21743 v2_t = tcg_temp_new();
21745 gen_load_gpr(v1_t, v1);
21746 gen_load_gpr(v2_t, v2);
21748 switch (op1) {
21749 case OPC_CMPU_EQ_QB_DSP:
21750 switch (op2) {
21751 case OPC_CMPU_EQ_QB:
21752 check_dsp(ctx);
21753 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
21754 break;
21755 case OPC_CMPU_LT_QB:
21756 check_dsp(ctx);
21757 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
21758 break;
21759 case OPC_CMPU_LE_QB:
21760 check_dsp(ctx);
21761 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
21762 break;
21763 case OPC_CMPGU_EQ_QB:
21764 check_dsp(ctx);
21765 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
21766 break;
21767 case OPC_CMPGU_LT_QB:
21768 check_dsp(ctx);
21769 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
21770 break;
21771 case OPC_CMPGU_LE_QB:
21772 check_dsp(ctx);
21773 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
21774 break;
21775 case OPC_CMPGDU_EQ_QB:
21776 check_dspr2(ctx);
21777 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
21778 tcg_gen_mov_tl(cpu_gpr[ret], t1);
21779 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
21780 tcg_gen_shli_tl(t1, t1, 24);
21781 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
21782 break;
21783 case OPC_CMPGDU_LT_QB:
21784 check_dspr2(ctx);
21785 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
21786 tcg_gen_mov_tl(cpu_gpr[ret], t1);
21787 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
21788 tcg_gen_shli_tl(t1, t1, 24);
21789 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
21790 break;
21791 case OPC_CMPGDU_LE_QB:
21792 check_dspr2(ctx);
21793 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
21794 tcg_gen_mov_tl(cpu_gpr[ret], t1);
21795 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
21796 tcg_gen_shli_tl(t1, t1, 24);
21797 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
21798 break;
21799 case OPC_CMP_EQ_PH:
21800 check_dsp(ctx);
21801 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
21802 break;
21803 case OPC_CMP_LT_PH:
21804 check_dsp(ctx);
21805 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
21806 break;
21807 case OPC_CMP_LE_PH:
21808 check_dsp(ctx);
21809 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
21810 break;
21811 case OPC_PICK_QB:
21812 check_dsp(ctx);
21813 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21814 break;
21815 case OPC_PICK_PH:
21816 check_dsp(ctx);
21817 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21818 break;
21819 case OPC_PACKRL_PH:
21820 check_dsp(ctx);
21821 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
21822 break;
21824 break;
21825 #ifdef TARGET_MIPS64
21826 case OPC_CMPU_EQ_OB_DSP:
21827 switch (op2) {
21828 case OPC_CMP_EQ_PW:
21829 check_dsp(ctx);
21830 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
21831 break;
21832 case OPC_CMP_LT_PW:
21833 check_dsp(ctx);
21834 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
21835 break;
21836 case OPC_CMP_LE_PW:
21837 check_dsp(ctx);
21838 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
21839 break;
21840 case OPC_CMP_EQ_QH:
21841 check_dsp(ctx);
21842 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
21843 break;
21844 case OPC_CMP_LT_QH:
21845 check_dsp(ctx);
21846 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
21847 break;
21848 case OPC_CMP_LE_QH:
21849 check_dsp(ctx);
21850 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
21851 break;
21852 case OPC_CMPGDU_EQ_OB:
21853 check_dspr2(ctx);
21854 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21855 break;
21856 case OPC_CMPGDU_LT_OB:
21857 check_dspr2(ctx);
21858 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21859 break;
21860 case OPC_CMPGDU_LE_OB:
21861 check_dspr2(ctx);
21862 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21863 break;
21864 case OPC_CMPGU_EQ_OB:
21865 check_dsp(ctx);
21866 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
21867 break;
21868 case OPC_CMPGU_LT_OB:
21869 check_dsp(ctx);
21870 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
21871 break;
21872 case OPC_CMPGU_LE_OB:
21873 check_dsp(ctx);
21874 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
21875 break;
21876 case OPC_CMPU_EQ_OB:
21877 check_dsp(ctx);
21878 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
21879 break;
21880 case OPC_CMPU_LT_OB:
21881 check_dsp(ctx);
21882 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
21883 break;
21884 case OPC_CMPU_LE_OB:
21885 check_dsp(ctx);
21886 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
21887 break;
21888 case OPC_PACKRL_PW:
21889 check_dsp(ctx);
21890 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
21891 break;
21892 case OPC_PICK_OB:
21893 check_dsp(ctx);
21894 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21895 break;
21896 case OPC_PICK_PW:
21897 check_dsp(ctx);
21898 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21899 break;
21900 case OPC_PICK_QH:
21901 check_dsp(ctx);
21902 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21903 break;
21905 break;
21906 #endif
21909 tcg_temp_free(t1);
21910 tcg_temp_free(v1_t);
21911 tcg_temp_free(v2_t);
21914 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
21915 uint32_t op1, int rt, int rs, int sa)
21917 TCGv t0;
21919 check_dspr2(ctx);
21921 if (rt == 0) {
21922 /* Treat as NOP. */
21923 return;
21926 t0 = tcg_temp_new();
21927 gen_load_gpr(t0, rs);
21929 switch (op1) {
21930 case OPC_APPEND_DSP:
21931 switch (MASK_APPEND(ctx->opcode)) {
21932 case OPC_APPEND:
21933 if (sa != 0) {
21934 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
21936 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21937 break;
21938 case OPC_PREPEND:
21939 if (sa != 0) {
21940 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
21941 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
21942 tcg_gen_shli_tl(t0, t0, 32 - sa);
21943 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
21945 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21946 break;
21947 case OPC_BALIGN:
21948 sa &= 3;
21949 if (sa != 0 && sa != 2) {
21950 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
21951 tcg_gen_ext32u_tl(t0, t0);
21952 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
21953 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
21955 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21956 break;
21957 default: /* Invalid */
21958 MIPS_INVAL("MASK APPEND");
21959 generate_exception_end(ctx, EXCP_RI);
21960 break;
21962 break;
21963 #ifdef TARGET_MIPS64
21964 case OPC_DAPPEND_DSP:
21965 switch (MASK_DAPPEND(ctx->opcode)) {
21966 case OPC_DAPPEND:
21967 if (sa != 0) {
21968 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
21970 break;
21971 case OPC_PREPENDD:
21972 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
21973 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
21974 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
21975 break;
21976 case OPC_PREPENDW:
21977 if (sa != 0) {
21978 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
21979 tcg_gen_shli_tl(t0, t0, 64 - sa);
21980 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
21982 break;
21983 case OPC_DBALIGN:
21984 sa &= 7;
21985 if (sa != 0 && sa != 2 && sa != 4) {
21986 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
21987 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
21988 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
21990 break;
21991 default: /* Invalid */
21992 MIPS_INVAL("MASK DAPPEND");
21993 generate_exception_end(ctx, EXCP_RI);
21994 break;
21996 break;
21997 #endif
21999 tcg_temp_free(t0);
22002 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22003 int ret, int v1, int v2, int check_ret)
22006 TCGv t0;
22007 TCGv t1;
22008 TCGv v1_t;
22009 TCGv v2_t;
22010 int16_t imm;
22012 if ((ret == 0) && (check_ret == 1)) {
22013 /* Treat as NOP. */
22014 return;
22017 t0 = tcg_temp_new();
22018 t1 = tcg_temp_new();
22019 v1_t = tcg_temp_new();
22020 v2_t = tcg_temp_new();
22022 gen_load_gpr(v1_t, v1);
22023 gen_load_gpr(v2_t, v2);
22025 switch (op1) {
22026 case OPC_EXTR_W_DSP:
22027 check_dsp(ctx);
22028 switch (op2) {
22029 case OPC_EXTR_W:
22030 tcg_gen_movi_tl(t0, v2);
22031 tcg_gen_movi_tl(t1, v1);
22032 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
22033 break;
22034 case OPC_EXTR_R_W:
22035 tcg_gen_movi_tl(t0, v2);
22036 tcg_gen_movi_tl(t1, v1);
22037 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22038 break;
22039 case OPC_EXTR_RS_W:
22040 tcg_gen_movi_tl(t0, v2);
22041 tcg_gen_movi_tl(t1, v1);
22042 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22043 break;
22044 case OPC_EXTR_S_H:
22045 tcg_gen_movi_tl(t0, v2);
22046 tcg_gen_movi_tl(t1, v1);
22047 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22048 break;
22049 case OPC_EXTRV_S_H:
22050 tcg_gen_movi_tl(t0, v2);
22051 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
22052 break;
22053 case OPC_EXTRV_W:
22054 tcg_gen_movi_tl(t0, v2);
22055 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22056 break;
22057 case OPC_EXTRV_R_W:
22058 tcg_gen_movi_tl(t0, v2);
22059 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22060 break;
22061 case OPC_EXTRV_RS_W:
22062 tcg_gen_movi_tl(t0, v2);
22063 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22064 break;
22065 case OPC_EXTP:
22066 tcg_gen_movi_tl(t0, v2);
22067 tcg_gen_movi_tl(t1, v1);
22068 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
22069 break;
22070 case OPC_EXTPV:
22071 tcg_gen_movi_tl(t0, v2);
22072 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
22073 break;
22074 case OPC_EXTPDP:
22075 tcg_gen_movi_tl(t0, v2);
22076 tcg_gen_movi_tl(t1, v1);
22077 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
22078 break;
22079 case OPC_EXTPDPV:
22080 tcg_gen_movi_tl(t0, v2);
22081 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22082 break;
22083 case OPC_SHILO:
22084 imm = (ctx->opcode >> 20) & 0x3F;
22085 tcg_gen_movi_tl(t0, ret);
22086 tcg_gen_movi_tl(t1, imm);
22087 gen_helper_shilo(t0, t1, cpu_env);
22088 break;
22089 case OPC_SHILOV:
22090 tcg_gen_movi_tl(t0, ret);
22091 gen_helper_shilo(t0, v1_t, cpu_env);
22092 break;
22093 case OPC_MTHLIP:
22094 tcg_gen_movi_tl(t0, ret);
22095 gen_helper_mthlip(t0, v1_t, cpu_env);
22096 break;
22097 case OPC_WRDSP:
22098 imm = (ctx->opcode >> 11) & 0x3FF;
22099 tcg_gen_movi_tl(t0, imm);
22100 gen_helper_wrdsp(v1_t, t0, cpu_env);
22101 break;
22102 case OPC_RDDSP:
22103 imm = (ctx->opcode >> 16) & 0x03FF;
22104 tcg_gen_movi_tl(t0, imm);
22105 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
22106 break;
22108 break;
22109 #ifdef TARGET_MIPS64
22110 case OPC_DEXTR_W_DSP:
22111 check_dsp(ctx);
22112 switch (op2) {
22113 case OPC_DMTHLIP:
22114 tcg_gen_movi_tl(t0, ret);
22115 gen_helper_dmthlip(v1_t, t0, cpu_env);
22116 break;
22117 case OPC_DSHILO:
22119 int shift = (ctx->opcode >> 19) & 0x7F;
22120 int ac = (ctx->opcode >> 11) & 0x03;
22121 tcg_gen_movi_tl(t0, shift);
22122 tcg_gen_movi_tl(t1, ac);
22123 gen_helper_dshilo(t0, t1, cpu_env);
22124 break;
22126 case OPC_DSHILOV:
22128 int ac = (ctx->opcode >> 11) & 0x03;
22129 tcg_gen_movi_tl(t0, ac);
22130 gen_helper_dshilo(v1_t, t0, cpu_env);
22131 break;
22133 case OPC_DEXTP:
22134 tcg_gen_movi_tl(t0, v2);
22135 tcg_gen_movi_tl(t1, v1);
22137 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
22138 break;
22139 case OPC_DEXTPV:
22140 tcg_gen_movi_tl(t0, v2);
22141 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
22142 break;
22143 case OPC_DEXTPDP:
22144 tcg_gen_movi_tl(t0, v2);
22145 tcg_gen_movi_tl(t1, v1);
22146 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
22147 break;
22148 case OPC_DEXTPDPV:
22149 tcg_gen_movi_tl(t0, v2);
22150 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22151 break;
22152 case OPC_DEXTR_L:
22153 tcg_gen_movi_tl(t0, v2);
22154 tcg_gen_movi_tl(t1, v1);
22155 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
22156 break;
22157 case OPC_DEXTR_R_L:
22158 tcg_gen_movi_tl(t0, v2);
22159 tcg_gen_movi_tl(t1, v1);
22160 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
22161 break;
22162 case OPC_DEXTR_RS_L:
22163 tcg_gen_movi_tl(t0, v2);
22164 tcg_gen_movi_tl(t1, v1);
22165 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
22166 break;
22167 case OPC_DEXTR_W:
22168 tcg_gen_movi_tl(t0, v2);
22169 tcg_gen_movi_tl(t1, v1);
22170 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
22171 break;
22172 case OPC_DEXTR_R_W:
22173 tcg_gen_movi_tl(t0, v2);
22174 tcg_gen_movi_tl(t1, v1);
22175 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22176 break;
22177 case OPC_DEXTR_RS_W:
22178 tcg_gen_movi_tl(t0, v2);
22179 tcg_gen_movi_tl(t1, v1);
22180 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22181 break;
22182 case OPC_DEXTR_S_H:
22183 tcg_gen_movi_tl(t0, v2);
22184 tcg_gen_movi_tl(t1, v1);
22185 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22186 break;
22187 case OPC_DEXTRV_S_H:
22188 tcg_gen_movi_tl(t0, v2);
22189 tcg_gen_movi_tl(t1, v1);
22190 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22191 break;
22192 case OPC_DEXTRV_L:
22193 tcg_gen_movi_tl(t0, v2);
22194 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22195 break;
22196 case OPC_DEXTRV_R_L:
22197 tcg_gen_movi_tl(t0, v2);
22198 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22199 break;
22200 case OPC_DEXTRV_RS_L:
22201 tcg_gen_movi_tl(t0, v2);
22202 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22203 break;
22204 case OPC_DEXTRV_W:
22205 tcg_gen_movi_tl(t0, v2);
22206 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22207 break;
22208 case OPC_DEXTRV_R_W:
22209 tcg_gen_movi_tl(t0, v2);
22210 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22211 break;
22212 case OPC_DEXTRV_RS_W:
22213 tcg_gen_movi_tl(t0, v2);
22214 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22215 break;
22217 break;
22218 #endif
22221 tcg_temp_free(t0);
22222 tcg_temp_free(t1);
22223 tcg_temp_free(v1_t);
22224 tcg_temp_free(v2_t);
22227 /* End MIPSDSP functions. */
22229 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
22231 int rs, rt, rd, sa;
22232 uint32_t op1, op2;
22234 rs = (ctx->opcode >> 21) & 0x1f;
22235 rt = (ctx->opcode >> 16) & 0x1f;
22236 rd = (ctx->opcode >> 11) & 0x1f;
22237 sa = (ctx->opcode >> 6) & 0x1f;
22239 op1 = MASK_SPECIAL(ctx->opcode);
22240 switch (op1) {
22241 case OPC_LSA:
22242 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
22243 break;
22244 case OPC_MULT:
22245 case OPC_MULTU:
22246 case OPC_DIV:
22247 case OPC_DIVU:
22248 op2 = MASK_R6_MULDIV(ctx->opcode);
22249 switch (op2) {
22250 case R6_OPC_MUL:
22251 case R6_OPC_MUH:
22252 case R6_OPC_MULU:
22253 case R6_OPC_MUHU:
22254 case R6_OPC_DIV:
22255 case R6_OPC_MOD:
22256 case R6_OPC_DIVU:
22257 case R6_OPC_MODU:
22258 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22259 break;
22260 default:
22261 MIPS_INVAL("special_r6 muldiv");
22262 generate_exception_end(ctx, EXCP_RI);
22263 break;
22265 break;
22266 case OPC_SELEQZ:
22267 case OPC_SELNEZ:
22268 gen_cond_move(ctx, op1, rd, rs, rt);
22269 break;
22270 case R6_OPC_CLO:
22271 case R6_OPC_CLZ:
22272 if (rt == 0 && sa == 1) {
22273 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22274 We need additionally to check other fields */
22275 gen_cl(ctx, op1, rd, rs);
22276 } else {
22277 generate_exception_end(ctx, EXCP_RI);
22279 break;
22280 case R6_OPC_SDBBP:
22281 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
22282 gen_helper_do_semihosting(cpu_env);
22283 } else {
22284 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22285 generate_exception_end(ctx, EXCP_RI);
22286 } else {
22287 generate_exception_end(ctx, EXCP_DBp);
22290 break;
22291 #if defined(TARGET_MIPS64)
22292 case OPC_DLSA:
22293 check_mips_64(ctx);
22294 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
22295 break;
22296 case R6_OPC_DCLO:
22297 case R6_OPC_DCLZ:
22298 if (rt == 0 && sa == 1) {
22299 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22300 We need additionally to check other fields */
22301 check_mips_64(ctx);
22302 gen_cl(ctx, op1, rd, rs);
22303 } else {
22304 generate_exception_end(ctx, EXCP_RI);
22306 break;
22307 case OPC_DMULT:
22308 case OPC_DMULTU:
22309 case OPC_DDIV:
22310 case OPC_DDIVU:
22312 op2 = MASK_R6_MULDIV(ctx->opcode);
22313 switch (op2) {
22314 case R6_OPC_DMUL:
22315 case R6_OPC_DMUH:
22316 case R6_OPC_DMULU:
22317 case R6_OPC_DMUHU:
22318 case R6_OPC_DDIV:
22319 case R6_OPC_DMOD:
22320 case R6_OPC_DDIVU:
22321 case R6_OPC_DMODU:
22322 check_mips_64(ctx);
22323 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22324 break;
22325 default:
22326 MIPS_INVAL("special_r6 muldiv");
22327 generate_exception_end(ctx, EXCP_RI);
22328 break;
22330 break;
22331 #endif
22332 default: /* Invalid */
22333 MIPS_INVAL("special_r6");
22334 generate_exception_end(ctx, EXCP_RI);
22335 break;
22339 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
22341 int rs, rt, rd, sa;
22342 uint32_t op1;
22344 rs = (ctx->opcode >> 21) & 0x1f;
22345 rt = (ctx->opcode >> 16) & 0x1f;
22346 rd = (ctx->opcode >> 11) & 0x1f;
22347 sa = (ctx->opcode >> 6) & 0x1f;
22349 op1 = MASK_SPECIAL(ctx->opcode);
22350 switch (op1) {
22351 case OPC_MOVN: /* Conditional move */
22352 case OPC_MOVZ:
22353 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
22354 INSN_LOONGSON2E | INSN_LOONGSON2F);
22355 gen_cond_move(ctx, op1, rd, rs, rt);
22356 break;
22357 case OPC_MFHI: /* Move from HI/LO */
22358 case OPC_MFLO:
22359 gen_HILO(ctx, op1, rs & 3, rd);
22360 break;
22361 case OPC_MTHI:
22362 case OPC_MTLO: /* Move to HI/LO */
22363 gen_HILO(ctx, op1, rd & 3, rs);
22364 break;
22365 case OPC_MOVCI:
22366 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
22367 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
22368 check_cp1_enabled(ctx);
22369 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
22370 (ctx->opcode >> 16) & 1);
22371 } else {
22372 generate_exception_err(ctx, EXCP_CpU, 1);
22374 break;
22375 case OPC_MULT:
22376 case OPC_MULTU:
22377 if (sa) {
22378 check_insn(ctx, INSN_VR54XX);
22379 op1 = MASK_MUL_VR54XX(ctx->opcode);
22380 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
22381 } else {
22382 gen_muldiv(ctx, op1, rd & 3, rs, rt);
22384 break;
22385 case OPC_DIV:
22386 case OPC_DIVU:
22387 gen_muldiv(ctx, op1, 0, rs, rt);
22388 break;
22389 #if defined(TARGET_MIPS64)
22390 case OPC_DMULT:
22391 case OPC_DMULTU:
22392 case OPC_DDIV:
22393 case OPC_DDIVU:
22394 check_insn(ctx, ISA_MIPS3);
22395 check_mips_64(ctx);
22396 gen_muldiv(ctx, op1, 0, rs, rt);
22397 break;
22398 #endif
22399 case OPC_JR:
22400 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
22401 break;
22402 case OPC_SPIM:
22403 #ifdef MIPS_STRICT_STANDARD
22404 MIPS_INVAL("SPIM");
22405 generate_exception_end(ctx, EXCP_RI);
22406 #else
22407 /* Implemented as RI exception for now. */
22408 MIPS_INVAL("spim (unofficial)");
22409 generate_exception_end(ctx, EXCP_RI);
22410 #endif
22411 break;
22412 default: /* Invalid */
22413 MIPS_INVAL("special_legacy");
22414 generate_exception_end(ctx, EXCP_RI);
22415 break;
22419 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
22421 int rs, rt, rd, sa;
22422 uint32_t op1;
22424 rs = (ctx->opcode >> 21) & 0x1f;
22425 rt = (ctx->opcode >> 16) & 0x1f;
22426 rd = (ctx->opcode >> 11) & 0x1f;
22427 sa = (ctx->opcode >> 6) & 0x1f;
22429 op1 = MASK_SPECIAL(ctx->opcode);
22430 switch (op1) {
22431 case OPC_SLL: /* Shift with immediate */
22432 if (sa == 5 && rd == 0 &&
22433 rs == 0 && rt == 0) { /* PAUSE */
22434 if ((ctx->insn_flags & ISA_MIPS32R6) &&
22435 (ctx->hflags & MIPS_HFLAG_BMASK)) {
22436 generate_exception_end(ctx, EXCP_RI);
22437 break;
22440 /* Fallthrough */
22441 case OPC_SRA:
22442 gen_shift_imm(ctx, op1, rd, rt, sa);
22443 break;
22444 case OPC_SRL:
22445 switch ((ctx->opcode >> 21) & 0x1f) {
22446 case 1:
22447 /* rotr is decoded as srl on non-R2 CPUs */
22448 if (ctx->insn_flags & ISA_MIPS32R2) {
22449 op1 = OPC_ROTR;
22451 /* Fallthrough */
22452 case 0:
22453 gen_shift_imm(ctx, op1, rd, rt, sa);
22454 break;
22455 default:
22456 generate_exception_end(ctx, EXCP_RI);
22457 break;
22459 break;
22460 case OPC_ADD:
22461 case OPC_ADDU:
22462 case OPC_SUB:
22463 case OPC_SUBU:
22464 gen_arith(ctx, op1, rd, rs, rt);
22465 break;
22466 case OPC_SLLV: /* Shifts */
22467 case OPC_SRAV:
22468 gen_shift(ctx, op1, rd, rs, rt);
22469 break;
22470 case OPC_SRLV:
22471 switch ((ctx->opcode >> 6) & 0x1f) {
22472 case 1:
22473 /* rotrv is decoded as srlv on non-R2 CPUs */
22474 if (ctx->insn_flags & ISA_MIPS32R2) {
22475 op1 = OPC_ROTRV;
22477 /* Fallthrough */
22478 case 0:
22479 gen_shift(ctx, op1, rd, rs, rt);
22480 break;
22481 default:
22482 generate_exception_end(ctx, EXCP_RI);
22483 break;
22485 break;
22486 case OPC_SLT: /* Set on less than */
22487 case OPC_SLTU:
22488 gen_slt(ctx, op1, rd, rs, rt);
22489 break;
22490 case OPC_AND: /* Logic*/
22491 case OPC_OR:
22492 case OPC_NOR:
22493 case OPC_XOR:
22494 gen_logic(ctx, op1, rd, rs, rt);
22495 break;
22496 case OPC_JALR:
22497 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
22498 break;
22499 case OPC_TGE: /* Traps */
22500 case OPC_TGEU:
22501 case OPC_TLT:
22502 case OPC_TLTU:
22503 case OPC_TEQ:
22504 case OPC_TNE:
22505 check_insn(ctx, ISA_MIPS2);
22506 gen_trap(ctx, op1, rs, rt, -1);
22507 break;
22508 case OPC_LSA: /* OPC_PMON */
22509 if ((ctx->insn_flags & ISA_MIPS32R6) ||
22510 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
22511 decode_opc_special_r6(env, ctx);
22512 } else {
22513 /* Pmon entry point, also R4010 selsl */
22514 #ifdef MIPS_STRICT_STANDARD
22515 MIPS_INVAL("PMON / selsl");
22516 generate_exception_end(ctx, EXCP_RI);
22517 #else
22518 gen_helper_0e0i(pmon, sa);
22519 #endif
22521 break;
22522 case OPC_SYSCALL:
22523 generate_exception_end(ctx, EXCP_SYSCALL);
22524 break;
22525 case OPC_BREAK:
22526 generate_exception_end(ctx, EXCP_BREAK);
22527 break;
22528 case OPC_SYNC:
22529 check_insn(ctx, ISA_MIPS2);
22530 gen_sync(extract32(ctx->opcode, 6, 5));
22531 break;
22533 #if defined(TARGET_MIPS64)
22534 /* MIPS64 specific opcodes */
22535 case OPC_DSLL:
22536 case OPC_DSRA:
22537 case OPC_DSLL32:
22538 case OPC_DSRA32:
22539 check_insn(ctx, ISA_MIPS3);
22540 check_mips_64(ctx);
22541 gen_shift_imm(ctx, op1, rd, rt, sa);
22542 break;
22543 case OPC_DSRL:
22544 switch ((ctx->opcode >> 21) & 0x1f) {
22545 case 1:
22546 /* drotr is decoded as dsrl on non-R2 CPUs */
22547 if (ctx->insn_flags & ISA_MIPS32R2) {
22548 op1 = OPC_DROTR;
22550 /* Fallthrough */
22551 case 0:
22552 check_insn(ctx, ISA_MIPS3);
22553 check_mips_64(ctx);
22554 gen_shift_imm(ctx, op1, rd, rt, sa);
22555 break;
22556 default:
22557 generate_exception_end(ctx, EXCP_RI);
22558 break;
22560 break;
22561 case OPC_DSRL32:
22562 switch ((ctx->opcode >> 21) & 0x1f) {
22563 case 1:
22564 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
22565 if (ctx->insn_flags & ISA_MIPS32R2) {
22566 op1 = OPC_DROTR32;
22568 /* Fallthrough */
22569 case 0:
22570 check_insn(ctx, ISA_MIPS3);
22571 check_mips_64(ctx);
22572 gen_shift_imm(ctx, op1, rd, rt, sa);
22573 break;
22574 default:
22575 generate_exception_end(ctx, EXCP_RI);
22576 break;
22578 break;
22579 case OPC_DADD:
22580 case OPC_DADDU:
22581 case OPC_DSUB:
22582 case OPC_DSUBU:
22583 check_insn(ctx, ISA_MIPS3);
22584 check_mips_64(ctx);
22585 gen_arith(ctx, op1, rd, rs, rt);
22586 break;
22587 case OPC_DSLLV:
22588 case OPC_DSRAV:
22589 check_insn(ctx, ISA_MIPS3);
22590 check_mips_64(ctx);
22591 gen_shift(ctx, op1, rd, rs, rt);
22592 break;
22593 case OPC_DSRLV:
22594 switch ((ctx->opcode >> 6) & 0x1f) {
22595 case 1:
22596 /* drotrv is decoded as dsrlv on non-R2 CPUs */
22597 if (ctx->insn_flags & ISA_MIPS32R2) {
22598 op1 = OPC_DROTRV;
22600 /* Fallthrough */
22601 case 0:
22602 check_insn(ctx, ISA_MIPS3);
22603 check_mips_64(ctx);
22604 gen_shift(ctx, op1, rd, rs, rt);
22605 break;
22606 default:
22607 generate_exception_end(ctx, EXCP_RI);
22608 break;
22610 break;
22611 case OPC_DLSA:
22612 if ((ctx->insn_flags & ISA_MIPS32R6) ||
22613 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
22614 decode_opc_special_r6(env, ctx);
22616 break;
22617 #endif
22618 default:
22619 if (ctx->insn_flags & ISA_MIPS32R6) {
22620 decode_opc_special_r6(env, ctx);
22621 } else {
22622 decode_opc_special_legacy(env, ctx);
22627 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
22629 int rs, rt, rd;
22630 uint32_t op1;
22632 check_insn_opc_removed(ctx, ISA_MIPS32R6);
22634 rs = (ctx->opcode >> 21) & 0x1f;
22635 rt = (ctx->opcode >> 16) & 0x1f;
22636 rd = (ctx->opcode >> 11) & 0x1f;
22638 op1 = MASK_SPECIAL2(ctx->opcode);
22639 switch (op1) {
22640 case OPC_MADD: /* Multiply and add/sub */
22641 case OPC_MADDU:
22642 case OPC_MSUB:
22643 case OPC_MSUBU:
22644 check_insn(ctx, ISA_MIPS32);
22645 gen_muldiv(ctx, op1, rd & 3, rs, rt);
22646 break;
22647 case OPC_MUL:
22648 gen_arith(ctx, op1, rd, rs, rt);
22649 break;
22650 case OPC_DIV_G_2F:
22651 case OPC_DIVU_G_2F:
22652 case OPC_MULT_G_2F:
22653 case OPC_MULTU_G_2F:
22654 case OPC_MOD_G_2F:
22655 case OPC_MODU_G_2F:
22656 check_insn(ctx, INSN_LOONGSON2F);
22657 gen_loongson_integer(ctx, op1, rd, rs, rt);
22658 break;
22659 case OPC_CLO:
22660 case OPC_CLZ:
22661 check_insn(ctx, ISA_MIPS32);
22662 gen_cl(ctx, op1, rd, rs);
22663 break;
22664 case OPC_SDBBP:
22665 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
22666 gen_helper_do_semihosting(cpu_env);
22667 } else {
22668 /* XXX: not clear which exception should be raised
22669 * when in debug mode...
22671 check_insn(ctx, ISA_MIPS32);
22672 generate_exception_end(ctx, EXCP_DBp);
22674 break;
22675 #if defined(TARGET_MIPS64)
22676 case OPC_DCLO:
22677 case OPC_DCLZ:
22678 check_insn(ctx, ISA_MIPS64);
22679 check_mips_64(ctx);
22680 gen_cl(ctx, op1, rd, rs);
22681 break;
22682 case OPC_DMULT_G_2F:
22683 case OPC_DMULTU_G_2F:
22684 case OPC_DDIV_G_2F:
22685 case OPC_DDIVU_G_2F:
22686 case OPC_DMOD_G_2F:
22687 case OPC_DMODU_G_2F:
22688 check_insn(ctx, INSN_LOONGSON2F);
22689 gen_loongson_integer(ctx, op1, rd, rs, rt);
22690 break;
22691 #endif
22692 default: /* Invalid */
22693 MIPS_INVAL("special2_legacy");
22694 generate_exception_end(ctx, EXCP_RI);
22695 break;
22699 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
22701 int rs, rt, rd, sa;
22702 uint32_t op1, op2;
22703 int16_t imm;
22705 rs = (ctx->opcode >> 21) & 0x1f;
22706 rt = (ctx->opcode >> 16) & 0x1f;
22707 rd = (ctx->opcode >> 11) & 0x1f;
22708 sa = (ctx->opcode >> 6) & 0x1f;
22709 imm = (int16_t)ctx->opcode >> 7;
22711 op1 = MASK_SPECIAL3(ctx->opcode);
22712 switch (op1) {
22713 case R6_OPC_PREF:
22714 if (rt >= 24) {
22715 /* hint codes 24-31 are reserved and signal RI */
22716 generate_exception_end(ctx, EXCP_RI);
22718 /* Treat as NOP. */
22719 break;
22720 case R6_OPC_CACHE:
22721 check_cp0_enabled(ctx);
22722 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22723 gen_cache_operation(ctx, rt, rs, imm);
22725 break;
22726 case R6_OPC_SC:
22727 gen_st_cond(ctx, op1, rt, rs, imm);
22728 break;
22729 case R6_OPC_LL:
22730 gen_ld(ctx, op1, rt, rs, imm);
22731 break;
22732 case OPC_BSHFL:
22734 if (rd == 0) {
22735 /* Treat as NOP. */
22736 break;
22738 op2 = MASK_BSHFL(ctx->opcode);
22739 switch (op2) {
22740 case OPC_ALIGN:
22741 case OPC_ALIGN_END:
22742 gen_align(ctx, 32, rd, rs, rt, sa & 3);
22743 break;
22744 case OPC_BITSWAP:
22745 gen_bitswap(ctx, op2, rd, rt);
22746 break;
22749 break;
22750 #if defined(TARGET_MIPS64)
22751 case R6_OPC_SCD:
22752 gen_st_cond(ctx, op1, rt, rs, imm);
22753 break;
22754 case R6_OPC_LLD:
22755 gen_ld(ctx, op1, rt, rs, imm);
22756 break;
22757 case OPC_DBSHFL:
22758 check_mips_64(ctx);
22760 if (rd == 0) {
22761 /* Treat as NOP. */
22762 break;
22764 op2 = MASK_DBSHFL(ctx->opcode);
22765 switch (op2) {
22766 case OPC_DALIGN:
22767 case OPC_DALIGN_END:
22768 gen_align(ctx, 64, rd, rs, rt, sa & 7);
22769 break;
22770 case OPC_DBITSWAP:
22771 gen_bitswap(ctx, op2, rd, rt);
22772 break;
22776 break;
22777 #endif
22778 default: /* Invalid */
22779 MIPS_INVAL("special3_r6");
22780 generate_exception_end(ctx, EXCP_RI);
22781 break;
22785 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
22787 int rs, rt, rd;
22788 uint32_t op1, op2;
22790 rs = (ctx->opcode >> 21) & 0x1f;
22791 rt = (ctx->opcode >> 16) & 0x1f;
22792 rd = (ctx->opcode >> 11) & 0x1f;
22794 op1 = MASK_SPECIAL3(ctx->opcode);
22795 switch (op1) {
22796 case OPC_DIV_G_2E:
22797 case OPC_DIVU_G_2E:
22798 case OPC_MOD_G_2E:
22799 case OPC_MODU_G_2E:
22800 case OPC_MULT_G_2E:
22801 case OPC_MULTU_G_2E:
22802 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22803 * the same mask and op1. */
22804 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
22805 op2 = MASK_ADDUH_QB(ctx->opcode);
22806 switch (op2) {
22807 case OPC_ADDUH_QB:
22808 case OPC_ADDUH_R_QB:
22809 case OPC_ADDQH_PH:
22810 case OPC_ADDQH_R_PH:
22811 case OPC_ADDQH_W:
22812 case OPC_ADDQH_R_W:
22813 case OPC_SUBUH_QB:
22814 case OPC_SUBUH_R_QB:
22815 case OPC_SUBQH_PH:
22816 case OPC_SUBQH_R_PH:
22817 case OPC_SUBQH_W:
22818 case OPC_SUBQH_R_W:
22819 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22820 break;
22821 case OPC_MUL_PH:
22822 case OPC_MUL_S_PH:
22823 case OPC_MULQ_S_W:
22824 case OPC_MULQ_RS_W:
22825 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
22826 break;
22827 default:
22828 MIPS_INVAL("MASK ADDUH.QB");
22829 generate_exception_end(ctx, EXCP_RI);
22830 break;
22832 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
22833 gen_loongson_integer(ctx, op1, rd, rs, rt);
22834 } else {
22835 generate_exception_end(ctx, EXCP_RI);
22837 break;
22838 case OPC_LX_DSP:
22839 op2 = MASK_LX(ctx->opcode);
22840 switch (op2) {
22841 #if defined(TARGET_MIPS64)
22842 case OPC_LDX:
22843 #endif
22844 case OPC_LBUX:
22845 case OPC_LHX:
22846 case OPC_LWX:
22847 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
22848 break;
22849 default: /* Invalid */
22850 MIPS_INVAL("MASK LX");
22851 generate_exception_end(ctx, EXCP_RI);
22852 break;
22854 break;
22855 case OPC_ABSQ_S_PH_DSP:
22856 op2 = MASK_ABSQ_S_PH(ctx->opcode);
22857 switch (op2) {
22858 case OPC_ABSQ_S_QB:
22859 case OPC_ABSQ_S_PH:
22860 case OPC_ABSQ_S_W:
22861 case OPC_PRECEQ_W_PHL:
22862 case OPC_PRECEQ_W_PHR:
22863 case OPC_PRECEQU_PH_QBL:
22864 case OPC_PRECEQU_PH_QBR:
22865 case OPC_PRECEQU_PH_QBLA:
22866 case OPC_PRECEQU_PH_QBRA:
22867 case OPC_PRECEU_PH_QBL:
22868 case OPC_PRECEU_PH_QBR:
22869 case OPC_PRECEU_PH_QBLA:
22870 case OPC_PRECEU_PH_QBRA:
22871 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22872 break;
22873 case OPC_BITREV:
22874 case OPC_REPL_QB:
22875 case OPC_REPLV_QB:
22876 case OPC_REPL_PH:
22877 case OPC_REPLV_PH:
22878 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
22879 break;
22880 default:
22881 MIPS_INVAL("MASK ABSQ_S.PH");
22882 generate_exception_end(ctx, EXCP_RI);
22883 break;
22885 break;
22886 case OPC_ADDU_QB_DSP:
22887 op2 = MASK_ADDU_QB(ctx->opcode);
22888 switch (op2) {
22889 case OPC_ADDQ_PH:
22890 case OPC_ADDQ_S_PH:
22891 case OPC_ADDQ_S_W:
22892 case OPC_ADDU_QB:
22893 case OPC_ADDU_S_QB:
22894 case OPC_ADDU_PH:
22895 case OPC_ADDU_S_PH:
22896 case OPC_SUBQ_PH:
22897 case OPC_SUBQ_S_PH:
22898 case OPC_SUBQ_S_W:
22899 case OPC_SUBU_QB:
22900 case OPC_SUBU_S_QB:
22901 case OPC_SUBU_PH:
22902 case OPC_SUBU_S_PH:
22903 case OPC_ADDSC:
22904 case OPC_ADDWC:
22905 case OPC_MODSUB:
22906 case OPC_RADDU_W_QB:
22907 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22908 break;
22909 case OPC_MULEU_S_PH_QBL:
22910 case OPC_MULEU_S_PH_QBR:
22911 case OPC_MULQ_RS_PH:
22912 case OPC_MULEQ_S_W_PHL:
22913 case OPC_MULEQ_S_W_PHR:
22914 case OPC_MULQ_S_PH:
22915 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
22916 break;
22917 default: /* Invalid */
22918 MIPS_INVAL("MASK ADDU.QB");
22919 generate_exception_end(ctx, EXCP_RI);
22920 break;
22923 break;
22924 case OPC_CMPU_EQ_QB_DSP:
22925 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
22926 switch (op2) {
22927 case OPC_PRECR_SRA_PH_W:
22928 case OPC_PRECR_SRA_R_PH_W:
22929 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
22930 break;
22931 case OPC_PRECR_QB_PH:
22932 case OPC_PRECRQ_QB_PH:
22933 case OPC_PRECRQ_PH_W:
22934 case OPC_PRECRQ_RS_PH_W:
22935 case OPC_PRECRQU_S_QB_PH:
22936 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
22937 break;
22938 case OPC_CMPU_EQ_QB:
22939 case OPC_CMPU_LT_QB:
22940 case OPC_CMPU_LE_QB:
22941 case OPC_CMP_EQ_PH:
22942 case OPC_CMP_LT_PH:
22943 case OPC_CMP_LE_PH:
22944 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
22945 break;
22946 case OPC_CMPGU_EQ_QB:
22947 case OPC_CMPGU_LT_QB:
22948 case OPC_CMPGU_LE_QB:
22949 case OPC_CMPGDU_EQ_QB:
22950 case OPC_CMPGDU_LT_QB:
22951 case OPC_CMPGDU_LE_QB:
22952 case OPC_PICK_QB:
22953 case OPC_PICK_PH:
22954 case OPC_PACKRL_PH:
22955 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
22956 break;
22957 default: /* Invalid */
22958 MIPS_INVAL("MASK CMPU.EQ.QB");
22959 generate_exception_end(ctx, EXCP_RI);
22960 break;
22962 break;
22963 case OPC_SHLL_QB_DSP:
22964 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
22965 break;
22966 case OPC_DPA_W_PH_DSP:
22967 op2 = MASK_DPA_W_PH(ctx->opcode);
22968 switch (op2) {
22969 case OPC_DPAU_H_QBL:
22970 case OPC_DPAU_H_QBR:
22971 case OPC_DPSU_H_QBL:
22972 case OPC_DPSU_H_QBR:
22973 case OPC_DPA_W_PH:
22974 case OPC_DPAX_W_PH:
22975 case OPC_DPAQ_S_W_PH:
22976 case OPC_DPAQX_S_W_PH:
22977 case OPC_DPAQX_SA_W_PH:
22978 case OPC_DPS_W_PH:
22979 case OPC_DPSX_W_PH:
22980 case OPC_DPSQ_S_W_PH:
22981 case OPC_DPSQX_S_W_PH:
22982 case OPC_DPSQX_SA_W_PH:
22983 case OPC_MULSAQ_S_W_PH:
22984 case OPC_DPAQ_SA_L_W:
22985 case OPC_DPSQ_SA_L_W:
22986 case OPC_MAQ_S_W_PHL:
22987 case OPC_MAQ_S_W_PHR:
22988 case OPC_MAQ_SA_W_PHL:
22989 case OPC_MAQ_SA_W_PHR:
22990 case OPC_MULSA_W_PH:
22991 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
22992 break;
22993 default: /* Invalid */
22994 MIPS_INVAL("MASK DPAW.PH");
22995 generate_exception_end(ctx, EXCP_RI);
22996 break;
22998 break;
22999 case OPC_INSV_DSP:
23000 op2 = MASK_INSV(ctx->opcode);
23001 switch (op2) {
23002 case OPC_INSV:
23003 check_dsp(ctx);
23005 TCGv t0, t1;
23007 if (rt == 0) {
23008 break;
23011 t0 = tcg_temp_new();
23012 t1 = tcg_temp_new();
23014 gen_load_gpr(t0, rt);
23015 gen_load_gpr(t1, rs);
23017 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
23019 tcg_temp_free(t0);
23020 tcg_temp_free(t1);
23021 break;
23023 default: /* Invalid */
23024 MIPS_INVAL("MASK INSV");
23025 generate_exception_end(ctx, EXCP_RI);
23026 break;
23028 break;
23029 case OPC_APPEND_DSP:
23030 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23031 break;
23032 case OPC_EXTR_W_DSP:
23033 op2 = MASK_EXTR_W(ctx->opcode);
23034 switch (op2) {
23035 case OPC_EXTR_W:
23036 case OPC_EXTR_R_W:
23037 case OPC_EXTR_RS_W:
23038 case OPC_EXTR_S_H:
23039 case OPC_EXTRV_S_H:
23040 case OPC_EXTRV_W:
23041 case OPC_EXTRV_R_W:
23042 case OPC_EXTRV_RS_W:
23043 case OPC_EXTP:
23044 case OPC_EXTPV:
23045 case OPC_EXTPDP:
23046 case OPC_EXTPDPV:
23047 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23048 break;
23049 case OPC_RDDSP:
23050 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
23051 break;
23052 case OPC_SHILO:
23053 case OPC_SHILOV:
23054 case OPC_MTHLIP:
23055 case OPC_WRDSP:
23056 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23057 break;
23058 default: /* Invalid */
23059 MIPS_INVAL("MASK EXTR.W");
23060 generate_exception_end(ctx, EXCP_RI);
23061 break;
23063 break;
23064 #if defined(TARGET_MIPS64)
23065 case OPC_DDIV_G_2E:
23066 case OPC_DDIVU_G_2E:
23067 case OPC_DMULT_G_2E:
23068 case OPC_DMULTU_G_2E:
23069 case OPC_DMOD_G_2E:
23070 case OPC_DMODU_G_2E:
23071 check_insn(ctx, INSN_LOONGSON2E);
23072 gen_loongson_integer(ctx, op1, rd, rs, rt);
23073 break;
23074 case OPC_ABSQ_S_QH_DSP:
23075 op2 = MASK_ABSQ_S_QH(ctx->opcode);
23076 switch (op2) {
23077 case OPC_PRECEQ_L_PWL:
23078 case OPC_PRECEQ_L_PWR:
23079 case OPC_PRECEQ_PW_QHL:
23080 case OPC_PRECEQ_PW_QHR:
23081 case OPC_PRECEQ_PW_QHLA:
23082 case OPC_PRECEQ_PW_QHRA:
23083 case OPC_PRECEQU_QH_OBL:
23084 case OPC_PRECEQU_QH_OBR:
23085 case OPC_PRECEQU_QH_OBLA:
23086 case OPC_PRECEQU_QH_OBRA:
23087 case OPC_PRECEU_QH_OBL:
23088 case OPC_PRECEU_QH_OBR:
23089 case OPC_PRECEU_QH_OBLA:
23090 case OPC_PRECEU_QH_OBRA:
23091 case OPC_ABSQ_S_OB:
23092 case OPC_ABSQ_S_PW:
23093 case OPC_ABSQ_S_QH:
23094 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23095 break;
23096 case OPC_REPL_OB:
23097 case OPC_REPL_PW:
23098 case OPC_REPL_QH:
23099 case OPC_REPLV_OB:
23100 case OPC_REPLV_PW:
23101 case OPC_REPLV_QH:
23102 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23103 break;
23104 default: /* Invalid */
23105 MIPS_INVAL("MASK ABSQ_S.QH");
23106 generate_exception_end(ctx, EXCP_RI);
23107 break;
23109 break;
23110 case OPC_ADDU_OB_DSP:
23111 op2 = MASK_ADDU_OB(ctx->opcode);
23112 switch (op2) {
23113 case OPC_RADDU_L_OB:
23114 case OPC_SUBQ_PW:
23115 case OPC_SUBQ_S_PW:
23116 case OPC_SUBQ_QH:
23117 case OPC_SUBQ_S_QH:
23118 case OPC_SUBU_OB:
23119 case OPC_SUBU_S_OB:
23120 case OPC_SUBU_QH:
23121 case OPC_SUBU_S_QH:
23122 case OPC_SUBUH_OB:
23123 case OPC_SUBUH_R_OB:
23124 case OPC_ADDQ_PW:
23125 case OPC_ADDQ_S_PW:
23126 case OPC_ADDQ_QH:
23127 case OPC_ADDQ_S_QH:
23128 case OPC_ADDU_OB:
23129 case OPC_ADDU_S_OB:
23130 case OPC_ADDU_QH:
23131 case OPC_ADDU_S_QH:
23132 case OPC_ADDUH_OB:
23133 case OPC_ADDUH_R_OB:
23134 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23135 break;
23136 case OPC_MULEQ_S_PW_QHL:
23137 case OPC_MULEQ_S_PW_QHR:
23138 case OPC_MULEU_S_QH_OBL:
23139 case OPC_MULEU_S_QH_OBR:
23140 case OPC_MULQ_RS_QH:
23141 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23142 break;
23143 default: /* Invalid */
23144 MIPS_INVAL("MASK ADDU.OB");
23145 generate_exception_end(ctx, EXCP_RI);
23146 break;
23148 break;
23149 case OPC_CMPU_EQ_OB_DSP:
23150 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
23151 switch (op2) {
23152 case OPC_PRECR_SRA_QH_PW:
23153 case OPC_PRECR_SRA_R_QH_PW:
23154 /* Return value is rt. */
23155 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
23156 break;
23157 case OPC_PRECR_OB_QH:
23158 case OPC_PRECRQ_OB_QH:
23159 case OPC_PRECRQ_PW_L:
23160 case OPC_PRECRQ_QH_PW:
23161 case OPC_PRECRQ_RS_QH_PW:
23162 case OPC_PRECRQU_S_OB_QH:
23163 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23164 break;
23165 case OPC_CMPU_EQ_OB:
23166 case OPC_CMPU_LT_OB:
23167 case OPC_CMPU_LE_OB:
23168 case OPC_CMP_EQ_QH:
23169 case OPC_CMP_LT_QH:
23170 case OPC_CMP_LE_QH:
23171 case OPC_CMP_EQ_PW:
23172 case OPC_CMP_LT_PW:
23173 case OPC_CMP_LE_PW:
23174 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
23175 break;
23176 case OPC_CMPGDU_EQ_OB:
23177 case OPC_CMPGDU_LT_OB:
23178 case OPC_CMPGDU_LE_OB:
23179 case OPC_CMPGU_EQ_OB:
23180 case OPC_CMPGU_LT_OB:
23181 case OPC_CMPGU_LE_OB:
23182 case OPC_PACKRL_PW:
23183 case OPC_PICK_OB:
23184 case OPC_PICK_PW:
23185 case OPC_PICK_QH:
23186 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
23187 break;
23188 default: /* Invalid */
23189 MIPS_INVAL("MASK CMPU_EQ.OB");
23190 generate_exception_end(ctx, EXCP_RI);
23191 break;
23193 break;
23194 case OPC_DAPPEND_DSP:
23195 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23196 break;
23197 case OPC_DEXTR_W_DSP:
23198 op2 = MASK_DEXTR_W(ctx->opcode);
23199 switch (op2) {
23200 case OPC_DEXTP:
23201 case OPC_DEXTPDP:
23202 case OPC_DEXTPDPV:
23203 case OPC_DEXTPV:
23204 case OPC_DEXTR_L:
23205 case OPC_DEXTR_R_L:
23206 case OPC_DEXTR_RS_L:
23207 case OPC_DEXTR_W:
23208 case OPC_DEXTR_R_W:
23209 case OPC_DEXTR_RS_W:
23210 case OPC_DEXTR_S_H:
23211 case OPC_DEXTRV_L:
23212 case OPC_DEXTRV_R_L:
23213 case OPC_DEXTRV_RS_L:
23214 case OPC_DEXTRV_S_H:
23215 case OPC_DEXTRV_W:
23216 case OPC_DEXTRV_R_W:
23217 case OPC_DEXTRV_RS_W:
23218 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23219 break;
23220 case OPC_DMTHLIP:
23221 case OPC_DSHILO:
23222 case OPC_DSHILOV:
23223 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23224 break;
23225 default: /* Invalid */
23226 MIPS_INVAL("MASK EXTR.W");
23227 generate_exception_end(ctx, EXCP_RI);
23228 break;
23230 break;
23231 case OPC_DPAQ_W_QH_DSP:
23232 op2 = MASK_DPAQ_W_QH(ctx->opcode);
23233 switch (op2) {
23234 case OPC_DPAU_H_OBL:
23235 case OPC_DPAU_H_OBR:
23236 case OPC_DPSU_H_OBL:
23237 case OPC_DPSU_H_OBR:
23238 case OPC_DPA_W_QH:
23239 case OPC_DPAQ_S_W_QH:
23240 case OPC_DPS_W_QH:
23241 case OPC_DPSQ_S_W_QH:
23242 case OPC_MULSAQ_S_W_QH:
23243 case OPC_DPAQ_SA_L_PW:
23244 case OPC_DPSQ_SA_L_PW:
23245 case OPC_MULSAQ_S_L_PW:
23246 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23247 break;
23248 case OPC_MAQ_S_W_QHLL:
23249 case OPC_MAQ_S_W_QHLR:
23250 case OPC_MAQ_S_W_QHRL:
23251 case OPC_MAQ_S_W_QHRR:
23252 case OPC_MAQ_SA_W_QHLL:
23253 case OPC_MAQ_SA_W_QHLR:
23254 case OPC_MAQ_SA_W_QHRL:
23255 case OPC_MAQ_SA_W_QHRR:
23256 case OPC_MAQ_S_L_PWL:
23257 case OPC_MAQ_S_L_PWR:
23258 case OPC_DMADD:
23259 case OPC_DMADDU:
23260 case OPC_DMSUB:
23261 case OPC_DMSUBU:
23262 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23263 break;
23264 default: /* Invalid */
23265 MIPS_INVAL("MASK DPAQ.W.QH");
23266 generate_exception_end(ctx, EXCP_RI);
23267 break;
23269 break;
23270 case OPC_DINSV_DSP:
23271 op2 = MASK_INSV(ctx->opcode);
23272 switch (op2) {
23273 case OPC_DINSV:
23275 TCGv t0, t1;
23277 if (rt == 0) {
23278 break;
23280 check_dsp(ctx);
23282 t0 = tcg_temp_new();
23283 t1 = tcg_temp_new();
23285 gen_load_gpr(t0, rt);
23286 gen_load_gpr(t1, rs);
23288 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
23290 tcg_temp_free(t0);
23291 tcg_temp_free(t1);
23292 break;
23294 default: /* Invalid */
23295 MIPS_INVAL("MASK DINSV");
23296 generate_exception_end(ctx, EXCP_RI);
23297 break;
23299 break;
23300 case OPC_SHLL_OB_DSP:
23301 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23302 break;
23303 #endif
23304 default: /* Invalid */
23305 MIPS_INVAL("special3_legacy");
23306 generate_exception_end(ctx, EXCP_RI);
23307 break;
23311 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
23313 int rs, rt, rd, sa;
23314 uint32_t op1, op2;
23315 int16_t imm;
23317 rs = (ctx->opcode >> 21) & 0x1f;
23318 rt = (ctx->opcode >> 16) & 0x1f;
23319 rd = (ctx->opcode >> 11) & 0x1f;
23320 sa = (ctx->opcode >> 6) & 0x1f;
23321 imm = sextract32(ctx->opcode, 7, 9);
23323 op1 = MASK_SPECIAL3(ctx->opcode);
23326 * EVA loads and stores overlap Loongson 2E instructions decoded by
23327 * decode_opc_special3_legacy(), so be careful to allow their decoding when
23328 * EVA is absent.
23330 if (ctx->eva) {
23331 switch (op1) {
23332 case OPC_LWLE:
23333 case OPC_LWRE:
23334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23335 /* fall through */
23336 case OPC_LBUE:
23337 case OPC_LHUE:
23338 case OPC_LBE:
23339 case OPC_LHE:
23340 case OPC_LLE:
23341 case OPC_LWE:
23342 check_cp0_enabled(ctx);
23343 gen_ld(ctx, op1, rt, rs, imm);
23344 return;
23345 case OPC_SWLE:
23346 case OPC_SWRE:
23347 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23348 /* fall through */
23349 case OPC_SBE:
23350 case OPC_SHE:
23351 case OPC_SWE:
23352 check_cp0_enabled(ctx);
23353 gen_st(ctx, op1, rt, rs, imm);
23354 return;
23355 case OPC_SCE:
23356 check_cp0_enabled(ctx);
23357 gen_st_cond(ctx, op1, rt, rs, imm);
23358 return;
23359 case OPC_CACHEE:
23360 check_cp0_enabled(ctx);
23361 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23362 gen_cache_operation(ctx, rt, rs, imm);
23364 /* Treat as NOP. */
23365 return;
23366 case OPC_PREFE:
23367 check_cp0_enabled(ctx);
23368 /* Treat as NOP. */
23369 return;
23373 switch (op1) {
23374 case OPC_EXT:
23375 case OPC_INS:
23376 check_insn(ctx, ISA_MIPS32R2);
23377 gen_bitops(ctx, op1, rt, rs, sa, rd);
23378 break;
23379 case OPC_BSHFL:
23380 op2 = MASK_BSHFL(ctx->opcode);
23381 switch (op2) {
23382 case OPC_ALIGN:
23383 case OPC_ALIGN_END:
23384 case OPC_BITSWAP:
23385 check_insn(ctx, ISA_MIPS32R6);
23386 decode_opc_special3_r6(env, ctx);
23387 break;
23388 default:
23389 check_insn(ctx, ISA_MIPS32R2);
23390 gen_bshfl(ctx, op2, rt, rd);
23391 break;
23393 break;
23394 #if defined(TARGET_MIPS64)
23395 case OPC_DEXTM:
23396 case OPC_DEXTU:
23397 case OPC_DEXT:
23398 case OPC_DINSM:
23399 case OPC_DINSU:
23400 case OPC_DINS:
23401 check_insn(ctx, ISA_MIPS64R2);
23402 check_mips_64(ctx);
23403 gen_bitops(ctx, op1, rt, rs, sa, rd);
23404 break;
23405 case OPC_DBSHFL:
23406 op2 = MASK_DBSHFL(ctx->opcode);
23407 switch (op2) {
23408 case OPC_DALIGN:
23409 case OPC_DALIGN_END:
23410 case OPC_DBITSWAP:
23411 check_insn(ctx, ISA_MIPS32R6);
23412 decode_opc_special3_r6(env, ctx);
23413 break;
23414 default:
23415 check_insn(ctx, ISA_MIPS64R2);
23416 check_mips_64(ctx);
23417 op2 = MASK_DBSHFL(ctx->opcode);
23418 gen_bshfl(ctx, op2, rt, rd);
23419 break;
23421 break;
23422 #endif
23423 case OPC_RDHWR:
23424 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
23425 break;
23426 case OPC_FORK:
23427 check_mt(ctx);
23429 TCGv t0 = tcg_temp_new();
23430 TCGv t1 = tcg_temp_new();
23432 gen_load_gpr(t0, rt);
23433 gen_load_gpr(t1, rs);
23434 gen_helper_fork(t0, t1);
23435 tcg_temp_free(t0);
23436 tcg_temp_free(t1);
23438 break;
23439 case OPC_YIELD:
23440 check_mt(ctx);
23442 TCGv t0 = tcg_temp_new();
23444 gen_load_gpr(t0, rs);
23445 gen_helper_yield(t0, cpu_env, t0);
23446 gen_store_gpr(t0, rd);
23447 tcg_temp_free(t0);
23449 break;
23450 default:
23451 if (ctx->insn_flags & ISA_MIPS32R6) {
23452 decode_opc_special3_r6(env, ctx);
23453 } else {
23454 decode_opc_special3_legacy(env, ctx);
23459 /* MIPS SIMD Architecture (MSA) */
23460 static inline int check_msa_access(DisasContext *ctx)
23462 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
23463 !(ctx->hflags & MIPS_HFLAG_F64))) {
23464 generate_exception_end(ctx, EXCP_RI);
23465 return 0;
23468 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
23469 if (ctx->insn_flags & ASE_MSA) {
23470 generate_exception_end(ctx, EXCP_MSADIS);
23471 return 0;
23472 } else {
23473 generate_exception_end(ctx, EXCP_RI);
23474 return 0;
23477 return 1;
23480 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
23482 /* generates tcg ops to check if any element is 0 */
23483 /* Note this function only works with MSA_WRLEN = 128 */
23484 uint64_t eval_zero_or_big = 0;
23485 uint64_t eval_big = 0;
23486 TCGv_i64 t0 = tcg_temp_new_i64();
23487 TCGv_i64 t1 = tcg_temp_new_i64();
23488 switch (df) {
23489 case DF_BYTE:
23490 eval_zero_or_big = 0x0101010101010101ULL;
23491 eval_big = 0x8080808080808080ULL;
23492 break;
23493 case DF_HALF:
23494 eval_zero_or_big = 0x0001000100010001ULL;
23495 eval_big = 0x8000800080008000ULL;
23496 break;
23497 case DF_WORD:
23498 eval_zero_or_big = 0x0000000100000001ULL;
23499 eval_big = 0x8000000080000000ULL;
23500 break;
23501 case DF_DOUBLE:
23502 eval_zero_or_big = 0x0000000000000001ULL;
23503 eval_big = 0x8000000000000000ULL;
23504 break;
23506 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
23507 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
23508 tcg_gen_andi_i64(t0, t0, eval_big);
23509 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
23510 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
23511 tcg_gen_andi_i64(t1, t1, eval_big);
23512 tcg_gen_or_i64(t0, t0, t1);
23513 /* if all bits are zero then all elements are not zero */
23514 /* if some bit is non-zero then some element is zero */
23515 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
23516 tcg_gen_trunc_i64_tl(tresult, t0);
23517 tcg_temp_free_i64(t0);
23518 tcg_temp_free_i64(t1);
23521 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
23523 uint8_t df = (ctx->opcode >> 21) & 0x3;
23524 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
23525 int64_t s16 = (int16_t)ctx->opcode;
23527 check_msa_access(ctx);
23529 if (ctx->hflags & MIPS_HFLAG_BMASK) {
23530 generate_exception_end(ctx, EXCP_RI);
23531 return;
23533 switch (op1) {
23534 case OPC_BZ_V:
23535 case OPC_BNZ_V:
23537 TCGv_i64 t0 = tcg_temp_new_i64();
23538 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
23539 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
23540 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
23541 tcg_gen_trunc_i64_tl(bcond, t0);
23542 tcg_temp_free_i64(t0);
23544 break;
23545 case OPC_BZ_B:
23546 case OPC_BZ_H:
23547 case OPC_BZ_W:
23548 case OPC_BZ_D:
23549 gen_check_zero_element(bcond, df, wt);
23550 break;
23551 case OPC_BNZ_B:
23552 case OPC_BNZ_H:
23553 case OPC_BNZ_W:
23554 case OPC_BNZ_D:
23555 gen_check_zero_element(bcond, df, wt);
23556 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
23557 break;
23560 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
23562 ctx->hflags |= MIPS_HFLAG_BC;
23563 ctx->hflags |= MIPS_HFLAG_BDS32;
23566 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
23568 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
23569 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
23570 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23571 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23573 TCGv_i32 twd = tcg_const_i32(wd);
23574 TCGv_i32 tws = tcg_const_i32(ws);
23575 TCGv_i32 ti8 = tcg_const_i32(i8);
23577 switch (MASK_MSA_I8(ctx->opcode)) {
23578 case OPC_ANDI_B:
23579 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
23580 break;
23581 case OPC_ORI_B:
23582 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
23583 break;
23584 case OPC_NORI_B:
23585 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
23586 break;
23587 case OPC_XORI_B:
23588 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
23589 break;
23590 case OPC_BMNZI_B:
23591 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
23592 break;
23593 case OPC_BMZI_B:
23594 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
23595 break;
23596 case OPC_BSELI_B:
23597 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
23598 break;
23599 case OPC_SHF_B:
23600 case OPC_SHF_H:
23601 case OPC_SHF_W:
23603 uint8_t df = (ctx->opcode >> 24) & 0x3;
23604 if (df == DF_DOUBLE) {
23605 generate_exception_end(ctx, EXCP_RI);
23606 } else {
23607 TCGv_i32 tdf = tcg_const_i32(df);
23608 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
23609 tcg_temp_free_i32(tdf);
23612 break;
23613 default:
23614 MIPS_INVAL("MSA instruction");
23615 generate_exception_end(ctx, EXCP_RI);
23616 break;
23619 tcg_temp_free_i32(twd);
23620 tcg_temp_free_i32(tws);
23621 tcg_temp_free_i32(ti8);
23624 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
23626 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
23627 uint8_t df = (ctx->opcode >> 21) & 0x3;
23628 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
23629 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
23630 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23631 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23633 TCGv_i32 tdf = tcg_const_i32(df);
23634 TCGv_i32 twd = tcg_const_i32(wd);
23635 TCGv_i32 tws = tcg_const_i32(ws);
23636 TCGv_i32 timm = tcg_temp_new_i32();
23637 tcg_gen_movi_i32(timm, u5);
23639 switch (MASK_MSA_I5(ctx->opcode)) {
23640 case OPC_ADDVI_df:
23641 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
23642 break;
23643 case OPC_SUBVI_df:
23644 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
23645 break;
23646 case OPC_MAXI_S_df:
23647 tcg_gen_movi_i32(timm, s5);
23648 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
23649 break;
23650 case OPC_MAXI_U_df:
23651 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
23652 break;
23653 case OPC_MINI_S_df:
23654 tcg_gen_movi_i32(timm, s5);
23655 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
23656 break;
23657 case OPC_MINI_U_df:
23658 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
23659 break;
23660 case OPC_CEQI_df:
23661 tcg_gen_movi_i32(timm, s5);
23662 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
23663 break;
23664 case OPC_CLTI_S_df:
23665 tcg_gen_movi_i32(timm, s5);
23666 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
23667 break;
23668 case OPC_CLTI_U_df:
23669 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
23670 break;
23671 case OPC_CLEI_S_df:
23672 tcg_gen_movi_i32(timm, s5);
23673 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
23674 break;
23675 case OPC_CLEI_U_df:
23676 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
23677 break;
23678 case OPC_LDI_df:
23680 int32_t s10 = sextract32(ctx->opcode, 11, 10);
23681 tcg_gen_movi_i32(timm, s10);
23682 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
23684 break;
23685 default:
23686 MIPS_INVAL("MSA instruction");
23687 generate_exception_end(ctx, EXCP_RI);
23688 break;
23691 tcg_temp_free_i32(tdf);
23692 tcg_temp_free_i32(twd);
23693 tcg_temp_free_i32(tws);
23694 tcg_temp_free_i32(timm);
23697 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
23699 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
23700 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
23701 uint32_t df = 0, m = 0;
23702 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23703 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23705 TCGv_i32 tdf;
23706 TCGv_i32 tm;
23707 TCGv_i32 twd;
23708 TCGv_i32 tws;
23710 if ((dfm & 0x40) == 0x00) {
23711 m = dfm & 0x3f;
23712 df = DF_DOUBLE;
23713 } else if ((dfm & 0x60) == 0x40) {
23714 m = dfm & 0x1f;
23715 df = DF_WORD;
23716 } else if ((dfm & 0x70) == 0x60) {
23717 m = dfm & 0x0f;
23718 df = DF_HALF;
23719 } else if ((dfm & 0x78) == 0x70) {
23720 m = dfm & 0x7;
23721 df = DF_BYTE;
23722 } else {
23723 generate_exception_end(ctx, EXCP_RI);
23724 return;
23727 tdf = tcg_const_i32(df);
23728 tm = tcg_const_i32(m);
23729 twd = tcg_const_i32(wd);
23730 tws = tcg_const_i32(ws);
23732 switch (MASK_MSA_BIT(ctx->opcode)) {
23733 case OPC_SLLI_df:
23734 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
23735 break;
23736 case OPC_SRAI_df:
23737 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
23738 break;
23739 case OPC_SRLI_df:
23740 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
23741 break;
23742 case OPC_BCLRI_df:
23743 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
23744 break;
23745 case OPC_BSETI_df:
23746 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
23747 break;
23748 case OPC_BNEGI_df:
23749 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
23750 break;
23751 case OPC_BINSLI_df:
23752 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
23753 break;
23754 case OPC_BINSRI_df:
23755 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
23756 break;
23757 case OPC_SAT_S_df:
23758 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
23759 break;
23760 case OPC_SAT_U_df:
23761 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
23762 break;
23763 case OPC_SRARI_df:
23764 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
23765 break;
23766 case OPC_SRLRI_df:
23767 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
23768 break;
23769 default:
23770 MIPS_INVAL("MSA instruction");
23771 generate_exception_end(ctx, EXCP_RI);
23772 break;
23775 tcg_temp_free_i32(tdf);
23776 tcg_temp_free_i32(tm);
23777 tcg_temp_free_i32(twd);
23778 tcg_temp_free_i32(tws);
23781 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
23783 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
23784 uint8_t df = (ctx->opcode >> 21) & 0x3;
23785 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
23786 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
23787 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
23789 TCGv_i32 tdf = tcg_const_i32(df);
23790 TCGv_i32 twd = tcg_const_i32(wd);
23791 TCGv_i32 tws = tcg_const_i32(ws);
23792 TCGv_i32 twt = tcg_const_i32(wt);
23794 switch (MASK_MSA_3R(ctx->opcode)) {
23795 case OPC_SLL_df:
23796 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
23797 break;
23798 case OPC_ADDV_df:
23799 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
23800 break;
23801 case OPC_CEQ_df:
23802 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
23803 break;
23804 case OPC_ADD_A_df:
23805 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
23806 break;
23807 case OPC_SUBS_S_df:
23808 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
23809 break;
23810 case OPC_MULV_df:
23811 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
23812 break;
23813 case OPC_SLD_df:
23814 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
23815 break;
23816 case OPC_VSHF_df:
23817 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
23818 break;
23819 case OPC_SRA_df:
23820 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
23821 break;
23822 case OPC_SUBV_df:
23823 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
23824 break;
23825 case OPC_ADDS_A_df:
23826 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
23827 break;
23828 case OPC_SUBS_U_df:
23829 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
23830 break;
23831 case OPC_MADDV_df:
23832 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
23833 break;
23834 case OPC_SPLAT_df:
23835 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
23836 break;
23837 case OPC_SRAR_df:
23838 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
23839 break;
23840 case OPC_SRL_df:
23841 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
23842 break;
23843 case OPC_MAX_S_df:
23844 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
23845 break;
23846 case OPC_CLT_S_df:
23847 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
23848 break;
23849 case OPC_ADDS_S_df:
23850 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
23851 break;
23852 case OPC_SUBSUS_U_df:
23853 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
23854 break;
23855 case OPC_MSUBV_df:
23856 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
23857 break;
23858 case OPC_PCKEV_df:
23859 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
23860 break;
23861 case OPC_SRLR_df:
23862 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
23863 break;
23864 case OPC_BCLR_df:
23865 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
23866 break;
23867 case OPC_MAX_U_df:
23868 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
23869 break;
23870 case OPC_CLT_U_df:
23871 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
23872 break;
23873 case OPC_ADDS_U_df:
23874 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
23875 break;
23876 case OPC_SUBSUU_S_df:
23877 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
23878 break;
23879 case OPC_PCKOD_df:
23880 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
23881 break;
23882 case OPC_BSET_df:
23883 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
23884 break;
23885 case OPC_MIN_S_df:
23886 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
23887 break;
23888 case OPC_CLE_S_df:
23889 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
23890 break;
23891 case OPC_AVE_S_df:
23892 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
23893 break;
23894 case OPC_ASUB_S_df:
23895 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
23896 break;
23897 case OPC_DIV_S_df:
23898 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
23899 break;
23900 case OPC_ILVL_df:
23901 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
23902 break;
23903 case OPC_BNEG_df:
23904 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
23905 break;
23906 case OPC_MIN_U_df:
23907 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
23908 break;
23909 case OPC_CLE_U_df:
23910 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
23911 break;
23912 case OPC_AVE_U_df:
23913 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
23914 break;
23915 case OPC_ASUB_U_df:
23916 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
23917 break;
23918 case OPC_DIV_U_df:
23919 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
23920 break;
23921 case OPC_ILVR_df:
23922 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
23923 break;
23924 case OPC_BINSL_df:
23925 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
23926 break;
23927 case OPC_MAX_A_df:
23928 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
23929 break;
23930 case OPC_AVER_S_df:
23931 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
23932 break;
23933 case OPC_MOD_S_df:
23934 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
23935 break;
23936 case OPC_ILVEV_df:
23937 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
23938 break;
23939 case OPC_BINSR_df:
23940 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
23941 break;
23942 case OPC_MIN_A_df:
23943 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
23944 break;
23945 case OPC_AVER_U_df:
23946 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
23947 break;
23948 case OPC_MOD_U_df:
23949 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
23950 break;
23951 case OPC_ILVOD_df:
23952 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
23953 break;
23955 case OPC_DOTP_S_df:
23956 case OPC_DOTP_U_df:
23957 case OPC_DPADD_S_df:
23958 case OPC_DPADD_U_df:
23959 case OPC_DPSUB_S_df:
23960 case OPC_HADD_S_df:
23961 case OPC_DPSUB_U_df:
23962 case OPC_HADD_U_df:
23963 case OPC_HSUB_S_df:
23964 case OPC_HSUB_U_df:
23965 if (df == DF_BYTE) {
23966 generate_exception_end(ctx, EXCP_RI);
23967 break;
23969 switch (MASK_MSA_3R(ctx->opcode)) {
23970 case OPC_DOTP_S_df:
23971 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
23972 break;
23973 case OPC_DOTP_U_df:
23974 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
23975 break;
23976 case OPC_DPADD_S_df:
23977 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
23978 break;
23979 case OPC_DPADD_U_df:
23980 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
23981 break;
23982 case OPC_DPSUB_S_df:
23983 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
23984 break;
23985 case OPC_HADD_S_df:
23986 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
23987 break;
23988 case OPC_DPSUB_U_df:
23989 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
23990 break;
23991 case OPC_HADD_U_df:
23992 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
23993 break;
23994 case OPC_HSUB_S_df:
23995 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
23996 break;
23997 case OPC_HSUB_U_df:
23998 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
23999 break;
24001 break;
24002 default:
24003 MIPS_INVAL("MSA instruction");
24004 generate_exception_end(ctx, EXCP_RI);
24005 break;
24007 tcg_temp_free_i32(twd);
24008 tcg_temp_free_i32(tws);
24009 tcg_temp_free_i32(twt);
24010 tcg_temp_free_i32(tdf);
24013 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
24015 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
24016 uint8_t source = (ctx->opcode >> 11) & 0x1f;
24017 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
24018 TCGv telm = tcg_temp_new();
24019 TCGv_i32 tsr = tcg_const_i32(source);
24020 TCGv_i32 tdt = tcg_const_i32(dest);
24022 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
24023 case OPC_CTCMSA:
24024 gen_load_gpr(telm, source);
24025 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
24026 break;
24027 case OPC_CFCMSA:
24028 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
24029 gen_store_gpr(telm, dest);
24030 break;
24031 case OPC_MOVE_V:
24032 gen_helper_msa_move_v(cpu_env, tdt, tsr);
24033 break;
24034 default:
24035 MIPS_INVAL("MSA instruction");
24036 generate_exception_end(ctx, EXCP_RI);
24037 break;
24040 tcg_temp_free(telm);
24041 tcg_temp_free_i32(tdt);
24042 tcg_temp_free_i32(tsr);
24045 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
24046 uint32_t n)
24048 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24049 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24050 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24052 TCGv_i32 tws = tcg_const_i32(ws);
24053 TCGv_i32 twd = tcg_const_i32(wd);
24054 TCGv_i32 tn = tcg_const_i32(n);
24055 TCGv_i32 tdf = tcg_const_i32(df);
24057 switch (MASK_MSA_ELM(ctx->opcode)) {
24058 case OPC_SLDI_df:
24059 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
24060 break;
24061 case OPC_SPLATI_df:
24062 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
24063 break;
24064 case OPC_INSVE_df:
24065 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
24066 break;
24067 case OPC_COPY_S_df:
24068 case OPC_COPY_U_df:
24069 case OPC_INSERT_df:
24070 #if !defined(TARGET_MIPS64)
24071 /* Double format valid only for MIPS64 */
24072 if (df == DF_DOUBLE) {
24073 generate_exception_end(ctx, EXCP_RI);
24074 break;
24076 #endif
24077 switch (MASK_MSA_ELM(ctx->opcode)) {
24078 case OPC_COPY_S_df:
24079 if (likely(wd != 0)) {
24080 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
24082 break;
24083 case OPC_COPY_U_df:
24084 if (likely(wd != 0)) {
24085 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
24087 break;
24088 case OPC_INSERT_df:
24089 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
24090 break;
24092 break;
24093 default:
24094 MIPS_INVAL("MSA instruction");
24095 generate_exception_end(ctx, EXCP_RI);
24097 tcg_temp_free_i32(twd);
24098 tcg_temp_free_i32(tws);
24099 tcg_temp_free_i32(tn);
24100 tcg_temp_free_i32(tdf);
24103 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
24105 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
24106 uint32_t df = 0, n = 0;
24108 if ((dfn & 0x30) == 0x00) {
24109 n = dfn & 0x0f;
24110 df = DF_BYTE;
24111 } else if ((dfn & 0x38) == 0x20) {
24112 n = dfn & 0x07;
24113 df = DF_HALF;
24114 } else if ((dfn & 0x3c) == 0x30) {
24115 n = dfn & 0x03;
24116 df = DF_WORD;
24117 } else if ((dfn & 0x3e) == 0x38) {
24118 n = dfn & 0x01;
24119 df = DF_DOUBLE;
24120 } else if (dfn == 0x3E) {
24121 /* CTCMSA, CFCMSA, MOVE.V */
24122 gen_msa_elm_3e(env, ctx);
24123 return;
24124 } else {
24125 generate_exception_end(ctx, EXCP_RI);
24126 return;
24129 gen_msa_elm_df(env, ctx, df, n);
24132 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
24134 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24135 uint8_t df = (ctx->opcode >> 21) & 0x1;
24136 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24137 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24138 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24140 TCGv_i32 twd = tcg_const_i32(wd);
24141 TCGv_i32 tws = tcg_const_i32(ws);
24142 TCGv_i32 twt = tcg_const_i32(wt);
24143 TCGv_i32 tdf = tcg_temp_new_i32();
24145 /* adjust df value for floating-point instruction */
24146 tcg_gen_movi_i32(tdf, df + 2);
24148 switch (MASK_MSA_3RF(ctx->opcode)) {
24149 case OPC_FCAF_df:
24150 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
24151 break;
24152 case OPC_FADD_df:
24153 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
24154 break;
24155 case OPC_FCUN_df:
24156 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
24157 break;
24158 case OPC_FSUB_df:
24159 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
24160 break;
24161 case OPC_FCOR_df:
24162 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
24163 break;
24164 case OPC_FCEQ_df:
24165 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
24166 break;
24167 case OPC_FMUL_df:
24168 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
24169 break;
24170 case OPC_FCUNE_df:
24171 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
24172 break;
24173 case OPC_FCUEQ_df:
24174 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
24175 break;
24176 case OPC_FDIV_df:
24177 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
24178 break;
24179 case OPC_FCNE_df:
24180 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
24181 break;
24182 case OPC_FCLT_df:
24183 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
24184 break;
24185 case OPC_FMADD_df:
24186 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
24187 break;
24188 case OPC_MUL_Q_df:
24189 tcg_gen_movi_i32(tdf, df + 1);
24190 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
24191 break;
24192 case OPC_FCULT_df:
24193 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
24194 break;
24195 case OPC_FMSUB_df:
24196 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
24197 break;
24198 case OPC_MADD_Q_df:
24199 tcg_gen_movi_i32(tdf, df + 1);
24200 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
24201 break;
24202 case OPC_FCLE_df:
24203 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
24204 break;
24205 case OPC_MSUB_Q_df:
24206 tcg_gen_movi_i32(tdf, df + 1);
24207 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
24208 break;
24209 case OPC_FCULE_df:
24210 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
24211 break;
24212 case OPC_FEXP2_df:
24213 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
24214 break;
24215 case OPC_FSAF_df:
24216 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
24217 break;
24218 case OPC_FEXDO_df:
24219 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
24220 break;
24221 case OPC_FSUN_df:
24222 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
24223 break;
24224 case OPC_FSOR_df:
24225 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
24226 break;
24227 case OPC_FSEQ_df:
24228 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
24229 break;
24230 case OPC_FTQ_df:
24231 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
24232 break;
24233 case OPC_FSUNE_df:
24234 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
24235 break;
24236 case OPC_FSUEQ_df:
24237 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
24238 break;
24239 case OPC_FSNE_df:
24240 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
24241 break;
24242 case OPC_FSLT_df:
24243 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
24244 break;
24245 case OPC_FMIN_df:
24246 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
24247 break;
24248 case OPC_MULR_Q_df:
24249 tcg_gen_movi_i32(tdf, df + 1);
24250 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
24251 break;
24252 case OPC_FSULT_df:
24253 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
24254 break;
24255 case OPC_FMIN_A_df:
24256 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
24257 break;
24258 case OPC_MADDR_Q_df:
24259 tcg_gen_movi_i32(tdf, df + 1);
24260 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
24261 break;
24262 case OPC_FSLE_df:
24263 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
24264 break;
24265 case OPC_FMAX_df:
24266 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
24267 break;
24268 case OPC_MSUBR_Q_df:
24269 tcg_gen_movi_i32(tdf, df + 1);
24270 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
24271 break;
24272 case OPC_FSULE_df:
24273 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
24274 break;
24275 case OPC_FMAX_A_df:
24276 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
24277 break;
24278 default:
24279 MIPS_INVAL("MSA instruction");
24280 generate_exception_end(ctx, EXCP_RI);
24281 break;
24284 tcg_temp_free_i32(twd);
24285 tcg_temp_free_i32(tws);
24286 tcg_temp_free_i32(twt);
24287 tcg_temp_free_i32(tdf);
24290 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
24292 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24293 (op & (0x7 << 18)))
24294 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24295 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24296 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24297 uint8_t df = (ctx->opcode >> 16) & 0x3;
24298 TCGv_i32 twd = tcg_const_i32(wd);
24299 TCGv_i32 tws = tcg_const_i32(ws);
24300 TCGv_i32 twt = tcg_const_i32(wt);
24301 TCGv_i32 tdf = tcg_const_i32(df);
24303 switch (MASK_MSA_2R(ctx->opcode)) {
24304 case OPC_FILL_df:
24305 #if !defined(TARGET_MIPS64)
24306 /* Double format valid only for MIPS64 */
24307 if (df == DF_DOUBLE) {
24308 generate_exception_end(ctx, EXCP_RI);
24309 break;
24311 #endif
24312 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
24313 break;
24314 case OPC_PCNT_df:
24315 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
24316 break;
24317 case OPC_NLOC_df:
24318 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
24319 break;
24320 case OPC_NLZC_df:
24321 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
24322 break;
24323 default:
24324 MIPS_INVAL("MSA instruction");
24325 generate_exception_end(ctx, EXCP_RI);
24326 break;
24329 tcg_temp_free_i32(twd);
24330 tcg_temp_free_i32(tws);
24331 tcg_temp_free_i32(twt);
24332 tcg_temp_free_i32(tdf);
24335 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
24337 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24338 (op & (0xf << 17)))
24339 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24340 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24341 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24342 uint8_t df = (ctx->opcode >> 16) & 0x1;
24343 TCGv_i32 twd = tcg_const_i32(wd);
24344 TCGv_i32 tws = tcg_const_i32(ws);
24345 TCGv_i32 twt = tcg_const_i32(wt);
24346 /* adjust df value for floating-point instruction */
24347 TCGv_i32 tdf = tcg_const_i32(df + 2);
24349 switch (MASK_MSA_2RF(ctx->opcode)) {
24350 case OPC_FCLASS_df:
24351 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
24352 break;
24353 case OPC_FTRUNC_S_df:
24354 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
24355 break;
24356 case OPC_FTRUNC_U_df:
24357 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
24358 break;
24359 case OPC_FSQRT_df:
24360 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
24361 break;
24362 case OPC_FRSQRT_df:
24363 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
24364 break;
24365 case OPC_FRCP_df:
24366 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
24367 break;
24368 case OPC_FRINT_df:
24369 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
24370 break;
24371 case OPC_FLOG2_df:
24372 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
24373 break;
24374 case OPC_FEXUPL_df:
24375 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
24376 break;
24377 case OPC_FEXUPR_df:
24378 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
24379 break;
24380 case OPC_FFQL_df:
24381 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
24382 break;
24383 case OPC_FFQR_df:
24384 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
24385 break;
24386 case OPC_FTINT_S_df:
24387 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
24388 break;
24389 case OPC_FTINT_U_df:
24390 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
24391 break;
24392 case OPC_FFINT_S_df:
24393 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
24394 break;
24395 case OPC_FFINT_U_df:
24396 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
24397 break;
24400 tcg_temp_free_i32(twd);
24401 tcg_temp_free_i32(tws);
24402 tcg_temp_free_i32(twt);
24403 tcg_temp_free_i32(tdf);
24406 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
24408 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
24409 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24410 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24411 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24412 TCGv_i32 twd = tcg_const_i32(wd);
24413 TCGv_i32 tws = tcg_const_i32(ws);
24414 TCGv_i32 twt = tcg_const_i32(wt);
24416 switch (MASK_MSA_VEC(ctx->opcode)) {
24417 case OPC_AND_V:
24418 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
24419 break;
24420 case OPC_OR_V:
24421 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
24422 break;
24423 case OPC_NOR_V:
24424 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
24425 break;
24426 case OPC_XOR_V:
24427 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
24428 break;
24429 case OPC_BMNZ_V:
24430 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
24431 break;
24432 case OPC_BMZ_V:
24433 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
24434 break;
24435 case OPC_BSEL_V:
24436 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
24437 break;
24438 default:
24439 MIPS_INVAL("MSA instruction");
24440 generate_exception_end(ctx, EXCP_RI);
24441 break;
24444 tcg_temp_free_i32(twd);
24445 tcg_temp_free_i32(tws);
24446 tcg_temp_free_i32(twt);
24449 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
24451 switch (MASK_MSA_VEC(ctx->opcode)) {
24452 case OPC_AND_V:
24453 case OPC_OR_V:
24454 case OPC_NOR_V:
24455 case OPC_XOR_V:
24456 case OPC_BMNZ_V:
24457 case OPC_BMZ_V:
24458 case OPC_BSEL_V:
24459 gen_msa_vec_v(env, ctx);
24460 break;
24461 case OPC_MSA_2R:
24462 gen_msa_2r(env, ctx);
24463 break;
24464 case OPC_MSA_2RF:
24465 gen_msa_2rf(env, ctx);
24466 break;
24467 default:
24468 MIPS_INVAL("MSA instruction");
24469 generate_exception_end(ctx, EXCP_RI);
24470 break;
24474 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
24476 uint32_t opcode = ctx->opcode;
24477 check_insn(ctx, ASE_MSA);
24478 check_msa_access(ctx);
24480 switch (MASK_MSA_MINOR(opcode)) {
24481 case OPC_MSA_I8_00:
24482 case OPC_MSA_I8_01:
24483 case OPC_MSA_I8_02:
24484 gen_msa_i8(env, ctx);
24485 break;
24486 case OPC_MSA_I5_06:
24487 case OPC_MSA_I5_07:
24488 gen_msa_i5(env, ctx);
24489 break;
24490 case OPC_MSA_BIT_09:
24491 case OPC_MSA_BIT_0A:
24492 gen_msa_bit(env, ctx);
24493 break;
24494 case OPC_MSA_3R_0D:
24495 case OPC_MSA_3R_0E:
24496 case OPC_MSA_3R_0F:
24497 case OPC_MSA_3R_10:
24498 case OPC_MSA_3R_11:
24499 case OPC_MSA_3R_12:
24500 case OPC_MSA_3R_13:
24501 case OPC_MSA_3R_14:
24502 case OPC_MSA_3R_15:
24503 gen_msa_3r(env, ctx);
24504 break;
24505 case OPC_MSA_ELM:
24506 gen_msa_elm(env, ctx);
24507 break;
24508 case OPC_MSA_3RF_1A:
24509 case OPC_MSA_3RF_1B:
24510 case OPC_MSA_3RF_1C:
24511 gen_msa_3rf(env, ctx);
24512 break;
24513 case OPC_MSA_VEC:
24514 gen_msa_vec(env, ctx);
24515 break;
24516 case OPC_LD_B:
24517 case OPC_LD_H:
24518 case OPC_LD_W:
24519 case OPC_LD_D:
24520 case OPC_ST_B:
24521 case OPC_ST_H:
24522 case OPC_ST_W:
24523 case OPC_ST_D:
24525 int32_t s10 = sextract32(ctx->opcode, 16, 10);
24526 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
24527 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24528 uint8_t df = (ctx->opcode >> 0) & 0x3;
24530 TCGv_i32 twd = tcg_const_i32(wd);
24531 TCGv taddr = tcg_temp_new();
24532 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
24534 switch (MASK_MSA_MINOR(opcode)) {
24535 case OPC_LD_B:
24536 gen_helper_msa_ld_b(cpu_env, twd, taddr);
24537 break;
24538 case OPC_LD_H:
24539 gen_helper_msa_ld_h(cpu_env, twd, taddr);
24540 break;
24541 case OPC_LD_W:
24542 gen_helper_msa_ld_w(cpu_env, twd, taddr);
24543 break;
24544 case OPC_LD_D:
24545 gen_helper_msa_ld_d(cpu_env, twd, taddr);
24546 break;
24547 case OPC_ST_B:
24548 gen_helper_msa_st_b(cpu_env, twd, taddr);
24549 break;
24550 case OPC_ST_H:
24551 gen_helper_msa_st_h(cpu_env, twd, taddr);
24552 break;
24553 case OPC_ST_W:
24554 gen_helper_msa_st_w(cpu_env, twd, taddr);
24555 break;
24556 case OPC_ST_D:
24557 gen_helper_msa_st_d(cpu_env, twd, taddr);
24558 break;
24561 tcg_temp_free_i32(twd);
24562 tcg_temp_free(taddr);
24564 break;
24565 default:
24566 MIPS_INVAL("MSA instruction");
24567 generate_exception_end(ctx, EXCP_RI);
24568 break;
24573 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
24575 int32_t offset;
24576 int rs, rt, rd, sa;
24577 uint32_t op, op1;
24578 int16_t imm;
24580 /* make sure instructions are on a word boundary */
24581 if (ctx->base.pc_next & 0x3) {
24582 env->CP0_BadVAddr = ctx->base.pc_next;
24583 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
24584 return;
24587 /* Handle blikely not taken case */
24588 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
24589 TCGLabel *l1 = gen_new_label();
24591 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
24592 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
24593 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
24594 gen_set_label(l1);
24597 op = MASK_OP_MAJOR(ctx->opcode);
24598 rs = (ctx->opcode >> 21) & 0x1f;
24599 rt = (ctx->opcode >> 16) & 0x1f;
24600 rd = (ctx->opcode >> 11) & 0x1f;
24601 sa = (ctx->opcode >> 6) & 0x1f;
24602 imm = (int16_t)ctx->opcode;
24603 switch (op) {
24604 case OPC_SPECIAL:
24605 decode_opc_special(env, ctx);
24606 break;
24607 case OPC_SPECIAL2:
24608 decode_opc_special2_legacy(env, ctx);
24609 break;
24610 case OPC_SPECIAL3:
24611 decode_opc_special3(env, ctx);
24612 break;
24613 case OPC_REGIMM:
24614 op1 = MASK_REGIMM(ctx->opcode);
24615 switch (op1) {
24616 case OPC_BLTZL: /* REGIMM branches */
24617 case OPC_BGEZL:
24618 case OPC_BLTZALL:
24619 case OPC_BGEZALL:
24620 check_insn(ctx, ISA_MIPS2);
24621 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24622 /* Fallthrough */
24623 case OPC_BLTZ:
24624 case OPC_BGEZ:
24625 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24626 break;
24627 case OPC_BLTZAL:
24628 case OPC_BGEZAL:
24629 if (ctx->insn_flags & ISA_MIPS32R6) {
24630 if (rs == 0) {
24631 /* OPC_NAL, OPC_BAL */
24632 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
24633 } else {
24634 generate_exception_end(ctx, EXCP_RI);
24636 } else {
24637 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24639 break;
24640 case OPC_TGEI: /* REGIMM traps */
24641 case OPC_TGEIU:
24642 case OPC_TLTI:
24643 case OPC_TLTIU:
24644 case OPC_TEQI:
24646 case OPC_TNEI:
24647 check_insn(ctx, ISA_MIPS2);
24648 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24649 gen_trap(ctx, op1, rs, -1, imm);
24650 break;
24651 case OPC_SIGRIE:
24652 check_insn(ctx, ISA_MIPS32R6);
24653 generate_exception_end(ctx, EXCP_RI);
24654 break;
24655 case OPC_SYNCI:
24656 check_insn(ctx, ISA_MIPS32R2);
24657 /* Break the TB to be able to sync copied instructions
24658 immediately */
24659 ctx->base.is_jmp = DISAS_STOP;
24660 break;
24661 case OPC_BPOSGE32: /* MIPS DSP branch */
24662 #if defined(TARGET_MIPS64)
24663 case OPC_BPOSGE64:
24664 #endif
24665 check_dsp(ctx);
24666 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
24667 break;
24668 #if defined(TARGET_MIPS64)
24669 case OPC_DAHI:
24670 check_insn(ctx, ISA_MIPS32R6);
24671 check_mips_64(ctx);
24672 if (rs != 0) {
24673 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24675 break;
24676 case OPC_DATI:
24677 check_insn(ctx, ISA_MIPS32R6);
24678 check_mips_64(ctx);
24679 if (rs != 0) {
24680 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24682 break;
24683 #endif
24684 default: /* Invalid */
24685 MIPS_INVAL("regimm");
24686 generate_exception_end(ctx, EXCP_RI);
24687 break;
24689 break;
24690 case OPC_CP0:
24691 check_cp0_enabled(ctx);
24692 op1 = MASK_CP0(ctx->opcode);
24693 switch (op1) {
24694 case OPC_MFC0:
24695 case OPC_MTC0:
24696 case OPC_MFTR:
24697 case OPC_MTTR:
24698 case OPC_MFHC0:
24699 case OPC_MTHC0:
24700 #if defined(TARGET_MIPS64)
24701 case OPC_DMFC0:
24702 case OPC_DMTC0:
24703 #endif
24704 #ifndef CONFIG_USER_ONLY
24705 gen_cp0(env, ctx, op1, rt, rd);
24706 #endif /* !CONFIG_USER_ONLY */
24707 break;
24708 case OPC_C0:
24709 case OPC_C0_1:
24710 case OPC_C0_2:
24711 case OPC_C0_3:
24712 case OPC_C0_4:
24713 case OPC_C0_5:
24714 case OPC_C0_6:
24715 case OPC_C0_7:
24716 case OPC_C0_8:
24717 case OPC_C0_9:
24718 case OPC_C0_A:
24719 case OPC_C0_B:
24720 case OPC_C0_C:
24721 case OPC_C0_D:
24722 case OPC_C0_E:
24723 case OPC_C0_F:
24724 #ifndef CONFIG_USER_ONLY
24725 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
24726 #endif /* !CONFIG_USER_ONLY */
24727 break;
24728 case OPC_MFMC0:
24729 #ifndef CONFIG_USER_ONLY
24731 uint32_t op2;
24732 TCGv t0 = tcg_temp_new();
24734 op2 = MASK_MFMC0(ctx->opcode);
24735 switch (op2) {
24736 case OPC_DMT:
24737 check_cp0_mt(ctx);
24738 gen_helper_dmt(t0);
24739 gen_store_gpr(t0, rt);
24740 break;
24741 case OPC_EMT:
24742 check_cp0_mt(ctx);
24743 gen_helper_emt(t0);
24744 gen_store_gpr(t0, rt);
24745 break;
24746 case OPC_DVPE:
24747 check_cp0_mt(ctx);
24748 gen_helper_dvpe(t0, cpu_env);
24749 gen_store_gpr(t0, rt);
24750 break;
24751 case OPC_EVPE:
24752 check_cp0_mt(ctx);
24753 gen_helper_evpe(t0, cpu_env);
24754 gen_store_gpr(t0, rt);
24755 break;
24756 case OPC_DVP:
24757 check_insn(ctx, ISA_MIPS32R6);
24758 if (ctx->vp) {
24759 gen_helper_dvp(t0, cpu_env);
24760 gen_store_gpr(t0, rt);
24762 break;
24763 case OPC_EVP:
24764 check_insn(ctx, ISA_MIPS32R6);
24765 if (ctx->vp) {
24766 gen_helper_evp(t0, cpu_env);
24767 gen_store_gpr(t0, rt);
24769 break;
24770 case OPC_DI:
24771 check_insn(ctx, ISA_MIPS32R2);
24772 save_cpu_state(ctx, 1);
24773 gen_helper_di(t0, cpu_env);
24774 gen_store_gpr(t0, rt);
24775 /* Stop translation as we may have switched
24776 the execution mode. */
24777 ctx->base.is_jmp = DISAS_STOP;
24778 break;
24779 case OPC_EI:
24780 check_insn(ctx, ISA_MIPS32R2);
24781 save_cpu_state(ctx, 1);
24782 gen_helper_ei(t0, cpu_env);
24783 gen_store_gpr(t0, rt);
24784 /* DISAS_STOP isn't sufficient, we need to ensure we break
24785 out of translated code to check for pending interrupts */
24786 gen_save_pc(ctx->base.pc_next + 4);
24787 ctx->base.is_jmp = DISAS_EXIT;
24788 break;
24789 default: /* Invalid */
24790 MIPS_INVAL("mfmc0");
24791 generate_exception_end(ctx, EXCP_RI);
24792 break;
24794 tcg_temp_free(t0);
24796 #endif /* !CONFIG_USER_ONLY */
24797 break;
24798 case OPC_RDPGPR:
24799 check_insn(ctx, ISA_MIPS32R2);
24800 gen_load_srsgpr(rt, rd);
24801 break;
24802 case OPC_WRPGPR:
24803 check_insn(ctx, ISA_MIPS32R2);
24804 gen_store_srsgpr(rt, rd);
24805 break;
24806 default:
24807 MIPS_INVAL("cp0");
24808 generate_exception_end(ctx, EXCP_RI);
24809 break;
24811 break;
24812 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
24813 if (ctx->insn_flags & ISA_MIPS32R6) {
24814 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
24815 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24816 } else {
24817 /* OPC_ADDI */
24818 /* Arithmetic with immediate opcode */
24819 gen_arith_imm(ctx, op, rt, rs, imm);
24821 break;
24822 case OPC_ADDIU:
24823 gen_arith_imm(ctx, op, rt, rs, imm);
24824 break;
24825 case OPC_SLTI: /* Set on less than with immediate opcode */
24826 case OPC_SLTIU:
24827 gen_slt_imm(ctx, op, rt, rs, imm);
24828 break;
24829 case OPC_ANDI: /* Arithmetic with immediate opcode */
24830 case OPC_LUI: /* OPC_AUI */
24831 case OPC_ORI:
24832 case OPC_XORI:
24833 gen_logic_imm(ctx, op, rt, rs, imm);
24834 break;
24835 case OPC_J: /* Jump */
24836 case OPC_JAL:
24837 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
24838 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
24839 break;
24840 /* Branch */
24841 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
24842 if (ctx->insn_flags & ISA_MIPS32R6) {
24843 if (rt == 0) {
24844 generate_exception_end(ctx, EXCP_RI);
24845 break;
24847 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
24848 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24849 } else {
24850 /* OPC_BLEZL */
24851 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24853 break;
24854 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
24855 if (ctx->insn_flags & ISA_MIPS32R6) {
24856 if (rt == 0) {
24857 generate_exception_end(ctx, EXCP_RI);
24858 break;
24860 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
24861 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24862 } else {
24863 /* OPC_BGTZL */
24864 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24866 break;
24867 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
24868 if (rt == 0) {
24869 /* OPC_BLEZ */
24870 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24871 } else {
24872 check_insn(ctx, ISA_MIPS32R6);
24873 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
24874 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24876 break;
24877 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
24878 if (rt == 0) {
24879 /* OPC_BGTZ */
24880 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24881 } else {
24882 check_insn(ctx, ISA_MIPS32R6);
24883 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
24884 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24886 break;
24887 case OPC_BEQL:
24888 case OPC_BNEL:
24889 check_insn(ctx, ISA_MIPS2);
24890 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24891 /* Fallthrough */
24892 case OPC_BEQ:
24893 case OPC_BNE:
24894 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24895 break;
24896 case OPC_LL: /* Load and stores */
24897 check_insn(ctx, ISA_MIPS2);
24898 /* Fallthrough */
24899 case OPC_LWL:
24900 case OPC_LWR:
24901 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24902 /* Fallthrough */
24903 case OPC_LB:
24904 case OPC_LH:
24905 case OPC_LW:
24906 case OPC_LWPC:
24907 case OPC_LBU:
24908 case OPC_LHU:
24909 gen_ld(ctx, op, rt, rs, imm);
24910 break;
24911 case OPC_SWL:
24912 case OPC_SWR:
24913 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24914 /* fall through */
24915 case OPC_SB:
24916 case OPC_SH:
24917 case OPC_SW:
24918 gen_st(ctx, op, rt, rs, imm);
24919 break;
24920 case OPC_SC:
24921 check_insn(ctx, ISA_MIPS2);
24922 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24923 gen_st_cond(ctx, op, rt, rs, imm);
24924 break;
24925 case OPC_CACHE:
24926 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24927 check_cp0_enabled(ctx);
24928 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
24929 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24930 gen_cache_operation(ctx, rt, rs, imm);
24932 /* Treat as NOP. */
24933 break;
24934 case OPC_PREF:
24935 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24936 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24937 /* Treat as NOP. */
24938 break;
24940 /* Floating point (COP1). */
24941 case OPC_LWC1:
24942 case OPC_LDC1:
24943 case OPC_SWC1:
24944 case OPC_SDC1:
24945 gen_cop1_ldst(ctx, op, rt, rs, imm);
24946 break;
24948 case OPC_CP1:
24949 op1 = MASK_CP1(ctx->opcode);
24951 switch (op1) {
24952 case OPC_MFHC1:
24953 case OPC_MTHC1:
24954 check_cp1_enabled(ctx);
24955 check_insn(ctx, ISA_MIPS32R2);
24956 /* fall through */
24957 case OPC_MFC1:
24958 case OPC_CFC1:
24959 case OPC_MTC1:
24960 case OPC_CTC1:
24961 check_cp1_enabled(ctx);
24962 gen_cp1(ctx, op1, rt, rd);
24963 break;
24964 #if defined(TARGET_MIPS64)
24965 case OPC_DMFC1:
24966 case OPC_DMTC1:
24967 check_cp1_enabled(ctx);
24968 check_insn(ctx, ISA_MIPS3);
24969 check_mips_64(ctx);
24970 gen_cp1(ctx, op1, rt, rd);
24971 break;
24972 #endif
24973 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
24974 check_cp1_enabled(ctx);
24975 if (ctx->insn_flags & ISA_MIPS32R6) {
24976 /* OPC_BC1EQZ */
24977 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
24978 rt, imm << 2, 4);
24979 } else {
24980 /* OPC_BC1ANY2 */
24981 check_cop1x(ctx);
24982 check_insn(ctx, ASE_MIPS3D);
24983 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
24984 (rt >> 2) & 0x7, imm << 2);
24986 break;
24987 case OPC_BC1NEZ:
24988 check_cp1_enabled(ctx);
24989 check_insn(ctx, ISA_MIPS32R6);
24990 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
24991 rt, imm << 2, 4);
24992 break;
24993 case OPC_BC1ANY4:
24994 check_cp1_enabled(ctx);
24995 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24996 check_cop1x(ctx);
24997 check_insn(ctx, ASE_MIPS3D);
24998 /* fall through */
24999 case OPC_BC1:
25000 check_cp1_enabled(ctx);
25001 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25002 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25003 (rt >> 2) & 0x7, imm << 2);
25004 break;
25005 case OPC_PS_FMT:
25006 check_ps(ctx);
25007 /* fall through */
25008 case OPC_S_FMT:
25009 case OPC_D_FMT:
25010 check_cp1_enabled(ctx);
25011 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25012 (imm >> 8) & 0x7);
25013 break;
25014 case OPC_W_FMT:
25015 case OPC_L_FMT:
25017 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25018 check_cp1_enabled(ctx);
25019 if (ctx->insn_flags & ISA_MIPS32R6) {
25020 switch (r6_op) {
25021 case R6_OPC_CMP_AF_S:
25022 case R6_OPC_CMP_UN_S:
25023 case R6_OPC_CMP_EQ_S:
25024 case R6_OPC_CMP_UEQ_S:
25025 case R6_OPC_CMP_LT_S:
25026 case R6_OPC_CMP_ULT_S:
25027 case R6_OPC_CMP_LE_S:
25028 case R6_OPC_CMP_ULE_S:
25029 case R6_OPC_CMP_SAF_S:
25030 case R6_OPC_CMP_SUN_S:
25031 case R6_OPC_CMP_SEQ_S:
25032 case R6_OPC_CMP_SEUQ_S:
25033 case R6_OPC_CMP_SLT_S:
25034 case R6_OPC_CMP_SULT_S:
25035 case R6_OPC_CMP_SLE_S:
25036 case R6_OPC_CMP_SULE_S:
25037 case R6_OPC_CMP_OR_S:
25038 case R6_OPC_CMP_UNE_S:
25039 case R6_OPC_CMP_NE_S:
25040 case R6_OPC_CMP_SOR_S:
25041 case R6_OPC_CMP_SUNE_S:
25042 case R6_OPC_CMP_SNE_S:
25043 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25044 break;
25045 case R6_OPC_CMP_AF_D:
25046 case R6_OPC_CMP_UN_D:
25047 case R6_OPC_CMP_EQ_D:
25048 case R6_OPC_CMP_UEQ_D:
25049 case R6_OPC_CMP_LT_D:
25050 case R6_OPC_CMP_ULT_D:
25051 case R6_OPC_CMP_LE_D:
25052 case R6_OPC_CMP_ULE_D:
25053 case R6_OPC_CMP_SAF_D:
25054 case R6_OPC_CMP_SUN_D:
25055 case R6_OPC_CMP_SEQ_D:
25056 case R6_OPC_CMP_SEUQ_D:
25057 case R6_OPC_CMP_SLT_D:
25058 case R6_OPC_CMP_SULT_D:
25059 case R6_OPC_CMP_SLE_D:
25060 case R6_OPC_CMP_SULE_D:
25061 case R6_OPC_CMP_OR_D:
25062 case R6_OPC_CMP_UNE_D:
25063 case R6_OPC_CMP_NE_D:
25064 case R6_OPC_CMP_SOR_D:
25065 case R6_OPC_CMP_SUNE_D:
25066 case R6_OPC_CMP_SNE_D:
25067 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25068 break;
25069 default:
25070 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25071 rt, rd, sa, (imm >> 8) & 0x7);
25073 break;
25075 } else {
25076 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25077 (imm >> 8) & 0x7);
25079 break;
25081 case OPC_BZ_V:
25082 case OPC_BNZ_V:
25083 case OPC_BZ_B:
25084 case OPC_BZ_H:
25085 case OPC_BZ_W:
25086 case OPC_BZ_D:
25087 case OPC_BNZ_B:
25088 case OPC_BNZ_H:
25089 case OPC_BNZ_W:
25090 case OPC_BNZ_D:
25091 check_insn(ctx, ASE_MSA);
25092 gen_msa_branch(env, ctx, op1);
25093 break;
25094 default:
25095 MIPS_INVAL("cp1");
25096 generate_exception_end(ctx, EXCP_RI);
25097 break;
25099 break;
25101 /* Compact branches [R6] and COP2 [non-R6] */
25102 case OPC_BC: /* OPC_LWC2 */
25103 case OPC_BALC: /* OPC_SWC2 */
25104 if (ctx->insn_flags & ISA_MIPS32R6) {
25105 /* OPC_BC, OPC_BALC */
25106 gen_compute_compact_branch(ctx, op, 0, 0,
25107 sextract32(ctx->opcode << 2, 0, 28));
25108 } else {
25109 /* OPC_LWC2, OPC_SWC2 */
25110 /* COP2: Not implemented. */
25111 generate_exception_err(ctx, EXCP_CpU, 2);
25113 break;
25114 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25115 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25116 if (ctx->insn_flags & ISA_MIPS32R6) {
25117 if (rs != 0) {
25118 /* OPC_BEQZC, OPC_BNEZC */
25119 gen_compute_compact_branch(ctx, op, rs, 0,
25120 sextract32(ctx->opcode << 2, 0, 23));
25121 } else {
25122 /* OPC_JIC, OPC_JIALC */
25123 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25125 } else {
25126 /* OPC_LWC2, OPC_SWC2 */
25127 /* COP2: Not implemented. */
25128 generate_exception_err(ctx, EXCP_CpU, 2);
25130 break;
25131 case OPC_CP2:
25132 check_insn(ctx, INSN_LOONGSON2F);
25133 /* Note that these instructions use different fields. */
25134 gen_loongson_multimedia(ctx, sa, rd, rt);
25135 break;
25137 case OPC_CP3:
25138 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25139 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
25140 check_cp1_enabled(ctx);
25141 op1 = MASK_CP3(ctx->opcode);
25142 switch (op1) {
25143 case OPC_LUXC1:
25144 case OPC_SUXC1:
25145 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
25146 /* Fallthrough */
25147 case OPC_LWXC1:
25148 case OPC_LDXC1:
25149 case OPC_SWXC1:
25150 case OPC_SDXC1:
25151 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25152 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
25153 break;
25154 case OPC_PREFX:
25155 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25156 /* Treat as NOP. */
25157 break;
25158 case OPC_ALNV_PS:
25159 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
25160 /* Fallthrough */
25161 case OPC_MADD_S:
25162 case OPC_MADD_D:
25163 case OPC_MADD_PS:
25164 case OPC_MSUB_S:
25165 case OPC_MSUB_D:
25166 case OPC_MSUB_PS:
25167 case OPC_NMADD_S:
25168 case OPC_NMADD_D:
25169 case OPC_NMADD_PS:
25170 case OPC_NMSUB_S:
25171 case OPC_NMSUB_D:
25172 case OPC_NMSUB_PS:
25173 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25174 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25175 break;
25176 default:
25177 MIPS_INVAL("cp3");
25178 generate_exception_end(ctx, EXCP_RI);
25179 break;
25181 } else {
25182 generate_exception_err(ctx, EXCP_CpU, 1);
25184 break;
25186 #if defined(TARGET_MIPS64)
25187 /* MIPS64 opcodes */
25188 case OPC_LDL:
25189 case OPC_LDR:
25190 case OPC_LLD:
25191 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25192 /* fall through */
25193 case OPC_LWU:
25194 case OPC_LD:
25195 check_insn(ctx, ISA_MIPS3);
25196 check_mips_64(ctx);
25197 gen_ld(ctx, op, rt, rs, imm);
25198 break;
25199 case OPC_SDL:
25200 case OPC_SDR:
25201 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25202 /* fall through */
25203 case OPC_SD:
25204 check_insn(ctx, ISA_MIPS3);
25205 check_mips_64(ctx);
25206 gen_st(ctx, op, rt, rs, imm);
25207 break;
25208 case OPC_SCD:
25209 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25210 check_insn(ctx, ISA_MIPS3);
25211 check_mips_64(ctx);
25212 gen_st_cond(ctx, op, rt, rs, imm);
25213 break;
25214 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25215 if (ctx->insn_flags & ISA_MIPS32R6) {
25216 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25217 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25218 } else {
25219 /* OPC_DADDI */
25220 check_insn(ctx, ISA_MIPS3);
25221 check_mips_64(ctx);
25222 gen_arith_imm(ctx, op, rt, rs, imm);
25224 break;
25225 case OPC_DADDIU:
25226 check_insn(ctx, ISA_MIPS3);
25227 check_mips_64(ctx);
25228 gen_arith_imm(ctx, op, rt, rs, imm);
25229 break;
25230 #else
25231 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25232 if (ctx->insn_flags & ISA_MIPS32R6) {
25233 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25234 } else {
25235 MIPS_INVAL("major opcode");
25236 generate_exception_end(ctx, EXCP_RI);
25238 break;
25239 #endif
25240 case OPC_DAUI: /* OPC_JALX */
25241 if (ctx->insn_flags & ISA_MIPS32R6) {
25242 #if defined(TARGET_MIPS64)
25243 /* OPC_DAUI */
25244 check_mips_64(ctx);
25245 if (rs == 0) {
25246 generate_exception(ctx, EXCP_RI);
25247 } else if (rt != 0) {
25248 TCGv t0 = tcg_temp_new();
25249 gen_load_gpr(t0, rs);
25250 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25251 tcg_temp_free(t0);
25253 #else
25254 generate_exception_end(ctx, EXCP_RI);
25255 MIPS_INVAL("major opcode");
25256 #endif
25257 } else {
25258 /* OPC_JALX */
25259 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25260 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25261 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25263 break;
25264 case OPC_MSA: /* OPC_MDMX */
25265 /* MDMX: Not implemented. */
25266 gen_msa(env, ctx);
25267 break;
25268 case OPC_PCREL:
25269 check_insn(ctx, ISA_MIPS32R6);
25270 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
25271 break;
25272 default: /* Invalid */
25273 MIPS_INVAL("major opcode");
25274 generate_exception_end(ctx, EXCP_RI);
25275 break;
25279 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
25281 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25282 CPUMIPSState *env = cs->env_ptr;
25284 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
25285 ctx->saved_pc = -1;
25286 ctx->insn_flags = env->insn_flags;
25287 ctx->CP0_Config1 = env->CP0_Config1;
25288 ctx->CP0_Config3 = env->CP0_Config3;
25289 ctx->CP0_Config5 = env->CP0_Config5;
25290 ctx->btarget = 0;
25291 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25292 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25293 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25294 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25295 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25296 ctx->PAMask = env->PAMask;
25297 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25298 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25299 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25300 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25301 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
25302 /* Restore delay slot state from the tb context. */
25303 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25304 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25305 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
25306 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
25307 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25308 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25309 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25310 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25311 restore_cpu_state(env, ctx);
25312 #ifdef CONFIG_USER_ONLY
25313 ctx->mem_idx = MIPS_HFLAG_UM;
25314 #else
25315 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
25316 #endif
25317 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
25318 MO_UNALN : MO_ALIGN;
25320 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25321 ctx->hflags);
25324 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25328 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25330 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25332 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25333 ctx->btarget);
25336 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25337 const CPUBreakpoint *bp)
25339 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25341 save_cpu_state(ctx, 1);
25342 ctx->base.is_jmp = DISAS_NORETURN;
25343 gen_helper_raise_exception_debug(cpu_env);
25344 /* The address covered by the breakpoint must be included in
25345 [tb->pc, tb->pc + tb->size) in order to for it to be
25346 properly cleared -- thus we increment the PC here so that
25347 the logic setting tb->size below does the right thing. */
25348 ctx->base.pc_next += 4;
25349 return true;
25352 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25354 CPUMIPSState *env = cs->env_ptr;
25355 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25356 int insn_bytes;
25357 int is_slot;
25359 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
25360 if (ctx->insn_flags & ISA_NANOMIPS32) {
25361 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25362 insn_bytes = decode_nanomips_opc(env, ctx);
25363 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
25364 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
25365 insn_bytes = 4;
25366 decode_opc(env, ctx);
25367 } else if (ctx->insn_flags & ASE_MICROMIPS) {
25368 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25369 insn_bytes = decode_micromips_opc(env, ctx);
25370 } else if (ctx->insn_flags & ASE_MIPS16) {
25371 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
25372 insn_bytes = decode_mips16_opc(env, ctx);
25373 } else {
25374 generate_exception_end(ctx, EXCP_RI);
25375 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25376 return;
25379 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25380 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25381 MIPS_HFLAG_FBNSLOT))) {
25382 /* force to generate branch as there is neither delay nor
25383 forbidden slot */
25384 is_slot = 1;
25386 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25387 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
25388 /* Force to generate branch as microMIPS R6 doesn't restrict
25389 branches in the forbidden slot. */
25390 is_slot = 1;
25393 if (is_slot) {
25394 gen_branch(ctx, insn_bytes);
25396 ctx->base.pc_next += insn_bytes;
25398 if (ctx->base.is_jmp != DISAS_NEXT) {
25399 return;
25401 /* Execute a branch and its delay slot as a single instruction.
25402 This is what GDB expects and is consistent with what the
25403 hardware does (e.g. if a delay slot instruction faults, the
25404 reported PC is the PC of the branch). */
25405 if (ctx->base.singlestep_enabled &&
25406 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25407 ctx->base.is_jmp = DISAS_TOO_MANY;
25409 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25410 ctx->base.is_jmp = DISAS_TOO_MANY;
25414 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25416 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25418 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25419 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
25420 gen_helper_raise_exception_debug(cpu_env);
25421 } else {
25422 switch (ctx->base.is_jmp) {
25423 case DISAS_STOP:
25424 gen_save_pc(ctx->base.pc_next);
25425 tcg_gen_lookup_and_goto_ptr();
25426 break;
25427 case DISAS_NEXT:
25428 case DISAS_TOO_MANY:
25429 save_cpu_state(ctx, 0);
25430 gen_goto_tb(ctx, 0, ctx->base.pc_next);
25431 break;
25432 case DISAS_EXIT:
25433 tcg_gen_exit_tb(NULL, 0);
25434 break;
25435 case DISAS_NORETURN:
25436 break;
25437 default:
25438 g_assert_not_reached();
25443 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25445 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25446 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25449 static const TranslatorOps mips_tr_ops = {
25450 .init_disas_context = mips_tr_init_disas_context,
25451 .tb_start = mips_tr_tb_start,
25452 .insn_start = mips_tr_insn_start,
25453 .breakpoint_check = mips_tr_breakpoint_check,
25454 .translate_insn = mips_tr_translate_insn,
25455 .tb_stop = mips_tr_tb_stop,
25456 .disas_log = mips_tr_disas_log,
25459 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
25461 DisasContext ctx;
25463 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
25466 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
25467 int flags)
25469 int i;
25470 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
25472 #define printfpr(fp) \
25473 do { \
25474 if (is_fpu64) \
25475 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
25476 " fd:%13g fs:%13g psu: %13g\n", \
25477 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
25478 (double)(fp)->fd, \
25479 (double)(fp)->fs[FP_ENDIAN_IDX], \
25480 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
25481 else { \
25482 fpr_t tmp; \
25483 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
25484 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
25485 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
25486 " fd:%13g fs:%13g psu:%13g\n", \
25487 tmp.w[FP_ENDIAN_IDX], tmp.d, \
25488 (double)tmp.fd, \
25489 (double)tmp.fs[FP_ENDIAN_IDX], \
25490 (double)tmp.fs[!FP_ENDIAN_IDX]); \
25492 } while(0)
25495 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
25496 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
25497 get_float_exception_flags(&env->active_fpu.fp_status));
25498 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
25499 fpu_fprintf(f, "%3s: ", fregnames[i]);
25500 printfpr(&env->active_fpu.fpr[i]);
25503 #undef printfpr
25506 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
25507 int flags)
25509 MIPSCPU *cpu = MIPS_CPU(cs);
25510 CPUMIPSState *env = &cpu->env;
25511 int i;
25513 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
25514 " LO=0x" TARGET_FMT_lx " ds %04x "
25515 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
25516 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
25517 env->hflags, env->btarget, env->bcond);
25518 for (i = 0; i < 32; i++) {
25519 if ((i & 3) == 0)
25520 cpu_fprintf(f, "GPR%02d:", i);
25521 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
25522 if ((i & 3) == 3)
25523 cpu_fprintf(f, "\n");
25526 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
25527 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
25528 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
25529 PRIx64 "\n",
25530 env->CP0_Config0, env->CP0_Config1, env->lladdr);
25531 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
25532 env->CP0_Config2, env->CP0_Config3);
25533 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
25534 env->CP0_Config4, env->CP0_Config5);
25535 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
25536 fpu_dump_state(env, f, cpu_fprintf, flags);
25540 void mips_tcg_init(void)
25542 int i;
25544 cpu_gpr[0] = NULL;
25545 for (i = 1; i < 32; i++)
25546 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
25547 offsetof(CPUMIPSState, active_tc.gpr[i]),
25548 regnames[i]);
25550 for (i = 0; i < 32; i++) {
25551 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
25552 msa_wr_d[i * 2] =
25553 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
25554 /* The scalar floating-point unit (FPU) registers are mapped on
25555 * the MSA vector registers. */
25556 fpu_f64[i] = msa_wr_d[i * 2];
25557 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
25558 msa_wr_d[i * 2 + 1] =
25559 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
25562 cpu_PC = tcg_global_mem_new(cpu_env,
25563 offsetof(CPUMIPSState, active_tc.PC), "PC");
25564 for (i = 0; i < MIPS_DSP_ACC; i++) {
25565 cpu_HI[i] = tcg_global_mem_new(cpu_env,
25566 offsetof(CPUMIPSState, active_tc.HI[i]),
25567 regnames_HI[i]);
25568 cpu_LO[i] = tcg_global_mem_new(cpu_env,
25569 offsetof(CPUMIPSState, active_tc.LO[i]),
25570 regnames_LO[i]);
25572 cpu_dspctrl = tcg_global_mem_new(cpu_env,
25573 offsetof(CPUMIPSState, active_tc.DSPControl),
25574 "DSPControl");
25575 bcond = tcg_global_mem_new(cpu_env,
25576 offsetof(CPUMIPSState, bcond), "bcond");
25577 btarget = tcg_global_mem_new(cpu_env,
25578 offsetof(CPUMIPSState, btarget), "btarget");
25579 hflags = tcg_global_mem_new_i32(cpu_env,
25580 offsetof(CPUMIPSState, hflags), "hflags");
25582 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
25583 offsetof(CPUMIPSState, active_fpu.fcr0),
25584 "fcr0");
25585 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
25586 offsetof(CPUMIPSState, active_fpu.fcr31),
25587 "fcr31");
25590 #include "translate_init.inc.c"
25592 void cpu_mips_realize_env(CPUMIPSState *env)
25594 env->exception_base = (int32_t)0xBFC00000;
25596 #ifndef CONFIG_USER_ONLY
25597 mmu_init(env, env->cpu_model);
25598 #endif
25599 fpu_init(env, env->cpu_model);
25600 mvp_init(env, env->cpu_model);
25603 bool cpu_supports_cps_smp(const char *cpu_type)
25605 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
25606 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
25609 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
25611 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
25612 return (mcc->cpu_def->insn_flags & isa) != 0;
25615 void cpu_set_exception_base(int vp_index, target_ulong address)
25617 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
25618 vp->env.exception_base = address;
25621 void cpu_state_reset(CPUMIPSState *env)
25623 MIPSCPU *cpu = mips_env_get_cpu(env);
25624 CPUState *cs = CPU(cpu);
25626 /* Reset registers to their default values */
25627 env->CP0_PRid = env->cpu_model->CP0_PRid;
25628 env->CP0_Config0 = env->cpu_model->CP0_Config0;
25629 #ifdef TARGET_WORDS_BIGENDIAN
25630 env->CP0_Config0 |= (1 << CP0C0_BE);
25631 #endif
25632 env->CP0_Config1 = env->cpu_model->CP0_Config1;
25633 env->CP0_Config2 = env->cpu_model->CP0_Config2;
25634 env->CP0_Config3 = env->cpu_model->CP0_Config3;
25635 env->CP0_Config4 = env->cpu_model->CP0_Config4;
25636 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
25637 env->CP0_Config5 = env->cpu_model->CP0_Config5;
25638 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
25639 env->CP0_Config6 = env->cpu_model->CP0_Config6;
25640 env->CP0_Config7 = env->cpu_model->CP0_Config7;
25641 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
25642 << env->cpu_model->CP0_LLAddr_shift;
25643 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
25644 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
25645 env->CCRes = env->cpu_model->CCRes;
25646 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
25647 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
25648 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
25649 env->current_tc = 0;
25650 env->SEGBITS = env->cpu_model->SEGBITS;
25651 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
25652 #if defined(TARGET_MIPS64)
25653 if (env->cpu_model->insn_flags & ISA_MIPS3) {
25654 env->SEGMask |= 3ULL << 62;
25656 #endif
25657 env->PABITS = env->cpu_model->PABITS;
25658 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
25659 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
25660 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
25661 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
25662 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
25663 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
25664 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
25665 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
25666 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
25667 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
25668 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
25669 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
25670 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
25671 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
25672 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
25673 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
25674 env->msair = env->cpu_model->MSAIR;
25675 env->insn_flags = env->cpu_model->insn_flags;
25677 #if defined(CONFIG_USER_ONLY)
25678 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
25679 # ifdef TARGET_MIPS64
25680 /* Enable 64-bit register mode. */
25681 env->CP0_Status |= (1 << CP0St_PX);
25682 # endif
25683 # ifdef TARGET_ABI_MIPSN64
25684 /* Enable 64-bit address mode. */
25685 env->CP0_Status |= (1 << CP0St_UX);
25686 # endif
25687 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
25688 hardware registers. */
25689 env->CP0_HWREna |= 0x0000000F;
25690 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
25691 env->CP0_Status |= (1 << CP0St_CU1);
25693 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
25694 env->CP0_Status |= (1 << CP0St_MX);
25696 # if defined(TARGET_MIPS64)
25697 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
25698 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
25699 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
25700 env->CP0_Status |= (1 << CP0St_FR);
25702 # endif
25703 #else
25704 if (env->hflags & MIPS_HFLAG_BMASK) {
25705 /* If the exception was raised from a delay slot,
25706 come back to the jump. */
25707 env->CP0_ErrorEPC = (env->active_tc.PC
25708 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
25709 } else {
25710 env->CP0_ErrorEPC = env->active_tc.PC;
25712 env->active_tc.PC = env->exception_base;
25713 env->CP0_Random = env->tlb->nb_tlb - 1;
25714 env->tlb->tlb_in_use = env->tlb->nb_tlb;
25715 env->CP0_Wired = 0;
25716 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
25717 env->CP0_EBase = (cs->cpu_index & 0x3FF);
25718 if (mips_um_ksegs_enabled()) {
25719 env->CP0_EBase |= 0x40000000;
25720 } else {
25721 env->CP0_EBase |= (int32_t)0x80000000;
25723 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
25724 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
25726 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
25727 0x3ff : 0xff;
25728 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
25729 /* vectored interrupts not implemented, timer on int 7,
25730 no performance counters. */
25731 env->CP0_IntCtl = 0xe0000000;
25733 int i;
25735 for (i = 0; i < 7; i++) {
25736 env->CP0_WatchLo[i] = 0;
25737 env->CP0_WatchHi[i] = 0x80000000;
25739 env->CP0_WatchLo[7] = 0;
25740 env->CP0_WatchHi[7] = 0;
25742 /* Count register increments in debug mode, EJTAG version 1 */
25743 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
25745 cpu_mips_store_count(env, 1);
25747 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
25748 int i;
25750 /* Only TC0 on VPE 0 starts as active. */
25751 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
25752 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
25753 env->tcs[i].CP0_TCHalt = 1;
25755 env->active_tc.CP0_TCHalt = 1;
25756 cs->halted = 1;
25758 if (cs->cpu_index == 0) {
25759 /* VPE0 starts up enabled. */
25760 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
25761 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
25763 /* TC0 starts up unhalted. */
25764 cs->halted = 0;
25765 env->active_tc.CP0_TCHalt = 0;
25766 env->tcs[0].CP0_TCHalt = 0;
25767 /* With thread 0 active. */
25768 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
25769 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
25774 * Configure default legacy segmentation control. We use this regardless of
25775 * whether segmentation control is presented to the guest.
25777 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
25778 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
25779 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
25780 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
25781 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
25782 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
25783 (2 << CP0SC_C);
25784 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
25785 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
25786 (3 << CP0SC_C)) << 16;
25787 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
25788 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
25789 (1 << CP0SC_EU) | (2 << CP0SC_C);
25790 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
25791 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
25792 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
25793 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
25794 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
25795 #endif
25796 if ((env->insn_flags & ISA_MIPS32R6) &&
25797 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
25798 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
25799 env->CP0_Status |= (1 << CP0St_FR);
25802 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
25803 /* microMIPS on reset when Config3.ISA is 3 */
25804 env->hflags |= MIPS_HFLAG_M16;
25807 /* MSA */
25808 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
25809 msa_reset(env);
25812 compute_hflags(env);
25813 restore_fp_status(env);
25814 restore_pamask(env);
25815 cs->exception_index = EXCP_NONE;
25817 if (semihosting_get_argc()) {
25818 /* UHI interface can be used to obtain argc and argv */
25819 env->active_tc.gpr[4] = -1;
25823 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
25824 target_ulong *data)
25826 env->active_tc.PC = data[0];
25827 env->hflags &= ~MIPS_HFLAG_BMASK;
25828 env->hflags |= data[1];
25829 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
25830 case MIPS_HFLAG_BR:
25831 break;
25832 case MIPS_HFLAG_BC:
25833 case MIPS_HFLAG_BL:
25834 case MIPS_HFLAG_B:
25835 env->btarget = data[2];
25836 break;