target/arm: Convert jazelle from feature bit to isar1 test
[qemu/ar7.git] / target / mips / translate.c
blob3a0bdd55c8c03a28897dc99b253b16d0236fcb26
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
467 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
468 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
471 /* DBSHFL opcodes */
472 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
474 enum {
475 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
476 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
477 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
478 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
479 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
482 /* MIPS DSP REGIMM opcodes */
483 enum {
484 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
485 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
488 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
489 /* MIPS DSP Load */
490 enum {
491 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
492 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
493 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
494 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
497 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498 enum {
499 /* MIPS DSP Arithmetic Sub-class */
500 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
501 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
502 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
503 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
507 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
508 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
509 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
516 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
517 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
518 /* MIPS DSP Multiply Sub-class insns */
519 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
521 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
522 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
527 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
528 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
532 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
533 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
543 /* MIPS DSP Multiply Sub-class insns */
544 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
545 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
546 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
550 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551 enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
554 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
555 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
566 /* DSP Bit/Manipulation Sub-class */
567 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
574 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
584 /* DSP Compare-Pick Sub-class */
585 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
602 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
603 enum {
604 /* MIPS DSP GPR-Based Shift Sub-class */
605 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
607 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
629 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
630 enum {
631 /* MIPS DSP Multiply Sub-class insns */
632 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
634 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
656 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657 enum {
658 /* DSP Bit/Manipulation Sub-class */
659 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
662 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
663 enum {
664 /* MIPS DSP Append Sub-class */
665 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
666 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
667 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
670 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
673 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
674 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
675 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
685 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
686 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
687 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
688 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
689 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
692 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
693 enum {
694 /* MIPS DSP Arithmetic Sub-class */
695 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
721 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
722 enum {
723 /* MIPS DSP Multiply Sub-class insns */
724 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
725 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
726 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
729 /* MIPS DSP Arithmetic Sub-class */
730 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
731 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
732 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
741 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
742 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
753 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
754 enum {
755 /* DSP Compare-Pick Sub-class */
756 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
786 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
787 enum {
788 /* DSP Append Sub-class */
789 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
790 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
791 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
792 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
795 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
798 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
799 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
800 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
801 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
821 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
822 enum {
823 /* DSP Bit/Manipulation Sub-class */
824 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
827 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
828 enum {
829 /* MIPS DSP Multiply Sub-class insns */
830 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
858 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
859 enum {
860 /* MIPS DSP GPR-Based Shift Sub-class */
861 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
889 /* Coprocessor 0 (rs field) */
890 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
892 enum {
893 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
894 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
895 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
896 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
897 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
898 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
899 OPC_MFTR = (0x08 << 21) | OPC_CP0,
900 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
901 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
902 OPC_MTTR = (0x0C << 21) | OPC_CP0,
903 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
904 OPC_C0 = (0x10 << 21) | OPC_CP0,
905 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
906 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
907 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
908 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
909 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
910 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
911 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
912 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
913 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
914 OPC_C0_A = (0x1A << 21) | OPC_CP0,
915 OPC_C0_B = (0x1B << 21) | OPC_CP0,
916 OPC_C0_C = (0x1C << 21) | OPC_CP0,
917 OPC_C0_D = (0x1D << 21) | OPC_CP0,
918 OPC_C0_E = (0x1E << 21) | OPC_CP0,
919 OPC_C0_F = (0x1F << 21) | OPC_CP0,
922 /* MFMC0 opcodes */
923 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
925 enum {
926 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
927 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
928 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
929 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
930 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
931 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
932 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
933 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
936 /* Coprocessor 0 (with rs == C0) */
937 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
939 enum {
940 OPC_TLBR = 0x01 | OPC_C0,
941 OPC_TLBWI = 0x02 | OPC_C0,
942 OPC_TLBINV = 0x03 | OPC_C0,
943 OPC_TLBINVF = 0x04 | OPC_C0,
944 OPC_TLBWR = 0x06 | OPC_C0,
945 OPC_TLBP = 0x08 | OPC_C0,
946 OPC_RFE = 0x10 | OPC_C0,
947 OPC_ERET = 0x18 | OPC_C0,
948 OPC_DERET = 0x1F | OPC_C0,
949 OPC_WAIT = 0x20 | OPC_C0,
952 /* Coprocessor 1 (rs field) */
953 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
955 /* Values for the fmt field in FP instructions */
956 enum {
957 /* 0 - 15 are reserved */
958 FMT_S = 16, /* single fp */
959 FMT_D = 17, /* double fp */
960 FMT_E = 18, /* extended fp */
961 FMT_Q = 19, /* quad fp */
962 FMT_W = 20, /* 32-bit fixed */
963 FMT_L = 21, /* 64-bit fixed */
964 FMT_PS = 22, /* paired single fp */
965 /* 23 - 31 are reserved */
968 enum {
969 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
970 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
971 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
972 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
973 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
974 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
975 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
976 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
977 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
978 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
979 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
980 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
981 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
982 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
983 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
984 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
985 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
986 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
987 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
988 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
989 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
990 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
991 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
992 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
993 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
994 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
995 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
996 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
997 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
998 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1001 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1002 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1004 enum {
1005 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1006 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1007 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1008 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1011 enum {
1012 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1013 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1016 enum {
1017 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1018 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1021 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1023 enum {
1024 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1025 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1026 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1027 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1028 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1029 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1030 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1031 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1032 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1033 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1034 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1037 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1039 enum {
1040 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1041 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1042 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1043 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1044 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1045 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1046 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1047 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1049 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1050 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1051 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1052 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1053 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1054 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1055 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1056 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1059 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1060 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1061 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1062 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1063 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1064 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1065 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1067 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1068 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1069 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1070 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1071 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1072 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1073 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1074 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1076 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1077 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1078 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1079 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1080 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1081 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1083 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1084 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1085 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1086 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1087 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1088 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1090 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1091 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1092 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1093 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1094 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1095 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1097 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1098 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1099 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1100 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1101 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1102 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1104 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1105 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1106 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1107 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1108 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1109 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1111 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1112 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1113 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1114 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1115 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1116 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1118 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1119 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1120 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1121 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1122 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1123 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1125 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1126 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1127 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1128 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1129 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1130 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1134 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1136 enum {
1137 OPC_LWXC1 = 0x00 | OPC_CP3,
1138 OPC_LDXC1 = 0x01 | OPC_CP3,
1139 OPC_LUXC1 = 0x05 | OPC_CP3,
1140 OPC_SWXC1 = 0x08 | OPC_CP3,
1141 OPC_SDXC1 = 0x09 | OPC_CP3,
1142 OPC_SUXC1 = 0x0D | OPC_CP3,
1143 OPC_PREFX = 0x0F | OPC_CP3,
1144 OPC_ALNV_PS = 0x1E | OPC_CP3,
1145 OPC_MADD_S = 0x20 | OPC_CP3,
1146 OPC_MADD_D = 0x21 | OPC_CP3,
1147 OPC_MADD_PS = 0x26 | OPC_CP3,
1148 OPC_MSUB_S = 0x28 | OPC_CP3,
1149 OPC_MSUB_D = 0x29 | OPC_CP3,
1150 OPC_MSUB_PS = 0x2E | OPC_CP3,
1151 OPC_NMADD_S = 0x30 | OPC_CP3,
1152 OPC_NMADD_D = 0x31 | OPC_CP3,
1153 OPC_NMADD_PS= 0x36 | OPC_CP3,
1154 OPC_NMSUB_S = 0x38 | OPC_CP3,
1155 OPC_NMSUB_D = 0x39 | OPC_CP3,
1156 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1159 /* MSA Opcodes */
1160 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1161 enum {
1162 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1163 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1164 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1165 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1166 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1167 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1168 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1169 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1170 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1171 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1172 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1173 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1174 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1175 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1176 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1177 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1178 OPC_MSA_ELM = 0x19 | OPC_MSA,
1179 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1180 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1181 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1182 OPC_MSA_VEC = 0x1E | OPC_MSA,
1184 /* MI10 instruction */
1185 OPC_LD_B = (0x20) | OPC_MSA,
1186 OPC_LD_H = (0x21) | OPC_MSA,
1187 OPC_LD_W = (0x22) | OPC_MSA,
1188 OPC_LD_D = (0x23) | OPC_MSA,
1189 OPC_ST_B = (0x24) | OPC_MSA,
1190 OPC_ST_H = (0x25) | OPC_MSA,
1191 OPC_ST_W = (0x26) | OPC_MSA,
1192 OPC_ST_D = (0x27) | OPC_MSA,
1195 enum {
1196 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1197 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1198 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1199 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1200 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1201 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1202 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1203 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1204 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1205 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1206 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1207 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1208 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1210 /* I8 instruction */
1211 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1212 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1213 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1214 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1215 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1216 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1217 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1218 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1219 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1220 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1222 /* VEC/2R/2RF instruction */
1223 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1224 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1225 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1226 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1227 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1228 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1229 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1231 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1232 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1234 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1235 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1236 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1237 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1238 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1240 /* 2RF instruction df(bit 16) = _w, _d */
1241 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1242 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1243 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1244 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1245 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1246 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1247 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1248 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1249 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1250 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1251 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1252 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1253 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1254 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1255 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1256 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1258 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1259 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1260 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1261 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1262 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1263 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1264 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1265 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1266 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1267 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1268 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1269 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1270 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1272 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1274 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1275 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1276 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1278 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1279 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1281 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1282 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1283 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1284 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1285 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1290 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1292 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1293 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1294 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1295 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1296 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1297 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1298 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1299 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1300 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1301 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1310 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1311 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1312 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1313 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1314 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1315 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1316 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1317 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1318 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1319 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1320 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1321 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1323 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1324 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1325 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1326 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1327 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1328 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1329 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1330 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1331 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1332 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1334 /* 3RF instruction _df(bit 21) = _w, _d */
1335 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1337 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1338 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1339 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1340 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1342 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1343 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1346 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1348 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1351 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1353 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1357 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1358 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1361 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1362 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1363 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1364 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1365 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1366 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1367 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1369 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1370 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1372 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1373 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1377 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1378 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1379 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1380 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1381 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1382 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1383 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1384 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1385 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1386 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1387 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1388 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1389 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1394 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1395 * ============================================
1397 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1398 * instructions set. It is designed to fit the needs of signal, graphical and
1399 * video processing applications. MXU instruction set is used in Xburst family
1400 * of microprocessors by Ingenic.
1402 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1403 * the control register.
1405 * The notation used in MXU assembler mnemonics:
1407 * XRa, XRb, XRc, XRd - MXU registers
1408 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1409 * s12 - a subfield of an instruction code
1410 * strd2 - a subfield of an instruction code
1411 * eptn2 - a subfield of an instruction code
1412 * eptn3 - a subfield of an instruction code
1413 * optn2 - a subfield of an instruction code
1414 * optn3 - a subfield of an instruction code
1415 * sft4 - a subfield of an instruction code
1417 * Load/Store instructions Multiplication instructions
1418 * ----------------------- ---------------------------
1420 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1421 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1422 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1423 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1424 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1425 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1426 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1427 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1428 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1429 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1430 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1431 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1432 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1433 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1434 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1435 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1436 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1437 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1438 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1439 * S16SDI XRa, Rb, s10, eptn2
1440 * S8LDD XRa, Rb, s8, eptn3
1441 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1442 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1443 * S8SDI XRa, Rb, s8, eptn3
1444 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1445 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1446 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1447 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1448 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1449 * S32CPS XRa, XRb, XRc
1450 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1451 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1452 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1453 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1454 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1455 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1456 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1457 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1458 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1459 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1460 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1461 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1462 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1463 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1464 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1465 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1466 * Q8SLT XRa, XRb, XRc
1467 * Q8SLTU XRa, XRb, XRc
1468 * Q8MOVZ XRa, XRb, XRc Shift instructions
1469 * Q8MOVN XRa, XRb, XRc ------------------
1471 * D32SLL XRa, XRb, XRc, XRd, sft4
1472 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1473 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1474 * D32SARL XRa, XRb, XRc, sft4
1475 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1476 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1477 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1478 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1479 * Q16SLL XRa, XRb, XRc, XRd, sft4
1480 * Q16SLR XRa, XRb, XRc, XRd, sft4
1481 * Miscelaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1482 * ------------------------- Q16SLLV XRa, XRb, Rb
1483 * Q16SLRV XRa, XRb, Rb
1484 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1485 * S32ALN XRa, XRb, XRc, Rb
1486 * S32ALNI XRa, XRb, XRc, s3
1487 * S32LUI XRa, s8, optn3 Move instructions
1488 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1489 * S32EXTRV XRa, XRb, Rs, Rt
1490 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1491 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1494 * bits
1495 * 05..00
1497 * ┌─ 000000 ─ OPC_MXU_S32MADD
1498 * ├─ 000001 ─ OPC_MXU_S32MADDU
1499 * ├─ 000010 ─ <not assigned>
1500 * │ 20..18
1501 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1502 * │ ├─ 001 ─ OPC_MXU_S32MIN
1503 * │ ├─ 010 ─ OPC_MXU_D16MAX
1504 * │ ├─ 011 ─ OPC_MXU_D16MIN
1505 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1506 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1507 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1508 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1509 * ├─ 000100 ─ OPC_MXU_S32MSUB
1510 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1511 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1512 * │ ├─ 001 ─ OPC_MXU_D16SLT
1513 * │ ├─ 010 ─ OPC_MXU_D16AVG
1514 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1515 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1516 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1517 * │ └─ 111 ─ OPC_MXU_Q8ADD
1518 * │
1519 * │ 20..18
1520 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1521 * │ ├─ 010 ─ OPC_MXU_D16CPS
1522 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1523 * │ └─ 110 ─ OPC_MXU_Q16SAT
1524 * ├─ 001000 ─ OPC_MXU_D16MUL
1525 * │ 25..24
1526 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1527 * │ └─ 01 ─ OPC_MXU_D16MULE
1528 * ├─ 001010 ─ OPC_MXU_D16MAC
1529 * ├─ 001011 ─ OPC_MXU_D16MACF
1530 * ├─ 001100 ─ OPC_MXU_D16MADL
1531 * │ 25..24
1532 * ├─ 001101 ─ OPC_MXU__POOL04 ─┬─ 00 ─ OPC_MXU_S16MAD
1533 * │ └─ 01 ─ OPC_MXU_S16MAD_1
1534 * ├─ 001110 ─ OPC_MXU_Q16ADD
1535 * ├─ 001111 ─ OPC_MXU_D16MACE
1536 * │ 23
1537 * ├─ 010000 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32LDD
1538 * │ └─ 1 ─ OPC_MXU_S32LDDR
1539 * │
1540 * │ 23
1541 * ├─ 010001 ─ OPC_MXU__POOL06 ─┬─ 0 ─ OPC_MXU_S32STD
1542 * │ └─ 1 ─ OPC_MXU_S32STDR
1543 * │
1544 * │ 13..10
1545 * ├─ 010010 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1546 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1547 * │
1548 * │ 13..10
1549 * ├─ 010011 ─ OPC_MXU__POOL08 ─┬─ 0000 ─ OPC_MXU_S32STDV
1550 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1551 * │
1552 * │ 23
1553 * ├─ 010100 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32LDI
1554 * │ └─ 1 ─ OPC_MXU_S32LDIR
1555 * │
1556 * │ 23
1557 * ├─ 010101 ─ OPC_MXU__POOL10 ─┬─ 0 ─ OPC_MXU_S32SDI
1558 * │ └─ 1 ─ OPC_MXU_S32SDIR
1559 * │
1560 * │ 13..10
1561 * ├─ 010110 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1562 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1563 * │
1564 * │ 13..10
1565 * ├─ 010111 ─ OPC_MXU__POOL12 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1566 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1567 * ├─ 011000 ─ OPC_MXU_D32ADD
1568 * │ 23..22
1569 * MXU ├─ 011001 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_D32ACC
1570 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1571 * │ └─ 10 ─ OPC_MXU_D32ASUM
1572 * ├─ 011010 ─ <not assigned>
1573 * │ 23..22
1574 * ├─ 011011 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q16ACC
1575 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1576 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1577 * │
1578 * │ 23..22
1579 * ├─ 011100 ─ OPC_MXU__POOL15 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1580 * │ ├─ 01 ─ OPC_MXU_D8SUM
1581 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1582 * ├─ 011110 ─ <not assigned>
1583 * ├─ 011111 ─ <not assigned>
1584 * ├─ 100000 ─ <not assigned>
1585 * ├─ 100001 ─ <not assigned>
1586 * ├─ 100010 ─ OPC_MXU_S8LDD
1587 * ├─ 100011 ─ OPC_MXU_S8STD
1588 * ├─ 100100 ─ OPC_MXU_S8LDI
1589 * ├─ 100101 ─ OPC_MXU_S8SDI
1590 * │ 15..14
1591 * ├─ 100110 ─ OPC_MXU__POOL16 ─┬─ 00 ─ OPC_MXU_S32MUL
1592 * │ ├─ 00 ─ OPC_MXU_S32MULU
1593 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1594 * │ └─ 00 ─ OPC_MXU_S32EXTRV
1595 * │
1596 * │ 20..18
1597 * ├─ 100111 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_D32SARW
1598 * │ ├─ 001 ─ OPC_MXU_S32ALN
1599 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1600 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1601 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1602 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1603 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1604 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1605 * ├─ 101000 ─ <not assigned>
1606 * ├─ 101001 ─ <not assigned>
1607 * ├─ 101010 ─ <not assigned>
1608 * ├─ 101011 ─ <not assigned>
1609 * ├─ 101100 ─ <not assigned>
1610 * ├─ 101101 ─ <not assigned>
1611 * ├─ 101110 ─ OPC_MXU_S32M2I
1612 * ├─ 101111 ─ OPC_MXU_S32I2M
1613 * ├─ 110000 ─ OPC_MXU_D32SLL
1614 * ├─ 110001 ─ OPC_MXU_D32SLR
1615 * ├─ 110010 ─ OPC_MXU_D32SARL
1616 * ├─ 110011 ─ OPC_MXU_D32SAR
1617 * ├─ 110100 ─ OPC_MXU_Q16SLL
1618 * ├─ 110101 ─ OPC_MXU_Q16SLR 20..18
1619 * ├─ 110110 ─ OPC_MXU__POOL18 ─┬─ 000 ─ OPC_MXU_D32SLLV
1620 * │ ├─ 001 ─ OPC_MXU_D32SLRV
1621 * │ ├─ 010 ─ OPC_MXU_D32SARV
1622 * │ ├─ 011 ─ OPC_MXU_Q16SLLV
1623 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1624 * │ └─ 101 ─ OPC_MXU_Q16SARV
1625 * ├─ 110111 ─ OPC_MXU_Q16SAR
1626 * │ 23..22
1627 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1628 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1629 * │
1630 * │ 20..18
1631 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1632 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1633 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1634 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1635 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1636 * │ └─ 101 ─ OPC_MXU_S32MOV
1637 * │
1638 * │ 23..22
1639 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1640 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1641 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1642 * ├─ 111100 ─ OPC_MXU_Q8MADL
1643 * ├─ 111101 ─ OPC_MXU_S32SFL
1644 * ├─ 111110 ─ OPC_MXU_Q8SAD
1645 * └─ 111111 ─ <not assigned>
1648 * Compiled after:
1650 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1651 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1654 enum {
1655 OPC_MXU_S32MADD = 0x00,
1656 OPC_MXU_S32MADDU = 0x01,
1657 /* not assigned 0x02 */
1658 OPC_MXU__POOL00 = 0x03,
1659 OPC_MXU_S32MSUB = 0x04,
1660 OPC_MXU_S32MSUBU = 0x05,
1661 OPC_MXU__POOL01 = 0x06,
1662 OPC_MXU__POOL02 = 0x07,
1663 OPC_MXU_D16MUL = 0x08,
1664 OPC_MXU__POOL03 = 0x09,
1665 OPC_MXU_D16MAC = 0x0A,
1666 OPC_MXU_D16MACF = 0x0B,
1667 OPC_MXU_D16MADL = 0x0C,
1668 OPC_MXU__POOL04 = 0x0D,
1669 OPC_MXU_Q16ADD = 0x0E,
1670 OPC_MXU_D16MACE = 0x0F,
1671 OPC_MXU__POOL05 = 0x10,
1672 OPC_MXU__POOL06 = 0x11,
1673 OPC_MXU__POOL07 = 0x12,
1674 OPC_MXU__POOL08 = 0x13,
1675 OPC_MXU__POOL09 = 0x14,
1676 OPC_MXU__POOL10 = 0x15,
1677 OPC_MXU__POOL11 = 0x16,
1678 OPC_MXU__POOL12 = 0x17,
1679 OPC_MXU_D32ADD = 0x18,
1680 OPC_MXU__POOL13 = 0x19,
1681 /* not assigned 0x1A */
1682 OPC_MXU__POOL14 = 0x1B,
1683 OPC_MXU__POOL15 = 0x1C,
1684 OPC_MXU_Q8ACCE = 0x1D,
1685 /* not assigned 0x1E */
1686 /* not assigned 0x1F */
1687 /* not assigned 0x20 */
1688 /* not assigned 0x21 */
1689 OPC_MXU_S8LDD = 0x22,
1690 OPC_MXU_S8STD = 0x23,
1691 OPC_MXU_S8LDI = 0x24,
1692 OPC_MXU_S8SDI = 0x25,
1693 OPC_MXU__POOL16 = 0x26,
1694 OPC_MXU__POOL17 = 0x27,
1695 OPC_MXU_LXB = 0x28,
1696 /* not assigned 0x29 */
1697 OPC_MXU_S16LDD = 0x2A,
1698 OPC_MXU_S16STD = 0x2B,
1699 OPC_MXU_S16LDI = 0x2C,
1700 OPC_MXU_S16SDI = 0x2D,
1701 OPC_MXU_S32M2I = 0x2E,
1702 OPC_MXU_S32I2M = 0x2F,
1703 OPC_MXU_D32SLL = 0x30,
1704 OPC_MXU_D32SLR = 0x31,
1705 OPC_MXU_D32SARL = 0x32,
1706 OPC_MXU_D32SAR = 0x33,
1707 OPC_MXU_Q16SLL = 0x34,
1708 OPC_MXU_Q16SLR = 0x35,
1709 OPC_MXU__POOL18 = 0x36,
1710 OPC_MXU_Q16SAR = 0x37,
1711 OPC_MXU__POOL19 = 0x38,
1712 OPC_MXU__POOL20 = 0x39,
1713 OPC_MXU__POOL21 = 0x3A,
1714 OPC_MXU_Q16SCOP = 0x3B,
1715 OPC_MXU_Q8MADL = 0x3C,
1716 OPC_MXU_S32SFL = 0x3D,
1717 OPC_MXU_Q8SAD = 0x3E,
1718 /* not assigned 0x3F */
1723 * MXU pool 00
1725 enum {
1726 OPC_MXU_S32MAX = 0x00,
1727 OPC_MXU_S32MIN = 0x01,
1728 OPC_MXU_D16MAX = 0x02,
1729 OPC_MXU_D16MIN = 0x03,
1730 OPC_MXU_Q8MAX = 0x04,
1731 OPC_MXU_Q8MIN = 0x05,
1732 OPC_MXU_Q8SLT = 0x06,
1733 OPC_MXU_Q8SLTU = 0x07,
1737 * MXU pool 01
1739 enum {
1740 OPC_MXU_S32SLT = 0x00,
1741 OPC_MXU_D16SLT = 0x01,
1742 OPC_MXU_D16AVG = 0x02,
1743 OPC_MXU_D16AVGR = 0x03,
1744 OPC_MXU_Q8AVG = 0x04,
1745 OPC_MXU_Q8AVGR = 0x05,
1746 OPC_MXU_Q8ADD = 0x07,
1750 * MXU pool 02
1752 enum {
1753 OPC_MXU_S32CPS = 0x00,
1754 OPC_MXU_D16CPS = 0x02,
1755 OPC_MXU_Q8ABD = 0x04,
1756 OPC_MXU_Q16SAT = 0x06,
1760 * MXU pool 03
1762 enum {
1763 OPC_MXU_D16MULF = 0x00,
1764 OPC_MXU_D16MULE = 0x01,
1768 * MXU pool 04
1770 enum {
1771 OPC_MXU_S16MAD = 0x00,
1772 OPC_MXU_S16MAD_1 = 0x01,
1776 * MXU pool 05
1778 enum {
1779 OPC_MXU_S32LDD = 0x00,
1780 OPC_MXU_S32LDDR = 0x01,
1784 * MXU pool 06
1786 enum {
1787 OPC_MXU_S32STD = 0x00,
1788 OPC_MXU_S32STDR = 0x01,
1792 * MXU pool 07
1794 enum {
1795 OPC_MXU_S32LDDV = 0x00,
1796 OPC_MXU_S32LDDVR = 0x01,
1800 * MXU pool 08
1802 enum {
1803 OPC_MXU_S32STDV = 0x00,
1804 OPC_MXU_S32STDVR = 0x01,
1808 * MXU pool 09
1810 enum {
1811 OPC_MXU_S32LDI = 0x00,
1812 OPC_MXU_S32LDIR = 0x01,
1816 * MXU pool 10
1818 enum {
1819 OPC_MXU_S32SDI = 0x00,
1820 OPC_MXU_S32SDIR = 0x01,
1824 * MXU pool 11
1826 enum {
1827 OPC_MXU_S32LDIV = 0x00,
1828 OPC_MXU_S32LDIVR = 0x01,
1832 * MXU pool 12
1834 enum {
1835 OPC_MXU_S32SDIV = 0x00,
1836 OPC_MXU_S32SDIVR = 0x01,
1840 * MXU pool 13
1842 enum {
1843 OPC_MXU_D32ACC = 0x00,
1844 OPC_MXU_D32ACCM = 0x01,
1845 OPC_MXU_D32ASUM = 0x02,
1849 * MXU pool 14
1851 enum {
1852 OPC_MXU_Q16ACC = 0x00,
1853 OPC_MXU_Q16ACCM = 0x01,
1854 OPC_MXU_Q16ASUM = 0x02,
1858 * MXU pool 15
1860 enum {
1861 OPC_MXU_Q8ADDE = 0x00,
1862 OPC_MXU_D8SUM = 0x01,
1863 OPC_MXU_D8SUMC = 0x02,
1867 * MXU pool 16
1869 enum {
1870 OPC_MXU_S32MUL = 0x00,
1871 OPC_MXU_S32MULU = 0x01,
1872 OPC_MXU_S32EXTR = 0x02,
1873 OPC_MXU_S32EXTRV = 0x03,
1877 * MXU pool 17
1879 enum {
1880 OPC_MXU_D32SARW = 0x00,
1881 OPC_MXU_S32ALN = 0x01,
1882 OPC_MXU_S32ALNI = 0x02,
1883 OPC_MXU_S32NOR = 0x03,
1884 OPC_MXU_S32AND = 0x04,
1885 OPC_MXU_S32OR = 0x05,
1886 OPC_MXU_S32XOR = 0x06,
1887 OPC_MXU_S32LUI = 0x07,
1891 * MXU pool 18
1893 enum {
1894 OPC_MXU_D32SLLV = 0x00,
1895 OPC_MXU_D32SLRV = 0x01,
1896 OPC_MXU_D32SARV = 0x03,
1897 OPC_MXU_Q16SLLV = 0x04,
1898 OPC_MXU_Q16SLRV = 0x05,
1899 OPC_MXU_Q16SARV = 0x07,
1903 * MXU pool 19
1905 enum {
1906 OPC_MXU_Q8MUL = 0x00,
1907 OPC_MXU_Q8MULSU = 0x01,
1911 * MXU pool 20
1913 enum {
1914 OPC_MXU_Q8MOVZ = 0x00,
1915 OPC_MXU_Q8MOVN = 0x01,
1916 OPC_MXU_D16MOVZ = 0x02,
1917 OPC_MXU_D16MOVN = 0x03,
1918 OPC_MXU_S32MOVZ = 0x04,
1919 OPC_MXU_S32MOVN = 0x05,
1923 * MXU pool 21
1925 enum {
1926 OPC_MXU_Q8MAC = 0x00,
1927 OPC_MXU_Q8MACSU = 0x01,
1931 /* global register indices */
1932 static TCGv cpu_gpr[32], cpu_PC;
1933 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1934 static TCGv cpu_dspctrl, btarget, bcond;
1935 static TCGv_i32 hflags;
1936 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1937 static TCGv_i64 fpu_f64[32];
1938 static TCGv_i64 msa_wr_d[64];
1940 #include "exec/gen-icount.h"
1942 #define gen_helper_0e0i(name, arg) do { \
1943 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1944 gen_helper_##name(cpu_env, helper_tmp); \
1945 tcg_temp_free_i32(helper_tmp); \
1946 } while(0)
1948 #define gen_helper_0e1i(name, arg1, arg2) do { \
1949 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1950 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1951 tcg_temp_free_i32(helper_tmp); \
1952 } while(0)
1954 #define gen_helper_1e0i(name, ret, arg1) do { \
1955 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1956 gen_helper_##name(ret, cpu_env, helper_tmp); \
1957 tcg_temp_free_i32(helper_tmp); \
1958 } while(0)
1960 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1961 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1962 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1963 tcg_temp_free_i32(helper_tmp); \
1964 } while(0)
1966 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1967 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1968 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1969 tcg_temp_free_i32(helper_tmp); \
1970 } while(0)
1972 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1973 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1974 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1975 tcg_temp_free_i32(helper_tmp); \
1976 } while(0)
1978 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1979 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1980 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1981 tcg_temp_free_i32(helper_tmp); \
1982 } while(0)
1984 typedef struct DisasContext {
1985 DisasContextBase base;
1986 target_ulong saved_pc;
1987 target_ulong page_start;
1988 uint32_t opcode;
1989 uint64_t insn_flags;
1990 int32_t CP0_Config1;
1991 int32_t CP0_Config2;
1992 int32_t CP0_Config3;
1993 int32_t CP0_Config5;
1994 /* Routine used to access memory */
1995 int mem_idx;
1996 TCGMemOp default_tcg_memop_mask;
1997 uint32_t hflags, saved_hflags;
1998 target_ulong btarget;
1999 bool ulri;
2000 int kscrexist;
2001 bool rxi;
2002 int ie;
2003 bool bi;
2004 bool bp;
2005 uint64_t PAMask;
2006 bool mvh;
2007 bool eva;
2008 bool sc;
2009 int CP0_LLAddr_shift;
2010 bool ps;
2011 bool vp;
2012 bool cmgcr;
2013 bool mrp;
2014 bool nan2008;
2015 bool abs2008;
2016 } DisasContext;
2018 #define DISAS_STOP DISAS_TARGET_0
2019 #define DISAS_EXIT DISAS_TARGET_1
2021 static const char * const regnames[] = {
2022 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2023 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2024 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2025 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2028 static const char * const regnames_HI[] = {
2029 "HI0", "HI1", "HI2", "HI3",
2032 static const char * const regnames_LO[] = {
2033 "LO0", "LO1", "LO2", "LO3",
2036 static const char * const fregnames[] = {
2037 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2038 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2039 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2040 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2043 static const char * const msaregnames[] = {
2044 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2045 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2046 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2047 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2048 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2049 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2050 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2051 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2052 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2053 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2054 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2055 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2056 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2057 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2058 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2059 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2062 #define LOG_DISAS(...) \
2063 do { \
2064 if (MIPS_DEBUG_DISAS) { \
2065 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2067 } while (0)
2069 #define MIPS_INVAL(op) \
2070 do { \
2071 if (MIPS_DEBUG_DISAS) { \
2072 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2073 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2074 ctx->base.pc_next, ctx->opcode, op, \
2075 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2076 ((ctx->opcode >> 16) & 0x1F)); \
2078 } while (0)
2080 /* General purpose registers moves. */
2081 static inline void gen_load_gpr (TCGv t, int reg)
2083 if (reg == 0)
2084 tcg_gen_movi_tl(t, 0);
2085 else
2086 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2089 static inline void gen_store_gpr (TCGv t, int reg)
2091 if (reg != 0)
2092 tcg_gen_mov_tl(cpu_gpr[reg], t);
2095 /* Moves to/from shadow registers. */
2096 static inline void gen_load_srsgpr (int from, int to)
2098 TCGv t0 = tcg_temp_new();
2100 if (from == 0)
2101 tcg_gen_movi_tl(t0, 0);
2102 else {
2103 TCGv_i32 t2 = tcg_temp_new_i32();
2104 TCGv_ptr addr = tcg_temp_new_ptr();
2106 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2107 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2108 tcg_gen_andi_i32(t2, t2, 0xf);
2109 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2110 tcg_gen_ext_i32_ptr(addr, t2);
2111 tcg_gen_add_ptr(addr, cpu_env, addr);
2113 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2114 tcg_temp_free_ptr(addr);
2115 tcg_temp_free_i32(t2);
2117 gen_store_gpr(t0, to);
2118 tcg_temp_free(t0);
2121 static inline void gen_store_srsgpr (int from, int to)
2123 if (to != 0) {
2124 TCGv t0 = tcg_temp_new();
2125 TCGv_i32 t2 = tcg_temp_new_i32();
2126 TCGv_ptr addr = tcg_temp_new_ptr();
2128 gen_load_gpr(t0, from);
2129 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2130 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2131 tcg_gen_andi_i32(t2, t2, 0xf);
2132 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2133 tcg_gen_ext_i32_ptr(addr, t2);
2134 tcg_gen_add_ptr(addr, cpu_env, addr);
2136 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2137 tcg_temp_free_ptr(addr);
2138 tcg_temp_free_i32(t2);
2139 tcg_temp_free(t0);
2143 /* Tests */
2144 static inline void gen_save_pc(target_ulong pc)
2146 tcg_gen_movi_tl(cpu_PC, pc);
2149 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2151 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2152 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2153 gen_save_pc(ctx->base.pc_next);
2154 ctx->saved_pc = ctx->base.pc_next;
2156 if (ctx->hflags != ctx->saved_hflags) {
2157 tcg_gen_movi_i32(hflags, ctx->hflags);
2158 ctx->saved_hflags = ctx->hflags;
2159 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2160 case MIPS_HFLAG_BR:
2161 break;
2162 case MIPS_HFLAG_BC:
2163 case MIPS_HFLAG_BL:
2164 case MIPS_HFLAG_B:
2165 tcg_gen_movi_tl(btarget, ctx->btarget);
2166 break;
2171 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2173 ctx->saved_hflags = ctx->hflags;
2174 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2175 case MIPS_HFLAG_BR:
2176 break;
2177 case MIPS_HFLAG_BC:
2178 case MIPS_HFLAG_BL:
2179 case MIPS_HFLAG_B:
2180 ctx->btarget = env->btarget;
2181 break;
2185 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2187 TCGv_i32 texcp = tcg_const_i32(excp);
2188 TCGv_i32 terr = tcg_const_i32(err);
2189 save_cpu_state(ctx, 1);
2190 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2191 tcg_temp_free_i32(terr);
2192 tcg_temp_free_i32(texcp);
2193 ctx->base.is_jmp = DISAS_NORETURN;
2196 static inline void generate_exception(DisasContext *ctx, int excp)
2198 gen_helper_0e0i(raise_exception, excp);
2201 static inline void generate_exception_end(DisasContext *ctx, int excp)
2203 generate_exception_err(ctx, excp, 0);
2206 /* Floating point register moves. */
2207 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2209 if (ctx->hflags & MIPS_HFLAG_FRE) {
2210 generate_exception(ctx, EXCP_RI);
2212 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2215 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2217 TCGv_i64 t64;
2218 if (ctx->hflags & MIPS_HFLAG_FRE) {
2219 generate_exception(ctx, EXCP_RI);
2221 t64 = tcg_temp_new_i64();
2222 tcg_gen_extu_i32_i64(t64, t);
2223 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2224 tcg_temp_free_i64(t64);
2227 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2229 if (ctx->hflags & MIPS_HFLAG_F64) {
2230 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2231 } else {
2232 gen_load_fpr32(ctx, t, reg | 1);
2236 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2238 if (ctx->hflags & MIPS_HFLAG_F64) {
2239 TCGv_i64 t64 = tcg_temp_new_i64();
2240 tcg_gen_extu_i32_i64(t64, t);
2241 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2242 tcg_temp_free_i64(t64);
2243 } else {
2244 gen_store_fpr32(ctx, t, reg | 1);
2248 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2250 if (ctx->hflags & MIPS_HFLAG_F64) {
2251 tcg_gen_mov_i64(t, fpu_f64[reg]);
2252 } else {
2253 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2257 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2259 if (ctx->hflags & MIPS_HFLAG_F64) {
2260 tcg_gen_mov_i64(fpu_f64[reg], t);
2261 } else {
2262 TCGv_i64 t0;
2263 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2264 t0 = tcg_temp_new_i64();
2265 tcg_gen_shri_i64(t0, t, 32);
2266 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2267 tcg_temp_free_i64(t0);
2271 static inline int get_fp_bit (int cc)
2273 if (cc)
2274 return 24 + cc;
2275 else
2276 return 23;
2279 /* Addresses computation */
2280 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2282 tcg_gen_add_tl(ret, arg0, arg1);
2284 #if defined(TARGET_MIPS64)
2285 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2286 tcg_gen_ext32s_i64(ret, ret);
2288 #endif
2291 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2292 target_long ofs)
2294 tcg_gen_addi_tl(ret, base, ofs);
2296 #if defined(TARGET_MIPS64)
2297 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2298 tcg_gen_ext32s_i64(ret, ret);
2300 #endif
2303 /* Addresses computation (translation time) */
2304 static target_long addr_add(DisasContext *ctx, target_long base,
2305 target_long offset)
2307 target_long sum = base + offset;
2309 #if defined(TARGET_MIPS64)
2310 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2311 sum = (int32_t)sum;
2313 #endif
2314 return sum;
2317 /* Sign-extract the low 32-bits to a target_long. */
2318 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2320 #if defined(TARGET_MIPS64)
2321 tcg_gen_ext32s_i64(ret, arg);
2322 #else
2323 tcg_gen_extrl_i64_i32(ret, arg);
2324 #endif
2327 /* Sign-extract the high 32-bits to a target_long. */
2328 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2330 #if defined(TARGET_MIPS64)
2331 tcg_gen_sari_i64(ret, arg, 32);
2332 #else
2333 tcg_gen_extrh_i64_i32(ret, arg);
2334 #endif
2337 static inline void check_cp0_enabled(DisasContext *ctx)
2339 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2340 generate_exception_err(ctx, EXCP_CpU, 0);
2343 static inline void check_cp1_enabled(DisasContext *ctx)
2345 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2346 generate_exception_err(ctx, EXCP_CpU, 1);
2349 /* Verify that the processor is running with COP1X instructions enabled.
2350 This is associated with the nabla symbol in the MIPS32 and MIPS64
2351 opcode tables. */
2353 static inline void check_cop1x(DisasContext *ctx)
2355 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2356 generate_exception_end(ctx, EXCP_RI);
2359 /* Verify that the processor is running with 64-bit floating-point
2360 operations enabled. */
2362 static inline void check_cp1_64bitmode(DisasContext *ctx)
2364 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2365 generate_exception_end(ctx, EXCP_RI);
2369 * Verify if floating point register is valid; an operation is not defined
2370 * if bit 0 of any register specification is set and the FR bit in the
2371 * Status register equals zero, since the register numbers specify an
2372 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2373 * in the Status register equals one, both even and odd register numbers
2374 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2376 * Multiple 64 bit wide registers can be checked by calling
2377 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2379 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2381 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2382 generate_exception_end(ctx, EXCP_RI);
2385 /* Verify that the processor is running with DSP instructions enabled.
2386 This is enabled by CP0 Status register MX(24) bit.
2389 static inline void check_dsp(DisasContext *ctx)
2391 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2392 if (ctx->insn_flags & ASE_DSP) {
2393 generate_exception_end(ctx, EXCP_DSPDIS);
2394 } else {
2395 generate_exception_end(ctx, EXCP_RI);
2400 static inline void check_dsp_r2(DisasContext *ctx)
2402 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2403 if (ctx->insn_flags & ASE_DSP) {
2404 generate_exception_end(ctx, EXCP_DSPDIS);
2405 } else {
2406 generate_exception_end(ctx, EXCP_RI);
2411 static inline void check_dsp_r3(DisasContext *ctx)
2413 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2414 if (ctx->insn_flags & ASE_DSP) {
2415 generate_exception_end(ctx, EXCP_DSPDIS);
2416 } else {
2417 generate_exception_end(ctx, EXCP_RI);
2422 /* This code generates a "reserved instruction" exception if the
2423 CPU does not support the instruction set corresponding to flags. */
2424 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2426 if (unlikely(!(ctx->insn_flags & flags))) {
2427 generate_exception_end(ctx, EXCP_RI);
2431 /* This code generates a "reserved instruction" exception if the
2432 CPU has corresponding flag set which indicates that the instruction
2433 has been removed. */
2434 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2436 if (unlikely(ctx->insn_flags & flags)) {
2437 generate_exception_end(ctx, EXCP_RI);
2441 /* This code generates a "reserved instruction" exception if the
2442 CPU does not support 64-bit paired-single (PS) floating point data type */
2443 static inline void check_ps(DisasContext *ctx)
2445 if (unlikely(!ctx->ps)) {
2446 generate_exception(ctx, EXCP_RI);
2448 check_cp1_64bitmode(ctx);
2451 #ifdef TARGET_MIPS64
2452 /* This code generates a "reserved instruction" exception if 64-bit
2453 instructions are not enabled. */
2454 static inline void check_mips_64(DisasContext *ctx)
2456 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2457 generate_exception_end(ctx, EXCP_RI);
2459 #endif
2461 #ifndef CONFIG_USER_ONLY
2462 static inline void check_mvh(DisasContext *ctx)
2464 if (unlikely(!ctx->mvh)) {
2465 generate_exception(ctx, EXCP_RI);
2468 #endif
2471 * This code generates a "reserved instruction" exception if the
2472 * Config5 XNP bit is set.
2474 static inline void check_xnp(DisasContext *ctx)
2476 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2477 generate_exception_end(ctx, EXCP_RI);
2481 #ifndef CONFIG_USER_ONLY
2483 * This code generates a "reserved instruction" exception if the
2484 * Config3 PW bit is NOT set.
2486 static inline void check_pw(DisasContext *ctx)
2488 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2489 generate_exception_end(ctx, EXCP_RI);
2492 #endif
2495 * This code generates a "reserved instruction" exception if the
2496 * Config3 MT bit is NOT set.
2498 static inline void check_mt(DisasContext *ctx)
2500 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2501 generate_exception_end(ctx, EXCP_RI);
2505 #ifndef CONFIG_USER_ONLY
2507 * This code generates a "coprocessor unusable" exception if CP0 is not
2508 * available, and, if that is not the case, generates a "reserved instruction"
2509 * exception if the Config5 MT bit is NOT set. This is needed for availability
2510 * control of some of MT ASE instructions.
2512 static inline void check_cp0_mt(DisasContext *ctx)
2514 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2515 generate_exception_err(ctx, EXCP_CpU, 0);
2516 } else {
2517 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2518 generate_exception_err(ctx, EXCP_RI, 0);
2522 #endif
2525 * This code generates a "reserved instruction" exception if the
2526 * Config5 NMS bit is set.
2528 static inline void check_nms(DisasContext *ctx)
2530 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2531 generate_exception_end(ctx, EXCP_RI);
2536 /* Define small wrappers for gen_load_fpr* so that we have a uniform
2537 calling interface for 32 and 64-bit FPRs. No sense in changing
2538 all callers for gen_load_fpr32 when we need the CTX parameter for
2539 this one use. */
2540 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2541 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2542 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2543 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2544 int ft, int fs, int cc) \
2546 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
2547 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
2548 switch (ifmt) { \
2549 case FMT_PS: \
2550 check_ps(ctx); \
2551 break; \
2552 case FMT_D: \
2553 if (abs) { \
2554 check_cop1x(ctx); \
2556 check_cp1_registers(ctx, fs | ft); \
2557 break; \
2558 case FMT_S: \
2559 if (abs) { \
2560 check_cop1x(ctx); \
2562 break; \
2564 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
2565 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
2566 switch (n) { \
2567 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
2568 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
2569 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
2570 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
2571 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
2572 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
2573 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
2574 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
2575 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
2576 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
2577 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
2578 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
2579 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
2580 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
2581 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
2582 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
2583 default: abort(); \
2585 tcg_temp_free_i##bits (fp0); \
2586 tcg_temp_free_i##bits (fp1); \
2589 FOP_CONDS(, 0, d, FMT_D, 64)
2590 FOP_CONDS(abs, 1, d, FMT_D, 64)
2591 FOP_CONDS(, 0, s, FMT_S, 32)
2592 FOP_CONDS(abs, 1, s, FMT_S, 32)
2593 FOP_CONDS(, 0, ps, FMT_PS, 64)
2594 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2595 #undef FOP_CONDS
2597 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2598 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
2599 int ft, int fs, int fd) \
2601 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2602 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2603 if (ifmt == FMT_D) { \
2604 check_cp1_registers(ctx, fs | ft | fd); \
2606 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2607 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2608 switch (n) { \
2609 case 0: \
2610 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2611 break; \
2612 case 1: \
2613 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2614 break; \
2615 case 2: \
2616 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2617 break; \
2618 case 3: \
2619 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2620 break; \
2621 case 4: \
2622 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2623 break; \
2624 case 5: \
2625 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2626 break; \
2627 case 6: \
2628 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2629 break; \
2630 case 7: \
2631 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2632 break; \
2633 case 8: \
2634 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2635 break; \
2636 case 9: \
2637 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2638 break; \
2639 case 10: \
2640 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2641 break; \
2642 case 11: \
2643 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2644 break; \
2645 case 12: \
2646 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2647 break; \
2648 case 13: \
2649 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2650 break; \
2651 case 14: \
2652 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2653 break; \
2654 case 15: \
2655 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2656 break; \
2657 case 17: \
2658 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2659 break; \
2660 case 18: \
2661 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2662 break; \
2663 case 19: \
2664 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2665 break; \
2666 case 25: \
2667 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2668 break; \
2669 case 26: \
2670 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2671 break; \
2672 case 27: \
2673 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2674 break; \
2675 default: \
2676 abort(); \
2678 STORE; \
2679 tcg_temp_free_i ## bits (fp0); \
2680 tcg_temp_free_i ## bits (fp1); \
2683 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2684 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2685 #undef FOP_CONDNS
2686 #undef gen_ldcmp_fpr32
2687 #undef gen_ldcmp_fpr64
2689 /* load/store instructions. */
2690 #ifdef CONFIG_USER_ONLY
2691 #define OP_LD_ATOMIC(insn,fname) \
2692 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2693 DisasContext *ctx) \
2695 TCGv t0 = tcg_temp_new(); \
2696 tcg_gen_mov_tl(t0, arg1); \
2697 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2698 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2699 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2700 tcg_temp_free(t0); \
2702 #else
2703 #define OP_LD_ATOMIC(insn,fname) \
2704 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2705 DisasContext *ctx) \
2707 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2709 #endif
2710 OP_LD_ATOMIC(ll,ld32s);
2711 #if defined(TARGET_MIPS64)
2712 OP_LD_ATOMIC(lld,ld64);
2713 #endif
2714 #undef OP_LD_ATOMIC
2716 #ifdef CONFIG_USER_ONLY
2717 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2718 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2719 DisasContext *ctx) \
2721 TCGv t0 = tcg_temp_new(); \
2722 TCGLabel *l1 = gen_new_label(); \
2723 TCGLabel *l2 = gen_new_label(); \
2725 tcg_gen_andi_tl(t0, arg2, almask); \
2726 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2727 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2728 generate_exception(ctx, EXCP_AdES); \
2729 gen_set_label(l1); \
2730 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2731 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2732 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2733 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2734 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2735 generate_exception_end(ctx, EXCP_SC); \
2736 gen_set_label(l2); \
2737 tcg_gen_movi_tl(t0, 0); \
2738 gen_store_gpr(t0, rt); \
2739 tcg_temp_free(t0); \
2741 #else
2742 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2743 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2744 DisasContext *ctx) \
2746 TCGv t0 = tcg_temp_new(); \
2747 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
2748 gen_store_gpr(t0, rt); \
2749 tcg_temp_free(t0); \
2751 #endif
2752 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2753 #if defined(TARGET_MIPS64)
2754 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2755 #endif
2756 #undef OP_ST_ATOMIC
2758 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2759 int base, int offset)
2761 if (base == 0) {
2762 tcg_gen_movi_tl(addr, offset);
2763 } else if (offset == 0) {
2764 gen_load_gpr(addr, base);
2765 } else {
2766 tcg_gen_movi_tl(addr, offset);
2767 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2771 static target_ulong pc_relative_pc (DisasContext *ctx)
2773 target_ulong pc = ctx->base.pc_next;
2775 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2776 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2778 pc -= branch_bytes;
2781 pc &= ~(target_ulong)3;
2782 return pc;
2785 /* Load */
2786 static void gen_ld(DisasContext *ctx, uint32_t opc,
2787 int rt, int base, int offset)
2789 TCGv t0, t1, t2;
2790 int mem_idx = ctx->mem_idx;
2792 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2793 /* Loongson CPU uses a load to zero register for prefetch.
2794 We emulate it as a NOP. On other CPU we must perform the
2795 actual memory access. */
2796 return;
2799 t0 = tcg_temp_new();
2800 gen_base_offset_addr(ctx, t0, base, offset);
2802 switch (opc) {
2803 #if defined(TARGET_MIPS64)
2804 case OPC_LWU:
2805 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2806 ctx->default_tcg_memop_mask);
2807 gen_store_gpr(t0, rt);
2808 break;
2809 case OPC_LD:
2810 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2811 ctx->default_tcg_memop_mask);
2812 gen_store_gpr(t0, rt);
2813 break;
2814 case OPC_LLD:
2815 case R6_OPC_LLD:
2816 op_ld_lld(t0, t0, mem_idx, ctx);
2817 gen_store_gpr(t0, rt);
2818 break;
2819 case OPC_LDL:
2820 t1 = tcg_temp_new();
2821 /* Do a byte access to possibly trigger a page
2822 fault with the unaligned address. */
2823 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2824 tcg_gen_andi_tl(t1, t0, 7);
2825 #ifndef TARGET_WORDS_BIGENDIAN
2826 tcg_gen_xori_tl(t1, t1, 7);
2827 #endif
2828 tcg_gen_shli_tl(t1, t1, 3);
2829 tcg_gen_andi_tl(t0, t0, ~7);
2830 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2831 tcg_gen_shl_tl(t0, t0, t1);
2832 t2 = tcg_const_tl(-1);
2833 tcg_gen_shl_tl(t2, t2, t1);
2834 gen_load_gpr(t1, rt);
2835 tcg_gen_andc_tl(t1, t1, t2);
2836 tcg_temp_free(t2);
2837 tcg_gen_or_tl(t0, t0, t1);
2838 tcg_temp_free(t1);
2839 gen_store_gpr(t0, rt);
2840 break;
2841 case OPC_LDR:
2842 t1 = tcg_temp_new();
2843 /* Do a byte access to possibly trigger a page
2844 fault with the unaligned address. */
2845 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2846 tcg_gen_andi_tl(t1, t0, 7);
2847 #ifdef TARGET_WORDS_BIGENDIAN
2848 tcg_gen_xori_tl(t1, t1, 7);
2849 #endif
2850 tcg_gen_shli_tl(t1, t1, 3);
2851 tcg_gen_andi_tl(t0, t0, ~7);
2852 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2853 tcg_gen_shr_tl(t0, t0, t1);
2854 tcg_gen_xori_tl(t1, t1, 63);
2855 t2 = tcg_const_tl(0xfffffffffffffffeull);
2856 tcg_gen_shl_tl(t2, t2, t1);
2857 gen_load_gpr(t1, rt);
2858 tcg_gen_and_tl(t1, t1, t2);
2859 tcg_temp_free(t2);
2860 tcg_gen_or_tl(t0, t0, t1);
2861 tcg_temp_free(t1);
2862 gen_store_gpr(t0, rt);
2863 break;
2864 case OPC_LDPC:
2865 t1 = tcg_const_tl(pc_relative_pc(ctx));
2866 gen_op_addr_add(ctx, t0, t0, t1);
2867 tcg_temp_free(t1);
2868 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2869 gen_store_gpr(t0, rt);
2870 break;
2871 #endif
2872 case OPC_LWPC:
2873 t1 = tcg_const_tl(pc_relative_pc(ctx));
2874 gen_op_addr_add(ctx, t0, t0, t1);
2875 tcg_temp_free(t1);
2876 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2877 gen_store_gpr(t0, rt);
2878 break;
2879 case OPC_LWE:
2880 mem_idx = MIPS_HFLAG_UM;
2881 /* fall through */
2882 case OPC_LW:
2883 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2884 ctx->default_tcg_memop_mask);
2885 gen_store_gpr(t0, rt);
2886 break;
2887 case OPC_LHE:
2888 mem_idx = MIPS_HFLAG_UM;
2889 /* fall through */
2890 case OPC_LH:
2891 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2892 ctx->default_tcg_memop_mask);
2893 gen_store_gpr(t0, rt);
2894 break;
2895 case OPC_LHUE:
2896 mem_idx = MIPS_HFLAG_UM;
2897 /* fall through */
2898 case OPC_LHU:
2899 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2900 ctx->default_tcg_memop_mask);
2901 gen_store_gpr(t0, rt);
2902 break;
2903 case OPC_LBE:
2904 mem_idx = MIPS_HFLAG_UM;
2905 /* fall through */
2906 case OPC_LB:
2907 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2908 gen_store_gpr(t0, rt);
2909 break;
2910 case OPC_LBUE:
2911 mem_idx = MIPS_HFLAG_UM;
2912 /* fall through */
2913 case OPC_LBU:
2914 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2915 gen_store_gpr(t0, rt);
2916 break;
2917 case OPC_LWLE:
2918 mem_idx = MIPS_HFLAG_UM;
2919 /* fall through */
2920 case OPC_LWL:
2921 t1 = tcg_temp_new();
2922 /* Do a byte access to possibly trigger a page
2923 fault with the unaligned address. */
2924 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2925 tcg_gen_andi_tl(t1, t0, 3);
2926 #ifndef TARGET_WORDS_BIGENDIAN
2927 tcg_gen_xori_tl(t1, t1, 3);
2928 #endif
2929 tcg_gen_shli_tl(t1, t1, 3);
2930 tcg_gen_andi_tl(t0, t0, ~3);
2931 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2932 tcg_gen_shl_tl(t0, t0, t1);
2933 t2 = tcg_const_tl(-1);
2934 tcg_gen_shl_tl(t2, t2, t1);
2935 gen_load_gpr(t1, rt);
2936 tcg_gen_andc_tl(t1, t1, t2);
2937 tcg_temp_free(t2);
2938 tcg_gen_or_tl(t0, t0, t1);
2939 tcg_temp_free(t1);
2940 tcg_gen_ext32s_tl(t0, t0);
2941 gen_store_gpr(t0, rt);
2942 break;
2943 case OPC_LWRE:
2944 mem_idx = MIPS_HFLAG_UM;
2945 /* fall through */
2946 case OPC_LWR:
2947 t1 = tcg_temp_new();
2948 /* Do a byte access to possibly trigger a page
2949 fault with the unaligned address. */
2950 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2951 tcg_gen_andi_tl(t1, t0, 3);
2952 #ifdef TARGET_WORDS_BIGENDIAN
2953 tcg_gen_xori_tl(t1, t1, 3);
2954 #endif
2955 tcg_gen_shli_tl(t1, t1, 3);
2956 tcg_gen_andi_tl(t0, t0, ~3);
2957 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2958 tcg_gen_shr_tl(t0, t0, t1);
2959 tcg_gen_xori_tl(t1, t1, 31);
2960 t2 = tcg_const_tl(0xfffffffeull);
2961 tcg_gen_shl_tl(t2, t2, t1);
2962 gen_load_gpr(t1, rt);
2963 tcg_gen_and_tl(t1, t1, t2);
2964 tcg_temp_free(t2);
2965 tcg_gen_or_tl(t0, t0, t1);
2966 tcg_temp_free(t1);
2967 tcg_gen_ext32s_tl(t0, t0);
2968 gen_store_gpr(t0, rt);
2969 break;
2970 case OPC_LLE:
2971 mem_idx = MIPS_HFLAG_UM;
2972 /* fall through */
2973 case OPC_LL:
2974 case R6_OPC_LL:
2975 op_ld_ll(t0, t0, mem_idx, ctx);
2976 gen_store_gpr(t0, rt);
2977 break;
2979 tcg_temp_free(t0);
2982 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2983 uint32_t reg1, uint32_t reg2)
2985 TCGv taddr = tcg_temp_new();
2986 TCGv_i64 tval = tcg_temp_new_i64();
2987 TCGv tmp1 = tcg_temp_new();
2988 TCGv tmp2 = tcg_temp_new();
2990 gen_base_offset_addr(ctx, taddr, base, offset);
2991 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2992 #ifdef TARGET_WORDS_BIGENDIAN
2993 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2994 #else
2995 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2996 #endif
2997 gen_store_gpr(tmp1, reg1);
2998 tcg_temp_free(tmp1);
2999 gen_store_gpr(tmp2, reg2);
3000 tcg_temp_free(tmp2);
3001 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3002 tcg_temp_free_i64(tval);
3003 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3004 tcg_temp_free(taddr);
3007 /* Store */
3008 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3009 int base, int offset)
3011 TCGv t0 = tcg_temp_new();
3012 TCGv t1 = tcg_temp_new();
3013 int mem_idx = ctx->mem_idx;
3015 gen_base_offset_addr(ctx, t0, base, offset);
3016 gen_load_gpr(t1, rt);
3017 switch (opc) {
3018 #if defined(TARGET_MIPS64)
3019 case OPC_SD:
3020 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3021 ctx->default_tcg_memop_mask);
3022 break;
3023 case OPC_SDL:
3024 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3025 break;
3026 case OPC_SDR:
3027 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3028 break;
3029 #endif
3030 case OPC_SWE:
3031 mem_idx = MIPS_HFLAG_UM;
3032 /* fall through */
3033 case OPC_SW:
3034 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3035 ctx->default_tcg_memop_mask);
3036 break;
3037 case OPC_SHE:
3038 mem_idx = MIPS_HFLAG_UM;
3039 /* fall through */
3040 case OPC_SH:
3041 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3042 ctx->default_tcg_memop_mask);
3043 break;
3044 case OPC_SBE:
3045 mem_idx = MIPS_HFLAG_UM;
3046 /* fall through */
3047 case OPC_SB:
3048 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3049 break;
3050 case OPC_SWLE:
3051 mem_idx = MIPS_HFLAG_UM;
3052 /* fall through */
3053 case OPC_SWL:
3054 gen_helper_0e2i(swl, t1, t0, mem_idx);
3055 break;
3056 case OPC_SWRE:
3057 mem_idx = MIPS_HFLAG_UM;
3058 /* fall through */
3059 case OPC_SWR:
3060 gen_helper_0e2i(swr, t1, t0, mem_idx);
3061 break;
3063 tcg_temp_free(t0);
3064 tcg_temp_free(t1);
3068 /* Store conditional */
3069 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3070 int base, int16_t offset)
3072 TCGv t0, t1;
3073 int mem_idx = ctx->mem_idx;
3075 #ifdef CONFIG_USER_ONLY
3076 t0 = tcg_temp_local_new();
3077 t1 = tcg_temp_local_new();
3078 #else
3079 t0 = tcg_temp_new();
3080 t1 = tcg_temp_new();
3081 #endif
3082 gen_base_offset_addr(ctx, t0, base, offset);
3083 gen_load_gpr(t1, rt);
3084 switch (opc) {
3085 #if defined(TARGET_MIPS64)
3086 case OPC_SCD:
3087 case R6_OPC_SCD:
3088 op_st_scd(t1, t0, rt, mem_idx, ctx);
3089 break;
3090 #endif
3091 case OPC_SCE:
3092 mem_idx = MIPS_HFLAG_UM;
3093 /* fall through */
3094 case OPC_SC:
3095 case R6_OPC_SC:
3096 op_st_sc(t1, t0, rt, mem_idx, ctx);
3097 break;
3099 tcg_temp_free(t1);
3100 tcg_temp_free(t0);
3103 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3104 uint32_t reg1, uint32_t reg2)
3106 TCGv taddr = tcg_temp_local_new();
3107 TCGv lladdr = tcg_temp_local_new();
3108 TCGv_i64 tval = tcg_temp_new_i64();
3109 TCGv_i64 llval = tcg_temp_new_i64();
3110 TCGv_i64 val = tcg_temp_new_i64();
3111 TCGv tmp1 = tcg_temp_new();
3112 TCGv tmp2 = tcg_temp_new();
3113 TCGLabel *lab_fail = gen_new_label();
3114 TCGLabel *lab_done = gen_new_label();
3116 gen_base_offset_addr(ctx, taddr, base, offset);
3118 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3119 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3121 gen_load_gpr(tmp1, reg1);
3122 gen_load_gpr(tmp2, reg2);
3124 #ifdef TARGET_WORDS_BIGENDIAN
3125 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3126 #else
3127 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3128 #endif
3130 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3131 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3132 ctx->mem_idx, MO_64);
3133 if (reg1 != 0) {
3134 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3136 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3138 gen_set_label(lab_fail);
3140 if (reg1 != 0) {
3141 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3143 gen_set_label(lab_done);
3144 tcg_gen_movi_tl(lladdr, -1);
3145 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3148 /* Load and store */
3149 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3150 TCGv t0)
3152 /* Don't do NOP if destination is zero: we must perform the actual
3153 memory access. */
3154 switch (opc) {
3155 case OPC_LWC1:
3157 TCGv_i32 fp0 = tcg_temp_new_i32();
3158 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3159 ctx->default_tcg_memop_mask);
3160 gen_store_fpr32(ctx, fp0, ft);
3161 tcg_temp_free_i32(fp0);
3163 break;
3164 case OPC_SWC1:
3166 TCGv_i32 fp0 = tcg_temp_new_i32();
3167 gen_load_fpr32(ctx, fp0, ft);
3168 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3169 ctx->default_tcg_memop_mask);
3170 tcg_temp_free_i32(fp0);
3172 break;
3173 case OPC_LDC1:
3175 TCGv_i64 fp0 = tcg_temp_new_i64();
3176 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3177 ctx->default_tcg_memop_mask);
3178 gen_store_fpr64(ctx, fp0, ft);
3179 tcg_temp_free_i64(fp0);
3181 break;
3182 case OPC_SDC1:
3184 TCGv_i64 fp0 = tcg_temp_new_i64();
3185 gen_load_fpr64(ctx, fp0, ft);
3186 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3187 ctx->default_tcg_memop_mask);
3188 tcg_temp_free_i64(fp0);
3190 break;
3191 default:
3192 MIPS_INVAL("flt_ldst");
3193 generate_exception_end(ctx, EXCP_RI);
3194 break;
3198 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3199 int rs, int16_t imm)
3201 TCGv t0 = tcg_temp_new();
3203 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3204 check_cp1_enabled(ctx);
3205 switch (op) {
3206 case OPC_LDC1:
3207 case OPC_SDC1:
3208 check_insn(ctx, ISA_MIPS2);
3209 /* Fallthrough */
3210 default:
3211 gen_base_offset_addr(ctx, t0, rs, imm);
3212 gen_flt_ldst(ctx, op, rt, t0);
3214 } else {
3215 generate_exception_err(ctx, EXCP_CpU, 1);
3217 tcg_temp_free(t0);
3220 /* Arithmetic with immediate operand */
3221 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3222 int rt, int rs, int imm)
3224 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3226 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3227 /* If no destination, treat it as a NOP.
3228 For addi, we must generate the overflow exception when needed. */
3229 return;
3231 switch (opc) {
3232 case OPC_ADDI:
3234 TCGv t0 = tcg_temp_local_new();
3235 TCGv t1 = tcg_temp_new();
3236 TCGv t2 = tcg_temp_new();
3237 TCGLabel *l1 = gen_new_label();
3239 gen_load_gpr(t1, rs);
3240 tcg_gen_addi_tl(t0, t1, uimm);
3241 tcg_gen_ext32s_tl(t0, t0);
3243 tcg_gen_xori_tl(t1, t1, ~uimm);
3244 tcg_gen_xori_tl(t2, t0, uimm);
3245 tcg_gen_and_tl(t1, t1, t2);
3246 tcg_temp_free(t2);
3247 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3248 tcg_temp_free(t1);
3249 /* operands of same sign, result different sign */
3250 generate_exception(ctx, EXCP_OVERFLOW);
3251 gen_set_label(l1);
3252 tcg_gen_ext32s_tl(t0, t0);
3253 gen_store_gpr(t0, rt);
3254 tcg_temp_free(t0);
3256 break;
3257 case OPC_ADDIU:
3258 if (rs != 0) {
3259 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3260 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3261 } else {
3262 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3264 break;
3265 #if defined(TARGET_MIPS64)
3266 case OPC_DADDI:
3268 TCGv t0 = tcg_temp_local_new();
3269 TCGv t1 = tcg_temp_new();
3270 TCGv t2 = tcg_temp_new();
3271 TCGLabel *l1 = gen_new_label();
3273 gen_load_gpr(t1, rs);
3274 tcg_gen_addi_tl(t0, t1, uimm);
3276 tcg_gen_xori_tl(t1, t1, ~uimm);
3277 tcg_gen_xori_tl(t2, t0, uimm);
3278 tcg_gen_and_tl(t1, t1, t2);
3279 tcg_temp_free(t2);
3280 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3281 tcg_temp_free(t1);
3282 /* operands of same sign, result different sign */
3283 generate_exception(ctx, EXCP_OVERFLOW);
3284 gen_set_label(l1);
3285 gen_store_gpr(t0, rt);
3286 tcg_temp_free(t0);
3288 break;
3289 case OPC_DADDIU:
3290 if (rs != 0) {
3291 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3292 } else {
3293 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3295 break;
3296 #endif
3300 /* Logic with immediate operand */
3301 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3302 int rt, int rs, int16_t imm)
3304 target_ulong uimm;
3306 if (rt == 0) {
3307 /* If no destination, treat it as a NOP. */
3308 return;
3310 uimm = (uint16_t)imm;
3311 switch (opc) {
3312 case OPC_ANDI:
3313 if (likely(rs != 0))
3314 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3315 else
3316 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3317 break;
3318 case OPC_ORI:
3319 if (rs != 0)
3320 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3321 else
3322 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3323 break;
3324 case OPC_XORI:
3325 if (likely(rs != 0))
3326 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3327 else
3328 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3329 break;
3330 case OPC_LUI:
3331 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3332 /* OPC_AUI */
3333 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3334 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3335 } else {
3336 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3338 break;
3340 default:
3341 break;
3345 /* Set on less than with immediate operand */
3346 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3347 int rt, int rs, int16_t imm)
3349 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3350 TCGv t0;
3352 if (rt == 0) {
3353 /* If no destination, treat it as a NOP. */
3354 return;
3356 t0 = tcg_temp_new();
3357 gen_load_gpr(t0, rs);
3358 switch (opc) {
3359 case OPC_SLTI:
3360 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3361 break;
3362 case OPC_SLTIU:
3363 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3364 break;
3366 tcg_temp_free(t0);
3369 /* Shifts with immediate operand */
3370 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3371 int rt, int rs, int16_t imm)
3373 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3374 TCGv t0;
3376 if (rt == 0) {
3377 /* If no destination, treat it as a NOP. */
3378 return;
3381 t0 = tcg_temp_new();
3382 gen_load_gpr(t0, rs);
3383 switch (opc) {
3384 case OPC_SLL:
3385 tcg_gen_shli_tl(t0, t0, uimm);
3386 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3387 break;
3388 case OPC_SRA:
3389 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3390 break;
3391 case OPC_SRL:
3392 if (uimm != 0) {
3393 tcg_gen_ext32u_tl(t0, t0);
3394 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3395 } else {
3396 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3398 break;
3399 case OPC_ROTR:
3400 if (uimm != 0) {
3401 TCGv_i32 t1 = tcg_temp_new_i32();
3403 tcg_gen_trunc_tl_i32(t1, t0);
3404 tcg_gen_rotri_i32(t1, t1, uimm);
3405 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3406 tcg_temp_free_i32(t1);
3407 } else {
3408 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3410 break;
3411 #if defined(TARGET_MIPS64)
3412 case OPC_DSLL:
3413 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3414 break;
3415 case OPC_DSRA:
3416 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3417 break;
3418 case OPC_DSRL:
3419 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3420 break;
3421 case OPC_DROTR:
3422 if (uimm != 0) {
3423 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3424 } else {
3425 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3427 break;
3428 case OPC_DSLL32:
3429 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3430 break;
3431 case OPC_DSRA32:
3432 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3433 break;
3434 case OPC_DSRL32:
3435 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3436 break;
3437 case OPC_DROTR32:
3438 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3439 break;
3440 #endif
3442 tcg_temp_free(t0);
3445 /* Arithmetic */
3446 static void gen_arith(DisasContext *ctx, uint32_t opc,
3447 int rd, int rs, int rt)
3449 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3450 && opc != OPC_DADD && opc != OPC_DSUB) {
3451 /* If no destination, treat it as a NOP.
3452 For add & sub, we must generate the overflow exception when needed. */
3453 return;
3456 switch (opc) {
3457 case OPC_ADD:
3459 TCGv t0 = tcg_temp_local_new();
3460 TCGv t1 = tcg_temp_new();
3461 TCGv t2 = tcg_temp_new();
3462 TCGLabel *l1 = gen_new_label();
3464 gen_load_gpr(t1, rs);
3465 gen_load_gpr(t2, rt);
3466 tcg_gen_add_tl(t0, t1, t2);
3467 tcg_gen_ext32s_tl(t0, t0);
3468 tcg_gen_xor_tl(t1, t1, t2);
3469 tcg_gen_xor_tl(t2, t0, t2);
3470 tcg_gen_andc_tl(t1, t2, t1);
3471 tcg_temp_free(t2);
3472 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3473 tcg_temp_free(t1);
3474 /* operands of same sign, result different sign */
3475 generate_exception(ctx, EXCP_OVERFLOW);
3476 gen_set_label(l1);
3477 gen_store_gpr(t0, rd);
3478 tcg_temp_free(t0);
3480 break;
3481 case OPC_ADDU:
3482 if (rs != 0 && rt != 0) {
3483 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3484 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3485 } else if (rs == 0 && rt != 0) {
3486 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3487 } else if (rs != 0 && rt == 0) {
3488 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3489 } else {
3490 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3492 break;
3493 case OPC_SUB:
3495 TCGv t0 = tcg_temp_local_new();
3496 TCGv t1 = tcg_temp_new();
3497 TCGv t2 = tcg_temp_new();
3498 TCGLabel *l1 = gen_new_label();
3500 gen_load_gpr(t1, rs);
3501 gen_load_gpr(t2, rt);
3502 tcg_gen_sub_tl(t0, t1, t2);
3503 tcg_gen_ext32s_tl(t0, t0);
3504 tcg_gen_xor_tl(t2, t1, t2);
3505 tcg_gen_xor_tl(t1, t0, t1);
3506 tcg_gen_and_tl(t1, t1, t2);
3507 tcg_temp_free(t2);
3508 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3509 tcg_temp_free(t1);
3510 /* operands of different sign, first operand and result different sign */
3511 generate_exception(ctx, EXCP_OVERFLOW);
3512 gen_set_label(l1);
3513 gen_store_gpr(t0, rd);
3514 tcg_temp_free(t0);
3516 break;
3517 case OPC_SUBU:
3518 if (rs != 0 && rt != 0) {
3519 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3520 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3521 } else if (rs == 0 && rt != 0) {
3522 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3523 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3524 } else if (rs != 0 && rt == 0) {
3525 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3526 } else {
3527 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3529 break;
3530 #if defined(TARGET_MIPS64)
3531 case OPC_DADD:
3533 TCGv t0 = tcg_temp_local_new();
3534 TCGv t1 = tcg_temp_new();
3535 TCGv t2 = tcg_temp_new();
3536 TCGLabel *l1 = gen_new_label();
3538 gen_load_gpr(t1, rs);
3539 gen_load_gpr(t2, rt);
3540 tcg_gen_add_tl(t0, t1, t2);
3541 tcg_gen_xor_tl(t1, t1, t2);
3542 tcg_gen_xor_tl(t2, t0, t2);
3543 tcg_gen_andc_tl(t1, t2, t1);
3544 tcg_temp_free(t2);
3545 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3546 tcg_temp_free(t1);
3547 /* operands of same sign, result different sign */
3548 generate_exception(ctx, EXCP_OVERFLOW);
3549 gen_set_label(l1);
3550 gen_store_gpr(t0, rd);
3551 tcg_temp_free(t0);
3553 break;
3554 case OPC_DADDU:
3555 if (rs != 0 && rt != 0) {
3556 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3557 } else if (rs == 0 && rt != 0) {
3558 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3559 } else if (rs != 0 && rt == 0) {
3560 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3561 } else {
3562 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3564 break;
3565 case OPC_DSUB:
3567 TCGv t0 = tcg_temp_local_new();
3568 TCGv t1 = tcg_temp_new();
3569 TCGv t2 = tcg_temp_new();
3570 TCGLabel *l1 = gen_new_label();
3572 gen_load_gpr(t1, rs);
3573 gen_load_gpr(t2, rt);
3574 tcg_gen_sub_tl(t0, t1, t2);
3575 tcg_gen_xor_tl(t2, t1, t2);
3576 tcg_gen_xor_tl(t1, t0, t1);
3577 tcg_gen_and_tl(t1, t1, t2);
3578 tcg_temp_free(t2);
3579 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3580 tcg_temp_free(t1);
3581 /* operands of different sign, first operand and result different sign */
3582 generate_exception(ctx, EXCP_OVERFLOW);
3583 gen_set_label(l1);
3584 gen_store_gpr(t0, rd);
3585 tcg_temp_free(t0);
3587 break;
3588 case OPC_DSUBU:
3589 if (rs != 0 && rt != 0) {
3590 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3591 } else if (rs == 0 && rt != 0) {
3592 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3593 } else if (rs != 0 && rt == 0) {
3594 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3595 } else {
3596 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3598 break;
3599 #endif
3600 case OPC_MUL:
3601 if (likely(rs != 0 && rt != 0)) {
3602 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3603 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3604 } else {
3605 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3607 break;
3611 /* Conditional move */
3612 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3613 int rd, int rs, int rt)
3615 TCGv t0, t1, t2;
3617 if (rd == 0) {
3618 /* If no destination, treat it as a NOP. */
3619 return;
3622 t0 = tcg_temp_new();
3623 gen_load_gpr(t0, rt);
3624 t1 = tcg_const_tl(0);
3625 t2 = tcg_temp_new();
3626 gen_load_gpr(t2, rs);
3627 switch (opc) {
3628 case OPC_MOVN:
3629 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3630 break;
3631 case OPC_MOVZ:
3632 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3633 break;
3634 case OPC_SELNEZ:
3635 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3636 break;
3637 case OPC_SELEQZ:
3638 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3639 break;
3641 tcg_temp_free(t2);
3642 tcg_temp_free(t1);
3643 tcg_temp_free(t0);
3646 /* Logic */
3647 static void gen_logic(DisasContext *ctx, uint32_t opc,
3648 int rd, int rs, int rt)
3650 if (rd == 0) {
3651 /* If no destination, treat it as a NOP. */
3652 return;
3655 switch (opc) {
3656 case OPC_AND:
3657 if (likely(rs != 0 && rt != 0)) {
3658 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3659 } else {
3660 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3662 break;
3663 case OPC_NOR:
3664 if (rs != 0 && rt != 0) {
3665 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3666 } else if (rs == 0 && rt != 0) {
3667 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3668 } else if (rs != 0 && rt == 0) {
3669 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3670 } else {
3671 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3673 break;
3674 case OPC_OR:
3675 if (likely(rs != 0 && rt != 0)) {
3676 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3677 } else if (rs == 0 && rt != 0) {
3678 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3679 } else if (rs != 0 && rt == 0) {
3680 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3681 } else {
3682 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3684 break;
3685 case OPC_XOR:
3686 if (likely(rs != 0 && rt != 0)) {
3687 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3688 } else if (rs == 0 && rt != 0) {
3689 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3690 } else if (rs != 0 && rt == 0) {
3691 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3692 } else {
3693 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3695 break;
3699 /* Set on lower than */
3700 static void gen_slt(DisasContext *ctx, uint32_t opc,
3701 int rd, int rs, int rt)
3703 TCGv t0, t1;
3705 if (rd == 0) {
3706 /* If no destination, treat it as a NOP. */
3707 return;
3710 t0 = tcg_temp_new();
3711 t1 = tcg_temp_new();
3712 gen_load_gpr(t0, rs);
3713 gen_load_gpr(t1, rt);
3714 switch (opc) {
3715 case OPC_SLT:
3716 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3717 break;
3718 case OPC_SLTU:
3719 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3720 break;
3722 tcg_temp_free(t0);
3723 tcg_temp_free(t1);
3726 /* Shifts */
3727 static void gen_shift(DisasContext *ctx, uint32_t opc,
3728 int rd, int rs, int rt)
3730 TCGv t0, t1;
3732 if (rd == 0) {
3733 /* If no destination, treat it as a NOP.
3734 For add & sub, we must generate the overflow exception when needed. */
3735 return;
3738 t0 = tcg_temp_new();
3739 t1 = tcg_temp_new();
3740 gen_load_gpr(t0, rs);
3741 gen_load_gpr(t1, rt);
3742 switch (opc) {
3743 case OPC_SLLV:
3744 tcg_gen_andi_tl(t0, t0, 0x1f);
3745 tcg_gen_shl_tl(t0, t1, t0);
3746 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3747 break;
3748 case OPC_SRAV:
3749 tcg_gen_andi_tl(t0, t0, 0x1f);
3750 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3751 break;
3752 case OPC_SRLV:
3753 tcg_gen_ext32u_tl(t1, t1);
3754 tcg_gen_andi_tl(t0, t0, 0x1f);
3755 tcg_gen_shr_tl(t0, t1, t0);
3756 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3757 break;
3758 case OPC_ROTRV:
3760 TCGv_i32 t2 = tcg_temp_new_i32();
3761 TCGv_i32 t3 = tcg_temp_new_i32();
3763 tcg_gen_trunc_tl_i32(t2, t0);
3764 tcg_gen_trunc_tl_i32(t3, t1);
3765 tcg_gen_andi_i32(t2, t2, 0x1f);
3766 tcg_gen_rotr_i32(t2, t3, t2);
3767 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3768 tcg_temp_free_i32(t2);
3769 tcg_temp_free_i32(t3);
3771 break;
3772 #if defined(TARGET_MIPS64)
3773 case OPC_DSLLV:
3774 tcg_gen_andi_tl(t0, t0, 0x3f);
3775 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3776 break;
3777 case OPC_DSRAV:
3778 tcg_gen_andi_tl(t0, t0, 0x3f);
3779 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3780 break;
3781 case OPC_DSRLV:
3782 tcg_gen_andi_tl(t0, t0, 0x3f);
3783 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3784 break;
3785 case OPC_DROTRV:
3786 tcg_gen_andi_tl(t0, t0, 0x3f);
3787 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3788 break;
3789 #endif
3791 tcg_temp_free(t0);
3792 tcg_temp_free(t1);
3795 /* Arithmetic on HI/LO registers */
3796 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3798 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3799 /* Treat as NOP. */
3800 return;
3803 if (acc != 0) {
3804 check_dsp(ctx);
3807 switch (opc) {
3808 case OPC_MFHI:
3809 #if defined(TARGET_MIPS64)
3810 if (acc != 0) {
3811 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3812 } else
3813 #endif
3815 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3817 break;
3818 case OPC_MFLO:
3819 #if defined(TARGET_MIPS64)
3820 if (acc != 0) {
3821 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3822 } else
3823 #endif
3825 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3827 break;
3828 case OPC_MTHI:
3829 if (reg != 0) {
3830 #if defined(TARGET_MIPS64)
3831 if (acc != 0) {
3832 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3833 } else
3834 #endif
3836 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3838 } else {
3839 tcg_gen_movi_tl(cpu_HI[acc], 0);
3841 break;
3842 case OPC_MTLO:
3843 if (reg != 0) {
3844 #if defined(TARGET_MIPS64)
3845 if (acc != 0) {
3846 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3847 } else
3848 #endif
3850 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3852 } else {
3853 tcg_gen_movi_tl(cpu_LO[acc], 0);
3855 break;
3859 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3860 TCGMemOp memop)
3862 TCGv t0 = tcg_const_tl(addr);
3863 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3864 gen_store_gpr(t0, reg);
3865 tcg_temp_free(t0);
3868 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3869 int rs)
3871 target_long offset;
3872 target_long addr;
3874 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3875 case OPC_ADDIUPC:
3876 if (rs != 0) {
3877 offset = sextract32(ctx->opcode << 2, 0, 21);
3878 addr = addr_add(ctx, pc, offset);
3879 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3881 break;
3882 case R6_OPC_LWPC:
3883 offset = sextract32(ctx->opcode << 2, 0, 21);
3884 addr = addr_add(ctx, pc, offset);
3885 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3886 break;
3887 #if defined(TARGET_MIPS64)
3888 case OPC_LWUPC:
3889 check_mips_64(ctx);
3890 offset = sextract32(ctx->opcode << 2, 0, 21);
3891 addr = addr_add(ctx, pc, offset);
3892 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3893 break;
3894 #endif
3895 default:
3896 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3897 case OPC_AUIPC:
3898 if (rs != 0) {
3899 offset = sextract32(ctx->opcode, 0, 16) << 16;
3900 addr = addr_add(ctx, pc, offset);
3901 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3903 break;
3904 case OPC_ALUIPC:
3905 if (rs != 0) {
3906 offset = sextract32(ctx->opcode, 0, 16) << 16;
3907 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3908 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3910 break;
3911 #if defined(TARGET_MIPS64)
3912 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3913 case R6_OPC_LDPC + (1 << 16):
3914 case R6_OPC_LDPC + (2 << 16):
3915 case R6_OPC_LDPC + (3 << 16):
3916 check_mips_64(ctx);
3917 offset = sextract32(ctx->opcode << 3, 0, 21);
3918 addr = addr_add(ctx, (pc & ~0x7), offset);
3919 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3920 break;
3921 #endif
3922 default:
3923 MIPS_INVAL("OPC_PCREL");
3924 generate_exception_end(ctx, EXCP_RI);
3925 break;
3927 break;
3931 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3933 TCGv t0, t1;
3935 if (rd == 0) {
3936 /* Treat as NOP. */
3937 return;
3940 t0 = tcg_temp_new();
3941 t1 = tcg_temp_new();
3943 gen_load_gpr(t0, rs);
3944 gen_load_gpr(t1, rt);
3946 switch (opc) {
3947 case R6_OPC_DIV:
3949 TCGv t2 = tcg_temp_new();
3950 TCGv t3 = tcg_temp_new();
3951 tcg_gen_ext32s_tl(t0, t0);
3952 tcg_gen_ext32s_tl(t1, t1);
3953 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3954 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3955 tcg_gen_and_tl(t2, t2, t3);
3956 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3957 tcg_gen_or_tl(t2, t2, t3);
3958 tcg_gen_movi_tl(t3, 0);
3959 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3960 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3961 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3962 tcg_temp_free(t3);
3963 tcg_temp_free(t2);
3965 break;
3966 case R6_OPC_MOD:
3968 TCGv t2 = tcg_temp_new();
3969 TCGv t3 = tcg_temp_new();
3970 tcg_gen_ext32s_tl(t0, t0);
3971 tcg_gen_ext32s_tl(t1, t1);
3972 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3973 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3974 tcg_gen_and_tl(t2, t2, t3);
3975 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3976 tcg_gen_or_tl(t2, t2, t3);
3977 tcg_gen_movi_tl(t3, 0);
3978 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3979 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3980 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3981 tcg_temp_free(t3);
3982 tcg_temp_free(t2);
3984 break;
3985 case R6_OPC_DIVU:
3987 TCGv t2 = tcg_const_tl(0);
3988 TCGv t3 = tcg_const_tl(1);
3989 tcg_gen_ext32u_tl(t0, t0);
3990 tcg_gen_ext32u_tl(t1, t1);
3991 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3992 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3993 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3994 tcg_temp_free(t3);
3995 tcg_temp_free(t2);
3997 break;
3998 case R6_OPC_MODU:
4000 TCGv t2 = tcg_const_tl(0);
4001 TCGv t3 = tcg_const_tl(1);
4002 tcg_gen_ext32u_tl(t0, t0);
4003 tcg_gen_ext32u_tl(t1, t1);
4004 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4005 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4006 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4007 tcg_temp_free(t3);
4008 tcg_temp_free(t2);
4010 break;
4011 case R6_OPC_MUL:
4013 TCGv_i32 t2 = tcg_temp_new_i32();
4014 TCGv_i32 t3 = tcg_temp_new_i32();
4015 tcg_gen_trunc_tl_i32(t2, t0);
4016 tcg_gen_trunc_tl_i32(t3, t1);
4017 tcg_gen_mul_i32(t2, t2, t3);
4018 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4019 tcg_temp_free_i32(t2);
4020 tcg_temp_free_i32(t3);
4022 break;
4023 case R6_OPC_MUH:
4025 TCGv_i32 t2 = tcg_temp_new_i32();
4026 TCGv_i32 t3 = tcg_temp_new_i32();
4027 tcg_gen_trunc_tl_i32(t2, t0);
4028 tcg_gen_trunc_tl_i32(t3, t1);
4029 tcg_gen_muls2_i32(t2, t3, t2, t3);
4030 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4031 tcg_temp_free_i32(t2);
4032 tcg_temp_free_i32(t3);
4034 break;
4035 case R6_OPC_MULU:
4037 TCGv_i32 t2 = tcg_temp_new_i32();
4038 TCGv_i32 t3 = tcg_temp_new_i32();
4039 tcg_gen_trunc_tl_i32(t2, t0);
4040 tcg_gen_trunc_tl_i32(t3, t1);
4041 tcg_gen_mul_i32(t2, t2, t3);
4042 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4043 tcg_temp_free_i32(t2);
4044 tcg_temp_free_i32(t3);
4046 break;
4047 case R6_OPC_MUHU:
4049 TCGv_i32 t2 = tcg_temp_new_i32();
4050 TCGv_i32 t3 = tcg_temp_new_i32();
4051 tcg_gen_trunc_tl_i32(t2, t0);
4052 tcg_gen_trunc_tl_i32(t3, t1);
4053 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4054 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4055 tcg_temp_free_i32(t2);
4056 tcg_temp_free_i32(t3);
4058 break;
4059 #if defined(TARGET_MIPS64)
4060 case R6_OPC_DDIV:
4062 TCGv t2 = tcg_temp_new();
4063 TCGv t3 = tcg_temp_new();
4064 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4065 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4066 tcg_gen_and_tl(t2, t2, t3);
4067 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4068 tcg_gen_or_tl(t2, t2, t3);
4069 tcg_gen_movi_tl(t3, 0);
4070 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4071 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4072 tcg_temp_free(t3);
4073 tcg_temp_free(t2);
4075 break;
4076 case R6_OPC_DMOD:
4078 TCGv t2 = tcg_temp_new();
4079 TCGv t3 = tcg_temp_new();
4080 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4081 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4082 tcg_gen_and_tl(t2, t2, t3);
4083 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4084 tcg_gen_or_tl(t2, t2, t3);
4085 tcg_gen_movi_tl(t3, 0);
4086 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4087 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4088 tcg_temp_free(t3);
4089 tcg_temp_free(t2);
4091 break;
4092 case R6_OPC_DDIVU:
4094 TCGv t2 = tcg_const_tl(0);
4095 TCGv t3 = tcg_const_tl(1);
4096 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4097 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4098 tcg_temp_free(t3);
4099 tcg_temp_free(t2);
4101 break;
4102 case R6_OPC_DMODU:
4104 TCGv t2 = tcg_const_tl(0);
4105 TCGv t3 = tcg_const_tl(1);
4106 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4107 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4108 tcg_temp_free(t3);
4109 tcg_temp_free(t2);
4111 break;
4112 case R6_OPC_DMUL:
4113 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4114 break;
4115 case R6_OPC_DMUH:
4117 TCGv t2 = tcg_temp_new();
4118 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4119 tcg_temp_free(t2);
4121 break;
4122 case R6_OPC_DMULU:
4123 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4124 break;
4125 case R6_OPC_DMUHU:
4127 TCGv t2 = tcg_temp_new();
4128 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4129 tcg_temp_free(t2);
4131 break;
4132 #endif
4133 default:
4134 MIPS_INVAL("r6 mul/div");
4135 generate_exception_end(ctx, EXCP_RI);
4136 goto out;
4138 out:
4139 tcg_temp_free(t0);
4140 tcg_temp_free(t1);
4143 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4144 int acc, int rs, int rt)
4146 TCGv t0, t1;
4148 t0 = tcg_temp_new();
4149 t1 = tcg_temp_new();
4151 gen_load_gpr(t0, rs);
4152 gen_load_gpr(t1, rt);
4154 if (acc != 0) {
4155 check_dsp(ctx);
4158 switch (opc) {
4159 case OPC_DIV:
4161 TCGv t2 = tcg_temp_new();
4162 TCGv t3 = tcg_temp_new();
4163 tcg_gen_ext32s_tl(t0, t0);
4164 tcg_gen_ext32s_tl(t1, t1);
4165 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4166 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4167 tcg_gen_and_tl(t2, t2, t3);
4168 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4169 tcg_gen_or_tl(t2, t2, t3);
4170 tcg_gen_movi_tl(t3, 0);
4171 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4172 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4173 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4174 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4175 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4176 tcg_temp_free(t3);
4177 tcg_temp_free(t2);
4179 break;
4180 case OPC_DIVU:
4182 TCGv t2 = tcg_const_tl(0);
4183 TCGv t3 = tcg_const_tl(1);
4184 tcg_gen_ext32u_tl(t0, t0);
4185 tcg_gen_ext32u_tl(t1, t1);
4186 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4187 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4188 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4189 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4190 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4191 tcg_temp_free(t3);
4192 tcg_temp_free(t2);
4194 break;
4195 case OPC_MULT:
4197 TCGv_i32 t2 = tcg_temp_new_i32();
4198 TCGv_i32 t3 = tcg_temp_new_i32();
4199 tcg_gen_trunc_tl_i32(t2, t0);
4200 tcg_gen_trunc_tl_i32(t3, t1);
4201 tcg_gen_muls2_i32(t2, t3, t2, t3);
4202 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4203 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4204 tcg_temp_free_i32(t2);
4205 tcg_temp_free_i32(t3);
4207 break;
4208 case OPC_MULTU:
4210 TCGv_i32 t2 = tcg_temp_new_i32();
4211 TCGv_i32 t3 = tcg_temp_new_i32();
4212 tcg_gen_trunc_tl_i32(t2, t0);
4213 tcg_gen_trunc_tl_i32(t3, t1);
4214 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4215 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4216 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4217 tcg_temp_free_i32(t2);
4218 tcg_temp_free_i32(t3);
4220 break;
4221 #if defined(TARGET_MIPS64)
4222 case OPC_DDIV:
4224 TCGv t2 = tcg_temp_new();
4225 TCGv t3 = tcg_temp_new();
4226 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4227 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4228 tcg_gen_and_tl(t2, t2, t3);
4229 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4230 tcg_gen_or_tl(t2, t2, t3);
4231 tcg_gen_movi_tl(t3, 0);
4232 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4233 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4234 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4235 tcg_temp_free(t3);
4236 tcg_temp_free(t2);
4238 break;
4239 case OPC_DDIVU:
4241 TCGv t2 = tcg_const_tl(0);
4242 TCGv t3 = tcg_const_tl(1);
4243 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4244 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4245 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4246 tcg_temp_free(t3);
4247 tcg_temp_free(t2);
4249 break;
4250 case OPC_DMULT:
4251 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4252 break;
4253 case OPC_DMULTU:
4254 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4255 break;
4256 #endif
4257 case OPC_MADD:
4259 TCGv_i64 t2 = tcg_temp_new_i64();
4260 TCGv_i64 t3 = tcg_temp_new_i64();
4262 tcg_gen_ext_tl_i64(t2, t0);
4263 tcg_gen_ext_tl_i64(t3, t1);
4264 tcg_gen_mul_i64(t2, t2, t3);
4265 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4266 tcg_gen_add_i64(t2, t2, t3);
4267 tcg_temp_free_i64(t3);
4268 gen_move_low32(cpu_LO[acc], t2);
4269 gen_move_high32(cpu_HI[acc], t2);
4270 tcg_temp_free_i64(t2);
4272 break;
4273 case OPC_MADDU:
4275 TCGv_i64 t2 = tcg_temp_new_i64();
4276 TCGv_i64 t3 = tcg_temp_new_i64();
4278 tcg_gen_ext32u_tl(t0, t0);
4279 tcg_gen_ext32u_tl(t1, t1);
4280 tcg_gen_extu_tl_i64(t2, t0);
4281 tcg_gen_extu_tl_i64(t3, t1);
4282 tcg_gen_mul_i64(t2, t2, t3);
4283 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4284 tcg_gen_add_i64(t2, t2, t3);
4285 tcg_temp_free_i64(t3);
4286 gen_move_low32(cpu_LO[acc], t2);
4287 gen_move_high32(cpu_HI[acc], t2);
4288 tcg_temp_free_i64(t2);
4290 break;
4291 case OPC_MSUB:
4293 TCGv_i64 t2 = tcg_temp_new_i64();
4294 TCGv_i64 t3 = tcg_temp_new_i64();
4296 tcg_gen_ext_tl_i64(t2, t0);
4297 tcg_gen_ext_tl_i64(t3, t1);
4298 tcg_gen_mul_i64(t2, t2, t3);
4299 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4300 tcg_gen_sub_i64(t2, t3, t2);
4301 tcg_temp_free_i64(t3);
4302 gen_move_low32(cpu_LO[acc], t2);
4303 gen_move_high32(cpu_HI[acc], t2);
4304 tcg_temp_free_i64(t2);
4306 break;
4307 case OPC_MSUBU:
4309 TCGv_i64 t2 = tcg_temp_new_i64();
4310 TCGv_i64 t3 = tcg_temp_new_i64();
4312 tcg_gen_ext32u_tl(t0, t0);
4313 tcg_gen_ext32u_tl(t1, t1);
4314 tcg_gen_extu_tl_i64(t2, t0);
4315 tcg_gen_extu_tl_i64(t3, t1);
4316 tcg_gen_mul_i64(t2, t2, t3);
4317 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4318 tcg_gen_sub_i64(t2, t3, t2);
4319 tcg_temp_free_i64(t3);
4320 gen_move_low32(cpu_LO[acc], t2);
4321 gen_move_high32(cpu_HI[acc], t2);
4322 tcg_temp_free_i64(t2);
4324 break;
4325 default:
4326 MIPS_INVAL("mul/div");
4327 generate_exception_end(ctx, EXCP_RI);
4328 goto out;
4330 out:
4331 tcg_temp_free(t0);
4332 tcg_temp_free(t1);
4335 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4336 int rd, int rs, int rt)
4338 TCGv t0 = tcg_temp_new();
4339 TCGv t1 = tcg_temp_new();
4341 gen_load_gpr(t0, rs);
4342 gen_load_gpr(t1, rt);
4344 switch (opc) {
4345 case OPC_VR54XX_MULS:
4346 gen_helper_muls(t0, cpu_env, t0, t1);
4347 break;
4348 case OPC_VR54XX_MULSU:
4349 gen_helper_mulsu(t0, cpu_env, t0, t1);
4350 break;
4351 case OPC_VR54XX_MACC:
4352 gen_helper_macc(t0, cpu_env, t0, t1);
4353 break;
4354 case OPC_VR54XX_MACCU:
4355 gen_helper_maccu(t0, cpu_env, t0, t1);
4356 break;
4357 case OPC_VR54XX_MSAC:
4358 gen_helper_msac(t0, cpu_env, t0, t1);
4359 break;
4360 case OPC_VR54XX_MSACU:
4361 gen_helper_msacu(t0, cpu_env, t0, t1);
4362 break;
4363 case OPC_VR54XX_MULHI:
4364 gen_helper_mulhi(t0, cpu_env, t0, t1);
4365 break;
4366 case OPC_VR54XX_MULHIU:
4367 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4368 break;
4369 case OPC_VR54XX_MULSHI:
4370 gen_helper_mulshi(t0, cpu_env, t0, t1);
4371 break;
4372 case OPC_VR54XX_MULSHIU:
4373 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4374 break;
4375 case OPC_VR54XX_MACCHI:
4376 gen_helper_macchi(t0, cpu_env, t0, t1);
4377 break;
4378 case OPC_VR54XX_MACCHIU:
4379 gen_helper_macchiu(t0, cpu_env, t0, t1);
4380 break;
4381 case OPC_VR54XX_MSACHI:
4382 gen_helper_msachi(t0, cpu_env, t0, t1);
4383 break;
4384 case OPC_VR54XX_MSACHIU:
4385 gen_helper_msachiu(t0, cpu_env, t0, t1);
4386 break;
4387 default:
4388 MIPS_INVAL("mul vr54xx");
4389 generate_exception_end(ctx, EXCP_RI);
4390 goto out;
4392 gen_store_gpr(t0, rd);
4394 out:
4395 tcg_temp_free(t0);
4396 tcg_temp_free(t1);
4399 static void gen_cl (DisasContext *ctx, uint32_t opc,
4400 int rd, int rs)
4402 TCGv t0;
4404 if (rd == 0) {
4405 /* Treat as NOP. */
4406 return;
4408 t0 = cpu_gpr[rd];
4409 gen_load_gpr(t0, rs);
4411 switch (opc) {
4412 case OPC_CLO:
4413 case R6_OPC_CLO:
4414 #if defined(TARGET_MIPS64)
4415 case OPC_DCLO:
4416 case R6_OPC_DCLO:
4417 #endif
4418 tcg_gen_not_tl(t0, t0);
4419 break;
4422 switch (opc) {
4423 case OPC_CLO:
4424 case R6_OPC_CLO:
4425 case OPC_CLZ:
4426 case R6_OPC_CLZ:
4427 tcg_gen_ext32u_tl(t0, t0);
4428 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4429 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4430 break;
4431 #if defined(TARGET_MIPS64)
4432 case OPC_DCLO:
4433 case R6_OPC_DCLO:
4434 case OPC_DCLZ:
4435 case R6_OPC_DCLZ:
4436 tcg_gen_clzi_i64(t0, t0, 64);
4437 break;
4438 #endif
4442 /* Godson integer instructions */
4443 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4444 int rd, int rs, int rt)
4446 TCGv t0, t1;
4448 if (rd == 0) {
4449 /* Treat as NOP. */
4450 return;
4453 switch (opc) {
4454 case OPC_MULT_G_2E:
4455 case OPC_MULT_G_2F:
4456 case OPC_MULTU_G_2E:
4457 case OPC_MULTU_G_2F:
4458 #if defined(TARGET_MIPS64)
4459 case OPC_DMULT_G_2E:
4460 case OPC_DMULT_G_2F:
4461 case OPC_DMULTU_G_2E:
4462 case OPC_DMULTU_G_2F:
4463 #endif
4464 t0 = tcg_temp_new();
4465 t1 = tcg_temp_new();
4466 break;
4467 default:
4468 t0 = tcg_temp_local_new();
4469 t1 = tcg_temp_local_new();
4470 break;
4473 gen_load_gpr(t0, rs);
4474 gen_load_gpr(t1, rt);
4476 switch (opc) {
4477 case OPC_MULT_G_2E:
4478 case OPC_MULT_G_2F:
4479 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4480 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4481 break;
4482 case OPC_MULTU_G_2E:
4483 case OPC_MULTU_G_2F:
4484 tcg_gen_ext32u_tl(t0, t0);
4485 tcg_gen_ext32u_tl(t1, t1);
4486 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4487 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4488 break;
4489 case OPC_DIV_G_2E:
4490 case OPC_DIV_G_2F:
4492 TCGLabel *l1 = gen_new_label();
4493 TCGLabel *l2 = gen_new_label();
4494 TCGLabel *l3 = gen_new_label();
4495 tcg_gen_ext32s_tl(t0, t0);
4496 tcg_gen_ext32s_tl(t1, t1);
4497 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4498 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4499 tcg_gen_br(l3);
4500 gen_set_label(l1);
4501 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4502 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4503 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4504 tcg_gen_br(l3);
4505 gen_set_label(l2);
4506 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4507 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4508 gen_set_label(l3);
4510 break;
4511 case OPC_DIVU_G_2E:
4512 case OPC_DIVU_G_2F:
4514 TCGLabel *l1 = gen_new_label();
4515 TCGLabel *l2 = gen_new_label();
4516 tcg_gen_ext32u_tl(t0, t0);
4517 tcg_gen_ext32u_tl(t1, t1);
4518 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4519 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4520 tcg_gen_br(l2);
4521 gen_set_label(l1);
4522 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4523 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4524 gen_set_label(l2);
4526 break;
4527 case OPC_MOD_G_2E:
4528 case OPC_MOD_G_2F:
4530 TCGLabel *l1 = gen_new_label();
4531 TCGLabel *l2 = gen_new_label();
4532 TCGLabel *l3 = gen_new_label();
4533 tcg_gen_ext32u_tl(t0, t0);
4534 tcg_gen_ext32u_tl(t1, t1);
4535 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4536 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4537 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4538 gen_set_label(l1);
4539 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4540 tcg_gen_br(l3);
4541 gen_set_label(l2);
4542 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4543 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4544 gen_set_label(l3);
4546 break;
4547 case OPC_MODU_G_2E:
4548 case OPC_MODU_G_2F:
4550 TCGLabel *l1 = gen_new_label();
4551 TCGLabel *l2 = gen_new_label();
4552 tcg_gen_ext32u_tl(t0, t0);
4553 tcg_gen_ext32u_tl(t1, t1);
4554 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4555 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4556 tcg_gen_br(l2);
4557 gen_set_label(l1);
4558 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4559 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4560 gen_set_label(l2);
4562 break;
4563 #if defined(TARGET_MIPS64)
4564 case OPC_DMULT_G_2E:
4565 case OPC_DMULT_G_2F:
4566 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4567 break;
4568 case OPC_DMULTU_G_2E:
4569 case OPC_DMULTU_G_2F:
4570 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4571 break;
4572 case OPC_DDIV_G_2E:
4573 case OPC_DDIV_G_2F:
4575 TCGLabel *l1 = gen_new_label();
4576 TCGLabel *l2 = gen_new_label();
4577 TCGLabel *l3 = gen_new_label();
4578 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4579 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4580 tcg_gen_br(l3);
4581 gen_set_label(l1);
4582 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4583 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4584 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4585 tcg_gen_br(l3);
4586 gen_set_label(l2);
4587 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4588 gen_set_label(l3);
4590 break;
4591 case OPC_DDIVU_G_2E:
4592 case OPC_DDIVU_G_2F:
4594 TCGLabel *l1 = gen_new_label();
4595 TCGLabel *l2 = gen_new_label();
4596 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4597 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4598 tcg_gen_br(l2);
4599 gen_set_label(l1);
4600 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4601 gen_set_label(l2);
4603 break;
4604 case OPC_DMOD_G_2E:
4605 case OPC_DMOD_G_2F:
4607 TCGLabel *l1 = gen_new_label();
4608 TCGLabel *l2 = gen_new_label();
4609 TCGLabel *l3 = gen_new_label();
4610 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4611 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4612 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4613 gen_set_label(l1);
4614 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4615 tcg_gen_br(l3);
4616 gen_set_label(l2);
4617 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4618 gen_set_label(l3);
4620 break;
4621 case OPC_DMODU_G_2E:
4622 case OPC_DMODU_G_2F:
4624 TCGLabel *l1 = gen_new_label();
4625 TCGLabel *l2 = gen_new_label();
4626 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4627 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4628 tcg_gen_br(l2);
4629 gen_set_label(l1);
4630 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4631 gen_set_label(l2);
4633 break;
4634 #endif
4637 tcg_temp_free(t0);
4638 tcg_temp_free(t1);
4641 /* Loongson multimedia instructions */
4642 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4644 uint32_t opc, shift_max;
4645 TCGv_i64 t0, t1;
4647 opc = MASK_LMI(ctx->opcode);
4648 switch (opc) {
4649 case OPC_ADD_CP2:
4650 case OPC_SUB_CP2:
4651 case OPC_DADD_CP2:
4652 case OPC_DSUB_CP2:
4653 t0 = tcg_temp_local_new_i64();
4654 t1 = tcg_temp_local_new_i64();
4655 break;
4656 default:
4657 t0 = tcg_temp_new_i64();
4658 t1 = tcg_temp_new_i64();
4659 break;
4662 check_cp1_enabled(ctx);
4663 gen_load_fpr64(ctx, t0, rs);
4664 gen_load_fpr64(ctx, t1, rt);
4666 #define LMI_HELPER(UP, LO) \
4667 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
4668 #define LMI_HELPER_1(UP, LO) \
4669 case OPC_##UP: gen_helper_##LO(t0, t0); break
4670 #define LMI_DIRECT(UP, LO, OP) \
4671 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
4673 switch (opc) {
4674 LMI_HELPER(PADDSH, paddsh);
4675 LMI_HELPER(PADDUSH, paddush);
4676 LMI_HELPER(PADDH, paddh);
4677 LMI_HELPER(PADDW, paddw);
4678 LMI_HELPER(PADDSB, paddsb);
4679 LMI_HELPER(PADDUSB, paddusb);
4680 LMI_HELPER(PADDB, paddb);
4682 LMI_HELPER(PSUBSH, psubsh);
4683 LMI_HELPER(PSUBUSH, psubush);
4684 LMI_HELPER(PSUBH, psubh);
4685 LMI_HELPER(PSUBW, psubw);
4686 LMI_HELPER(PSUBSB, psubsb);
4687 LMI_HELPER(PSUBUSB, psubusb);
4688 LMI_HELPER(PSUBB, psubb);
4690 LMI_HELPER(PSHUFH, pshufh);
4691 LMI_HELPER(PACKSSWH, packsswh);
4692 LMI_HELPER(PACKSSHB, packsshb);
4693 LMI_HELPER(PACKUSHB, packushb);
4695 LMI_HELPER(PUNPCKLHW, punpcklhw);
4696 LMI_HELPER(PUNPCKHHW, punpckhhw);
4697 LMI_HELPER(PUNPCKLBH, punpcklbh);
4698 LMI_HELPER(PUNPCKHBH, punpckhbh);
4699 LMI_HELPER(PUNPCKLWD, punpcklwd);
4700 LMI_HELPER(PUNPCKHWD, punpckhwd);
4702 LMI_HELPER(PAVGH, pavgh);
4703 LMI_HELPER(PAVGB, pavgb);
4704 LMI_HELPER(PMAXSH, pmaxsh);
4705 LMI_HELPER(PMINSH, pminsh);
4706 LMI_HELPER(PMAXUB, pmaxub);
4707 LMI_HELPER(PMINUB, pminub);
4709 LMI_HELPER(PCMPEQW, pcmpeqw);
4710 LMI_HELPER(PCMPGTW, pcmpgtw);
4711 LMI_HELPER(PCMPEQH, pcmpeqh);
4712 LMI_HELPER(PCMPGTH, pcmpgth);
4713 LMI_HELPER(PCMPEQB, pcmpeqb);
4714 LMI_HELPER(PCMPGTB, pcmpgtb);
4716 LMI_HELPER(PSLLW, psllw);
4717 LMI_HELPER(PSLLH, psllh);
4718 LMI_HELPER(PSRLW, psrlw);
4719 LMI_HELPER(PSRLH, psrlh);
4720 LMI_HELPER(PSRAW, psraw);
4721 LMI_HELPER(PSRAH, psrah);
4723 LMI_HELPER(PMULLH, pmullh);
4724 LMI_HELPER(PMULHH, pmulhh);
4725 LMI_HELPER(PMULHUH, pmulhuh);
4726 LMI_HELPER(PMADDHW, pmaddhw);
4728 LMI_HELPER(PASUBUB, pasubub);
4729 LMI_HELPER_1(BIADD, biadd);
4730 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4732 LMI_DIRECT(PADDD, paddd, add);
4733 LMI_DIRECT(PSUBD, psubd, sub);
4734 LMI_DIRECT(XOR_CP2, xor, xor);
4735 LMI_DIRECT(NOR_CP2, nor, nor);
4736 LMI_DIRECT(AND_CP2, and, and);
4737 LMI_DIRECT(OR_CP2, or, or);
4739 case OPC_PANDN:
4740 tcg_gen_andc_i64(t0, t1, t0);
4741 break;
4743 case OPC_PINSRH_0:
4744 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4745 break;
4746 case OPC_PINSRH_1:
4747 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4748 break;
4749 case OPC_PINSRH_2:
4750 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4751 break;
4752 case OPC_PINSRH_3:
4753 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4754 break;
4756 case OPC_PEXTRH:
4757 tcg_gen_andi_i64(t1, t1, 3);
4758 tcg_gen_shli_i64(t1, t1, 4);
4759 tcg_gen_shr_i64(t0, t0, t1);
4760 tcg_gen_ext16u_i64(t0, t0);
4761 break;
4763 case OPC_ADDU_CP2:
4764 tcg_gen_add_i64(t0, t0, t1);
4765 tcg_gen_ext32s_i64(t0, t0);
4766 break;
4767 case OPC_SUBU_CP2:
4768 tcg_gen_sub_i64(t0, t0, t1);
4769 tcg_gen_ext32s_i64(t0, t0);
4770 break;
4772 case OPC_SLL_CP2:
4773 shift_max = 32;
4774 goto do_shift;
4775 case OPC_SRL_CP2:
4776 shift_max = 32;
4777 goto do_shift;
4778 case OPC_SRA_CP2:
4779 shift_max = 32;
4780 goto do_shift;
4781 case OPC_DSLL_CP2:
4782 shift_max = 64;
4783 goto do_shift;
4784 case OPC_DSRL_CP2:
4785 shift_max = 64;
4786 goto do_shift;
4787 case OPC_DSRA_CP2:
4788 shift_max = 64;
4789 goto do_shift;
4790 do_shift:
4791 /* Make sure shift count isn't TCG undefined behaviour. */
4792 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4794 switch (opc) {
4795 case OPC_SLL_CP2:
4796 case OPC_DSLL_CP2:
4797 tcg_gen_shl_i64(t0, t0, t1);
4798 break;
4799 case OPC_SRA_CP2:
4800 case OPC_DSRA_CP2:
4801 /* Since SRA is UndefinedResult without sign-extended inputs,
4802 we can treat SRA and DSRA the same. */
4803 tcg_gen_sar_i64(t0, t0, t1);
4804 break;
4805 case OPC_SRL_CP2:
4806 /* We want to shift in zeros for SRL; zero-extend first. */
4807 tcg_gen_ext32u_i64(t0, t0);
4808 /* FALLTHRU */
4809 case OPC_DSRL_CP2:
4810 tcg_gen_shr_i64(t0, t0, t1);
4811 break;
4814 if (shift_max == 32) {
4815 tcg_gen_ext32s_i64(t0, t0);
4818 /* Shifts larger than MAX produce zero. */
4819 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4820 tcg_gen_neg_i64(t1, t1);
4821 tcg_gen_and_i64(t0, t0, t1);
4822 break;
4824 case OPC_ADD_CP2:
4825 case OPC_DADD_CP2:
4827 TCGv_i64 t2 = tcg_temp_new_i64();
4828 TCGLabel *lab = gen_new_label();
4830 tcg_gen_mov_i64(t2, t0);
4831 tcg_gen_add_i64(t0, t1, t2);
4832 if (opc == OPC_ADD_CP2) {
4833 tcg_gen_ext32s_i64(t0, t0);
4835 tcg_gen_xor_i64(t1, t1, t2);
4836 tcg_gen_xor_i64(t2, t2, t0);
4837 tcg_gen_andc_i64(t1, t2, t1);
4838 tcg_temp_free_i64(t2);
4839 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4840 generate_exception(ctx, EXCP_OVERFLOW);
4841 gen_set_label(lab);
4842 break;
4845 case OPC_SUB_CP2:
4846 case OPC_DSUB_CP2:
4848 TCGv_i64 t2 = tcg_temp_new_i64();
4849 TCGLabel *lab = gen_new_label();
4851 tcg_gen_mov_i64(t2, t0);
4852 tcg_gen_sub_i64(t0, t1, t2);
4853 if (opc == OPC_SUB_CP2) {
4854 tcg_gen_ext32s_i64(t0, t0);
4856 tcg_gen_xor_i64(t1, t1, t2);
4857 tcg_gen_xor_i64(t2, t2, t0);
4858 tcg_gen_and_i64(t1, t1, t2);
4859 tcg_temp_free_i64(t2);
4860 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4861 generate_exception(ctx, EXCP_OVERFLOW);
4862 gen_set_label(lab);
4863 break;
4866 case OPC_PMULUW:
4867 tcg_gen_ext32u_i64(t0, t0);
4868 tcg_gen_ext32u_i64(t1, t1);
4869 tcg_gen_mul_i64(t0, t0, t1);
4870 break;
4872 case OPC_SEQU_CP2:
4873 case OPC_SEQ_CP2:
4874 case OPC_SLTU_CP2:
4875 case OPC_SLT_CP2:
4876 case OPC_SLEU_CP2:
4877 case OPC_SLE_CP2:
4878 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4879 FD field is the CC field? */
4880 default:
4881 MIPS_INVAL("loongson_cp2");
4882 generate_exception_end(ctx, EXCP_RI);
4883 return;
4886 #undef LMI_HELPER
4887 #undef LMI_DIRECT
4889 gen_store_fpr64(ctx, t0, rd);
4891 tcg_temp_free_i64(t0);
4892 tcg_temp_free_i64(t1);
4895 /* Traps */
4896 static void gen_trap (DisasContext *ctx, uint32_t opc,
4897 int rs, int rt, int16_t imm)
4899 int cond;
4900 TCGv t0 = tcg_temp_new();
4901 TCGv t1 = tcg_temp_new();
4903 cond = 0;
4904 /* Load needed operands */
4905 switch (opc) {
4906 case OPC_TEQ:
4907 case OPC_TGE:
4908 case OPC_TGEU:
4909 case OPC_TLT:
4910 case OPC_TLTU:
4911 case OPC_TNE:
4912 /* Compare two registers */
4913 if (rs != rt) {
4914 gen_load_gpr(t0, rs);
4915 gen_load_gpr(t1, rt);
4916 cond = 1;
4918 break;
4919 case OPC_TEQI:
4920 case OPC_TGEI:
4921 case OPC_TGEIU:
4922 case OPC_TLTI:
4923 case OPC_TLTIU:
4924 case OPC_TNEI:
4925 /* Compare register to immediate */
4926 if (rs != 0 || imm != 0) {
4927 gen_load_gpr(t0, rs);
4928 tcg_gen_movi_tl(t1, (int32_t)imm);
4929 cond = 1;
4931 break;
4933 if (cond == 0) {
4934 switch (opc) {
4935 case OPC_TEQ: /* rs == rs */
4936 case OPC_TEQI: /* r0 == 0 */
4937 case OPC_TGE: /* rs >= rs */
4938 case OPC_TGEI: /* r0 >= 0 */
4939 case OPC_TGEU: /* rs >= rs unsigned */
4940 case OPC_TGEIU: /* r0 >= 0 unsigned */
4941 /* Always trap */
4942 generate_exception_end(ctx, EXCP_TRAP);
4943 break;
4944 case OPC_TLT: /* rs < rs */
4945 case OPC_TLTI: /* r0 < 0 */
4946 case OPC_TLTU: /* rs < rs unsigned */
4947 case OPC_TLTIU: /* r0 < 0 unsigned */
4948 case OPC_TNE: /* rs != rs */
4949 case OPC_TNEI: /* r0 != 0 */
4950 /* Never trap: treat as NOP. */
4951 break;
4953 } else {
4954 TCGLabel *l1 = gen_new_label();
4956 switch (opc) {
4957 case OPC_TEQ:
4958 case OPC_TEQI:
4959 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4960 break;
4961 case OPC_TGE:
4962 case OPC_TGEI:
4963 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4964 break;
4965 case OPC_TGEU:
4966 case OPC_TGEIU:
4967 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4968 break;
4969 case OPC_TLT:
4970 case OPC_TLTI:
4971 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4972 break;
4973 case OPC_TLTU:
4974 case OPC_TLTIU:
4975 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4976 break;
4977 case OPC_TNE:
4978 case OPC_TNEI:
4979 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4980 break;
4982 generate_exception(ctx, EXCP_TRAP);
4983 gen_set_label(l1);
4985 tcg_temp_free(t0);
4986 tcg_temp_free(t1);
4989 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4991 if (unlikely(ctx->base.singlestep_enabled)) {
4992 return false;
4995 #ifndef CONFIG_USER_ONLY
4996 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4997 #else
4998 return true;
4999 #endif
5002 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5004 if (use_goto_tb(ctx, dest)) {
5005 tcg_gen_goto_tb(n);
5006 gen_save_pc(dest);
5007 tcg_gen_exit_tb(ctx->base.tb, n);
5008 } else {
5009 gen_save_pc(dest);
5010 if (ctx->base.singlestep_enabled) {
5011 save_cpu_state(ctx, 0);
5012 gen_helper_raise_exception_debug(cpu_env);
5014 tcg_gen_lookup_and_goto_ptr();
5018 /* Branches (before delay slot) */
5019 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5020 int insn_bytes,
5021 int rs, int rt, int32_t offset,
5022 int delayslot_size)
5024 target_ulong btgt = -1;
5025 int blink = 0;
5026 int bcond_compute = 0;
5027 TCGv t0 = tcg_temp_new();
5028 TCGv t1 = tcg_temp_new();
5030 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5031 #ifdef MIPS_DEBUG_DISAS
5032 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5033 TARGET_FMT_lx "\n", ctx->base.pc_next);
5034 #endif
5035 generate_exception_end(ctx, EXCP_RI);
5036 goto out;
5039 /* Load needed operands */
5040 switch (opc) {
5041 case OPC_BEQ:
5042 case OPC_BEQL:
5043 case OPC_BNE:
5044 case OPC_BNEL:
5045 /* Compare two registers */
5046 if (rs != rt) {
5047 gen_load_gpr(t0, rs);
5048 gen_load_gpr(t1, rt);
5049 bcond_compute = 1;
5051 btgt = ctx->base.pc_next + insn_bytes + offset;
5052 break;
5053 case OPC_BGEZ:
5054 case OPC_BGEZAL:
5055 case OPC_BGEZALL:
5056 case OPC_BGEZL:
5057 case OPC_BGTZ:
5058 case OPC_BGTZL:
5059 case OPC_BLEZ:
5060 case OPC_BLEZL:
5061 case OPC_BLTZ:
5062 case OPC_BLTZAL:
5063 case OPC_BLTZALL:
5064 case OPC_BLTZL:
5065 /* Compare to zero */
5066 if (rs != 0) {
5067 gen_load_gpr(t0, rs);
5068 bcond_compute = 1;
5070 btgt = ctx->base.pc_next + insn_bytes + offset;
5071 break;
5072 case OPC_BPOSGE32:
5073 #if defined(TARGET_MIPS64)
5074 case OPC_BPOSGE64:
5075 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5076 #else
5077 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5078 #endif
5079 bcond_compute = 1;
5080 btgt = ctx->base.pc_next + insn_bytes + offset;
5081 break;
5082 case OPC_J:
5083 case OPC_JAL:
5084 case OPC_JALX:
5085 /* Jump to immediate */
5086 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5087 (uint32_t)offset;
5088 break;
5089 case OPC_JR:
5090 case OPC_JALR:
5091 /* Jump to register */
5092 if (offset != 0 && offset != 16) {
5093 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5094 others are reserved. */
5095 MIPS_INVAL("jump hint");
5096 generate_exception_end(ctx, EXCP_RI);
5097 goto out;
5099 gen_load_gpr(btarget, rs);
5100 break;
5101 default:
5102 MIPS_INVAL("branch/jump");
5103 generate_exception_end(ctx, EXCP_RI);
5104 goto out;
5106 if (bcond_compute == 0) {
5107 /* No condition to be computed */
5108 switch (opc) {
5109 case OPC_BEQ: /* rx == rx */
5110 case OPC_BEQL: /* rx == rx likely */
5111 case OPC_BGEZ: /* 0 >= 0 */
5112 case OPC_BGEZL: /* 0 >= 0 likely */
5113 case OPC_BLEZ: /* 0 <= 0 */
5114 case OPC_BLEZL: /* 0 <= 0 likely */
5115 /* Always take */
5116 ctx->hflags |= MIPS_HFLAG_B;
5117 break;
5118 case OPC_BGEZAL: /* 0 >= 0 */
5119 case OPC_BGEZALL: /* 0 >= 0 likely */
5120 /* Always take and link */
5121 blink = 31;
5122 ctx->hflags |= MIPS_HFLAG_B;
5123 break;
5124 case OPC_BNE: /* rx != rx */
5125 case OPC_BGTZ: /* 0 > 0 */
5126 case OPC_BLTZ: /* 0 < 0 */
5127 /* Treat as NOP. */
5128 goto out;
5129 case OPC_BLTZAL: /* 0 < 0 */
5130 /* Handle as an unconditional branch to get correct delay
5131 slot checking. */
5132 blink = 31;
5133 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5134 ctx->hflags |= MIPS_HFLAG_B;
5135 break;
5136 case OPC_BLTZALL: /* 0 < 0 likely */
5137 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5138 /* Skip the instruction in the delay slot */
5139 ctx->base.pc_next += 4;
5140 goto out;
5141 case OPC_BNEL: /* rx != rx likely */
5142 case OPC_BGTZL: /* 0 > 0 likely */
5143 case OPC_BLTZL: /* 0 < 0 likely */
5144 /* Skip the instruction in the delay slot */
5145 ctx->base.pc_next += 4;
5146 goto out;
5147 case OPC_J:
5148 ctx->hflags |= MIPS_HFLAG_B;
5149 break;
5150 case OPC_JALX:
5151 ctx->hflags |= MIPS_HFLAG_BX;
5152 /* Fallthrough */
5153 case OPC_JAL:
5154 blink = 31;
5155 ctx->hflags |= MIPS_HFLAG_B;
5156 break;
5157 case OPC_JR:
5158 ctx->hflags |= MIPS_HFLAG_BR;
5159 break;
5160 case OPC_JALR:
5161 blink = rt;
5162 ctx->hflags |= MIPS_HFLAG_BR;
5163 break;
5164 default:
5165 MIPS_INVAL("branch/jump");
5166 generate_exception_end(ctx, EXCP_RI);
5167 goto out;
5169 } else {
5170 switch (opc) {
5171 case OPC_BEQ:
5172 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5173 goto not_likely;
5174 case OPC_BEQL:
5175 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5176 goto likely;
5177 case OPC_BNE:
5178 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5179 goto not_likely;
5180 case OPC_BNEL:
5181 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5182 goto likely;
5183 case OPC_BGEZ:
5184 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5185 goto not_likely;
5186 case OPC_BGEZL:
5187 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5188 goto likely;
5189 case OPC_BGEZAL:
5190 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5191 blink = 31;
5192 goto not_likely;
5193 case OPC_BGEZALL:
5194 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5195 blink = 31;
5196 goto likely;
5197 case OPC_BGTZ:
5198 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5199 goto not_likely;
5200 case OPC_BGTZL:
5201 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5202 goto likely;
5203 case OPC_BLEZ:
5204 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5205 goto not_likely;
5206 case OPC_BLEZL:
5207 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5208 goto likely;
5209 case OPC_BLTZ:
5210 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5211 goto not_likely;
5212 case OPC_BLTZL:
5213 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5214 goto likely;
5215 case OPC_BPOSGE32:
5216 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5217 goto not_likely;
5218 #if defined(TARGET_MIPS64)
5219 case OPC_BPOSGE64:
5220 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5221 goto not_likely;
5222 #endif
5223 case OPC_BLTZAL:
5224 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5225 blink = 31;
5226 not_likely:
5227 ctx->hflags |= MIPS_HFLAG_BC;
5228 break;
5229 case OPC_BLTZALL:
5230 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5231 blink = 31;
5232 likely:
5233 ctx->hflags |= MIPS_HFLAG_BL;
5234 break;
5235 default:
5236 MIPS_INVAL("conditional branch/jump");
5237 generate_exception_end(ctx, EXCP_RI);
5238 goto out;
5242 ctx->btarget = btgt;
5244 switch (delayslot_size) {
5245 case 2:
5246 ctx->hflags |= MIPS_HFLAG_BDS16;
5247 break;
5248 case 4:
5249 ctx->hflags |= MIPS_HFLAG_BDS32;
5250 break;
5253 if (blink > 0) {
5254 int post_delay = insn_bytes + delayslot_size;
5255 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5257 tcg_gen_movi_tl(cpu_gpr[blink],
5258 ctx->base.pc_next + post_delay + lowbit);
5261 out:
5262 if (insn_bytes == 2)
5263 ctx->hflags |= MIPS_HFLAG_B16;
5264 tcg_temp_free(t0);
5265 tcg_temp_free(t1);
5269 /* nanoMIPS Branches */
5270 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5271 int insn_bytes,
5272 int rs, int rt, int32_t offset)
5274 target_ulong btgt = -1;
5275 int bcond_compute = 0;
5276 TCGv t0 = tcg_temp_new();
5277 TCGv t1 = tcg_temp_new();
5279 /* Load needed operands */
5280 switch (opc) {
5281 case OPC_BEQ:
5282 case OPC_BNE:
5283 /* Compare two registers */
5284 if (rs != rt) {
5285 gen_load_gpr(t0, rs);
5286 gen_load_gpr(t1, rt);
5287 bcond_compute = 1;
5289 btgt = ctx->base.pc_next + insn_bytes + offset;
5290 break;
5291 case OPC_BGEZAL:
5292 /* Compare to zero */
5293 if (rs != 0) {
5294 gen_load_gpr(t0, rs);
5295 bcond_compute = 1;
5297 btgt = ctx->base.pc_next + insn_bytes + offset;
5298 break;
5299 case OPC_BPOSGE32:
5300 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5301 bcond_compute = 1;
5302 btgt = ctx->base.pc_next + insn_bytes + offset;
5303 break;
5304 case OPC_JR:
5305 case OPC_JALR:
5306 /* Jump to register */
5307 if (offset != 0 && offset != 16) {
5308 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5309 others are reserved. */
5310 MIPS_INVAL("jump hint");
5311 generate_exception_end(ctx, EXCP_RI);
5312 goto out;
5314 gen_load_gpr(btarget, rs);
5315 break;
5316 default:
5317 MIPS_INVAL("branch/jump");
5318 generate_exception_end(ctx, EXCP_RI);
5319 goto out;
5321 if (bcond_compute == 0) {
5322 /* No condition to be computed */
5323 switch (opc) {
5324 case OPC_BEQ: /* rx == rx */
5325 /* Always take */
5326 ctx->hflags |= MIPS_HFLAG_B;
5327 break;
5328 case OPC_BGEZAL: /* 0 >= 0 */
5329 /* Always take and link */
5330 tcg_gen_movi_tl(cpu_gpr[31],
5331 ctx->base.pc_next + insn_bytes);
5332 ctx->hflags |= MIPS_HFLAG_B;
5333 break;
5334 case OPC_BNE: /* rx != rx */
5335 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5336 /* Skip the instruction in the delay slot */
5337 ctx->base.pc_next += 4;
5338 goto out;
5339 case OPC_JR:
5340 ctx->hflags |= MIPS_HFLAG_BR;
5341 break;
5342 case OPC_JALR:
5343 if (rt > 0) {
5344 tcg_gen_movi_tl(cpu_gpr[rt],
5345 ctx->base.pc_next + insn_bytes);
5347 ctx->hflags |= MIPS_HFLAG_BR;
5348 break;
5349 default:
5350 MIPS_INVAL("branch/jump");
5351 generate_exception_end(ctx, EXCP_RI);
5352 goto out;
5354 } else {
5355 switch (opc) {
5356 case OPC_BEQ:
5357 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5358 goto not_likely;
5359 case OPC_BNE:
5360 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5361 goto not_likely;
5362 case OPC_BGEZAL:
5363 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5364 tcg_gen_movi_tl(cpu_gpr[31],
5365 ctx->base.pc_next + insn_bytes);
5366 goto not_likely;
5367 case OPC_BPOSGE32:
5368 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5369 not_likely:
5370 ctx->hflags |= MIPS_HFLAG_BC;
5371 break;
5372 default:
5373 MIPS_INVAL("conditional branch/jump");
5374 generate_exception_end(ctx, EXCP_RI);
5375 goto out;
5379 ctx->btarget = btgt;
5381 out:
5382 if (insn_bytes == 2) {
5383 ctx->hflags |= MIPS_HFLAG_B16;
5385 tcg_temp_free(t0);
5386 tcg_temp_free(t1);
5390 /* special3 bitfield operations */
5391 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5392 int rs, int lsb, int msb)
5394 TCGv t0 = tcg_temp_new();
5395 TCGv t1 = tcg_temp_new();
5397 gen_load_gpr(t1, rs);
5398 switch (opc) {
5399 case OPC_EXT:
5400 if (lsb + msb > 31) {
5401 goto fail;
5403 if (msb != 31) {
5404 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5405 } else {
5406 /* The two checks together imply that lsb == 0,
5407 so this is a simple sign-extension. */
5408 tcg_gen_ext32s_tl(t0, t1);
5410 break;
5411 #if defined(TARGET_MIPS64)
5412 case OPC_DEXTU:
5413 lsb += 32;
5414 goto do_dext;
5415 case OPC_DEXTM:
5416 msb += 32;
5417 goto do_dext;
5418 case OPC_DEXT:
5419 do_dext:
5420 if (lsb + msb > 63) {
5421 goto fail;
5423 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5424 break;
5425 #endif
5426 case OPC_INS:
5427 if (lsb > msb) {
5428 goto fail;
5430 gen_load_gpr(t0, rt);
5431 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5432 tcg_gen_ext32s_tl(t0, t0);
5433 break;
5434 #if defined(TARGET_MIPS64)
5435 case OPC_DINSU:
5436 lsb += 32;
5437 /* FALLTHRU */
5438 case OPC_DINSM:
5439 msb += 32;
5440 /* FALLTHRU */
5441 case OPC_DINS:
5442 if (lsb > msb) {
5443 goto fail;
5445 gen_load_gpr(t0, rt);
5446 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5447 break;
5448 #endif
5449 default:
5450 fail:
5451 MIPS_INVAL("bitops");
5452 generate_exception_end(ctx, EXCP_RI);
5453 tcg_temp_free(t0);
5454 tcg_temp_free(t1);
5455 return;
5457 gen_store_gpr(t0, rt);
5458 tcg_temp_free(t0);
5459 tcg_temp_free(t1);
5462 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
5464 TCGv t0;
5466 if (rd == 0) {
5467 /* If no destination, treat it as a NOP. */
5468 return;
5471 t0 = tcg_temp_new();
5472 gen_load_gpr(t0, rt);
5473 switch (op2) {
5474 case OPC_WSBH:
5476 TCGv t1 = tcg_temp_new();
5477 TCGv t2 = tcg_const_tl(0x00FF00FF);
5479 tcg_gen_shri_tl(t1, t0, 8);
5480 tcg_gen_and_tl(t1, t1, t2);
5481 tcg_gen_and_tl(t0, t0, t2);
5482 tcg_gen_shli_tl(t0, t0, 8);
5483 tcg_gen_or_tl(t0, t0, t1);
5484 tcg_temp_free(t2);
5485 tcg_temp_free(t1);
5486 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5488 break;
5489 case OPC_SEB:
5490 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5491 break;
5492 case OPC_SEH:
5493 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5494 break;
5495 #if defined(TARGET_MIPS64)
5496 case OPC_DSBH:
5498 TCGv t1 = tcg_temp_new();
5499 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5501 tcg_gen_shri_tl(t1, t0, 8);
5502 tcg_gen_and_tl(t1, t1, t2);
5503 tcg_gen_and_tl(t0, t0, t2);
5504 tcg_gen_shli_tl(t0, t0, 8);
5505 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5506 tcg_temp_free(t2);
5507 tcg_temp_free(t1);
5509 break;
5510 case OPC_DSHD:
5512 TCGv t1 = tcg_temp_new();
5513 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5515 tcg_gen_shri_tl(t1, t0, 16);
5516 tcg_gen_and_tl(t1, t1, t2);
5517 tcg_gen_and_tl(t0, t0, t2);
5518 tcg_gen_shli_tl(t0, t0, 16);
5519 tcg_gen_or_tl(t0, t0, t1);
5520 tcg_gen_shri_tl(t1, t0, 32);
5521 tcg_gen_shli_tl(t0, t0, 32);
5522 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5523 tcg_temp_free(t2);
5524 tcg_temp_free(t1);
5526 break;
5527 #endif
5528 default:
5529 MIPS_INVAL("bsfhl");
5530 generate_exception_end(ctx, EXCP_RI);
5531 tcg_temp_free(t0);
5532 return;
5534 tcg_temp_free(t0);
5537 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
5538 int imm2)
5540 TCGv t0;
5541 TCGv t1;
5542 if (rd == 0) {
5543 /* Treat as NOP. */
5544 return;
5546 t0 = tcg_temp_new();
5547 t1 = tcg_temp_new();
5548 gen_load_gpr(t0, rs);
5549 gen_load_gpr(t1, rt);
5550 tcg_gen_shli_tl(t0, t0, imm2 + 1);
5551 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
5552 if (opc == OPC_LSA) {
5553 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5556 tcg_temp_free(t1);
5557 tcg_temp_free(t0);
5559 return;
5562 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5563 int rt, int bits)
5565 TCGv t0;
5566 if (rd == 0) {
5567 /* Treat as NOP. */
5568 return;
5570 t0 = tcg_temp_new();
5571 if (bits == 0 || bits == wordsz) {
5572 if (bits == 0) {
5573 gen_load_gpr(t0, rt);
5574 } else {
5575 gen_load_gpr(t0, rs);
5577 switch (wordsz) {
5578 case 32:
5579 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5580 break;
5581 #if defined(TARGET_MIPS64)
5582 case 64:
5583 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5584 break;
5585 #endif
5587 } else {
5588 TCGv t1 = tcg_temp_new();
5589 gen_load_gpr(t0, rt);
5590 gen_load_gpr(t1, rs);
5591 switch (wordsz) {
5592 case 32:
5594 TCGv_i64 t2 = tcg_temp_new_i64();
5595 tcg_gen_concat_tl_i64(t2, t1, t0);
5596 tcg_gen_shri_i64(t2, t2, 32 - bits);
5597 gen_move_low32(cpu_gpr[rd], t2);
5598 tcg_temp_free_i64(t2);
5600 break;
5601 #if defined(TARGET_MIPS64)
5602 case 64:
5603 tcg_gen_shli_tl(t0, t0, bits);
5604 tcg_gen_shri_tl(t1, t1, 64 - bits);
5605 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5606 break;
5607 #endif
5609 tcg_temp_free(t1);
5612 tcg_temp_free(t0);
5615 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5616 int bp)
5618 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5621 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5622 int shift)
5624 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5627 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5629 TCGv t0;
5630 if (rd == 0) {
5631 /* Treat as NOP. */
5632 return;
5634 t0 = tcg_temp_new();
5635 gen_load_gpr(t0, rt);
5636 switch (opc) {
5637 case OPC_BITSWAP:
5638 gen_helper_bitswap(cpu_gpr[rd], t0);
5639 break;
5640 #if defined(TARGET_MIPS64)
5641 case OPC_DBITSWAP:
5642 gen_helper_dbitswap(cpu_gpr[rd], t0);
5643 break;
5644 #endif
5646 tcg_temp_free(t0);
5649 #ifndef CONFIG_USER_ONLY
5650 /* CP0 (MMU and control) */
5651 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5653 TCGv_i64 t0 = tcg_temp_new_i64();
5654 TCGv_i64 t1 = tcg_temp_new_i64();
5656 tcg_gen_ext_tl_i64(t0, arg);
5657 tcg_gen_ld_i64(t1, cpu_env, off);
5658 #if defined(TARGET_MIPS64)
5659 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5660 #else
5661 tcg_gen_concat32_i64(t1, t1, t0);
5662 #endif
5663 tcg_gen_st_i64(t1, cpu_env, off);
5664 tcg_temp_free_i64(t1);
5665 tcg_temp_free_i64(t0);
5668 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5670 TCGv_i64 t0 = tcg_temp_new_i64();
5671 TCGv_i64 t1 = tcg_temp_new_i64();
5673 tcg_gen_ext_tl_i64(t0, arg);
5674 tcg_gen_ld_i64(t1, cpu_env, off);
5675 tcg_gen_concat32_i64(t1, t1, t0);
5676 tcg_gen_st_i64(t1, cpu_env, off);
5677 tcg_temp_free_i64(t1);
5678 tcg_temp_free_i64(t0);
5681 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5683 TCGv_i64 t0 = tcg_temp_new_i64();
5685 tcg_gen_ld_i64(t0, cpu_env, off);
5686 #if defined(TARGET_MIPS64)
5687 tcg_gen_shri_i64(t0, t0, 30);
5688 #else
5689 tcg_gen_shri_i64(t0, t0, 32);
5690 #endif
5691 gen_move_low32(arg, t0);
5692 tcg_temp_free_i64(t0);
5695 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5697 TCGv_i64 t0 = tcg_temp_new_i64();
5699 tcg_gen_ld_i64(t0, cpu_env, off);
5700 tcg_gen_shri_i64(t0, t0, 32 + shift);
5701 gen_move_low32(arg, t0);
5702 tcg_temp_free_i64(t0);
5705 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5707 TCGv_i32 t0 = tcg_temp_new_i32();
5709 tcg_gen_ld_i32(t0, cpu_env, off);
5710 tcg_gen_ext_i32_tl(arg, t0);
5711 tcg_temp_free_i32(t0);
5714 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5716 tcg_gen_ld_tl(arg, cpu_env, off);
5717 tcg_gen_ext32s_tl(arg, arg);
5720 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5722 TCGv_i32 t0 = tcg_temp_new_i32();
5724 tcg_gen_trunc_tl_i32(t0, arg);
5725 tcg_gen_st_i32(t0, cpu_env, off);
5726 tcg_temp_free_i32(t0);
5729 #define CP0_CHECK(c) \
5730 do { \
5731 if (!(c)) { \
5732 goto cp0_unimplemented; \
5734 } while (0)
5736 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5738 const char *rn = "invalid";
5740 switch (reg) {
5741 case 2:
5742 switch (sel) {
5743 case 0:
5744 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5745 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5746 rn = "EntryLo0";
5747 break;
5748 default:
5749 goto cp0_unimplemented;
5751 break;
5752 case 3:
5753 switch (sel) {
5754 case 0:
5755 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5756 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5757 rn = "EntryLo1";
5758 break;
5759 default:
5760 goto cp0_unimplemented;
5762 break;
5763 case 17:
5764 switch (sel) {
5765 case 0:
5766 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
5767 ctx->CP0_LLAddr_shift);
5768 rn = "LLAddr";
5769 break;
5770 case 1:
5771 CP0_CHECK(ctx->mrp);
5772 gen_helper_mfhc0_maar(arg, cpu_env);
5773 rn = "MAAR";
5774 break;
5775 default:
5776 goto cp0_unimplemented;
5778 break;
5779 case 28:
5780 switch (sel) {
5781 case 0:
5782 case 2:
5783 case 4:
5784 case 6:
5785 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5786 rn = "TagLo";
5787 break;
5788 default:
5789 goto cp0_unimplemented;
5791 break;
5792 default:
5793 goto cp0_unimplemented;
5795 trace_mips_translate_c0("mfhc0", rn, reg, sel);
5796 return;
5798 cp0_unimplemented:
5799 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
5800 tcg_gen_movi_tl(arg, 0);
5803 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5805 const char *rn = "invalid";
5806 uint64_t mask = ctx->PAMask >> 36;
5808 switch (reg) {
5809 case 2:
5810 switch (sel) {
5811 case 0:
5812 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5813 tcg_gen_andi_tl(arg, arg, mask);
5814 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5815 rn = "EntryLo0";
5816 break;
5817 default:
5818 goto cp0_unimplemented;
5820 break;
5821 case 3:
5822 switch (sel) {
5823 case 0:
5824 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5825 tcg_gen_andi_tl(arg, arg, mask);
5826 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5827 rn = "EntryLo1";
5828 break;
5829 default:
5830 goto cp0_unimplemented;
5832 break;
5833 case 17:
5834 switch (sel) {
5835 case 0:
5836 /* LLAddr is read-only (the only exception is bit 0 if LLB is
5837 supported); the CP0_LLAddr_rw_bitmask does not seem to be
5838 relevant for modern MIPS cores supporting MTHC0, therefore
5839 treating MTHC0 to LLAddr as NOP. */
5840 rn = "LLAddr";
5841 break;
5842 case 1:
5843 CP0_CHECK(ctx->mrp);
5844 gen_helper_mthc0_maar(cpu_env, arg);
5845 rn = "MAAR";
5846 break;
5847 default:
5848 goto cp0_unimplemented;
5850 break;
5851 case 28:
5852 switch (sel) {
5853 case 0:
5854 case 2:
5855 case 4:
5856 case 6:
5857 tcg_gen_andi_tl(arg, arg, mask);
5858 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5859 rn = "TagLo";
5860 break;
5861 default:
5862 goto cp0_unimplemented;
5864 break;
5865 default:
5866 goto cp0_unimplemented;
5868 trace_mips_translate_c0("mthc0", rn, reg, sel);
5870 cp0_unimplemented:
5871 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5874 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5876 if (ctx->insn_flags & ISA_MIPS32R6) {
5877 tcg_gen_movi_tl(arg, 0);
5878 } else {
5879 tcg_gen_movi_tl(arg, ~0);
5883 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5885 const char *rn = "invalid";
5887 if (sel != 0)
5888 check_insn(ctx, ISA_MIPS32);
5890 switch (reg) {
5891 case 0:
5892 switch (sel) {
5893 case 0:
5894 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5895 rn = "Index";
5896 break;
5897 case 1:
5898 CP0_CHECK(ctx->insn_flags & ASE_MT);
5899 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5900 rn = "MVPControl";
5901 break;
5902 case 2:
5903 CP0_CHECK(ctx->insn_flags & ASE_MT);
5904 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5905 rn = "MVPConf0";
5906 break;
5907 case 3:
5908 CP0_CHECK(ctx->insn_flags & ASE_MT);
5909 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5910 rn = "MVPConf1";
5911 break;
5912 case 4:
5913 CP0_CHECK(ctx->vp);
5914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5915 rn = "VPControl";
5916 break;
5917 default:
5918 goto cp0_unimplemented;
5920 break;
5921 case 1:
5922 switch (sel) {
5923 case 0:
5924 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5925 gen_helper_mfc0_random(arg, cpu_env);
5926 rn = "Random";
5927 break;
5928 case 1:
5929 CP0_CHECK(ctx->insn_flags & ASE_MT);
5930 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5931 rn = "VPEControl";
5932 break;
5933 case 2:
5934 CP0_CHECK(ctx->insn_flags & ASE_MT);
5935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5936 rn = "VPEConf0";
5937 break;
5938 case 3:
5939 CP0_CHECK(ctx->insn_flags & ASE_MT);
5940 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5941 rn = "VPEConf1";
5942 break;
5943 case 4:
5944 CP0_CHECK(ctx->insn_flags & ASE_MT);
5945 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5946 rn = "YQMask";
5947 break;
5948 case 5:
5949 CP0_CHECK(ctx->insn_flags & ASE_MT);
5950 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5951 rn = "VPESchedule";
5952 break;
5953 case 6:
5954 CP0_CHECK(ctx->insn_flags & ASE_MT);
5955 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5956 rn = "VPEScheFBack";
5957 break;
5958 case 7:
5959 CP0_CHECK(ctx->insn_flags & ASE_MT);
5960 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5961 rn = "VPEOpt";
5962 break;
5963 default:
5964 goto cp0_unimplemented;
5966 break;
5967 case 2:
5968 switch (sel) {
5969 case 0:
5971 TCGv_i64 tmp = tcg_temp_new_i64();
5972 tcg_gen_ld_i64(tmp, cpu_env,
5973 offsetof(CPUMIPSState, CP0_EntryLo0));
5974 #if defined(TARGET_MIPS64)
5975 if (ctx->rxi) {
5976 /* Move RI/XI fields to bits 31:30 */
5977 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5978 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5980 #endif
5981 gen_move_low32(arg, tmp);
5982 tcg_temp_free_i64(tmp);
5984 rn = "EntryLo0";
5985 break;
5986 case 1:
5987 CP0_CHECK(ctx->insn_flags & ASE_MT);
5988 gen_helper_mfc0_tcstatus(arg, cpu_env);
5989 rn = "TCStatus";
5990 break;
5991 case 2:
5992 CP0_CHECK(ctx->insn_flags & ASE_MT);
5993 gen_helper_mfc0_tcbind(arg, cpu_env);
5994 rn = "TCBind";
5995 break;
5996 case 3:
5997 CP0_CHECK(ctx->insn_flags & ASE_MT);
5998 gen_helper_mfc0_tcrestart(arg, cpu_env);
5999 rn = "TCRestart";
6000 break;
6001 case 4:
6002 CP0_CHECK(ctx->insn_flags & ASE_MT);
6003 gen_helper_mfc0_tchalt(arg, cpu_env);
6004 rn = "TCHalt";
6005 break;
6006 case 5:
6007 CP0_CHECK(ctx->insn_flags & ASE_MT);
6008 gen_helper_mfc0_tccontext(arg, cpu_env);
6009 rn = "TCContext";
6010 break;
6011 case 6:
6012 CP0_CHECK(ctx->insn_flags & ASE_MT);
6013 gen_helper_mfc0_tcschedule(arg, cpu_env);
6014 rn = "TCSchedule";
6015 break;
6016 case 7:
6017 CP0_CHECK(ctx->insn_flags & ASE_MT);
6018 gen_helper_mfc0_tcschefback(arg, cpu_env);
6019 rn = "TCScheFBack";
6020 break;
6021 default:
6022 goto cp0_unimplemented;
6024 break;
6025 case 3:
6026 switch (sel) {
6027 case 0:
6029 TCGv_i64 tmp = tcg_temp_new_i64();
6030 tcg_gen_ld_i64(tmp, cpu_env,
6031 offsetof(CPUMIPSState, CP0_EntryLo1));
6032 #if defined(TARGET_MIPS64)
6033 if (ctx->rxi) {
6034 /* Move RI/XI fields to bits 31:30 */
6035 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6036 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6038 #endif
6039 gen_move_low32(arg, tmp);
6040 tcg_temp_free_i64(tmp);
6042 rn = "EntryLo1";
6043 break;
6044 case 1:
6045 CP0_CHECK(ctx->vp);
6046 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6047 rn = "GlobalNumber";
6048 break;
6049 default:
6050 goto cp0_unimplemented;
6052 break;
6053 case 4:
6054 switch (sel) {
6055 case 0:
6056 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6057 tcg_gen_ext32s_tl(arg, arg);
6058 rn = "Context";
6059 break;
6060 case 1:
6061 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6062 rn = "ContextConfig";
6063 goto cp0_unimplemented;
6064 case 2:
6065 CP0_CHECK(ctx->ulri);
6066 tcg_gen_ld_tl(arg, cpu_env,
6067 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6068 tcg_gen_ext32s_tl(arg, arg);
6069 rn = "UserLocal";
6070 break;
6071 default:
6072 goto cp0_unimplemented;
6074 break;
6075 case 5:
6076 switch (sel) {
6077 case 0:
6078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6079 rn = "PageMask";
6080 break;
6081 case 1:
6082 check_insn(ctx, ISA_MIPS32R2);
6083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6084 rn = "PageGrain";
6085 break;
6086 case 2:
6087 CP0_CHECK(ctx->sc);
6088 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6089 tcg_gen_ext32s_tl(arg, arg);
6090 rn = "SegCtl0";
6091 break;
6092 case 3:
6093 CP0_CHECK(ctx->sc);
6094 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6095 tcg_gen_ext32s_tl(arg, arg);
6096 rn = "SegCtl1";
6097 break;
6098 case 4:
6099 CP0_CHECK(ctx->sc);
6100 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6101 tcg_gen_ext32s_tl(arg, arg);
6102 rn = "SegCtl2";
6103 break;
6104 case 5:
6105 check_pw(ctx);
6106 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6107 rn = "PWBase";
6108 break;
6109 case 6:
6110 check_pw(ctx);
6111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6112 rn = "PWField";
6113 break;
6114 case 7:
6115 check_pw(ctx);
6116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6117 rn = "PWSize";
6118 break;
6119 default:
6120 goto cp0_unimplemented;
6122 break;
6123 case 6:
6124 switch (sel) {
6125 case 0:
6126 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6127 rn = "Wired";
6128 break;
6129 case 1:
6130 check_insn(ctx, ISA_MIPS32R2);
6131 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6132 rn = "SRSConf0";
6133 break;
6134 case 2:
6135 check_insn(ctx, ISA_MIPS32R2);
6136 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6137 rn = "SRSConf1";
6138 break;
6139 case 3:
6140 check_insn(ctx, ISA_MIPS32R2);
6141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6142 rn = "SRSConf2";
6143 break;
6144 case 4:
6145 check_insn(ctx, ISA_MIPS32R2);
6146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6147 rn = "SRSConf3";
6148 break;
6149 case 5:
6150 check_insn(ctx, ISA_MIPS32R2);
6151 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6152 rn = "SRSConf4";
6153 break;
6154 case 6:
6155 check_pw(ctx);
6156 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6157 rn = "PWCtl";
6158 break;
6159 default:
6160 goto cp0_unimplemented;
6162 break;
6163 case 7:
6164 switch (sel) {
6165 case 0:
6166 check_insn(ctx, ISA_MIPS32R2);
6167 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6168 rn = "HWREna";
6169 break;
6170 default:
6171 goto cp0_unimplemented;
6173 break;
6174 case 8:
6175 switch (sel) {
6176 case 0:
6177 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6178 tcg_gen_ext32s_tl(arg, arg);
6179 rn = "BadVAddr";
6180 break;
6181 case 1:
6182 CP0_CHECK(ctx->bi);
6183 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6184 rn = "BadInstr";
6185 break;
6186 case 2:
6187 CP0_CHECK(ctx->bp);
6188 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6189 rn = "BadInstrP";
6190 break;
6191 case 3:
6192 CP0_CHECK(ctx->bi);
6193 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6194 tcg_gen_andi_tl(arg, arg, ~0xffff);
6195 rn = "BadInstrX";
6196 break;
6197 default:
6198 goto cp0_unimplemented;
6200 break;
6201 case 9:
6202 switch (sel) {
6203 case 0:
6204 /* Mark as an IO operation because we read the time. */
6205 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6206 gen_io_start();
6208 gen_helper_mfc0_count(arg, cpu_env);
6209 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6210 gen_io_end();
6212 /* Break the TB to be able to take timer interrupts immediately
6213 after reading count. DISAS_STOP isn't sufficient, we need to
6214 ensure we break completely out of translated code. */
6215 gen_save_pc(ctx->base.pc_next + 4);
6216 ctx->base.is_jmp = DISAS_EXIT;
6217 rn = "Count";
6218 break;
6219 /* 6,7 are implementation dependent */
6220 default:
6221 goto cp0_unimplemented;
6223 break;
6224 case 10:
6225 switch (sel) {
6226 case 0:
6227 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6228 tcg_gen_ext32s_tl(arg, arg);
6229 rn = "EntryHi";
6230 break;
6231 default:
6232 goto cp0_unimplemented;
6234 break;
6235 case 11:
6236 switch (sel) {
6237 case 0:
6238 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6239 rn = "Compare";
6240 break;
6241 /* 6,7 are implementation dependent */
6242 default:
6243 goto cp0_unimplemented;
6245 break;
6246 case 12:
6247 switch (sel) {
6248 case 0:
6249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6250 rn = "Status";
6251 break;
6252 case 1:
6253 check_insn(ctx, ISA_MIPS32R2);
6254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6255 rn = "IntCtl";
6256 break;
6257 case 2:
6258 check_insn(ctx, ISA_MIPS32R2);
6259 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6260 rn = "SRSCtl";
6261 break;
6262 case 3:
6263 check_insn(ctx, ISA_MIPS32R2);
6264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6265 rn = "SRSMap";
6266 break;
6267 default:
6268 goto cp0_unimplemented;
6270 break;
6271 case 13:
6272 switch (sel) {
6273 case 0:
6274 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6275 rn = "Cause";
6276 break;
6277 default:
6278 goto cp0_unimplemented;
6280 break;
6281 case 14:
6282 switch (sel) {
6283 case 0:
6284 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6285 tcg_gen_ext32s_tl(arg, arg);
6286 rn = "EPC";
6287 break;
6288 default:
6289 goto cp0_unimplemented;
6291 break;
6292 case 15:
6293 switch (sel) {
6294 case 0:
6295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6296 rn = "PRid";
6297 break;
6298 case 1:
6299 check_insn(ctx, ISA_MIPS32R2);
6300 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6301 tcg_gen_ext32s_tl(arg, arg);
6302 rn = "EBase";
6303 break;
6304 case 3:
6305 check_insn(ctx, ISA_MIPS32R2);
6306 CP0_CHECK(ctx->cmgcr);
6307 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6308 tcg_gen_ext32s_tl(arg, arg);
6309 rn = "CMGCRBase";
6310 break;
6311 default:
6312 goto cp0_unimplemented;
6314 break;
6315 case 16:
6316 switch (sel) {
6317 case 0:
6318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6319 rn = "Config";
6320 break;
6321 case 1:
6322 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6323 rn = "Config1";
6324 break;
6325 case 2:
6326 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6327 rn = "Config2";
6328 break;
6329 case 3:
6330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6331 rn = "Config3";
6332 break;
6333 case 4:
6334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6335 rn = "Config4";
6336 break;
6337 case 5:
6338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6339 rn = "Config5";
6340 break;
6341 /* 6,7 are implementation dependent */
6342 case 6:
6343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6344 rn = "Config6";
6345 break;
6346 case 7:
6347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6348 rn = "Config7";
6349 break;
6350 default:
6351 goto cp0_unimplemented;
6353 break;
6354 case 17:
6355 switch (sel) {
6356 case 0:
6357 gen_helper_mfc0_lladdr(arg, cpu_env);
6358 rn = "LLAddr";
6359 break;
6360 case 1:
6361 CP0_CHECK(ctx->mrp);
6362 gen_helper_mfc0_maar(arg, cpu_env);
6363 rn = "MAAR";
6364 break;
6365 case 2:
6366 CP0_CHECK(ctx->mrp);
6367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6368 rn = "MAARI";
6369 break;
6370 default:
6371 goto cp0_unimplemented;
6373 break;
6374 case 18:
6375 switch (sel) {
6376 case 0:
6377 case 1:
6378 case 2:
6379 case 3:
6380 case 4:
6381 case 5:
6382 case 6:
6383 case 7:
6384 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6385 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6386 rn = "WatchLo";
6387 break;
6388 default:
6389 goto cp0_unimplemented;
6391 break;
6392 case 19:
6393 switch (sel) {
6394 case 0:
6395 case 1:
6396 case 2:
6397 case 3:
6398 case 4:
6399 case 5:
6400 case 6:
6401 case 7:
6402 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6403 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6404 rn = "WatchHi";
6405 break;
6406 default:
6407 goto cp0_unimplemented;
6409 break;
6410 case 20:
6411 switch (sel) {
6412 case 0:
6413 #if defined(TARGET_MIPS64)
6414 check_insn(ctx, ISA_MIPS3);
6415 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6416 tcg_gen_ext32s_tl(arg, arg);
6417 rn = "XContext";
6418 break;
6419 #endif
6420 default:
6421 goto cp0_unimplemented;
6423 break;
6424 case 21:
6425 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6426 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6427 switch (sel) {
6428 case 0:
6429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6430 rn = "Framemask";
6431 break;
6432 default:
6433 goto cp0_unimplemented;
6435 break;
6436 case 22:
6437 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6438 rn = "'Diagnostic"; /* implementation dependent */
6439 break;
6440 case 23:
6441 switch (sel) {
6442 case 0:
6443 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6444 rn = "Debug";
6445 break;
6446 case 1:
6447 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
6448 rn = "TraceControl";
6449 goto cp0_unimplemented;
6450 case 2:
6451 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
6452 rn = "TraceControl2";
6453 goto cp0_unimplemented;
6454 case 3:
6455 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
6456 rn = "UserTraceData";
6457 goto cp0_unimplemented;
6458 case 4:
6459 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
6460 rn = "TraceBPC";
6461 goto cp0_unimplemented;
6462 default:
6463 goto cp0_unimplemented;
6465 break;
6466 case 24:
6467 switch (sel) {
6468 case 0:
6469 /* EJTAG support */
6470 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6471 tcg_gen_ext32s_tl(arg, arg);
6472 rn = "DEPC";
6473 break;
6474 default:
6475 goto cp0_unimplemented;
6477 break;
6478 case 25:
6479 switch (sel) {
6480 case 0:
6481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6482 rn = "Performance0";
6483 break;
6484 case 1:
6485 // gen_helper_mfc0_performance1(arg);
6486 rn = "Performance1";
6487 goto cp0_unimplemented;
6488 case 2:
6489 // gen_helper_mfc0_performance2(arg);
6490 rn = "Performance2";
6491 goto cp0_unimplemented;
6492 case 3:
6493 // gen_helper_mfc0_performance3(arg);
6494 rn = "Performance3";
6495 goto cp0_unimplemented;
6496 case 4:
6497 // gen_helper_mfc0_performance4(arg);
6498 rn = "Performance4";
6499 goto cp0_unimplemented;
6500 case 5:
6501 // gen_helper_mfc0_performance5(arg);
6502 rn = "Performance5";
6503 goto cp0_unimplemented;
6504 case 6:
6505 // gen_helper_mfc0_performance6(arg);
6506 rn = "Performance6";
6507 goto cp0_unimplemented;
6508 case 7:
6509 // gen_helper_mfc0_performance7(arg);
6510 rn = "Performance7";
6511 goto cp0_unimplemented;
6512 default:
6513 goto cp0_unimplemented;
6515 break;
6516 case 26:
6517 switch (sel) {
6518 case 0:
6519 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6520 rn = "ErrCtl";
6521 break;
6522 default:
6523 goto cp0_unimplemented;
6525 break;
6526 case 27:
6527 switch (sel) {
6528 case 0:
6529 case 1:
6530 case 2:
6531 case 3:
6532 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6533 rn = "CacheErr";
6534 break;
6535 default:
6536 goto cp0_unimplemented;
6538 break;
6539 case 28:
6540 switch (sel) {
6541 case 0:
6542 case 2:
6543 case 4:
6544 case 6:
6546 TCGv_i64 tmp = tcg_temp_new_i64();
6547 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6548 gen_move_low32(arg, tmp);
6549 tcg_temp_free_i64(tmp);
6551 rn = "TagLo";
6552 break;
6553 case 1:
6554 case 3:
6555 case 5:
6556 case 7:
6557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6558 rn = "DataLo";
6559 break;
6560 default:
6561 goto cp0_unimplemented;
6563 break;
6564 case 29:
6565 switch (sel) {
6566 case 0:
6567 case 2:
6568 case 4:
6569 case 6:
6570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6571 rn = "TagHi";
6572 break;
6573 case 1:
6574 case 3:
6575 case 5:
6576 case 7:
6577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6578 rn = "DataHi";
6579 break;
6580 default:
6581 goto cp0_unimplemented;
6583 break;
6584 case 30:
6585 switch (sel) {
6586 case 0:
6587 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6588 tcg_gen_ext32s_tl(arg, arg);
6589 rn = "ErrorEPC";
6590 break;
6591 default:
6592 goto cp0_unimplemented;
6594 break;
6595 case 31:
6596 switch (sel) {
6597 case 0:
6598 /* EJTAG support */
6599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6600 rn = "DESAVE";
6601 break;
6602 case 2:
6603 case 3:
6604 case 4:
6605 case 5:
6606 case 6:
6607 case 7:
6608 CP0_CHECK(ctx->kscrexist & (1 << sel));
6609 tcg_gen_ld_tl(arg, cpu_env,
6610 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6611 tcg_gen_ext32s_tl(arg, arg);
6612 rn = "KScratch";
6613 break;
6614 default:
6615 goto cp0_unimplemented;
6617 break;
6618 default:
6619 goto cp0_unimplemented;
6621 trace_mips_translate_c0("mfc0", rn, reg, sel);
6622 return;
6624 cp0_unimplemented:
6625 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6626 gen_mfc0_unimplemented(ctx, arg);
6629 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6631 const char *rn = "invalid";
6633 if (sel != 0)
6634 check_insn(ctx, ISA_MIPS32);
6636 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6637 gen_io_start();
6640 switch (reg) {
6641 case 0:
6642 switch (sel) {
6643 case 0:
6644 gen_helper_mtc0_index(cpu_env, arg);
6645 rn = "Index";
6646 break;
6647 case 1:
6648 CP0_CHECK(ctx->insn_flags & ASE_MT);
6649 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6650 rn = "MVPControl";
6651 break;
6652 case 2:
6653 CP0_CHECK(ctx->insn_flags & ASE_MT);
6654 /* ignored */
6655 rn = "MVPConf0";
6656 break;
6657 case 3:
6658 CP0_CHECK(ctx->insn_flags & ASE_MT);
6659 /* ignored */
6660 rn = "MVPConf1";
6661 break;
6662 case 4:
6663 CP0_CHECK(ctx->vp);
6664 /* ignored */
6665 rn = "VPControl";
6666 break;
6667 default:
6668 goto cp0_unimplemented;
6670 break;
6671 case 1:
6672 switch (sel) {
6673 case 0:
6674 /* ignored */
6675 rn = "Random";
6676 break;
6677 case 1:
6678 CP0_CHECK(ctx->insn_flags & ASE_MT);
6679 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6680 rn = "VPEControl";
6681 break;
6682 case 2:
6683 CP0_CHECK(ctx->insn_flags & ASE_MT);
6684 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6685 rn = "VPEConf0";
6686 break;
6687 case 3:
6688 CP0_CHECK(ctx->insn_flags & ASE_MT);
6689 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6690 rn = "VPEConf1";
6691 break;
6692 case 4:
6693 CP0_CHECK(ctx->insn_flags & ASE_MT);
6694 gen_helper_mtc0_yqmask(cpu_env, arg);
6695 rn = "YQMask";
6696 break;
6697 case 5:
6698 CP0_CHECK(ctx->insn_flags & ASE_MT);
6699 tcg_gen_st_tl(arg, cpu_env,
6700 offsetof(CPUMIPSState, CP0_VPESchedule));
6701 rn = "VPESchedule";
6702 break;
6703 case 6:
6704 CP0_CHECK(ctx->insn_flags & ASE_MT);
6705 tcg_gen_st_tl(arg, cpu_env,
6706 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6707 rn = "VPEScheFBack";
6708 break;
6709 case 7:
6710 CP0_CHECK(ctx->insn_flags & ASE_MT);
6711 gen_helper_mtc0_vpeopt(cpu_env, arg);
6712 rn = "VPEOpt";
6713 break;
6714 default:
6715 goto cp0_unimplemented;
6717 break;
6718 case 2:
6719 switch (sel) {
6720 case 0:
6721 gen_helper_mtc0_entrylo0(cpu_env, arg);
6722 rn = "EntryLo0";
6723 break;
6724 case 1:
6725 CP0_CHECK(ctx->insn_flags & ASE_MT);
6726 gen_helper_mtc0_tcstatus(cpu_env, arg);
6727 rn = "TCStatus";
6728 break;
6729 case 2:
6730 CP0_CHECK(ctx->insn_flags & ASE_MT);
6731 gen_helper_mtc0_tcbind(cpu_env, arg);
6732 rn = "TCBind";
6733 break;
6734 case 3:
6735 CP0_CHECK(ctx->insn_flags & ASE_MT);
6736 gen_helper_mtc0_tcrestart(cpu_env, arg);
6737 rn = "TCRestart";
6738 break;
6739 case 4:
6740 CP0_CHECK(ctx->insn_flags & ASE_MT);
6741 gen_helper_mtc0_tchalt(cpu_env, arg);
6742 rn = "TCHalt";
6743 break;
6744 case 5:
6745 CP0_CHECK(ctx->insn_flags & ASE_MT);
6746 gen_helper_mtc0_tccontext(cpu_env, arg);
6747 rn = "TCContext";
6748 break;
6749 case 6:
6750 CP0_CHECK(ctx->insn_flags & ASE_MT);
6751 gen_helper_mtc0_tcschedule(cpu_env, arg);
6752 rn = "TCSchedule";
6753 break;
6754 case 7:
6755 CP0_CHECK(ctx->insn_flags & ASE_MT);
6756 gen_helper_mtc0_tcschefback(cpu_env, arg);
6757 rn = "TCScheFBack";
6758 break;
6759 default:
6760 goto cp0_unimplemented;
6762 break;
6763 case 3:
6764 switch (sel) {
6765 case 0:
6766 gen_helper_mtc0_entrylo1(cpu_env, arg);
6767 rn = "EntryLo1";
6768 break;
6769 case 1:
6770 CP0_CHECK(ctx->vp);
6771 /* ignored */
6772 rn = "GlobalNumber";
6773 break;
6774 default:
6775 goto cp0_unimplemented;
6777 break;
6778 case 4:
6779 switch (sel) {
6780 case 0:
6781 gen_helper_mtc0_context(cpu_env, arg);
6782 rn = "Context";
6783 break;
6784 case 1:
6785 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6786 rn = "ContextConfig";
6787 goto cp0_unimplemented;
6788 case 2:
6789 CP0_CHECK(ctx->ulri);
6790 tcg_gen_st_tl(arg, cpu_env,
6791 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6792 rn = "UserLocal";
6793 break;
6794 default:
6795 goto cp0_unimplemented;
6797 break;
6798 case 5:
6799 switch (sel) {
6800 case 0:
6801 gen_helper_mtc0_pagemask(cpu_env, arg);
6802 rn = "PageMask";
6803 break;
6804 case 1:
6805 check_insn(ctx, ISA_MIPS32R2);
6806 gen_helper_mtc0_pagegrain(cpu_env, arg);
6807 rn = "PageGrain";
6808 ctx->base.is_jmp = DISAS_STOP;
6809 break;
6810 case 2:
6811 CP0_CHECK(ctx->sc);
6812 gen_helper_mtc0_segctl0(cpu_env, arg);
6813 rn = "SegCtl0";
6814 break;
6815 case 3:
6816 CP0_CHECK(ctx->sc);
6817 gen_helper_mtc0_segctl1(cpu_env, arg);
6818 rn = "SegCtl1";
6819 break;
6820 case 4:
6821 CP0_CHECK(ctx->sc);
6822 gen_helper_mtc0_segctl2(cpu_env, arg);
6823 rn = "SegCtl2";
6824 break;
6825 case 5:
6826 check_pw(ctx);
6827 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6828 rn = "PWBase";
6829 break;
6830 case 6:
6831 check_pw(ctx);
6832 gen_helper_mtc0_pwfield(cpu_env, arg);
6833 rn = "PWField";
6834 break;
6835 case 7:
6836 check_pw(ctx);
6837 gen_helper_mtc0_pwsize(cpu_env, arg);
6838 rn = "PWSize";
6839 break;
6840 default:
6841 goto cp0_unimplemented;
6843 break;
6844 case 6:
6845 switch (sel) {
6846 case 0:
6847 gen_helper_mtc0_wired(cpu_env, arg);
6848 rn = "Wired";
6849 break;
6850 case 1:
6851 check_insn(ctx, ISA_MIPS32R2);
6852 gen_helper_mtc0_srsconf0(cpu_env, arg);
6853 rn = "SRSConf0";
6854 break;
6855 case 2:
6856 check_insn(ctx, ISA_MIPS32R2);
6857 gen_helper_mtc0_srsconf1(cpu_env, arg);
6858 rn = "SRSConf1";
6859 break;
6860 case 3:
6861 check_insn(ctx, ISA_MIPS32R2);
6862 gen_helper_mtc0_srsconf2(cpu_env, arg);
6863 rn = "SRSConf2";
6864 break;
6865 case 4:
6866 check_insn(ctx, ISA_MIPS32R2);
6867 gen_helper_mtc0_srsconf3(cpu_env, arg);
6868 rn = "SRSConf3";
6869 break;
6870 case 5:
6871 check_insn(ctx, ISA_MIPS32R2);
6872 gen_helper_mtc0_srsconf4(cpu_env, arg);
6873 rn = "SRSConf4";
6874 break;
6875 case 6:
6876 check_pw(ctx);
6877 gen_helper_mtc0_pwctl(cpu_env, arg);
6878 rn = "PWCtl";
6879 break;
6880 default:
6881 goto cp0_unimplemented;
6883 break;
6884 case 7:
6885 switch (sel) {
6886 case 0:
6887 check_insn(ctx, ISA_MIPS32R2);
6888 gen_helper_mtc0_hwrena(cpu_env, arg);
6889 ctx->base.is_jmp = DISAS_STOP;
6890 rn = "HWREna";
6891 break;
6892 default:
6893 goto cp0_unimplemented;
6895 break;
6896 case 8:
6897 switch (sel) {
6898 case 0:
6899 /* ignored */
6900 rn = "BadVAddr";
6901 break;
6902 case 1:
6903 /* ignored */
6904 rn = "BadInstr";
6905 break;
6906 case 2:
6907 /* ignored */
6908 rn = "BadInstrP";
6909 break;
6910 case 3:
6911 /* ignored */
6912 rn = "BadInstrX";
6913 break;
6914 default:
6915 goto cp0_unimplemented;
6917 break;
6918 case 9:
6919 switch (sel) {
6920 case 0:
6921 gen_helper_mtc0_count(cpu_env, arg);
6922 rn = "Count";
6923 break;
6924 /* 6,7 are implementation dependent */
6925 default:
6926 goto cp0_unimplemented;
6928 break;
6929 case 10:
6930 switch (sel) {
6931 case 0:
6932 gen_helper_mtc0_entryhi(cpu_env, arg);
6933 rn = "EntryHi";
6934 break;
6935 default:
6936 goto cp0_unimplemented;
6938 break;
6939 case 11:
6940 switch (sel) {
6941 case 0:
6942 gen_helper_mtc0_compare(cpu_env, arg);
6943 rn = "Compare";
6944 break;
6945 /* 6,7 are implementation dependent */
6946 default:
6947 goto cp0_unimplemented;
6949 break;
6950 case 12:
6951 switch (sel) {
6952 case 0:
6953 save_cpu_state(ctx, 1);
6954 gen_helper_mtc0_status(cpu_env, arg);
6955 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6956 gen_save_pc(ctx->base.pc_next + 4);
6957 ctx->base.is_jmp = DISAS_EXIT;
6958 rn = "Status";
6959 break;
6960 case 1:
6961 check_insn(ctx, ISA_MIPS32R2);
6962 gen_helper_mtc0_intctl(cpu_env, arg);
6963 /* Stop translation as we may have switched the execution mode */
6964 ctx->base.is_jmp = DISAS_STOP;
6965 rn = "IntCtl";
6966 break;
6967 case 2:
6968 check_insn(ctx, ISA_MIPS32R2);
6969 gen_helper_mtc0_srsctl(cpu_env, arg);
6970 /* Stop translation as we may have switched the execution mode */
6971 ctx->base.is_jmp = DISAS_STOP;
6972 rn = "SRSCtl";
6973 break;
6974 case 3:
6975 check_insn(ctx, ISA_MIPS32R2);
6976 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6977 /* Stop translation as we may have switched the execution mode */
6978 ctx->base.is_jmp = DISAS_STOP;
6979 rn = "SRSMap";
6980 break;
6981 default:
6982 goto cp0_unimplemented;
6984 break;
6985 case 13:
6986 switch (sel) {
6987 case 0:
6988 save_cpu_state(ctx, 1);
6989 gen_helper_mtc0_cause(cpu_env, arg);
6990 /* Stop translation as we may have triggered an interrupt.
6991 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6992 * translated code to check for pending interrupts. */
6993 gen_save_pc(ctx->base.pc_next + 4);
6994 ctx->base.is_jmp = DISAS_EXIT;
6995 rn = "Cause";
6996 break;
6997 default:
6998 goto cp0_unimplemented;
7000 break;
7001 case 14:
7002 switch (sel) {
7003 case 0:
7004 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7005 rn = "EPC";
7006 break;
7007 default:
7008 goto cp0_unimplemented;
7010 break;
7011 case 15:
7012 switch (sel) {
7013 case 0:
7014 /* ignored */
7015 rn = "PRid";
7016 break;
7017 case 1:
7018 check_insn(ctx, ISA_MIPS32R2);
7019 gen_helper_mtc0_ebase(cpu_env, arg);
7020 rn = "EBase";
7021 break;
7022 default:
7023 goto cp0_unimplemented;
7025 break;
7026 case 16:
7027 switch (sel) {
7028 case 0:
7029 gen_helper_mtc0_config0(cpu_env, arg);
7030 rn = "Config";
7031 /* Stop translation as we may have switched the execution mode */
7032 ctx->base.is_jmp = DISAS_STOP;
7033 break;
7034 case 1:
7035 /* ignored, read only */
7036 rn = "Config1";
7037 break;
7038 case 2:
7039 gen_helper_mtc0_config2(cpu_env, arg);
7040 rn = "Config2";
7041 /* Stop translation as we may have switched the execution mode */
7042 ctx->base.is_jmp = DISAS_STOP;
7043 break;
7044 case 3:
7045 gen_helper_mtc0_config3(cpu_env, arg);
7046 rn = "Config3";
7047 /* Stop translation as we may have switched the execution mode */
7048 ctx->base.is_jmp = DISAS_STOP;
7049 break;
7050 case 4:
7051 gen_helper_mtc0_config4(cpu_env, arg);
7052 rn = "Config4";
7053 ctx->base.is_jmp = DISAS_STOP;
7054 break;
7055 case 5:
7056 gen_helper_mtc0_config5(cpu_env, arg);
7057 rn = "Config5";
7058 /* Stop translation as we may have switched the execution mode */
7059 ctx->base.is_jmp = DISAS_STOP;
7060 break;
7061 /* 6,7 are implementation dependent */
7062 case 6:
7063 /* ignored */
7064 rn = "Config6";
7065 break;
7066 case 7:
7067 /* ignored */
7068 rn = "Config7";
7069 break;
7070 default:
7071 rn = "Invalid config selector";
7072 goto cp0_unimplemented;
7074 break;
7075 case 17:
7076 switch (sel) {
7077 case 0:
7078 gen_helper_mtc0_lladdr(cpu_env, arg);
7079 rn = "LLAddr";
7080 break;
7081 case 1:
7082 CP0_CHECK(ctx->mrp);
7083 gen_helper_mtc0_maar(cpu_env, arg);
7084 rn = "MAAR";
7085 break;
7086 case 2:
7087 CP0_CHECK(ctx->mrp);
7088 gen_helper_mtc0_maari(cpu_env, arg);
7089 rn = "MAARI";
7090 break;
7091 default:
7092 goto cp0_unimplemented;
7094 break;
7095 case 18:
7096 switch (sel) {
7097 case 0:
7098 case 1:
7099 case 2:
7100 case 3:
7101 case 4:
7102 case 5:
7103 case 6:
7104 case 7:
7105 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7106 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7107 rn = "WatchLo";
7108 break;
7109 default:
7110 goto cp0_unimplemented;
7112 break;
7113 case 19:
7114 switch (sel) {
7115 case 0:
7116 case 1:
7117 case 2:
7118 case 3:
7119 case 4:
7120 case 5:
7121 case 6:
7122 case 7:
7123 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7124 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7125 rn = "WatchHi";
7126 break;
7127 default:
7128 goto cp0_unimplemented;
7130 break;
7131 case 20:
7132 switch (sel) {
7133 case 0:
7134 #if defined(TARGET_MIPS64)
7135 check_insn(ctx, ISA_MIPS3);
7136 gen_helper_mtc0_xcontext(cpu_env, arg);
7137 rn = "XContext";
7138 break;
7139 #endif
7140 default:
7141 goto cp0_unimplemented;
7143 break;
7144 case 21:
7145 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7146 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7147 switch (sel) {
7148 case 0:
7149 gen_helper_mtc0_framemask(cpu_env, arg);
7150 rn = "Framemask";
7151 break;
7152 default:
7153 goto cp0_unimplemented;
7155 break;
7156 case 22:
7157 /* ignored */
7158 rn = "Diagnostic"; /* implementation dependent */
7159 break;
7160 case 23:
7161 switch (sel) {
7162 case 0:
7163 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7164 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7165 gen_save_pc(ctx->base.pc_next + 4);
7166 ctx->base.is_jmp = DISAS_EXIT;
7167 rn = "Debug";
7168 break;
7169 case 1:
7170 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7171 rn = "TraceControl";
7172 /* Stop translation as we may have switched the execution mode */
7173 ctx->base.is_jmp = DISAS_STOP;
7174 goto cp0_unimplemented;
7175 case 2:
7176 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7177 rn = "TraceControl2";
7178 /* Stop translation as we may have switched the execution mode */
7179 ctx->base.is_jmp = DISAS_STOP;
7180 goto cp0_unimplemented;
7181 case 3:
7182 /* Stop translation as we may have switched the execution mode */
7183 ctx->base.is_jmp = DISAS_STOP;
7184 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7185 rn = "UserTraceData";
7186 /* Stop translation as we may have switched the execution mode */
7187 ctx->base.is_jmp = DISAS_STOP;
7188 goto cp0_unimplemented;
7189 case 4:
7190 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7191 /* Stop translation as we may have switched the execution mode */
7192 ctx->base.is_jmp = DISAS_STOP;
7193 rn = "TraceBPC";
7194 goto cp0_unimplemented;
7195 default:
7196 goto cp0_unimplemented;
7198 break;
7199 case 24:
7200 switch (sel) {
7201 case 0:
7202 /* EJTAG support */
7203 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7204 rn = "DEPC";
7205 break;
7206 default:
7207 goto cp0_unimplemented;
7209 break;
7210 case 25:
7211 switch (sel) {
7212 case 0:
7213 gen_helper_mtc0_performance0(cpu_env, arg);
7214 rn = "Performance0";
7215 break;
7216 case 1:
7217 // gen_helper_mtc0_performance1(arg);
7218 rn = "Performance1";
7219 goto cp0_unimplemented;
7220 case 2:
7221 // gen_helper_mtc0_performance2(arg);
7222 rn = "Performance2";
7223 goto cp0_unimplemented;
7224 case 3:
7225 // gen_helper_mtc0_performance3(arg);
7226 rn = "Performance3";
7227 goto cp0_unimplemented;
7228 case 4:
7229 // gen_helper_mtc0_performance4(arg);
7230 rn = "Performance4";
7231 goto cp0_unimplemented;
7232 case 5:
7233 // gen_helper_mtc0_performance5(arg);
7234 rn = "Performance5";
7235 goto cp0_unimplemented;
7236 case 6:
7237 // gen_helper_mtc0_performance6(arg);
7238 rn = "Performance6";
7239 goto cp0_unimplemented;
7240 case 7:
7241 // gen_helper_mtc0_performance7(arg);
7242 rn = "Performance7";
7243 goto cp0_unimplemented;
7244 default:
7245 goto cp0_unimplemented;
7247 break;
7248 case 26:
7249 switch (sel) {
7250 case 0:
7251 gen_helper_mtc0_errctl(cpu_env, arg);
7252 ctx->base.is_jmp = DISAS_STOP;
7253 rn = "ErrCtl";
7254 break;
7255 default:
7256 goto cp0_unimplemented;
7258 break;
7259 case 27:
7260 switch (sel) {
7261 case 0:
7262 case 1:
7263 case 2:
7264 case 3:
7265 /* ignored */
7266 rn = "CacheErr";
7267 break;
7268 default:
7269 goto cp0_unimplemented;
7271 break;
7272 case 28:
7273 switch (sel) {
7274 case 0:
7275 case 2:
7276 case 4:
7277 case 6:
7278 gen_helper_mtc0_taglo(cpu_env, arg);
7279 rn = "TagLo";
7280 break;
7281 case 1:
7282 case 3:
7283 case 5:
7284 case 7:
7285 gen_helper_mtc0_datalo(cpu_env, arg);
7286 rn = "DataLo";
7287 break;
7288 default:
7289 goto cp0_unimplemented;
7291 break;
7292 case 29:
7293 switch (sel) {
7294 case 0:
7295 case 2:
7296 case 4:
7297 case 6:
7298 gen_helper_mtc0_taghi(cpu_env, arg);
7299 rn = "TagHi";
7300 break;
7301 case 1:
7302 case 3:
7303 case 5:
7304 case 7:
7305 gen_helper_mtc0_datahi(cpu_env, arg);
7306 rn = "DataHi";
7307 break;
7308 default:
7309 rn = "invalid sel";
7310 goto cp0_unimplemented;
7312 break;
7313 case 30:
7314 switch (sel) {
7315 case 0:
7316 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7317 rn = "ErrorEPC";
7318 break;
7319 default:
7320 goto cp0_unimplemented;
7322 break;
7323 case 31:
7324 switch (sel) {
7325 case 0:
7326 /* EJTAG support */
7327 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7328 rn = "DESAVE";
7329 break;
7330 case 2:
7331 case 3:
7332 case 4:
7333 case 5:
7334 case 6:
7335 case 7:
7336 CP0_CHECK(ctx->kscrexist & (1 << sel));
7337 tcg_gen_st_tl(arg, cpu_env,
7338 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7339 rn = "KScratch";
7340 break;
7341 default:
7342 goto cp0_unimplemented;
7344 break;
7345 default:
7346 goto cp0_unimplemented;
7348 trace_mips_translate_c0("mtc0", rn, reg, sel);
7350 /* For simplicity assume that all writes can cause interrupts. */
7351 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7352 gen_io_end();
7353 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7354 * translated code to check for pending interrupts. */
7355 gen_save_pc(ctx->base.pc_next + 4);
7356 ctx->base.is_jmp = DISAS_EXIT;
7358 return;
7360 cp0_unimplemented:
7361 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7364 #if defined(TARGET_MIPS64)
7365 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7367 const char *rn = "invalid";
7369 if (sel != 0)
7370 check_insn(ctx, ISA_MIPS64);
7372 switch (reg) {
7373 case 0:
7374 switch (sel) {
7375 case 0:
7376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7377 rn = "Index";
7378 break;
7379 case 1:
7380 CP0_CHECK(ctx->insn_flags & ASE_MT);
7381 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7382 rn = "MVPControl";
7383 break;
7384 case 2:
7385 CP0_CHECK(ctx->insn_flags & ASE_MT);
7386 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7387 rn = "MVPConf0";
7388 break;
7389 case 3:
7390 CP0_CHECK(ctx->insn_flags & ASE_MT);
7391 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7392 rn = "MVPConf1";
7393 break;
7394 case 4:
7395 CP0_CHECK(ctx->vp);
7396 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7397 rn = "VPControl";
7398 break;
7399 default:
7400 goto cp0_unimplemented;
7402 break;
7403 case 1:
7404 switch (sel) {
7405 case 0:
7406 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7407 gen_helper_mfc0_random(arg, cpu_env);
7408 rn = "Random";
7409 break;
7410 case 1:
7411 CP0_CHECK(ctx->insn_flags & ASE_MT);
7412 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7413 rn = "VPEControl";
7414 break;
7415 case 2:
7416 CP0_CHECK(ctx->insn_flags & ASE_MT);
7417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7418 rn = "VPEConf0";
7419 break;
7420 case 3:
7421 CP0_CHECK(ctx->insn_flags & ASE_MT);
7422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7423 rn = "VPEConf1";
7424 break;
7425 case 4:
7426 CP0_CHECK(ctx->insn_flags & ASE_MT);
7427 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
7428 rn = "YQMask";
7429 break;
7430 case 5:
7431 CP0_CHECK(ctx->insn_flags & ASE_MT);
7432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7433 rn = "VPESchedule";
7434 break;
7435 case 6:
7436 CP0_CHECK(ctx->insn_flags & ASE_MT);
7437 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7438 rn = "VPEScheFBack";
7439 break;
7440 case 7:
7441 CP0_CHECK(ctx->insn_flags & ASE_MT);
7442 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7443 rn = "VPEOpt";
7444 break;
7445 default:
7446 goto cp0_unimplemented;
7448 break;
7449 case 2:
7450 switch (sel) {
7451 case 0:
7452 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
7453 rn = "EntryLo0";
7454 break;
7455 case 1:
7456 CP0_CHECK(ctx->insn_flags & ASE_MT);
7457 gen_helper_mfc0_tcstatus(arg, cpu_env);
7458 rn = "TCStatus";
7459 break;
7460 case 2:
7461 CP0_CHECK(ctx->insn_flags & ASE_MT);
7462 gen_helper_mfc0_tcbind(arg, cpu_env);
7463 rn = "TCBind";
7464 break;
7465 case 3:
7466 CP0_CHECK(ctx->insn_flags & ASE_MT);
7467 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7468 rn = "TCRestart";
7469 break;
7470 case 4:
7471 CP0_CHECK(ctx->insn_flags & ASE_MT);
7472 gen_helper_dmfc0_tchalt(arg, cpu_env);
7473 rn = "TCHalt";
7474 break;
7475 case 5:
7476 CP0_CHECK(ctx->insn_flags & ASE_MT);
7477 gen_helper_dmfc0_tccontext(arg, cpu_env);
7478 rn = "TCContext";
7479 break;
7480 case 6:
7481 CP0_CHECK(ctx->insn_flags & ASE_MT);
7482 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7483 rn = "TCSchedule";
7484 break;
7485 case 7:
7486 CP0_CHECK(ctx->insn_flags & ASE_MT);
7487 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7488 rn = "TCScheFBack";
7489 break;
7490 default:
7491 goto cp0_unimplemented;
7493 break;
7494 case 3:
7495 switch (sel) {
7496 case 0:
7497 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7498 rn = "EntryLo1";
7499 break;
7500 case 1:
7501 CP0_CHECK(ctx->vp);
7502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7503 rn = "GlobalNumber";
7504 break;
7505 default:
7506 goto cp0_unimplemented;
7508 break;
7509 case 4:
7510 switch (sel) {
7511 case 0:
7512 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7513 rn = "Context";
7514 break;
7515 case 1:
7516 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
7517 rn = "ContextConfig";
7518 goto cp0_unimplemented;
7519 case 2:
7520 CP0_CHECK(ctx->ulri);
7521 tcg_gen_ld_tl(arg, cpu_env,
7522 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7523 rn = "UserLocal";
7524 break;
7525 default:
7526 goto cp0_unimplemented;
7528 break;
7529 case 5:
7530 switch (sel) {
7531 case 0:
7532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7533 rn = "PageMask";
7534 break;
7535 case 1:
7536 check_insn(ctx, ISA_MIPS32R2);
7537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7538 rn = "PageGrain";
7539 break;
7540 case 2:
7541 CP0_CHECK(ctx->sc);
7542 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7543 rn = "SegCtl0";
7544 break;
7545 case 3:
7546 CP0_CHECK(ctx->sc);
7547 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7548 rn = "SegCtl1";
7549 break;
7550 case 4:
7551 CP0_CHECK(ctx->sc);
7552 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7553 rn = "SegCtl2";
7554 break;
7555 case 5:
7556 check_pw(ctx);
7557 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7558 rn = "PWBase";
7559 break;
7560 case 6:
7561 check_pw(ctx);
7562 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7563 rn = "PWField";
7564 break;
7565 case 7:
7566 check_pw(ctx);
7567 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7568 rn = "PWSize";
7569 break;
7570 default:
7571 goto cp0_unimplemented;
7573 break;
7574 case 6:
7575 switch (sel) {
7576 case 0:
7577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7578 rn = "Wired";
7579 break;
7580 case 1:
7581 check_insn(ctx, ISA_MIPS32R2);
7582 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7583 rn = "SRSConf0";
7584 break;
7585 case 2:
7586 check_insn(ctx, ISA_MIPS32R2);
7587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7588 rn = "SRSConf1";
7589 break;
7590 case 3:
7591 check_insn(ctx, ISA_MIPS32R2);
7592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7593 rn = "SRSConf2";
7594 break;
7595 case 4:
7596 check_insn(ctx, ISA_MIPS32R2);
7597 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7598 rn = "SRSConf3";
7599 break;
7600 case 5:
7601 check_insn(ctx, ISA_MIPS32R2);
7602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7603 rn = "SRSConf4";
7604 break;
7605 case 6:
7606 check_pw(ctx);
7607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7608 rn = "PWCtl";
7609 break;
7610 default:
7611 goto cp0_unimplemented;
7613 break;
7614 case 7:
7615 switch (sel) {
7616 case 0:
7617 check_insn(ctx, ISA_MIPS32R2);
7618 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7619 rn = "HWREna";
7620 break;
7621 default:
7622 goto cp0_unimplemented;
7624 break;
7625 case 8:
7626 switch (sel) {
7627 case 0:
7628 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7629 rn = "BadVAddr";
7630 break;
7631 case 1:
7632 CP0_CHECK(ctx->bi);
7633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7634 rn = "BadInstr";
7635 break;
7636 case 2:
7637 CP0_CHECK(ctx->bp);
7638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7639 rn = "BadInstrP";
7640 break;
7641 case 3:
7642 CP0_CHECK(ctx->bi);
7643 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7644 tcg_gen_andi_tl(arg, arg, ~0xffff);
7645 rn = "BadInstrX";
7646 break;
7647 default:
7648 goto cp0_unimplemented;
7650 break;
7651 case 9:
7652 switch (sel) {
7653 case 0:
7654 /* Mark as an IO operation because we read the time. */
7655 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7656 gen_io_start();
7658 gen_helper_mfc0_count(arg, cpu_env);
7659 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7660 gen_io_end();
7662 /* Break the TB to be able to take timer interrupts immediately
7663 after reading count. DISAS_STOP isn't sufficient, we need to
7664 ensure we break completely out of translated code. */
7665 gen_save_pc(ctx->base.pc_next + 4);
7666 ctx->base.is_jmp = DISAS_EXIT;
7667 rn = "Count";
7668 break;
7669 /* 6,7 are implementation dependent */
7670 default:
7671 goto cp0_unimplemented;
7673 break;
7674 case 10:
7675 switch (sel) {
7676 case 0:
7677 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7678 rn = "EntryHi";
7679 break;
7680 default:
7681 goto cp0_unimplemented;
7683 break;
7684 case 11:
7685 switch (sel) {
7686 case 0:
7687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7688 rn = "Compare";
7689 break;
7690 /* 6,7 are implementation dependent */
7691 default:
7692 goto cp0_unimplemented;
7694 break;
7695 case 12:
7696 switch (sel) {
7697 case 0:
7698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7699 rn = "Status";
7700 break;
7701 case 1:
7702 check_insn(ctx, ISA_MIPS32R2);
7703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7704 rn = "IntCtl";
7705 break;
7706 case 2:
7707 check_insn(ctx, ISA_MIPS32R2);
7708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7709 rn = "SRSCtl";
7710 break;
7711 case 3:
7712 check_insn(ctx, ISA_MIPS32R2);
7713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7714 rn = "SRSMap";
7715 break;
7716 default:
7717 goto cp0_unimplemented;
7719 break;
7720 case 13:
7721 switch (sel) {
7722 case 0:
7723 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7724 rn = "Cause";
7725 break;
7726 default:
7727 goto cp0_unimplemented;
7729 break;
7730 case 14:
7731 switch (sel) {
7732 case 0:
7733 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7734 rn = "EPC";
7735 break;
7736 default:
7737 goto cp0_unimplemented;
7739 break;
7740 case 15:
7741 switch (sel) {
7742 case 0:
7743 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7744 rn = "PRid";
7745 break;
7746 case 1:
7747 check_insn(ctx, ISA_MIPS32R2);
7748 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7749 rn = "EBase";
7750 break;
7751 case 3:
7752 check_insn(ctx, ISA_MIPS32R2);
7753 CP0_CHECK(ctx->cmgcr);
7754 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7755 rn = "CMGCRBase";
7756 break;
7757 default:
7758 goto cp0_unimplemented;
7760 break;
7761 case 16:
7762 switch (sel) {
7763 case 0:
7764 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7765 rn = "Config";
7766 break;
7767 case 1:
7768 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7769 rn = "Config1";
7770 break;
7771 case 2:
7772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7773 rn = "Config2";
7774 break;
7775 case 3:
7776 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7777 rn = "Config3";
7778 break;
7779 case 4:
7780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7781 rn = "Config4";
7782 break;
7783 case 5:
7784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7785 rn = "Config5";
7786 break;
7787 /* 6,7 are implementation dependent */
7788 case 6:
7789 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7790 rn = "Config6";
7791 break;
7792 case 7:
7793 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7794 rn = "Config7";
7795 break;
7796 default:
7797 goto cp0_unimplemented;
7799 break;
7800 case 17:
7801 switch (sel) {
7802 case 0:
7803 gen_helper_dmfc0_lladdr(arg, cpu_env);
7804 rn = "LLAddr";
7805 break;
7806 case 1:
7807 CP0_CHECK(ctx->mrp);
7808 gen_helper_dmfc0_maar(arg, cpu_env);
7809 rn = "MAAR";
7810 break;
7811 case 2:
7812 CP0_CHECK(ctx->mrp);
7813 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7814 rn = "MAARI";
7815 break;
7816 default:
7817 goto cp0_unimplemented;
7819 break;
7820 case 18:
7821 switch (sel) {
7822 case 0:
7823 case 1:
7824 case 2:
7825 case 3:
7826 case 4:
7827 case 5:
7828 case 6:
7829 case 7:
7830 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7831 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7832 rn = "WatchLo";
7833 break;
7834 default:
7835 goto cp0_unimplemented;
7837 break;
7838 case 19:
7839 switch (sel) {
7840 case 0:
7841 case 1:
7842 case 2:
7843 case 3:
7844 case 4:
7845 case 5:
7846 case 6:
7847 case 7:
7848 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7849 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7850 rn = "WatchHi";
7851 break;
7852 default:
7853 goto cp0_unimplemented;
7855 break;
7856 case 20:
7857 switch (sel) {
7858 case 0:
7859 check_insn(ctx, ISA_MIPS3);
7860 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7861 rn = "XContext";
7862 break;
7863 default:
7864 goto cp0_unimplemented;
7866 break;
7867 case 21:
7868 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7869 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7870 switch (sel) {
7871 case 0:
7872 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7873 rn = "Framemask";
7874 break;
7875 default:
7876 goto cp0_unimplemented;
7878 break;
7879 case 22:
7880 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7881 rn = "'Diagnostic"; /* implementation dependent */
7882 break;
7883 case 23:
7884 switch (sel) {
7885 case 0:
7886 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7887 rn = "Debug";
7888 break;
7889 case 1:
7890 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
7891 rn = "TraceControl";
7892 goto cp0_unimplemented;
7893 case 2:
7894 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
7895 rn = "TraceControl2";
7896 goto cp0_unimplemented;
7897 case 3:
7898 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
7899 rn = "UserTraceData";
7900 goto cp0_unimplemented;
7901 case 4:
7902 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
7903 rn = "TraceBPC";
7904 goto cp0_unimplemented;
7905 default:
7906 goto cp0_unimplemented;
7908 break;
7909 case 24:
7910 switch (sel) {
7911 case 0:
7912 /* EJTAG support */
7913 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7914 rn = "DEPC";
7915 break;
7916 default:
7917 goto cp0_unimplemented;
7919 break;
7920 case 25:
7921 switch (sel) {
7922 case 0:
7923 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7924 rn = "Performance0";
7925 break;
7926 case 1:
7927 // gen_helper_dmfc0_performance1(arg);
7928 rn = "Performance1";
7929 goto cp0_unimplemented;
7930 case 2:
7931 // gen_helper_dmfc0_performance2(arg);
7932 rn = "Performance2";
7933 goto cp0_unimplemented;
7934 case 3:
7935 // gen_helper_dmfc0_performance3(arg);
7936 rn = "Performance3";
7937 goto cp0_unimplemented;
7938 case 4:
7939 // gen_helper_dmfc0_performance4(arg);
7940 rn = "Performance4";
7941 goto cp0_unimplemented;
7942 case 5:
7943 // gen_helper_dmfc0_performance5(arg);
7944 rn = "Performance5";
7945 goto cp0_unimplemented;
7946 case 6:
7947 // gen_helper_dmfc0_performance6(arg);
7948 rn = "Performance6";
7949 goto cp0_unimplemented;
7950 case 7:
7951 // gen_helper_dmfc0_performance7(arg);
7952 rn = "Performance7";
7953 goto cp0_unimplemented;
7954 default:
7955 goto cp0_unimplemented;
7957 break;
7958 case 26:
7959 switch (sel) {
7960 case 0:
7961 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7962 rn = "ErrCtl";
7963 break;
7964 default:
7965 goto cp0_unimplemented;
7967 break;
7968 case 27:
7969 switch (sel) {
7970 /* ignored */
7971 case 0:
7972 case 1:
7973 case 2:
7974 case 3:
7975 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7976 rn = "CacheErr";
7977 break;
7978 default:
7979 goto cp0_unimplemented;
7981 break;
7982 case 28:
7983 switch (sel) {
7984 case 0:
7985 case 2:
7986 case 4:
7987 case 6:
7988 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7989 rn = "TagLo";
7990 break;
7991 case 1:
7992 case 3:
7993 case 5:
7994 case 7:
7995 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7996 rn = "DataLo";
7997 break;
7998 default:
7999 goto cp0_unimplemented;
8001 break;
8002 case 29:
8003 switch (sel) {
8004 case 0:
8005 case 2:
8006 case 4:
8007 case 6:
8008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8009 rn = "TagHi";
8010 break;
8011 case 1:
8012 case 3:
8013 case 5:
8014 case 7:
8015 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8016 rn = "DataHi";
8017 break;
8018 default:
8019 goto cp0_unimplemented;
8021 break;
8022 case 30:
8023 switch (sel) {
8024 case 0:
8025 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8026 rn = "ErrorEPC";
8027 break;
8028 default:
8029 goto cp0_unimplemented;
8031 break;
8032 case 31:
8033 switch (sel) {
8034 case 0:
8035 /* EJTAG support */
8036 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8037 rn = "DESAVE";
8038 break;
8039 case 2:
8040 case 3:
8041 case 4:
8042 case 5:
8043 case 6:
8044 case 7:
8045 CP0_CHECK(ctx->kscrexist & (1 << sel));
8046 tcg_gen_ld_tl(arg, cpu_env,
8047 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8048 rn = "KScratch";
8049 break;
8050 default:
8051 goto cp0_unimplemented;
8053 break;
8054 default:
8055 goto cp0_unimplemented;
8057 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8058 return;
8060 cp0_unimplemented:
8061 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8062 gen_mfc0_unimplemented(ctx, arg);
8065 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8067 const char *rn = "invalid";
8069 if (sel != 0)
8070 check_insn(ctx, ISA_MIPS64);
8072 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8073 gen_io_start();
8076 switch (reg) {
8077 case 0:
8078 switch (sel) {
8079 case 0:
8080 gen_helper_mtc0_index(cpu_env, arg);
8081 rn = "Index";
8082 break;
8083 case 1:
8084 CP0_CHECK(ctx->insn_flags & ASE_MT);
8085 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8086 rn = "MVPControl";
8087 break;
8088 case 2:
8089 CP0_CHECK(ctx->insn_flags & ASE_MT);
8090 /* ignored */
8091 rn = "MVPConf0";
8092 break;
8093 case 3:
8094 CP0_CHECK(ctx->insn_flags & ASE_MT);
8095 /* ignored */
8096 rn = "MVPConf1";
8097 break;
8098 case 4:
8099 CP0_CHECK(ctx->vp);
8100 /* ignored */
8101 rn = "VPControl";
8102 break;
8103 default:
8104 goto cp0_unimplemented;
8106 break;
8107 case 1:
8108 switch (sel) {
8109 case 0:
8110 /* ignored */
8111 rn = "Random";
8112 break;
8113 case 1:
8114 CP0_CHECK(ctx->insn_flags & ASE_MT);
8115 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8116 rn = "VPEControl";
8117 break;
8118 case 2:
8119 CP0_CHECK(ctx->insn_flags & ASE_MT);
8120 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8121 rn = "VPEConf0";
8122 break;
8123 case 3:
8124 CP0_CHECK(ctx->insn_flags & ASE_MT);
8125 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8126 rn = "VPEConf1";
8127 break;
8128 case 4:
8129 CP0_CHECK(ctx->insn_flags & ASE_MT);
8130 gen_helper_mtc0_yqmask(cpu_env, arg);
8131 rn = "YQMask";
8132 break;
8133 case 5:
8134 CP0_CHECK(ctx->insn_flags & ASE_MT);
8135 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8136 rn = "VPESchedule";
8137 break;
8138 case 6:
8139 CP0_CHECK(ctx->insn_flags & ASE_MT);
8140 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8141 rn = "VPEScheFBack";
8142 break;
8143 case 7:
8144 CP0_CHECK(ctx->insn_flags & ASE_MT);
8145 gen_helper_mtc0_vpeopt(cpu_env, arg);
8146 rn = "VPEOpt";
8147 break;
8148 default:
8149 goto cp0_unimplemented;
8151 break;
8152 case 2:
8153 switch (sel) {
8154 case 0:
8155 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8156 rn = "EntryLo0";
8157 break;
8158 case 1:
8159 CP0_CHECK(ctx->insn_flags & ASE_MT);
8160 gen_helper_mtc0_tcstatus(cpu_env, arg);
8161 rn = "TCStatus";
8162 break;
8163 case 2:
8164 CP0_CHECK(ctx->insn_flags & ASE_MT);
8165 gen_helper_mtc0_tcbind(cpu_env, arg);
8166 rn = "TCBind";
8167 break;
8168 case 3:
8169 CP0_CHECK(ctx->insn_flags & ASE_MT);
8170 gen_helper_mtc0_tcrestart(cpu_env, arg);
8171 rn = "TCRestart";
8172 break;
8173 case 4:
8174 CP0_CHECK(ctx->insn_flags & ASE_MT);
8175 gen_helper_mtc0_tchalt(cpu_env, arg);
8176 rn = "TCHalt";
8177 break;
8178 case 5:
8179 CP0_CHECK(ctx->insn_flags & ASE_MT);
8180 gen_helper_mtc0_tccontext(cpu_env, arg);
8181 rn = "TCContext";
8182 break;
8183 case 6:
8184 CP0_CHECK(ctx->insn_flags & ASE_MT);
8185 gen_helper_mtc0_tcschedule(cpu_env, arg);
8186 rn = "TCSchedule";
8187 break;
8188 case 7:
8189 CP0_CHECK(ctx->insn_flags & ASE_MT);
8190 gen_helper_mtc0_tcschefback(cpu_env, arg);
8191 rn = "TCScheFBack";
8192 break;
8193 default:
8194 goto cp0_unimplemented;
8196 break;
8197 case 3:
8198 switch (sel) {
8199 case 0:
8200 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8201 rn = "EntryLo1";
8202 break;
8203 case 1:
8204 CP0_CHECK(ctx->vp);
8205 /* ignored */
8206 rn = "GlobalNumber";
8207 break;
8208 default:
8209 goto cp0_unimplemented;
8211 break;
8212 case 4:
8213 switch (sel) {
8214 case 0:
8215 gen_helper_mtc0_context(cpu_env, arg);
8216 rn = "Context";
8217 break;
8218 case 1:
8219 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8220 rn = "ContextConfig";
8221 goto cp0_unimplemented;
8222 case 2:
8223 CP0_CHECK(ctx->ulri);
8224 tcg_gen_st_tl(arg, cpu_env,
8225 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8226 rn = "UserLocal";
8227 break;
8228 default:
8229 goto cp0_unimplemented;
8231 break;
8232 case 5:
8233 switch (sel) {
8234 case 0:
8235 gen_helper_mtc0_pagemask(cpu_env, arg);
8236 rn = "PageMask";
8237 break;
8238 case 1:
8239 check_insn(ctx, ISA_MIPS32R2);
8240 gen_helper_mtc0_pagegrain(cpu_env, arg);
8241 rn = "PageGrain";
8242 break;
8243 case 2:
8244 CP0_CHECK(ctx->sc);
8245 gen_helper_mtc0_segctl0(cpu_env, arg);
8246 rn = "SegCtl0";
8247 break;
8248 case 3:
8249 CP0_CHECK(ctx->sc);
8250 gen_helper_mtc0_segctl1(cpu_env, arg);
8251 rn = "SegCtl1";
8252 break;
8253 case 4:
8254 CP0_CHECK(ctx->sc);
8255 gen_helper_mtc0_segctl2(cpu_env, arg);
8256 rn = "SegCtl2";
8257 break;
8258 case 5:
8259 check_pw(ctx);
8260 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8261 rn = "PWBase";
8262 break;
8263 case 6:
8264 check_pw(ctx);
8265 gen_helper_mtc0_pwfield(cpu_env, arg);
8266 rn = "PWField";
8267 break;
8268 case 7:
8269 check_pw(ctx);
8270 gen_helper_mtc0_pwsize(cpu_env, arg);
8271 rn = "PWSize";
8272 break;
8273 default:
8274 goto cp0_unimplemented;
8276 break;
8277 case 6:
8278 switch (sel) {
8279 case 0:
8280 gen_helper_mtc0_wired(cpu_env, arg);
8281 rn = "Wired";
8282 break;
8283 case 1:
8284 check_insn(ctx, ISA_MIPS32R2);
8285 gen_helper_mtc0_srsconf0(cpu_env, arg);
8286 rn = "SRSConf0";
8287 break;
8288 case 2:
8289 check_insn(ctx, ISA_MIPS32R2);
8290 gen_helper_mtc0_srsconf1(cpu_env, arg);
8291 rn = "SRSConf1";
8292 break;
8293 case 3:
8294 check_insn(ctx, ISA_MIPS32R2);
8295 gen_helper_mtc0_srsconf2(cpu_env, arg);
8296 rn = "SRSConf2";
8297 break;
8298 case 4:
8299 check_insn(ctx, ISA_MIPS32R2);
8300 gen_helper_mtc0_srsconf3(cpu_env, arg);
8301 rn = "SRSConf3";
8302 break;
8303 case 5:
8304 check_insn(ctx, ISA_MIPS32R2);
8305 gen_helper_mtc0_srsconf4(cpu_env, arg);
8306 rn = "SRSConf4";
8307 break;
8308 case 6:
8309 check_pw(ctx);
8310 gen_helper_mtc0_pwctl(cpu_env, arg);
8311 rn = "PWCtl";
8312 break;
8313 default:
8314 goto cp0_unimplemented;
8316 break;
8317 case 7:
8318 switch (sel) {
8319 case 0:
8320 check_insn(ctx, ISA_MIPS32R2);
8321 gen_helper_mtc0_hwrena(cpu_env, arg);
8322 ctx->base.is_jmp = DISAS_STOP;
8323 rn = "HWREna";
8324 break;
8325 default:
8326 goto cp0_unimplemented;
8328 break;
8329 case 8:
8330 switch (sel) {
8331 case 0:
8332 /* ignored */
8333 rn = "BadVAddr";
8334 break;
8335 case 1:
8336 /* ignored */
8337 rn = "BadInstr";
8338 break;
8339 case 2:
8340 /* ignored */
8341 rn = "BadInstrP";
8342 break;
8343 case 3:
8344 /* ignored */
8345 rn = "BadInstrX";
8346 break;
8347 default:
8348 goto cp0_unimplemented;
8350 break;
8351 case 9:
8352 switch (sel) {
8353 case 0:
8354 gen_helper_mtc0_count(cpu_env, arg);
8355 rn = "Count";
8356 break;
8357 /* 6,7 are implementation dependent */
8358 default:
8359 goto cp0_unimplemented;
8361 /* Stop translation as we may have switched the execution mode */
8362 ctx->base.is_jmp = DISAS_STOP;
8363 break;
8364 case 10:
8365 switch (sel) {
8366 case 0:
8367 gen_helper_mtc0_entryhi(cpu_env, arg);
8368 rn = "EntryHi";
8369 break;
8370 default:
8371 goto cp0_unimplemented;
8373 break;
8374 case 11:
8375 switch (sel) {
8376 case 0:
8377 gen_helper_mtc0_compare(cpu_env, arg);
8378 rn = "Compare";
8379 break;
8380 /* 6,7 are implementation dependent */
8381 default:
8382 goto cp0_unimplemented;
8384 /* Stop translation as we may have switched the execution mode */
8385 ctx->base.is_jmp = DISAS_STOP;
8386 break;
8387 case 12:
8388 switch (sel) {
8389 case 0:
8390 save_cpu_state(ctx, 1);
8391 gen_helper_mtc0_status(cpu_env, arg);
8392 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8393 gen_save_pc(ctx->base.pc_next + 4);
8394 ctx->base.is_jmp = DISAS_EXIT;
8395 rn = "Status";
8396 break;
8397 case 1:
8398 check_insn(ctx, ISA_MIPS32R2);
8399 gen_helper_mtc0_intctl(cpu_env, arg);
8400 /* Stop translation as we may have switched the execution mode */
8401 ctx->base.is_jmp = DISAS_STOP;
8402 rn = "IntCtl";
8403 break;
8404 case 2:
8405 check_insn(ctx, ISA_MIPS32R2);
8406 gen_helper_mtc0_srsctl(cpu_env, arg);
8407 /* Stop translation as we may have switched the execution mode */
8408 ctx->base.is_jmp = DISAS_STOP;
8409 rn = "SRSCtl";
8410 break;
8411 case 3:
8412 check_insn(ctx, ISA_MIPS32R2);
8413 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8414 /* Stop translation as we may have switched the execution mode */
8415 ctx->base.is_jmp = DISAS_STOP;
8416 rn = "SRSMap";
8417 break;
8418 default:
8419 goto cp0_unimplemented;
8421 break;
8422 case 13:
8423 switch (sel) {
8424 case 0:
8425 save_cpu_state(ctx, 1);
8426 gen_helper_mtc0_cause(cpu_env, arg);
8427 /* Stop translation as we may have triggered an interrupt.
8428 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8429 * translated code to check for pending interrupts. */
8430 gen_save_pc(ctx->base.pc_next + 4);
8431 ctx->base.is_jmp = DISAS_EXIT;
8432 rn = "Cause";
8433 break;
8434 default:
8435 goto cp0_unimplemented;
8437 break;
8438 case 14:
8439 switch (sel) {
8440 case 0:
8441 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8442 rn = "EPC";
8443 break;
8444 default:
8445 goto cp0_unimplemented;
8447 break;
8448 case 15:
8449 switch (sel) {
8450 case 0:
8451 /* ignored */
8452 rn = "PRid";
8453 break;
8454 case 1:
8455 check_insn(ctx, ISA_MIPS32R2);
8456 gen_helper_mtc0_ebase(cpu_env, arg);
8457 rn = "EBase";
8458 break;
8459 default:
8460 goto cp0_unimplemented;
8462 break;
8463 case 16:
8464 switch (sel) {
8465 case 0:
8466 gen_helper_mtc0_config0(cpu_env, arg);
8467 rn = "Config";
8468 /* Stop translation as we may have switched the execution mode */
8469 ctx->base.is_jmp = DISAS_STOP;
8470 break;
8471 case 1:
8472 /* ignored, read only */
8473 rn = "Config1";
8474 break;
8475 case 2:
8476 gen_helper_mtc0_config2(cpu_env, arg);
8477 rn = "Config2";
8478 /* Stop translation as we may have switched the execution mode */
8479 ctx->base.is_jmp = DISAS_STOP;
8480 break;
8481 case 3:
8482 gen_helper_mtc0_config3(cpu_env, arg);
8483 rn = "Config3";
8484 /* Stop translation as we may have switched the execution mode */
8485 ctx->base.is_jmp = DISAS_STOP;
8486 break;
8487 case 4:
8488 /* currently ignored */
8489 rn = "Config4";
8490 break;
8491 case 5:
8492 gen_helper_mtc0_config5(cpu_env, arg);
8493 rn = "Config5";
8494 /* Stop translation as we may have switched the execution mode */
8495 ctx->base.is_jmp = DISAS_STOP;
8496 break;
8497 /* 6,7 are implementation dependent */
8498 default:
8499 rn = "Invalid config selector";
8500 goto cp0_unimplemented;
8502 break;
8503 case 17:
8504 switch (sel) {
8505 case 0:
8506 gen_helper_mtc0_lladdr(cpu_env, arg);
8507 rn = "LLAddr";
8508 break;
8509 case 1:
8510 CP0_CHECK(ctx->mrp);
8511 gen_helper_mtc0_maar(cpu_env, arg);
8512 rn = "MAAR";
8513 break;
8514 case 2:
8515 CP0_CHECK(ctx->mrp);
8516 gen_helper_mtc0_maari(cpu_env, arg);
8517 rn = "MAARI";
8518 break;
8519 default:
8520 goto cp0_unimplemented;
8522 break;
8523 case 18:
8524 switch (sel) {
8525 case 0:
8526 case 1:
8527 case 2:
8528 case 3:
8529 case 4:
8530 case 5:
8531 case 6:
8532 case 7:
8533 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8534 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8535 rn = "WatchLo";
8536 break;
8537 default:
8538 goto cp0_unimplemented;
8540 break;
8541 case 19:
8542 switch (sel) {
8543 case 0:
8544 case 1:
8545 case 2:
8546 case 3:
8547 case 4:
8548 case 5:
8549 case 6:
8550 case 7:
8551 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8552 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8553 rn = "WatchHi";
8554 break;
8555 default:
8556 goto cp0_unimplemented;
8558 break;
8559 case 20:
8560 switch (sel) {
8561 case 0:
8562 check_insn(ctx, ISA_MIPS3);
8563 gen_helper_mtc0_xcontext(cpu_env, arg);
8564 rn = "XContext";
8565 break;
8566 default:
8567 goto cp0_unimplemented;
8569 break;
8570 case 21:
8571 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8572 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8573 switch (sel) {
8574 case 0:
8575 gen_helper_mtc0_framemask(cpu_env, arg);
8576 rn = "Framemask";
8577 break;
8578 default:
8579 goto cp0_unimplemented;
8581 break;
8582 case 22:
8583 /* ignored */
8584 rn = "Diagnostic"; /* implementation dependent */
8585 break;
8586 case 23:
8587 switch (sel) {
8588 case 0:
8589 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8590 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8591 gen_save_pc(ctx->base.pc_next + 4);
8592 ctx->base.is_jmp = DISAS_EXIT;
8593 rn = "Debug";
8594 break;
8595 case 1:
8596 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8597 /* Stop translation as we may have switched the execution mode */
8598 ctx->base.is_jmp = DISAS_STOP;
8599 rn = "TraceControl";
8600 goto cp0_unimplemented;
8601 case 2:
8602 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8603 /* Stop translation as we may have switched the execution mode */
8604 ctx->base.is_jmp = DISAS_STOP;
8605 rn = "TraceControl2";
8606 goto cp0_unimplemented;
8607 case 3:
8608 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8609 /* Stop translation as we may have switched the execution mode */
8610 ctx->base.is_jmp = DISAS_STOP;
8611 rn = "UserTraceData";
8612 goto cp0_unimplemented;
8613 case 4:
8614 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8615 /* Stop translation as we may have switched the execution mode */
8616 ctx->base.is_jmp = DISAS_STOP;
8617 rn = "TraceBPC";
8618 goto cp0_unimplemented;
8619 default:
8620 goto cp0_unimplemented;
8622 break;
8623 case 24:
8624 switch (sel) {
8625 case 0:
8626 /* EJTAG support */
8627 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8628 rn = "DEPC";
8629 break;
8630 default:
8631 goto cp0_unimplemented;
8633 break;
8634 case 25:
8635 switch (sel) {
8636 case 0:
8637 gen_helper_mtc0_performance0(cpu_env, arg);
8638 rn = "Performance0";
8639 break;
8640 case 1:
8641 // gen_helper_mtc0_performance1(cpu_env, arg);
8642 rn = "Performance1";
8643 goto cp0_unimplemented;
8644 case 2:
8645 // gen_helper_mtc0_performance2(cpu_env, arg);
8646 rn = "Performance2";
8647 goto cp0_unimplemented;
8648 case 3:
8649 // gen_helper_mtc0_performance3(cpu_env, arg);
8650 rn = "Performance3";
8651 goto cp0_unimplemented;
8652 case 4:
8653 // gen_helper_mtc0_performance4(cpu_env, arg);
8654 rn = "Performance4";
8655 goto cp0_unimplemented;
8656 case 5:
8657 // gen_helper_mtc0_performance5(cpu_env, arg);
8658 rn = "Performance5";
8659 goto cp0_unimplemented;
8660 case 6:
8661 // gen_helper_mtc0_performance6(cpu_env, arg);
8662 rn = "Performance6";
8663 goto cp0_unimplemented;
8664 case 7:
8665 // gen_helper_mtc0_performance7(cpu_env, arg);
8666 rn = "Performance7";
8667 goto cp0_unimplemented;
8668 default:
8669 goto cp0_unimplemented;
8671 break;
8672 case 26:
8673 switch (sel) {
8674 case 0:
8675 gen_helper_mtc0_errctl(cpu_env, arg);
8676 ctx->base.is_jmp = DISAS_STOP;
8677 rn = "ErrCtl";
8678 break;
8679 default:
8680 goto cp0_unimplemented;
8682 break;
8683 case 27:
8684 switch (sel) {
8685 case 0:
8686 case 1:
8687 case 2:
8688 case 3:
8689 /* ignored */
8690 rn = "CacheErr";
8691 break;
8692 default:
8693 goto cp0_unimplemented;
8695 break;
8696 case 28:
8697 switch (sel) {
8698 case 0:
8699 case 2:
8700 case 4:
8701 case 6:
8702 gen_helper_mtc0_taglo(cpu_env, arg);
8703 rn = "TagLo";
8704 break;
8705 case 1:
8706 case 3:
8707 case 5:
8708 case 7:
8709 gen_helper_mtc0_datalo(cpu_env, arg);
8710 rn = "DataLo";
8711 break;
8712 default:
8713 goto cp0_unimplemented;
8715 break;
8716 case 29:
8717 switch (sel) {
8718 case 0:
8719 case 2:
8720 case 4:
8721 case 6:
8722 gen_helper_mtc0_taghi(cpu_env, arg);
8723 rn = "TagHi";
8724 break;
8725 case 1:
8726 case 3:
8727 case 5:
8728 case 7:
8729 gen_helper_mtc0_datahi(cpu_env, arg);
8730 rn = "DataHi";
8731 break;
8732 default:
8733 rn = "invalid sel";
8734 goto cp0_unimplemented;
8736 break;
8737 case 30:
8738 switch (sel) {
8739 case 0:
8740 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8741 rn = "ErrorEPC";
8742 break;
8743 default:
8744 goto cp0_unimplemented;
8746 break;
8747 case 31:
8748 switch (sel) {
8749 case 0:
8750 /* EJTAG support */
8751 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8752 rn = "DESAVE";
8753 break;
8754 case 2:
8755 case 3:
8756 case 4:
8757 case 5:
8758 case 6:
8759 case 7:
8760 CP0_CHECK(ctx->kscrexist & (1 << sel));
8761 tcg_gen_st_tl(arg, cpu_env,
8762 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8763 rn = "KScratch";
8764 break;
8765 default:
8766 goto cp0_unimplemented;
8768 break;
8769 default:
8770 goto cp0_unimplemented;
8772 trace_mips_translate_c0("dmtc0", rn, reg, sel);
8774 /* For simplicity assume that all writes can cause interrupts. */
8775 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8776 gen_io_end();
8777 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8778 * translated code to check for pending interrupts. */
8779 gen_save_pc(ctx->base.pc_next + 4);
8780 ctx->base.is_jmp = DISAS_EXIT;
8782 return;
8784 cp0_unimplemented:
8785 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8787 #endif /* TARGET_MIPS64 */
8789 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8790 int u, int sel, int h)
8792 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8793 TCGv t0 = tcg_temp_local_new();
8795 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8796 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8797 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
8798 tcg_gen_movi_tl(t0, -1);
8799 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8800 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
8801 tcg_gen_movi_tl(t0, -1);
8802 else if (u == 0) {
8803 switch (rt) {
8804 case 1:
8805 switch (sel) {
8806 case 1:
8807 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8808 break;
8809 case 2:
8810 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8811 break;
8812 default:
8813 goto die;
8814 break;
8816 break;
8817 case 2:
8818 switch (sel) {
8819 case 1:
8820 gen_helper_mftc0_tcstatus(t0, cpu_env);
8821 break;
8822 case 2:
8823 gen_helper_mftc0_tcbind(t0, cpu_env);
8824 break;
8825 case 3:
8826 gen_helper_mftc0_tcrestart(t0, cpu_env);
8827 break;
8828 case 4:
8829 gen_helper_mftc0_tchalt(t0, cpu_env);
8830 break;
8831 case 5:
8832 gen_helper_mftc0_tccontext(t0, cpu_env);
8833 break;
8834 case 6:
8835 gen_helper_mftc0_tcschedule(t0, cpu_env);
8836 break;
8837 case 7:
8838 gen_helper_mftc0_tcschefback(t0, cpu_env);
8839 break;
8840 default:
8841 gen_mfc0(ctx, t0, rt, sel);
8842 break;
8844 break;
8845 case 10:
8846 switch (sel) {
8847 case 0:
8848 gen_helper_mftc0_entryhi(t0, cpu_env);
8849 break;
8850 default:
8851 gen_mfc0(ctx, t0, rt, sel);
8852 break;
8854 case 12:
8855 switch (sel) {
8856 case 0:
8857 gen_helper_mftc0_status(t0, cpu_env);
8858 break;
8859 default:
8860 gen_mfc0(ctx, t0, rt, sel);
8861 break;
8863 case 13:
8864 switch (sel) {
8865 case 0:
8866 gen_helper_mftc0_cause(t0, cpu_env);
8867 break;
8868 default:
8869 goto die;
8870 break;
8872 break;
8873 case 14:
8874 switch (sel) {
8875 case 0:
8876 gen_helper_mftc0_epc(t0, cpu_env);
8877 break;
8878 default:
8879 goto die;
8880 break;
8882 break;
8883 case 15:
8884 switch (sel) {
8885 case 1:
8886 gen_helper_mftc0_ebase(t0, cpu_env);
8887 break;
8888 default:
8889 goto die;
8890 break;
8892 break;
8893 case 16:
8894 switch (sel) {
8895 case 0:
8896 case 1:
8897 case 2:
8898 case 3:
8899 case 4:
8900 case 5:
8901 case 6:
8902 case 7:
8903 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
8904 break;
8905 default:
8906 goto die;
8907 break;
8909 break;
8910 case 23:
8911 switch (sel) {
8912 case 0:
8913 gen_helper_mftc0_debug(t0, cpu_env);
8914 break;
8915 default:
8916 gen_mfc0(ctx, t0, rt, sel);
8917 break;
8919 break;
8920 default:
8921 gen_mfc0(ctx, t0, rt, sel);
8923 } else switch (sel) {
8924 /* GPR registers. */
8925 case 0:
8926 gen_helper_1e0i(mftgpr, t0, rt);
8927 break;
8928 /* Auxiliary CPU registers */
8929 case 1:
8930 switch (rt) {
8931 case 0:
8932 gen_helper_1e0i(mftlo, t0, 0);
8933 break;
8934 case 1:
8935 gen_helper_1e0i(mfthi, t0, 0);
8936 break;
8937 case 2:
8938 gen_helper_1e0i(mftacx, t0, 0);
8939 break;
8940 case 4:
8941 gen_helper_1e0i(mftlo, t0, 1);
8942 break;
8943 case 5:
8944 gen_helper_1e0i(mfthi, t0, 1);
8945 break;
8946 case 6:
8947 gen_helper_1e0i(mftacx, t0, 1);
8948 break;
8949 case 8:
8950 gen_helper_1e0i(mftlo, t0, 2);
8951 break;
8952 case 9:
8953 gen_helper_1e0i(mfthi, t0, 2);
8954 break;
8955 case 10:
8956 gen_helper_1e0i(mftacx, t0, 2);
8957 break;
8958 case 12:
8959 gen_helper_1e0i(mftlo, t0, 3);
8960 break;
8961 case 13:
8962 gen_helper_1e0i(mfthi, t0, 3);
8963 break;
8964 case 14:
8965 gen_helper_1e0i(mftacx, t0, 3);
8966 break;
8967 case 16:
8968 gen_helper_mftdsp(t0, cpu_env);
8969 break;
8970 default:
8971 goto die;
8973 break;
8974 /* Floating point (COP1). */
8975 case 2:
8976 /* XXX: For now we support only a single FPU context. */
8977 if (h == 0) {
8978 TCGv_i32 fp0 = tcg_temp_new_i32();
8980 gen_load_fpr32(ctx, fp0, rt);
8981 tcg_gen_ext_i32_tl(t0, fp0);
8982 tcg_temp_free_i32(fp0);
8983 } else {
8984 TCGv_i32 fp0 = tcg_temp_new_i32();
8986 gen_load_fpr32h(ctx, fp0, rt);
8987 tcg_gen_ext_i32_tl(t0, fp0);
8988 tcg_temp_free_i32(fp0);
8990 break;
8991 case 3:
8992 /* XXX: For now we support only a single FPU context. */
8993 gen_helper_1e0i(cfc1, t0, rt);
8994 break;
8995 /* COP2: Not implemented. */
8996 case 4:
8997 case 5:
8998 /* fall through */
8999 default:
9000 goto die;
9002 trace_mips_translate_tr("mftr", rt, u, sel, h);
9003 gen_store_gpr(t0, rd);
9004 tcg_temp_free(t0);
9005 return;
9007 die:
9008 tcg_temp_free(t0);
9009 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9010 generate_exception_end(ctx, EXCP_RI);
9013 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9014 int u, int sel, int h)
9016 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9017 TCGv t0 = tcg_temp_local_new();
9019 gen_load_gpr(t0, rt);
9020 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9021 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9022 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9023 /* NOP */ ;
9024 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9025 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9026 /* NOP */ ;
9027 else if (u == 0) {
9028 switch (rd) {
9029 case 1:
9030 switch (sel) {
9031 case 1:
9032 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9033 break;
9034 case 2:
9035 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9036 break;
9037 default:
9038 goto die;
9039 break;
9041 break;
9042 case 2:
9043 switch (sel) {
9044 case 1:
9045 gen_helper_mttc0_tcstatus(cpu_env, t0);
9046 break;
9047 case 2:
9048 gen_helper_mttc0_tcbind(cpu_env, t0);
9049 break;
9050 case 3:
9051 gen_helper_mttc0_tcrestart(cpu_env, t0);
9052 break;
9053 case 4:
9054 gen_helper_mttc0_tchalt(cpu_env, t0);
9055 break;
9056 case 5:
9057 gen_helper_mttc0_tccontext(cpu_env, t0);
9058 break;
9059 case 6:
9060 gen_helper_mttc0_tcschedule(cpu_env, t0);
9061 break;
9062 case 7:
9063 gen_helper_mttc0_tcschefback(cpu_env, t0);
9064 break;
9065 default:
9066 gen_mtc0(ctx, t0, rd, sel);
9067 break;
9069 break;
9070 case 10:
9071 switch (sel) {
9072 case 0:
9073 gen_helper_mttc0_entryhi(cpu_env, t0);
9074 break;
9075 default:
9076 gen_mtc0(ctx, t0, rd, sel);
9077 break;
9079 case 12:
9080 switch (sel) {
9081 case 0:
9082 gen_helper_mttc0_status(cpu_env, t0);
9083 break;
9084 default:
9085 gen_mtc0(ctx, t0, rd, sel);
9086 break;
9088 case 13:
9089 switch (sel) {
9090 case 0:
9091 gen_helper_mttc0_cause(cpu_env, t0);
9092 break;
9093 default:
9094 goto die;
9095 break;
9097 break;
9098 case 15:
9099 switch (sel) {
9100 case 1:
9101 gen_helper_mttc0_ebase(cpu_env, t0);
9102 break;
9103 default:
9104 goto die;
9105 break;
9107 break;
9108 case 23:
9109 switch (sel) {
9110 case 0:
9111 gen_helper_mttc0_debug(cpu_env, t0);
9112 break;
9113 default:
9114 gen_mtc0(ctx, t0, rd, sel);
9115 break;
9117 break;
9118 default:
9119 gen_mtc0(ctx, t0, rd, sel);
9121 } else switch (sel) {
9122 /* GPR registers. */
9123 case 0:
9124 gen_helper_0e1i(mttgpr, t0, rd);
9125 break;
9126 /* Auxiliary CPU registers */
9127 case 1:
9128 switch (rd) {
9129 case 0:
9130 gen_helper_0e1i(mttlo, t0, 0);
9131 break;
9132 case 1:
9133 gen_helper_0e1i(mtthi, t0, 0);
9134 break;
9135 case 2:
9136 gen_helper_0e1i(mttacx, t0, 0);
9137 break;
9138 case 4:
9139 gen_helper_0e1i(mttlo, t0, 1);
9140 break;
9141 case 5:
9142 gen_helper_0e1i(mtthi, t0, 1);
9143 break;
9144 case 6:
9145 gen_helper_0e1i(mttacx, t0, 1);
9146 break;
9147 case 8:
9148 gen_helper_0e1i(mttlo, t0, 2);
9149 break;
9150 case 9:
9151 gen_helper_0e1i(mtthi, t0, 2);
9152 break;
9153 case 10:
9154 gen_helper_0e1i(mttacx, t0, 2);
9155 break;
9156 case 12:
9157 gen_helper_0e1i(mttlo, t0, 3);
9158 break;
9159 case 13:
9160 gen_helper_0e1i(mtthi, t0, 3);
9161 break;
9162 case 14:
9163 gen_helper_0e1i(mttacx, t0, 3);
9164 break;
9165 case 16:
9166 gen_helper_mttdsp(cpu_env, t0);
9167 break;
9168 default:
9169 goto die;
9171 break;
9172 /* Floating point (COP1). */
9173 case 2:
9174 /* XXX: For now we support only a single FPU context. */
9175 if (h == 0) {
9176 TCGv_i32 fp0 = tcg_temp_new_i32();
9178 tcg_gen_trunc_tl_i32(fp0, t0);
9179 gen_store_fpr32(ctx, fp0, rd);
9180 tcg_temp_free_i32(fp0);
9181 } else {
9182 TCGv_i32 fp0 = tcg_temp_new_i32();
9184 tcg_gen_trunc_tl_i32(fp0, t0);
9185 gen_store_fpr32h(ctx, fp0, rd);
9186 tcg_temp_free_i32(fp0);
9188 break;
9189 case 3:
9190 /* XXX: For now we support only a single FPU context. */
9192 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9194 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9195 tcg_temp_free_i32(fs_tmp);
9197 /* Stop translation as we may have changed hflags */
9198 ctx->base.is_jmp = DISAS_STOP;
9199 break;
9200 /* COP2: Not implemented. */
9201 case 4:
9202 case 5:
9203 /* fall through */
9204 default:
9205 goto die;
9207 trace_mips_translate_tr("mttr", rd, u, sel, h);
9208 tcg_temp_free(t0);
9209 return;
9211 die:
9212 tcg_temp_free(t0);
9213 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9214 generate_exception_end(ctx, EXCP_RI);
9217 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9219 const char *opn = "ldst";
9221 check_cp0_enabled(ctx);
9222 switch (opc) {
9223 case OPC_MFC0:
9224 if (rt == 0) {
9225 /* Treat as NOP. */
9226 return;
9228 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9229 opn = "mfc0";
9230 break;
9231 case OPC_MTC0:
9233 TCGv t0 = tcg_temp_new();
9235 gen_load_gpr(t0, rt);
9236 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9237 tcg_temp_free(t0);
9239 opn = "mtc0";
9240 break;
9241 #if defined(TARGET_MIPS64)
9242 case OPC_DMFC0:
9243 check_insn(ctx, ISA_MIPS3);
9244 if (rt == 0) {
9245 /* Treat as NOP. */
9246 return;
9248 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9249 opn = "dmfc0";
9250 break;
9251 case OPC_DMTC0:
9252 check_insn(ctx, ISA_MIPS3);
9254 TCGv t0 = tcg_temp_new();
9256 gen_load_gpr(t0, rt);
9257 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9258 tcg_temp_free(t0);
9260 opn = "dmtc0";
9261 break;
9262 #endif
9263 case OPC_MFHC0:
9264 check_mvh(ctx);
9265 if (rt == 0) {
9266 /* Treat as NOP. */
9267 return;
9269 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9270 opn = "mfhc0";
9271 break;
9272 case OPC_MTHC0:
9273 check_mvh(ctx);
9275 TCGv t0 = tcg_temp_new();
9276 gen_load_gpr(t0, rt);
9277 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9278 tcg_temp_free(t0);
9280 opn = "mthc0";
9281 break;
9282 case OPC_MFTR:
9283 check_cp0_enabled(ctx);
9284 if (rd == 0) {
9285 /* Treat as NOP. */
9286 return;
9288 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9289 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9290 opn = "mftr";
9291 break;
9292 case OPC_MTTR:
9293 check_cp0_enabled(ctx);
9294 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9295 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9296 opn = "mttr";
9297 break;
9298 case OPC_TLBWI:
9299 opn = "tlbwi";
9300 if (!env->tlb->helper_tlbwi)
9301 goto die;
9302 gen_helper_tlbwi(cpu_env);
9303 break;
9304 case OPC_TLBINV:
9305 opn = "tlbinv";
9306 if (ctx->ie >= 2) {
9307 if (!env->tlb->helper_tlbinv) {
9308 goto die;
9310 gen_helper_tlbinv(cpu_env);
9311 } /* treat as nop if TLBINV not supported */
9312 break;
9313 case OPC_TLBINVF:
9314 opn = "tlbinvf";
9315 if (ctx->ie >= 2) {
9316 if (!env->tlb->helper_tlbinvf) {
9317 goto die;
9319 gen_helper_tlbinvf(cpu_env);
9320 } /* treat as nop if TLBINV not supported */
9321 break;
9322 case OPC_TLBWR:
9323 opn = "tlbwr";
9324 if (!env->tlb->helper_tlbwr)
9325 goto die;
9326 gen_helper_tlbwr(cpu_env);
9327 break;
9328 case OPC_TLBP:
9329 opn = "tlbp";
9330 if (!env->tlb->helper_tlbp)
9331 goto die;
9332 gen_helper_tlbp(cpu_env);
9333 break;
9334 case OPC_TLBR:
9335 opn = "tlbr";
9336 if (!env->tlb->helper_tlbr)
9337 goto die;
9338 gen_helper_tlbr(cpu_env);
9339 break;
9340 case OPC_ERET: /* OPC_ERETNC */
9341 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9342 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9343 goto die;
9344 } else {
9345 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9346 if (ctx->opcode & (1 << bit_shift)) {
9347 /* OPC_ERETNC */
9348 opn = "eretnc";
9349 check_insn(ctx, ISA_MIPS32R5);
9350 gen_helper_eretnc(cpu_env);
9351 } else {
9352 /* OPC_ERET */
9353 opn = "eret";
9354 check_insn(ctx, ISA_MIPS2);
9355 gen_helper_eret(cpu_env);
9357 ctx->base.is_jmp = DISAS_EXIT;
9359 break;
9360 case OPC_DERET:
9361 opn = "deret";
9362 check_insn(ctx, ISA_MIPS32);
9363 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9364 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9365 goto die;
9367 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9368 MIPS_INVAL(opn);
9369 generate_exception_end(ctx, EXCP_RI);
9370 } else {
9371 gen_helper_deret(cpu_env);
9372 ctx->base.is_jmp = DISAS_EXIT;
9374 break;
9375 case OPC_WAIT:
9376 opn = "wait";
9377 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9378 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9379 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9380 goto die;
9382 /* If we get an exception, we want to restart at next instruction */
9383 ctx->base.pc_next += 4;
9384 save_cpu_state(ctx, 1);
9385 ctx->base.pc_next -= 4;
9386 gen_helper_wait(cpu_env);
9387 ctx->base.is_jmp = DISAS_NORETURN;
9388 break;
9389 default:
9390 die:
9391 MIPS_INVAL(opn);
9392 generate_exception_end(ctx, EXCP_RI);
9393 return;
9395 (void)opn; /* avoid a compiler warning */
9397 #endif /* !CONFIG_USER_ONLY */
9399 /* CP1 Branches (before delay slot) */
9400 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9401 int32_t cc, int32_t offset)
9403 target_ulong btarget;
9404 TCGv_i32 t0 = tcg_temp_new_i32();
9406 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9407 generate_exception_end(ctx, EXCP_RI);
9408 goto out;
9411 if (cc != 0)
9412 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9414 btarget = ctx->base.pc_next + 4 + offset;
9416 switch (op) {
9417 case OPC_BC1F:
9418 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9419 tcg_gen_not_i32(t0, t0);
9420 tcg_gen_andi_i32(t0, t0, 1);
9421 tcg_gen_extu_i32_tl(bcond, t0);
9422 goto not_likely;
9423 case OPC_BC1FL:
9424 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9425 tcg_gen_not_i32(t0, t0);
9426 tcg_gen_andi_i32(t0, t0, 1);
9427 tcg_gen_extu_i32_tl(bcond, t0);
9428 goto likely;
9429 case OPC_BC1T:
9430 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9431 tcg_gen_andi_i32(t0, t0, 1);
9432 tcg_gen_extu_i32_tl(bcond, t0);
9433 goto not_likely;
9434 case OPC_BC1TL:
9435 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9436 tcg_gen_andi_i32(t0, t0, 1);
9437 tcg_gen_extu_i32_tl(bcond, t0);
9438 likely:
9439 ctx->hflags |= MIPS_HFLAG_BL;
9440 break;
9441 case OPC_BC1FANY2:
9443 TCGv_i32 t1 = tcg_temp_new_i32();
9444 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9445 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9446 tcg_gen_nand_i32(t0, t0, t1);
9447 tcg_temp_free_i32(t1);
9448 tcg_gen_andi_i32(t0, t0, 1);
9449 tcg_gen_extu_i32_tl(bcond, t0);
9451 goto not_likely;
9452 case OPC_BC1TANY2:
9454 TCGv_i32 t1 = tcg_temp_new_i32();
9455 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9456 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9457 tcg_gen_or_i32(t0, t0, t1);
9458 tcg_temp_free_i32(t1);
9459 tcg_gen_andi_i32(t0, t0, 1);
9460 tcg_gen_extu_i32_tl(bcond, t0);
9462 goto not_likely;
9463 case OPC_BC1FANY4:
9465 TCGv_i32 t1 = tcg_temp_new_i32();
9466 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9467 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9468 tcg_gen_and_i32(t0, t0, t1);
9469 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9470 tcg_gen_and_i32(t0, t0, t1);
9471 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9472 tcg_gen_nand_i32(t0, t0, t1);
9473 tcg_temp_free_i32(t1);
9474 tcg_gen_andi_i32(t0, t0, 1);
9475 tcg_gen_extu_i32_tl(bcond, t0);
9477 goto not_likely;
9478 case OPC_BC1TANY4:
9480 TCGv_i32 t1 = tcg_temp_new_i32();
9481 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9482 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9483 tcg_gen_or_i32(t0, t0, t1);
9484 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9485 tcg_gen_or_i32(t0, t0, t1);
9486 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9487 tcg_gen_or_i32(t0, t0, t1);
9488 tcg_temp_free_i32(t1);
9489 tcg_gen_andi_i32(t0, t0, 1);
9490 tcg_gen_extu_i32_tl(bcond, t0);
9492 not_likely:
9493 ctx->hflags |= MIPS_HFLAG_BC;
9494 break;
9495 default:
9496 MIPS_INVAL("cp1 cond branch");
9497 generate_exception_end(ctx, EXCP_RI);
9498 goto out;
9500 ctx->btarget = btarget;
9501 ctx->hflags |= MIPS_HFLAG_BDS32;
9502 out:
9503 tcg_temp_free_i32(t0);
9506 /* R6 CP1 Branches */
9507 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9508 int32_t ft, int32_t offset,
9509 int delayslot_size)
9511 target_ulong btarget;
9512 TCGv_i64 t0 = tcg_temp_new_i64();
9514 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9515 #ifdef MIPS_DEBUG_DISAS
9516 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9517 "\n", ctx->base.pc_next);
9518 #endif
9519 generate_exception_end(ctx, EXCP_RI);
9520 goto out;
9523 gen_load_fpr64(ctx, t0, ft);
9524 tcg_gen_andi_i64(t0, t0, 1);
9526 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9528 switch (op) {
9529 case OPC_BC1EQZ:
9530 tcg_gen_xori_i64(t0, t0, 1);
9531 ctx->hflags |= MIPS_HFLAG_BC;
9532 break;
9533 case OPC_BC1NEZ:
9534 /* t0 already set */
9535 ctx->hflags |= MIPS_HFLAG_BC;
9536 break;
9537 default:
9538 MIPS_INVAL("cp1 cond branch");
9539 generate_exception_end(ctx, EXCP_RI);
9540 goto out;
9543 tcg_gen_trunc_i64_tl(bcond, t0);
9545 ctx->btarget = btarget;
9547 switch (delayslot_size) {
9548 case 2:
9549 ctx->hflags |= MIPS_HFLAG_BDS16;
9550 break;
9551 case 4:
9552 ctx->hflags |= MIPS_HFLAG_BDS32;
9553 break;
9556 out:
9557 tcg_temp_free_i64(t0);
9560 /* Coprocessor 1 (FPU) */
9562 #define FOP(func, fmt) (((fmt) << 21) | (func))
9564 enum fopcode {
9565 OPC_ADD_S = FOP(0, FMT_S),
9566 OPC_SUB_S = FOP(1, FMT_S),
9567 OPC_MUL_S = FOP(2, FMT_S),
9568 OPC_DIV_S = FOP(3, FMT_S),
9569 OPC_SQRT_S = FOP(4, FMT_S),
9570 OPC_ABS_S = FOP(5, FMT_S),
9571 OPC_MOV_S = FOP(6, FMT_S),
9572 OPC_NEG_S = FOP(7, FMT_S),
9573 OPC_ROUND_L_S = FOP(8, FMT_S),
9574 OPC_TRUNC_L_S = FOP(9, FMT_S),
9575 OPC_CEIL_L_S = FOP(10, FMT_S),
9576 OPC_FLOOR_L_S = FOP(11, FMT_S),
9577 OPC_ROUND_W_S = FOP(12, FMT_S),
9578 OPC_TRUNC_W_S = FOP(13, FMT_S),
9579 OPC_CEIL_W_S = FOP(14, FMT_S),
9580 OPC_FLOOR_W_S = FOP(15, FMT_S),
9581 OPC_SEL_S = FOP(16, FMT_S),
9582 OPC_MOVCF_S = FOP(17, FMT_S),
9583 OPC_MOVZ_S = FOP(18, FMT_S),
9584 OPC_MOVN_S = FOP(19, FMT_S),
9585 OPC_SELEQZ_S = FOP(20, FMT_S),
9586 OPC_RECIP_S = FOP(21, FMT_S),
9587 OPC_RSQRT_S = FOP(22, FMT_S),
9588 OPC_SELNEZ_S = FOP(23, FMT_S),
9589 OPC_MADDF_S = FOP(24, FMT_S),
9590 OPC_MSUBF_S = FOP(25, FMT_S),
9591 OPC_RINT_S = FOP(26, FMT_S),
9592 OPC_CLASS_S = FOP(27, FMT_S),
9593 OPC_MIN_S = FOP(28, FMT_S),
9594 OPC_RECIP2_S = FOP(28, FMT_S),
9595 OPC_MINA_S = FOP(29, FMT_S),
9596 OPC_RECIP1_S = FOP(29, FMT_S),
9597 OPC_MAX_S = FOP(30, FMT_S),
9598 OPC_RSQRT1_S = FOP(30, FMT_S),
9599 OPC_MAXA_S = FOP(31, FMT_S),
9600 OPC_RSQRT2_S = FOP(31, FMT_S),
9601 OPC_CVT_D_S = FOP(33, FMT_S),
9602 OPC_CVT_W_S = FOP(36, FMT_S),
9603 OPC_CVT_L_S = FOP(37, FMT_S),
9604 OPC_CVT_PS_S = FOP(38, FMT_S),
9605 OPC_CMP_F_S = FOP (48, FMT_S),
9606 OPC_CMP_UN_S = FOP (49, FMT_S),
9607 OPC_CMP_EQ_S = FOP (50, FMT_S),
9608 OPC_CMP_UEQ_S = FOP (51, FMT_S),
9609 OPC_CMP_OLT_S = FOP (52, FMT_S),
9610 OPC_CMP_ULT_S = FOP (53, FMT_S),
9611 OPC_CMP_OLE_S = FOP (54, FMT_S),
9612 OPC_CMP_ULE_S = FOP (55, FMT_S),
9613 OPC_CMP_SF_S = FOP (56, FMT_S),
9614 OPC_CMP_NGLE_S = FOP (57, FMT_S),
9615 OPC_CMP_SEQ_S = FOP (58, FMT_S),
9616 OPC_CMP_NGL_S = FOP (59, FMT_S),
9617 OPC_CMP_LT_S = FOP (60, FMT_S),
9618 OPC_CMP_NGE_S = FOP (61, FMT_S),
9619 OPC_CMP_LE_S = FOP (62, FMT_S),
9620 OPC_CMP_NGT_S = FOP (63, FMT_S),
9622 OPC_ADD_D = FOP(0, FMT_D),
9623 OPC_SUB_D = FOP(1, FMT_D),
9624 OPC_MUL_D = FOP(2, FMT_D),
9625 OPC_DIV_D = FOP(3, FMT_D),
9626 OPC_SQRT_D = FOP(4, FMT_D),
9627 OPC_ABS_D = FOP(5, FMT_D),
9628 OPC_MOV_D = FOP(6, FMT_D),
9629 OPC_NEG_D = FOP(7, FMT_D),
9630 OPC_ROUND_L_D = FOP(8, FMT_D),
9631 OPC_TRUNC_L_D = FOP(9, FMT_D),
9632 OPC_CEIL_L_D = FOP(10, FMT_D),
9633 OPC_FLOOR_L_D = FOP(11, FMT_D),
9634 OPC_ROUND_W_D = FOP(12, FMT_D),
9635 OPC_TRUNC_W_D = FOP(13, FMT_D),
9636 OPC_CEIL_W_D = FOP(14, FMT_D),
9637 OPC_FLOOR_W_D = FOP(15, FMT_D),
9638 OPC_SEL_D = FOP(16, FMT_D),
9639 OPC_MOVCF_D = FOP(17, FMT_D),
9640 OPC_MOVZ_D = FOP(18, FMT_D),
9641 OPC_MOVN_D = FOP(19, FMT_D),
9642 OPC_SELEQZ_D = FOP(20, FMT_D),
9643 OPC_RECIP_D = FOP(21, FMT_D),
9644 OPC_RSQRT_D = FOP(22, FMT_D),
9645 OPC_SELNEZ_D = FOP(23, FMT_D),
9646 OPC_MADDF_D = FOP(24, FMT_D),
9647 OPC_MSUBF_D = FOP(25, FMT_D),
9648 OPC_RINT_D = FOP(26, FMT_D),
9649 OPC_CLASS_D = FOP(27, FMT_D),
9650 OPC_MIN_D = FOP(28, FMT_D),
9651 OPC_RECIP2_D = FOP(28, FMT_D),
9652 OPC_MINA_D = FOP(29, FMT_D),
9653 OPC_RECIP1_D = FOP(29, FMT_D),
9654 OPC_MAX_D = FOP(30, FMT_D),
9655 OPC_RSQRT1_D = FOP(30, FMT_D),
9656 OPC_MAXA_D = FOP(31, FMT_D),
9657 OPC_RSQRT2_D = FOP(31, FMT_D),
9658 OPC_CVT_S_D = FOP(32, FMT_D),
9659 OPC_CVT_W_D = FOP(36, FMT_D),
9660 OPC_CVT_L_D = FOP(37, FMT_D),
9661 OPC_CMP_F_D = FOP (48, FMT_D),
9662 OPC_CMP_UN_D = FOP (49, FMT_D),
9663 OPC_CMP_EQ_D = FOP (50, FMT_D),
9664 OPC_CMP_UEQ_D = FOP (51, FMT_D),
9665 OPC_CMP_OLT_D = FOP (52, FMT_D),
9666 OPC_CMP_ULT_D = FOP (53, FMT_D),
9667 OPC_CMP_OLE_D = FOP (54, FMT_D),
9668 OPC_CMP_ULE_D = FOP (55, FMT_D),
9669 OPC_CMP_SF_D = FOP (56, FMT_D),
9670 OPC_CMP_NGLE_D = FOP (57, FMT_D),
9671 OPC_CMP_SEQ_D = FOP (58, FMT_D),
9672 OPC_CMP_NGL_D = FOP (59, FMT_D),
9673 OPC_CMP_LT_D = FOP (60, FMT_D),
9674 OPC_CMP_NGE_D = FOP (61, FMT_D),
9675 OPC_CMP_LE_D = FOP (62, FMT_D),
9676 OPC_CMP_NGT_D = FOP (63, FMT_D),
9678 OPC_CVT_S_W = FOP(32, FMT_W),
9679 OPC_CVT_D_W = FOP(33, FMT_W),
9680 OPC_CVT_S_L = FOP(32, FMT_L),
9681 OPC_CVT_D_L = FOP(33, FMT_L),
9682 OPC_CVT_PS_PW = FOP(38, FMT_W),
9684 OPC_ADD_PS = FOP(0, FMT_PS),
9685 OPC_SUB_PS = FOP(1, FMT_PS),
9686 OPC_MUL_PS = FOP(2, FMT_PS),
9687 OPC_DIV_PS = FOP(3, FMT_PS),
9688 OPC_ABS_PS = FOP(5, FMT_PS),
9689 OPC_MOV_PS = FOP(6, FMT_PS),
9690 OPC_NEG_PS = FOP(7, FMT_PS),
9691 OPC_MOVCF_PS = FOP(17, FMT_PS),
9692 OPC_MOVZ_PS = FOP(18, FMT_PS),
9693 OPC_MOVN_PS = FOP(19, FMT_PS),
9694 OPC_ADDR_PS = FOP(24, FMT_PS),
9695 OPC_MULR_PS = FOP(26, FMT_PS),
9696 OPC_RECIP2_PS = FOP(28, FMT_PS),
9697 OPC_RECIP1_PS = FOP(29, FMT_PS),
9698 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9699 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9701 OPC_CVT_S_PU = FOP(32, FMT_PS),
9702 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9703 OPC_CVT_S_PL = FOP(40, FMT_PS),
9704 OPC_PLL_PS = FOP(44, FMT_PS),
9705 OPC_PLU_PS = FOP(45, FMT_PS),
9706 OPC_PUL_PS = FOP(46, FMT_PS),
9707 OPC_PUU_PS = FOP(47, FMT_PS),
9708 OPC_CMP_F_PS = FOP (48, FMT_PS),
9709 OPC_CMP_UN_PS = FOP (49, FMT_PS),
9710 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
9711 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
9712 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
9713 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
9714 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
9715 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
9716 OPC_CMP_SF_PS = FOP (56, FMT_PS),
9717 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
9718 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
9719 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
9720 OPC_CMP_LT_PS = FOP (60, FMT_PS),
9721 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
9722 OPC_CMP_LE_PS = FOP (62, FMT_PS),
9723 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
9726 enum r6_f_cmp_op {
9727 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9728 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9729 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9730 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9731 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9732 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9733 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9734 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9735 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9736 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9737 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9738 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9739 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9740 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9741 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9742 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9743 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9744 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9745 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9746 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9747 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9748 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9750 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9751 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9752 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9753 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9754 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9755 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9756 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9757 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9758 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9759 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9760 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9761 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9762 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9763 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9764 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9765 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9766 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9767 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9768 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9769 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9770 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9771 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9773 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
9775 TCGv t0 = tcg_temp_new();
9777 switch (opc) {
9778 case OPC_MFC1:
9780 TCGv_i32 fp0 = tcg_temp_new_i32();
9782 gen_load_fpr32(ctx, fp0, fs);
9783 tcg_gen_ext_i32_tl(t0, fp0);
9784 tcg_temp_free_i32(fp0);
9786 gen_store_gpr(t0, rt);
9787 break;
9788 case OPC_MTC1:
9789 gen_load_gpr(t0, rt);
9791 TCGv_i32 fp0 = tcg_temp_new_i32();
9793 tcg_gen_trunc_tl_i32(fp0, t0);
9794 gen_store_fpr32(ctx, fp0, fs);
9795 tcg_temp_free_i32(fp0);
9797 break;
9798 case OPC_CFC1:
9799 gen_helper_1e0i(cfc1, t0, fs);
9800 gen_store_gpr(t0, rt);
9801 break;
9802 case OPC_CTC1:
9803 gen_load_gpr(t0, rt);
9804 save_cpu_state(ctx, 0);
9806 TCGv_i32 fs_tmp = tcg_const_i32(fs);
9808 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9809 tcg_temp_free_i32(fs_tmp);
9811 /* Stop translation as we may have changed hflags */
9812 ctx->base.is_jmp = DISAS_STOP;
9813 break;
9814 #if defined(TARGET_MIPS64)
9815 case OPC_DMFC1:
9816 gen_load_fpr64(ctx, t0, fs);
9817 gen_store_gpr(t0, rt);
9818 break;
9819 case OPC_DMTC1:
9820 gen_load_gpr(t0, rt);
9821 gen_store_fpr64(ctx, t0, fs);
9822 break;
9823 #endif
9824 case OPC_MFHC1:
9826 TCGv_i32 fp0 = tcg_temp_new_i32();
9828 gen_load_fpr32h(ctx, fp0, fs);
9829 tcg_gen_ext_i32_tl(t0, fp0);
9830 tcg_temp_free_i32(fp0);
9832 gen_store_gpr(t0, rt);
9833 break;
9834 case OPC_MTHC1:
9835 gen_load_gpr(t0, rt);
9837 TCGv_i32 fp0 = tcg_temp_new_i32();
9839 tcg_gen_trunc_tl_i32(fp0, t0);
9840 gen_store_fpr32h(ctx, fp0, fs);
9841 tcg_temp_free_i32(fp0);
9843 break;
9844 default:
9845 MIPS_INVAL("cp1 move");
9846 generate_exception_end(ctx, EXCP_RI);
9847 goto out;
9850 out:
9851 tcg_temp_free(t0);
9854 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
9856 TCGLabel *l1;
9857 TCGCond cond;
9858 TCGv_i32 t0;
9860 if (rd == 0) {
9861 /* Treat as NOP. */
9862 return;
9865 if (tf)
9866 cond = TCG_COND_EQ;
9867 else
9868 cond = TCG_COND_NE;
9870 l1 = gen_new_label();
9871 t0 = tcg_temp_new_i32();
9872 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9873 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9874 tcg_temp_free_i32(t0);
9875 if (rs == 0) {
9876 tcg_gen_movi_tl(cpu_gpr[rd], 0);
9877 } else {
9878 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
9880 gen_set_label(l1);
9883 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9884 int tf)
9886 int cond;
9887 TCGv_i32 t0 = tcg_temp_new_i32();
9888 TCGLabel *l1 = gen_new_label();
9890 if (tf)
9891 cond = TCG_COND_EQ;
9892 else
9893 cond = TCG_COND_NE;
9895 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9896 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9897 gen_load_fpr32(ctx, t0, fs);
9898 gen_store_fpr32(ctx, t0, fd);
9899 gen_set_label(l1);
9900 tcg_temp_free_i32(t0);
9903 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
9905 int cond;
9906 TCGv_i32 t0 = tcg_temp_new_i32();
9907 TCGv_i64 fp0;
9908 TCGLabel *l1 = gen_new_label();
9910 if (tf)
9911 cond = TCG_COND_EQ;
9912 else
9913 cond = TCG_COND_NE;
9915 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9916 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9917 tcg_temp_free_i32(t0);
9918 fp0 = tcg_temp_new_i64();
9919 gen_load_fpr64(ctx, fp0, fs);
9920 gen_store_fpr64(ctx, fp0, fd);
9921 tcg_temp_free_i64(fp0);
9922 gen_set_label(l1);
9925 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9926 int cc, int tf)
9928 int cond;
9929 TCGv_i32 t0 = tcg_temp_new_i32();
9930 TCGLabel *l1 = gen_new_label();
9931 TCGLabel *l2 = gen_new_label();
9933 if (tf)
9934 cond = TCG_COND_EQ;
9935 else
9936 cond = TCG_COND_NE;
9938 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9939 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9940 gen_load_fpr32(ctx, t0, fs);
9941 gen_store_fpr32(ctx, t0, fd);
9942 gen_set_label(l1);
9944 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
9945 tcg_gen_brcondi_i32(cond, t0, 0, l2);
9946 gen_load_fpr32h(ctx, t0, fs);
9947 gen_store_fpr32h(ctx, t0, fd);
9948 tcg_temp_free_i32(t0);
9949 gen_set_label(l2);
9952 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9953 int fs)
9955 TCGv_i32 t1 = tcg_const_i32(0);
9956 TCGv_i32 fp0 = tcg_temp_new_i32();
9957 TCGv_i32 fp1 = tcg_temp_new_i32();
9958 TCGv_i32 fp2 = tcg_temp_new_i32();
9959 gen_load_fpr32(ctx, fp0, fd);
9960 gen_load_fpr32(ctx, fp1, ft);
9961 gen_load_fpr32(ctx, fp2, fs);
9963 switch (op1) {
9964 case OPC_SEL_S:
9965 tcg_gen_andi_i32(fp0, fp0, 1);
9966 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9967 break;
9968 case OPC_SELEQZ_S:
9969 tcg_gen_andi_i32(fp1, fp1, 1);
9970 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9971 break;
9972 case OPC_SELNEZ_S:
9973 tcg_gen_andi_i32(fp1, fp1, 1);
9974 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9975 break;
9976 default:
9977 MIPS_INVAL("gen_sel_s");
9978 generate_exception_end(ctx, EXCP_RI);
9979 break;
9982 gen_store_fpr32(ctx, fp0, fd);
9983 tcg_temp_free_i32(fp2);
9984 tcg_temp_free_i32(fp1);
9985 tcg_temp_free_i32(fp0);
9986 tcg_temp_free_i32(t1);
9989 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9990 int fs)
9992 TCGv_i64 t1 = tcg_const_i64(0);
9993 TCGv_i64 fp0 = tcg_temp_new_i64();
9994 TCGv_i64 fp1 = tcg_temp_new_i64();
9995 TCGv_i64 fp2 = tcg_temp_new_i64();
9996 gen_load_fpr64(ctx, fp0, fd);
9997 gen_load_fpr64(ctx, fp1, ft);
9998 gen_load_fpr64(ctx, fp2, fs);
10000 switch (op1) {
10001 case OPC_SEL_D:
10002 tcg_gen_andi_i64(fp0, fp0, 1);
10003 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10004 break;
10005 case OPC_SELEQZ_D:
10006 tcg_gen_andi_i64(fp1, fp1, 1);
10007 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10008 break;
10009 case OPC_SELNEZ_D:
10010 tcg_gen_andi_i64(fp1, fp1, 1);
10011 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10012 break;
10013 default:
10014 MIPS_INVAL("gen_sel_d");
10015 generate_exception_end(ctx, EXCP_RI);
10016 break;
10019 gen_store_fpr64(ctx, fp0, fd);
10020 tcg_temp_free_i64(fp2);
10021 tcg_temp_free_i64(fp1);
10022 tcg_temp_free_i64(fp0);
10023 tcg_temp_free_i64(t1);
10026 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10027 int ft, int fs, int fd, int cc)
10029 uint32_t func = ctx->opcode & 0x3f;
10030 switch (op1) {
10031 case OPC_ADD_S:
10033 TCGv_i32 fp0 = tcg_temp_new_i32();
10034 TCGv_i32 fp1 = tcg_temp_new_i32();
10036 gen_load_fpr32(ctx, fp0, fs);
10037 gen_load_fpr32(ctx, fp1, ft);
10038 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10039 tcg_temp_free_i32(fp1);
10040 gen_store_fpr32(ctx, fp0, fd);
10041 tcg_temp_free_i32(fp0);
10043 break;
10044 case OPC_SUB_S:
10046 TCGv_i32 fp0 = tcg_temp_new_i32();
10047 TCGv_i32 fp1 = tcg_temp_new_i32();
10049 gen_load_fpr32(ctx, fp0, fs);
10050 gen_load_fpr32(ctx, fp1, ft);
10051 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10052 tcg_temp_free_i32(fp1);
10053 gen_store_fpr32(ctx, fp0, fd);
10054 tcg_temp_free_i32(fp0);
10056 break;
10057 case OPC_MUL_S:
10059 TCGv_i32 fp0 = tcg_temp_new_i32();
10060 TCGv_i32 fp1 = tcg_temp_new_i32();
10062 gen_load_fpr32(ctx, fp0, fs);
10063 gen_load_fpr32(ctx, fp1, ft);
10064 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10065 tcg_temp_free_i32(fp1);
10066 gen_store_fpr32(ctx, fp0, fd);
10067 tcg_temp_free_i32(fp0);
10069 break;
10070 case OPC_DIV_S:
10072 TCGv_i32 fp0 = tcg_temp_new_i32();
10073 TCGv_i32 fp1 = tcg_temp_new_i32();
10075 gen_load_fpr32(ctx, fp0, fs);
10076 gen_load_fpr32(ctx, fp1, ft);
10077 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10078 tcg_temp_free_i32(fp1);
10079 gen_store_fpr32(ctx, fp0, fd);
10080 tcg_temp_free_i32(fp0);
10082 break;
10083 case OPC_SQRT_S:
10085 TCGv_i32 fp0 = tcg_temp_new_i32();
10087 gen_load_fpr32(ctx, fp0, fs);
10088 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10089 gen_store_fpr32(ctx, fp0, fd);
10090 tcg_temp_free_i32(fp0);
10092 break;
10093 case OPC_ABS_S:
10095 TCGv_i32 fp0 = tcg_temp_new_i32();
10097 gen_load_fpr32(ctx, fp0, fs);
10098 if (ctx->abs2008) {
10099 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10100 } else {
10101 gen_helper_float_abs_s(fp0, fp0);
10103 gen_store_fpr32(ctx, fp0, fd);
10104 tcg_temp_free_i32(fp0);
10106 break;
10107 case OPC_MOV_S:
10109 TCGv_i32 fp0 = tcg_temp_new_i32();
10111 gen_load_fpr32(ctx, fp0, fs);
10112 gen_store_fpr32(ctx, fp0, fd);
10113 tcg_temp_free_i32(fp0);
10115 break;
10116 case OPC_NEG_S:
10118 TCGv_i32 fp0 = tcg_temp_new_i32();
10120 gen_load_fpr32(ctx, fp0, fs);
10121 if (ctx->abs2008) {
10122 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10123 } else {
10124 gen_helper_float_chs_s(fp0, fp0);
10126 gen_store_fpr32(ctx, fp0, fd);
10127 tcg_temp_free_i32(fp0);
10129 break;
10130 case OPC_ROUND_L_S:
10131 check_cp1_64bitmode(ctx);
10133 TCGv_i32 fp32 = tcg_temp_new_i32();
10134 TCGv_i64 fp64 = tcg_temp_new_i64();
10136 gen_load_fpr32(ctx, fp32, fs);
10137 if (ctx->nan2008) {
10138 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10139 } else {
10140 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10142 tcg_temp_free_i32(fp32);
10143 gen_store_fpr64(ctx, fp64, fd);
10144 tcg_temp_free_i64(fp64);
10146 break;
10147 case OPC_TRUNC_L_S:
10148 check_cp1_64bitmode(ctx);
10150 TCGv_i32 fp32 = tcg_temp_new_i32();
10151 TCGv_i64 fp64 = tcg_temp_new_i64();
10153 gen_load_fpr32(ctx, fp32, fs);
10154 if (ctx->nan2008) {
10155 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10156 } else {
10157 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10159 tcg_temp_free_i32(fp32);
10160 gen_store_fpr64(ctx, fp64, fd);
10161 tcg_temp_free_i64(fp64);
10163 break;
10164 case OPC_CEIL_L_S:
10165 check_cp1_64bitmode(ctx);
10167 TCGv_i32 fp32 = tcg_temp_new_i32();
10168 TCGv_i64 fp64 = tcg_temp_new_i64();
10170 gen_load_fpr32(ctx, fp32, fs);
10171 if (ctx->nan2008) {
10172 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10173 } else {
10174 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10176 tcg_temp_free_i32(fp32);
10177 gen_store_fpr64(ctx, fp64, fd);
10178 tcg_temp_free_i64(fp64);
10180 break;
10181 case OPC_FLOOR_L_S:
10182 check_cp1_64bitmode(ctx);
10184 TCGv_i32 fp32 = tcg_temp_new_i32();
10185 TCGv_i64 fp64 = tcg_temp_new_i64();
10187 gen_load_fpr32(ctx, fp32, fs);
10188 if (ctx->nan2008) {
10189 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10190 } else {
10191 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10193 tcg_temp_free_i32(fp32);
10194 gen_store_fpr64(ctx, fp64, fd);
10195 tcg_temp_free_i64(fp64);
10197 break;
10198 case OPC_ROUND_W_S:
10200 TCGv_i32 fp0 = tcg_temp_new_i32();
10202 gen_load_fpr32(ctx, fp0, fs);
10203 if (ctx->nan2008) {
10204 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10205 } else {
10206 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10208 gen_store_fpr32(ctx, fp0, fd);
10209 tcg_temp_free_i32(fp0);
10211 break;
10212 case OPC_TRUNC_W_S:
10214 TCGv_i32 fp0 = tcg_temp_new_i32();
10216 gen_load_fpr32(ctx, fp0, fs);
10217 if (ctx->nan2008) {
10218 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10219 } else {
10220 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10222 gen_store_fpr32(ctx, fp0, fd);
10223 tcg_temp_free_i32(fp0);
10225 break;
10226 case OPC_CEIL_W_S:
10228 TCGv_i32 fp0 = tcg_temp_new_i32();
10230 gen_load_fpr32(ctx, fp0, fs);
10231 if (ctx->nan2008) {
10232 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10233 } else {
10234 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10236 gen_store_fpr32(ctx, fp0, fd);
10237 tcg_temp_free_i32(fp0);
10239 break;
10240 case OPC_FLOOR_W_S:
10242 TCGv_i32 fp0 = tcg_temp_new_i32();
10244 gen_load_fpr32(ctx, fp0, fs);
10245 if (ctx->nan2008) {
10246 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10247 } else {
10248 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10250 gen_store_fpr32(ctx, fp0, fd);
10251 tcg_temp_free_i32(fp0);
10253 break;
10254 case OPC_SEL_S:
10255 check_insn(ctx, ISA_MIPS32R6);
10256 gen_sel_s(ctx, op1, fd, ft, fs);
10257 break;
10258 case OPC_SELEQZ_S:
10259 check_insn(ctx, ISA_MIPS32R6);
10260 gen_sel_s(ctx, op1, fd, ft, fs);
10261 break;
10262 case OPC_SELNEZ_S:
10263 check_insn(ctx, ISA_MIPS32R6);
10264 gen_sel_s(ctx, op1, fd, ft, fs);
10265 break;
10266 case OPC_MOVCF_S:
10267 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10268 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10269 break;
10270 case OPC_MOVZ_S:
10271 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10273 TCGLabel *l1 = gen_new_label();
10274 TCGv_i32 fp0;
10276 if (ft != 0) {
10277 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10279 fp0 = tcg_temp_new_i32();
10280 gen_load_fpr32(ctx, fp0, fs);
10281 gen_store_fpr32(ctx, fp0, fd);
10282 tcg_temp_free_i32(fp0);
10283 gen_set_label(l1);
10285 break;
10286 case OPC_MOVN_S:
10287 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10289 TCGLabel *l1 = gen_new_label();
10290 TCGv_i32 fp0;
10292 if (ft != 0) {
10293 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10294 fp0 = tcg_temp_new_i32();
10295 gen_load_fpr32(ctx, fp0, fs);
10296 gen_store_fpr32(ctx, fp0, fd);
10297 tcg_temp_free_i32(fp0);
10298 gen_set_label(l1);
10301 break;
10302 case OPC_RECIP_S:
10304 TCGv_i32 fp0 = tcg_temp_new_i32();
10306 gen_load_fpr32(ctx, fp0, fs);
10307 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10308 gen_store_fpr32(ctx, fp0, fd);
10309 tcg_temp_free_i32(fp0);
10311 break;
10312 case OPC_RSQRT_S:
10314 TCGv_i32 fp0 = tcg_temp_new_i32();
10316 gen_load_fpr32(ctx, fp0, fs);
10317 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10318 gen_store_fpr32(ctx, fp0, fd);
10319 tcg_temp_free_i32(fp0);
10321 break;
10322 case OPC_MADDF_S:
10323 check_insn(ctx, ISA_MIPS32R6);
10325 TCGv_i32 fp0 = tcg_temp_new_i32();
10326 TCGv_i32 fp1 = tcg_temp_new_i32();
10327 TCGv_i32 fp2 = tcg_temp_new_i32();
10328 gen_load_fpr32(ctx, fp0, fs);
10329 gen_load_fpr32(ctx, fp1, ft);
10330 gen_load_fpr32(ctx, fp2, fd);
10331 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10332 gen_store_fpr32(ctx, fp2, fd);
10333 tcg_temp_free_i32(fp2);
10334 tcg_temp_free_i32(fp1);
10335 tcg_temp_free_i32(fp0);
10337 break;
10338 case OPC_MSUBF_S:
10339 check_insn(ctx, ISA_MIPS32R6);
10341 TCGv_i32 fp0 = tcg_temp_new_i32();
10342 TCGv_i32 fp1 = tcg_temp_new_i32();
10343 TCGv_i32 fp2 = tcg_temp_new_i32();
10344 gen_load_fpr32(ctx, fp0, fs);
10345 gen_load_fpr32(ctx, fp1, ft);
10346 gen_load_fpr32(ctx, fp2, fd);
10347 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10348 gen_store_fpr32(ctx, fp2, fd);
10349 tcg_temp_free_i32(fp2);
10350 tcg_temp_free_i32(fp1);
10351 tcg_temp_free_i32(fp0);
10353 break;
10354 case OPC_RINT_S:
10355 check_insn(ctx, ISA_MIPS32R6);
10357 TCGv_i32 fp0 = tcg_temp_new_i32();
10358 gen_load_fpr32(ctx, fp0, fs);
10359 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10360 gen_store_fpr32(ctx, fp0, fd);
10361 tcg_temp_free_i32(fp0);
10363 break;
10364 case OPC_CLASS_S:
10365 check_insn(ctx, ISA_MIPS32R6);
10367 TCGv_i32 fp0 = tcg_temp_new_i32();
10368 gen_load_fpr32(ctx, fp0, fs);
10369 gen_helper_float_class_s(fp0, cpu_env, fp0);
10370 gen_store_fpr32(ctx, fp0, fd);
10371 tcg_temp_free_i32(fp0);
10373 break;
10374 case OPC_MIN_S: /* OPC_RECIP2_S */
10375 if (ctx->insn_flags & ISA_MIPS32R6) {
10376 /* OPC_MIN_S */
10377 TCGv_i32 fp0 = tcg_temp_new_i32();
10378 TCGv_i32 fp1 = tcg_temp_new_i32();
10379 TCGv_i32 fp2 = tcg_temp_new_i32();
10380 gen_load_fpr32(ctx, fp0, fs);
10381 gen_load_fpr32(ctx, fp1, ft);
10382 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10383 gen_store_fpr32(ctx, fp2, fd);
10384 tcg_temp_free_i32(fp2);
10385 tcg_temp_free_i32(fp1);
10386 tcg_temp_free_i32(fp0);
10387 } else {
10388 /* OPC_RECIP2_S */
10389 check_cp1_64bitmode(ctx);
10391 TCGv_i32 fp0 = tcg_temp_new_i32();
10392 TCGv_i32 fp1 = tcg_temp_new_i32();
10394 gen_load_fpr32(ctx, fp0, fs);
10395 gen_load_fpr32(ctx, fp1, ft);
10396 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10397 tcg_temp_free_i32(fp1);
10398 gen_store_fpr32(ctx, fp0, fd);
10399 tcg_temp_free_i32(fp0);
10402 break;
10403 case OPC_MINA_S: /* OPC_RECIP1_S */
10404 if (ctx->insn_flags & ISA_MIPS32R6) {
10405 /* OPC_MINA_S */
10406 TCGv_i32 fp0 = tcg_temp_new_i32();
10407 TCGv_i32 fp1 = tcg_temp_new_i32();
10408 TCGv_i32 fp2 = tcg_temp_new_i32();
10409 gen_load_fpr32(ctx, fp0, fs);
10410 gen_load_fpr32(ctx, fp1, ft);
10411 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10412 gen_store_fpr32(ctx, fp2, fd);
10413 tcg_temp_free_i32(fp2);
10414 tcg_temp_free_i32(fp1);
10415 tcg_temp_free_i32(fp0);
10416 } else {
10417 /* OPC_RECIP1_S */
10418 check_cp1_64bitmode(ctx);
10420 TCGv_i32 fp0 = tcg_temp_new_i32();
10422 gen_load_fpr32(ctx, fp0, fs);
10423 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10424 gen_store_fpr32(ctx, fp0, fd);
10425 tcg_temp_free_i32(fp0);
10428 break;
10429 case OPC_MAX_S: /* OPC_RSQRT1_S */
10430 if (ctx->insn_flags & ISA_MIPS32R6) {
10431 /* OPC_MAX_S */
10432 TCGv_i32 fp0 = tcg_temp_new_i32();
10433 TCGv_i32 fp1 = tcg_temp_new_i32();
10434 gen_load_fpr32(ctx, fp0, fs);
10435 gen_load_fpr32(ctx, fp1, ft);
10436 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10437 gen_store_fpr32(ctx, fp1, fd);
10438 tcg_temp_free_i32(fp1);
10439 tcg_temp_free_i32(fp0);
10440 } else {
10441 /* OPC_RSQRT1_S */
10442 check_cp1_64bitmode(ctx);
10444 TCGv_i32 fp0 = tcg_temp_new_i32();
10446 gen_load_fpr32(ctx, fp0, fs);
10447 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10448 gen_store_fpr32(ctx, fp0, fd);
10449 tcg_temp_free_i32(fp0);
10452 break;
10453 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10454 if (ctx->insn_flags & ISA_MIPS32R6) {
10455 /* OPC_MAXA_S */
10456 TCGv_i32 fp0 = tcg_temp_new_i32();
10457 TCGv_i32 fp1 = tcg_temp_new_i32();
10458 gen_load_fpr32(ctx, fp0, fs);
10459 gen_load_fpr32(ctx, fp1, ft);
10460 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10461 gen_store_fpr32(ctx, fp1, fd);
10462 tcg_temp_free_i32(fp1);
10463 tcg_temp_free_i32(fp0);
10464 } else {
10465 /* OPC_RSQRT2_S */
10466 check_cp1_64bitmode(ctx);
10468 TCGv_i32 fp0 = tcg_temp_new_i32();
10469 TCGv_i32 fp1 = tcg_temp_new_i32();
10471 gen_load_fpr32(ctx, fp0, fs);
10472 gen_load_fpr32(ctx, fp1, ft);
10473 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10474 tcg_temp_free_i32(fp1);
10475 gen_store_fpr32(ctx, fp0, fd);
10476 tcg_temp_free_i32(fp0);
10479 break;
10480 case OPC_CVT_D_S:
10481 check_cp1_registers(ctx, fd);
10483 TCGv_i32 fp32 = tcg_temp_new_i32();
10484 TCGv_i64 fp64 = tcg_temp_new_i64();
10486 gen_load_fpr32(ctx, fp32, fs);
10487 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10488 tcg_temp_free_i32(fp32);
10489 gen_store_fpr64(ctx, fp64, fd);
10490 tcg_temp_free_i64(fp64);
10492 break;
10493 case OPC_CVT_W_S:
10495 TCGv_i32 fp0 = tcg_temp_new_i32();
10497 gen_load_fpr32(ctx, fp0, fs);
10498 if (ctx->nan2008) {
10499 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10500 } else {
10501 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10503 gen_store_fpr32(ctx, fp0, fd);
10504 tcg_temp_free_i32(fp0);
10506 break;
10507 case OPC_CVT_L_S:
10508 check_cp1_64bitmode(ctx);
10510 TCGv_i32 fp32 = tcg_temp_new_i32();
10511 TCGv_i64 fp64 = tcg_temp_new_i64();
10513 gen_load_fpr32(ctx, fp32, fs);
10514 if (ctx->nan2008) {
10515 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10516 } else {
10517 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10519 tcg_temp_free_i32(fp32);
10520 gen_store_fpr64(ctx, fp64, fd);
10521 tcg_temp_free_i64(fp64);
10523 break;
10524 case OPC_CVT_PS_S:
10525 check_ps(ctx);
10527 TCGv_i64 fp64 = tcg_temp_new_i64();
10528 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10529 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10531 gen_load_fpr32(ctx, fp32_0, fs);
10532 gen_load_fpr32(ctx, fp32_1, ft);
10533 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10534 tcg_temp_free_i32(fp32_1);
10535 tcg_temp_free_i32(fp32_0);
10536 gen_store_fpr64(ctx, fp64, fd);
10537 tcg_temp_free_i64(fp64);
10539 break;
10540 case OPC_CMP_F_S:
10541 case OPC_CMP_UN_S:
10542 case OPC_CMP_EQ_S:
10543 case OPC_CMP_UEQ_S:
10544 case OPC_CMP_OLT_S:
10545 case OPC_CMP_ULT_S:
10546 case OPC_CMP_OLE_S:
10547 case OPC_CMP_ULE_S:
10548 case OPC_CMP_SF_S:
10549 case OPC_CMP_NGLE_S:
10550 case OPC_CMP_SEQ_S:
10551 case OPC_CMP_NGL_S:
10552 case OPC_CMP_LT_S:
10553 case OPC_CMP_NGE_S:
10554 case OPC_CMP_LE_S:
10555 case OPC_CMP_NGT_S:
10556 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10557 if (ctx->opcode & (1 << 6)) {
10558 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
10559 } else {
10560 gen_cmp_s(ctx, func-48, ft, fs, cc);
10562 break;
10563 case OPC_ADD_D:
10564 check_cp1_registers(ctx, fs | ft | fd);
10566 TCGv_i64 fp0 = tcg_temp_new_i64();
10567 TCGv_i64 fp1 = tcg_temp_new_i64();
10569 gen_load_fpr64(ctx, fp0, fs);
10570 gen_load_fpr64(ctx, fp1, ft);
10571 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10572 tcg_temp_free_i64(fp1);
10573 gen_store_fpr64(ctx, fp0, fd);
10574 tcg_temp_free_i64(fp0);
10576 break;
10577 case OPC_SUB_D:
10578 check_cp1_registers(ctx, fs | ft | fd);
10580 TCGv_i64 fp0 = tcg_temp_new_i64();
10581 TCGv_i64 fp1 = tcg_temp_new_i64();
10583 gen_load_fpr64(ctx, fp0, fs);
10584 gen_load_fpr64(ctx, fp1, ft);
10585 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10586 tcg_temp_free_i64(fp1);
10587 gen_store_fpr64(ctx, fp0, fd);
10588 tcg_temp_free_i64(fp0);
10590 break;
10591 case OPC_MUL_D:
10592 check_cp1_registers(ctx, fs | ft | fd);
10594 TCGv_i64 fp0 = tcg_temp_new_i64();
10595 TCGv_i64 fp1 = tcg_temp_new_i64();
10597 gen_load_fpr64(ctx, fp0, fs);
10598 gen_load_fpr64(ctx, fp1, ft);
10599 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10600 tcg_temp_free_i64(fp1);
10601 gen_store_fpr64(ctx, fp0, fd);
10602 tcg_temp_free_i64(fp0);
10604 break;
10605 case OPC_DIV_D:
10606 check_cp1_registers(ctx, fs | ft | fd);
10608 TCGv_i64 fp0 = tcg_temp_new_i64();
10609 TCGv_i64 fp1 = tcg_temp_new_i64();
10611 gen_load_fpr64(ctx, fp0, fs);
10612 gen_load_fpr64(ctx, fp1, ft);
10613 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10614 tcg_temp_free_i64(fp1);
10615 gen_store_fpr64(ctx, fp0, fd);
10616 tcg_temp_free_i64(fp0);
10618 break;
10619 case OPC_SQRT_D:
10620 check_cp1_registers(ctx, fs | fd);
10622 TCGv_i64 fp0 = tcg_temp_new_i64();
10624 gen_load_fpr64(ctx, fp0, fs);
10625 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10626 gen_store_fpr64(ctx, fp0, fd);
10627 tcg_temp_free_i64(fp0);
10629 break;
10630 case OPC_ABS_D:
10631 check_cp1_registers(ctx, fs | fd);
10633 TCGv_i64 fp0 = tcg_temp_new_i64();
10635 gen_load_fpr64(ctx, fp0, fs);
10636 if (ctx->abs2008) {
10637 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10638 } else {
10639 gen_helper_float_abs_d(fp0, fp0);
10641 gen_store_fpr64(ctx, fp0, fd);
10642 tcg_temp_free_i64(fp0);
10644 break;
10645 case OPC_MOV_D:
10646 check_cp1_registers(ctx, fs | fd);
10648 TCGv_i64 fp0 = tcg_temp_new_i64();
10650 gen_load_fpr64(ctx, fp0, fs);
10651 gen_store_fpr64(ctx, fp0, fd);
10652 tcg_temp_free_i64(fp0);
10654 break;
10655 case OPC_NEG_D:
10656 check_cp1_registers(ctx, fs | fd);
10658 TCGv_i64 fp0 = tcg_temp_new_i64();
10660 gen_load_fpr64(ctx, fp0, fs);
10661 if (ctx->abs2008) {
10662 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10663 } else {
10664 gen_helper_float_chs_d(fp0, fp0);
10666 gen_store_fpr64(ctx, fp0, fd);
10667 tcg_temp_free_i64(fp0);
10669 break;
10670 case OPC_ROUND_L_D:
10671 check_cp1_64bitmode(ctx);
10673 TCGv_i64 fp0 = tcg_temp_new_i64();
10675 gen_load_fpr64(ctx, fp0, fs);
10676 if (ctx->nan2008) {
10677 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10678 } else {
10679 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10681 gen_store_fpr64(ctx, fp0, fd);
10682 tcg_temp_free_i64(fp0);
10684 break;
10685 case OPC_TRUNC_L_D:
10686 check_cp1_64bitmode(ctx);
10688 TCGv_i64 fp0 = tcg_temp_new_i64();
10690 gen_load_fpr64(ctx, fp0, fs);
10691 if (ctx->nan2008) {
10692 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10693 } else {
10694 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10696 gen_store_fpr64(ctx, fp0, fd);
10697 tcg_temp_free_i64(fp0);
10699 break;
10700 case OPC_CEIL_L_D:
10701 check_cp1_64bitmode(ctx);
10703 TCGv_i64 fp0 = tcg_temp_new_i64();
10705 gen_load_fpr64(ctx, fp0, fs);
10706 if (ctx->nan2008) {
10707 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10708 } else {
10709 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10711 gen_store_fpr64(ctx, fp0, fd);
10712 tcg_temp_free_i64(fp0);
10714 break;
10715 case OPC_FLOOR_L_D:
10716 check_cp1_64bitmode(ctx);
10718 TCGv_i64 fp0 = tcg_temp_new_i64();
10720 gen_load_fpr64(ctx, fp0, fs);
10721 if (ctx->nan2008) {
10722 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10723 } else {
10724 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10726 gen_store_fpr64(ctx, fp0, fd);
10727 tcg_temp_free_i64(fp0);
10729 break;
10730 case OPC_ROUND_W_D:
10731 check_cp1_registers(ctx, fs);
10733 TCGv_i32 fp32 = tcg_temp_new_i32();
10734 TCGv_i64 fp64 = tcg_temp_new_i64();
10736 gen_load_fpr64(ctx, fp64, fs);
10737 if (ctx->nan2008) {
10738 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10739 } else {
10740 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10742 tcg_temp_free_i64(fp64);
10743 gen_store_fpr32(ctx, fp32, fd);
10744 tcg_temp_free_i32(fp32);
10746 break;
10747 case OPC_TRUNC_W_D:
10748 check_cp1_registers(ctx, fs);
10750 TCGv_i32 fp32 = tcg_temp_new_i32();
10751 TCGv_i64 fp64 = tcg_temp_new_i64();
10753 gen_load_fpr64(ctx, fp64, fs);
10754 if (ctx->nan2008) {
10755 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10756 } else {
10757 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10759 tcg_temp_free_i64(fp64);
10760 gen_store_fpr32(ctx, fp32, fd);
10761 tcg_temp_free_i32(fp32);
10763 break;
10764 case OPC_CEIL_W_D:
10765 check_cp1_registers(ctx, fs);
10767 TCGv_i32 fp32 = tcg_temp_new_i32();
10768 TCGv_i64 fp64 = tcg_temp_new_i64();
10770 gen_load_fpr64(ctx, fp64, fs);
10771 if (ctx->nan2008) {
10772 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10773 } else {
10774 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10776 tcg_temp_free_i64(fp64);
10777 gen_store_fpr32(ctx, fp32, fd);
10778 tcg_temp_free_i32(fp32);
10780 break;
10781 case OPC_FLOOR_W_D:
10782 check_cp1_registers(ctx, fs);
10784 TCGv_i32 fp32 = tcg_temp_new_i32();
10785 TCGv_i64 fp64 = tcg_temp_new_i64();
10787 gen_load_fpr64(ctx, fp64, fs);
10788 if (ctx->nan2008) {
10789 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10790 } else {
10791 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10793 tcg_temp_free_i64(fp64);
10794 gen_store_fpr32(ctx, fp32, fd);
10795 tcg_temp_free_i32(fp32);
10797 break;
10798 case OPC_SEL_D:
10799 check_insn(ctx, ISA_MIPS32R6);
10800 gen_sel_d(ctx, op1, fd, ft, fs);
10801 break;
10802 case OPC_SELEQZ_D:
10803 check_insn(ctx, ISA_MIPS32R6);
10804 gen_sel_d(ctx, op1, fd, ft, fs);
10805 break;
10806 case OPC_SELNEZ_D:
10807 check_insn(ctx, ISA_MIPS32R6);
10808 gen_sel_d(ctx, op1, fd, ft, fs);
10809 break;
10810 case OPC_MOVCF_D:
10811 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10812 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10813 break;
10814 case OPC_MOVZ_D:
10815 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10817 TCGLabel *l1 = gen_new_label();
10818 TCGv_i64 fp0;
10820 if (ft != 0) {
10821 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10823 fp0 = tcg_temp_new_i64();
10824 gen_load_fpr64(ctx, fp0, fs);
10825 gen_store_fpr64(ctx, fp0, fd);
10826 tcg_temp_free_i64(fp0);
10827 gen_set_label(l1);
10829 break;
10830 case OPC_MOVN_D:
10831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10833 TCGLabel *l1 = gen_new_label();
10834 TCGv_i64 fp0;
10836 if (ft != 0) {
10837 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10838 fp0 = tcg_temp_new_i64();
10839 gen_load_fpr64(ctx, fp0, fs);
10840 gen_store_fpr64(ctx, fp0, fd);
10841 tcg_temp_free_i64(fp0);
10842 gen_set_label(l1);
10845 break;
10846 case OPC_RECIP_D:
10847 check_cp1_registers(ctx, fs | fd);
10849 TCGv_i64 fp0 = tcg_temp_new_i64();
10851 gen_load_fpr64(ctx, fp0, fs);
10852 gen_helper_float_recip_d(fp0, cpu_env, fp0);
10853 gen_store_fpr64(ctx, fp0, fd);
10854 tcg_temp_free_i64(fp0);
10856 break;
10857 case OPC_RSQRT_D:
10858 check_cp1_registers(ctx, fs | fd);
10860 TCGv_i64 fp0 = tcg_temp_new_i64();
10862 gen_load_fpr64(ctx, fp0, fs);
10863 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
10864 gen_store_fpr64(ctx, fp0, fd);
10865 tcg_temp_free_i64(fp0);
10867 break;
10868 case OPC_MADDF_D:
10869 check_insn(ctx, ISA_MIPS32R6);
10871 TCGv_i64 fp0 = tcg_temp_new_i64();
10872 TCGv_i64 fp1 = tcg_temp_new_i64();
10873 TCGv_i64 fp2 = tcg_temp_new_i64();
10874 gen_load_fpr64(ctx, fp0, fs);
10875 gen_load_fpr64(ctx, fp1, ft);
10876 gen_load_fpr64(ctx, fp2, fd);
10877 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
10878 gen_store_fpr64(ctx, fp2, fd);
10879 tcg_temp_free_i64(fp2);
10880 tcg_temp_free_i64(fp1);
10881 tcg_temp_free_i64(fp0);
10883 break;
10884 case OPC_MSUBF_D:
10885 check_insn(ctx, ISA_MIPS32R6);
10887 TCGv_i64 fp0 = tcg_temp_new_i64();
10888 TCGv_i64 fp1 = tcg_temp_new_i64();
10889 TCGv_i64 fp2 = tcg_temp_new_i64();
10890 gen_load_fpr64(ctx, fp0, fs);
10891 gen_load_fpr64(ctx, fp1, ft);
10892 gen_load_fpr64(ctx, fp2, fd);
10893 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
10894 gen_store_fpr64(ctx, fp2, fd);
10895 tcg_temp_free_i64(fp2);
10896 tcg_temp_free_i64(fp1);
10897 tcg_temp_free_i64(fp0);
10899 break;
10900 case OPC_RINT_D:
10901 check_insn(ctx, ISA_MIPS32R6);
10903 TCGv_i64 fp0 = tcg_temp_new_i64();
10904 gen_load_fpr64(ctx, fp0, fs);
10905 gen_helper_float_rint_d(fp0, cpu_env, fp0);
10906 gen_store_fpr64(ctx, fp0, fd);
10907 tcg_temp_free_i64(fp0);
10909 break;
10910 case OPC_CLASS_D:
10911 check_insn(ctx, ISA_MIPS32R6);
10913 TCGv_i64 fp0 = tcg_temp_new_i64();
10914 gen_load_fpr64(ctx, fp0, fs);
10915 gen_helper_float_class_d(fp0, cpu_env, fp0);
10916 gen_store_fpr64(ctx, fp0, fd);
10917 tcg_temp_free_i64(fp0);
10919 break;
10920 case OPC_MIN_D: /* OPC_RECIP2_D */
10921 if (ctx->insn_flags & ISA_MIPS32R6) {
10922 /* OPC_MIN_D */
10923 TCGv_i64 fp0 = tcg_temp_new_i64();
10924 TCGv_i64 fp1 = tcg_temp_new_i64();
10925 gen_load_fpr64(ctx, fp0, fs);
10926 gen_load_fpr64(ctx, fp1, ft);
10927 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
10928 gen_store_fpr64(ctx, fp1, fd);
10929 tcg_temp_free_i64(fp1);
10930 tcg_temp_free_i64(fp0);
10931 } else {
10932 /* OPC_RECIP2_D */
10933 check_cp1_64bitmode(ctx);
10935 TCGv_i64 fp0 = tcg_temp_new_i64();
10936 TCGv_i64 fp1 = tcg_temp_new_i64();
10938 gen_load_fpr64(ctx, fp0, fs);
10939 gen_load_fpr64(ctx, fp1, ft);
10940 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
10941 tcg_temp_free_i64(fp1);
10942 gen_store_fpr64(ctx, fp0, fd);
10943 tcg_temp_free_i64(fp0);
10946 break;
10947 case OPC_MINA_D: /* OPC_RECIP1_D */
10948 if (ctx->insn_flags & ISA_MIPS32R6) {
10949 /* OPC_MINA_D */
10950 TCGv_i64 fp0 = tcg_temp_new_i64();
10951 TCGv_i64 fp1 = tcg_temp_new_i64();
10952 gen_load_fpr64(ctx, fp0, fs);
10953 gen_load_fpr64(ctx, fp1, ft);
10954 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
10955 gen_store_fpr64(ctx, fp1, fd);
10956 tcg_temp_free_i64(fp1);
10957 tcg_temp_free_i64(fp0);
10958 } else {
10959 /* OPC_RECIP1_D */
10960 check_cp1_64bitmode(ctx);
10962 TCGv_i64 fp0 = tcg_temp_new_i64();
10964 gen_load_fpr64(ctx, fp0, fs);
10965 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
10966 gen_store_fpr64(ctx, fp0, fd);
10967 tcg_temp_free_i64(fp0);
10970 break;
10971 case OPC_MAX_D: /* OPC_RSQRT1_D */
10972 if (ctx->insn_flags & ISA_MIPS32R6) {
10973 /* OPC_MAX_D */
10974 TCGv_i64 fp0 = tcg_temp_new_i64();
10975 TCGv_i64 fp1 = tcg_temp_new_i64();
10976 gen_load_fpr64(ctx, fp0, fs);
10977 gen_load_fpr64(ctx, fp1, ft);
10978 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
10979 gen_store_fpr64(ctx, fp1, fd);
10980 tcg_temp_free_i64(fp1);
10981 tcg_temp_free_i64(fp0);
10982 } else {
10983 /* OPC_RSQRT1_D */
10984 check_cp1_64bitmode(ctx);
10986 TCGv_i64 fp0 = tcg_temp_new_i64();
10988 gen_load_fpr64(ctx, fp0, fs);
10989 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
10990 gen_store_fpr64(ctx, fp0, fd);
10991 tcg_temp_free_i64(fp0);
10994 break;
10995 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10996 if (ctx->insn_flags & ISA_MIPS32R6) {
10997 /* OPC_MAXA_D */
10998 TCGv_i64 fp0 = tcg_temp_new_i64();
10999 TCGv_i64 fp1 = tcg_temp_new_i64();
11000 gen_load_fpr64(ctx, fp0, fs);
11001 gen_load_fpr64(ctx, fp1, ft);
11002 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11003 gen_store_fpr64(ctx, fp1, fd);
11004 tcg_temp_free_i64(fp1);
11005 tcg_temp_free_i64(fp0);
11006 } else {
11007 /* OPC_RSQRT2_D */
11008 check_cp1_64bitmode(ctx);
11010 TCGv_i64 fp0 = tcg_temp_new_i64();
11011 TCGv_i64 fp1 = tcg_temp_new_i64();
11013 gen_load_fpr64(ctx, fp0, fs);
11014 gen_load_fpr64(ctx, fp1, ft);
11015 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11016 tcg_temp_free_i64(fp1);
11017 gen_store_fpr64(ctx, fp0, fd);
11018 tcg_temp_free_i64(fp0);
11021 break;
11022 case OPC_CMP_F_D:
11023 case OPC_CMP_UN_D:
11024 case OPC_CMP_EQ_D:
11025 case OPC_CMP_UEQ_D:
11026 case OPC_CMP_OLT_D:
11027 case OPC_CMP_ULT_D:
11028 case OPC_CMP_OLE_D:
11029 case OPC_CMP_ULE_D:
11030 case OPC_CMP_SF_D:
11031 case OPC_CMP_NGLE_D:
11032 case OPC_CMP_SEQ_D:
11033 case OPC_CMP_NGL_D:
11034 case OPC_CMP_LT_D:
11035 case OPC_CMP_NGE_D:
11036 case OPC_CMP_LE_D:
11037 case OPC_CMP_NGT_D:
11038 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11039 if (ctx->opcode & (1 << 6)) {
11040 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11041 } else {
11042 gen_cmp_d(ctx, func-48, ft, fs, cc);
11044 break;
11045 case OPC_CVT_S_D:
11046 check_cp1_registers(ctx, fs);
11048 TCGv_i32 fp32 = tcg_temp_new_i32();
11049 TCGv_i64 fp64 = tcg_temp_new_i64();
11051 gen_load_fpr64(ctx, fp64, fs);
11052 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11053 tcg_temp_free_i64(fp64);
11054 gen_store_fpr32(ctx, fp32, fd);
11055 tcg_temp_free_i32(fp32);
11057 break;
11058 case OPC_CVT_W_D:
11059 check_cp1_registers(ctx, fs);
11061 TCGv_i32 fp32 = tcg_temp_new_i32();
11062 TCGv_i64 fp64 = tcg_temp_new_i64();
11064 gen_load_fpr64(ctx, fp64, fs);
11065 if (ctx->nan2008) {
11066 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11067 } else {
11068 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11070 tcg_temp_free_i64(fp64);
11071 gen_store_fpr32(ctx, fp32, fd);
11072 tcg_temp_free_i32(fp32);
11074 break;
11075 case OPC_CVT_L_D:
11076 check_cp1_64bitmode(ctx);
11078 TCGv_i64 fp0 = tcg_temp_new_i64();
11080 gen_load_fpr64(ctx, fp0, fs);
11081 if (ctx->nan2008) {
11082 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11083 } else {
11084 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11086 gen_store_fpr64(ctx, fp0, fd);
11087 tcg_temp_free_i64(fp0);
11089 break;
11090 case OPC_CVT_S_W:
11092 TCGv_i32 fp0 = tcg_temp_new_i32();
11094 gen_load_fpr32(ctx, fp0, fs);
11095 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11096 gen_store_fpr32(ctx, fp0, fd);
11097 tcg_temp_free_i32(fp0);
11099 break;
11100 case OPC_CVT_D_W:
11101 check_cp1_registers(ctx, fd);
11103 TCGv_i32 fp32 = tcg_temp_new_i32();
11104 TCGv_i64 fp64 = tcg_temp_new_i64();
11106 gen_load_fpr32(ctx, fp32, fs);
11107 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11108 tcg_temp_free_i32(fp32);
11109 gen_store_fpr64(ctx, fp64, fd);
11110 tcg_temp_free_i64(fp64);
11112 break;
11113 case OPC_CVT_S_L:
11114 check_cp1_64bitmode(ctx);
11116 TCGv_i32 fp32 = tcg_temp_new_i32();
11117 TCGv_i64 fp64 = tcg_temp_new_i64();
11119 gen_load_fpr64(ctx, fp64, fs);
11120 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11121 tcg_temp_free_i64(fp64);
11122 gen_store_fpr32(ctx, fp32, fd);
11123 tcg_temp_free_i32(fp32);
11125 break;
11126 case OPC_CVT_D_L:
11127 check_cp1_64bitmode(ctx);
11129 TCGv_i64 fp0 = tcg_temp_new_i64();
11131 gen_load_fpr64(ctx, fp0, fs);
11132 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11133 gen_store_fpr64(ctx, fp0, fd);
11134 tcg_temp_free_i64(fp0);
11136 break;
11137 case OPC_CVT_PS_PW:
11138 check_ps(ctx);
11140 TCGv_i64 fp0 = tcg_temp_new_i64();
11142 gen_load_fpr64(ctx, fp0, fs);
11143 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11144 gen_store_fpr64(ctx, fp0, fd);
11145 tcg_temp_free_i64(fp0);
11147 break;
11148 case OPC_ADD_PS:
11149 check_ps(ctx);
11151 TCGv_i64 fp0 = tcg_temp_new_i64();
11152 TCGv_i64 fp1 = tcg_temp_new_i64();
11154 gen_load_fpr64(ctx, fp0, fs);
11155 gen_load_fpr64(ctx, fp1, ft);
11156 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11157 tcg_temp_free_i64(fp1);
11158 gen_store_fpr64(ctx, fp0, fd);
11159 tcg_temp_free_i64(fp0);
11161 break;
11162 case OPC_SUB_PS:
11163 check_ps(ctx);
11165 TCGv_i64 fp0 = tcg_temp_new_i64();
11166 TCGv_i64 fp1 = tcg_temp_new_i64();
11168 gen_load_fpr64(ctx, fp0, fs);
11169 gen_load_fpr64(ctx, fp1, ft);
11170 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11171 tcg_temp_free_i64(fp1);
11172 gen_store_fpr64(ctx, fp0, fd);
11173 tcg_temp_free_i64(fp0);
11175 break;
11176 case OPC_MUL_PS:
11177 check_ps(ctx);
11179 TCGv_i64 fp0 = tcg_temp_new_i64();
11180 TCGv_i64 fp1 = tcg_temp_new_i64();
11182 gen_load_fpr64(ctx, fp0, fs);
11183 gen_load_fpr64(ctx, fp1, ft);
11184 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11185 tcg_temp_free_i64(fp1);
11186 gen_store_fpr64(ctx, fp0, fd);
11187 tcg_temp_free_i64(fp0);
11189 break;
11190 case OPC_ABS_PS:
11191 check_ps(ctx);
11193 TCGv_i64 fp0 = tcg_temp_new_i64();
11195 gen_load_fpr64(ctx, fp0, fs);
11196 gen_helper_float_abs_ps(fp0, fp0);
11197 gen_store_fpr64(ctx, fp0, fd);
11198 tcg_temp_free_i64(fp0);
11200 break;
11201 case OPC_MOV_PS:
11202 check_ps(ctx);
11204 TCGv_i64 fp0 = tcg_temp_new_i64();
11206 gen_load_fpr64(ctx, fp0, fs);
11207 gen_store_fpr64(ctx, fp0, fd);
11208 tcg_temp_free_i64(fp0);
11210 break;
11211 case OPC_NEG_PS:
11212 check_ps(ctx);
11214 TCGv_i64 fp0 = tcg_temp_new_i64();
11216 gen_load_fpr64(ctx, fp0, fs);
11217 gen_helper_float_chs_ps(fp0, fp0);
11218 gen_store_fpr64(ctx, fp0, fd);
11219 tcg_temp_free_i64(fp0);
11221 break;
11222 case OPC_MOVCF_PS:
11223 check_ps(ctx);
11224 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11225 break;
11226 case OPC_MOVZ_PS:
11227 check_ps(ctx);
11229 TCGLabel *l1 = gen_new_label();
11230 TCGv_i64 fp0;
11232 if (ft != 0)
11233 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11234 fp0 = tcg_temp_new_i64();
11235 gen_load_fpr64(ctx, fp0, fs);
11236 gen_store_fpr64(ctx, fp0, fd);
11237 tcg_temp_free_i64(fp0);
11238 gen_set_label(l1);
11240 break;
11241 case OPC_MOVN_PS:
11242 check_ps(ctx);
11244 TCGLabel *l1 = gen_new_label();
11245 TCGv_i64 fp0;
11247 if (ft != 0) {
11248 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11249 fp0 = tcg_temp_new_i64();
11250 gen_load_fpr64(ctx, fp0, fs);
11251 gen_store_fpr64(ctx, fp0, fd);
11252 tcg_temp_free_i64(fp0);
11253 gen_set_label(l1);
11256 break;
11257 case OPC_ADDR_PS:
11258 check_ps(ctx);
11260 TCGv_i64 fp0 = tcg_temp_new_i64();
11261 TCGv_i64 fp1 = tcg_temp_new_i64();
11263 gen_load_fpr64(ctx, fp0, ft);
11264 gen_load_fpr64(ctx, fp1, fs);
11265 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11266 tcg_temp_free_i64(fp1);
11267 gen_store_fpr64(ctx, fp0, fd);
11268 tcg_temp_free_i64(fp0);
11270 break;
11271 case OPC_MULR_PS:
11272 check_ps(ctx);
11274 TCGv_i64 fp0 = tcg_temp_new_i64();
11275 TCGv_i64 fp1 = tcg_temp_new_i64();
11277 gen_load_fpr64(ctx, fp0, ft);
11278 gen_load_fpr64(ctx, fp1, fs);
11279 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11280 tcg_temp_free_i64(fp1);
11281 gen_store_fpr64(ctx, fp0, fd);
11282 tcg_temp_free_i64(fp0);
11284 break;
11285 case OPC_RECIP2_PS:
11286 check_ps(ctx);
11288 TCGv_i64 fp0 = tcg_temp_new_i64();
11289 TCGv_i64 fp1 = tcg_temp_new_i64();
11291 gen_load_fpr64(ctx, fp0, fs);
11292 gen_load_fpr64(ctx, fp1, ft);
11293 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11294 tcg_temp_free_i64(fp1);
11295 gen_store_fpr64(ctx, fp0, fd);
11296 tcg_temp_free_i64(fp0);
11298 break;
11299 case OPC_RECIP1_PS:
11300 check_ps(ctx);
11302 TCGv_i64 fp0 = tcg_temp_new_i64();
11304 gen_load_fpr64(ctx, fp0, fs);
11305 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11306 gen_store_fpr64(ctx, fp0, fd);
11307 tcg_temp_free_i64(fp0);
11309 break;
11310 case OPC_RSQRT1_PS:
11311 check_ps(ctx);
11313 TCGv_i64 fp0 = tcg_temp_new_i64();
11315 gen_load_fpr64(ctx, fp0, fs);
11316 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11317 gen_store_fpr64(ctx, fp0, fd);
11318 tcg_temp_free_i64(fp0);
11320 break;
11321 case OPC_RSQRT2_PS:
11322 check_ps(ctx);
11324 TCGv_i64 fp0 = tcg_temp_new_i64();
11325 TCGv_i64 fp1 = tcg_temp_new_i64();
11327 gen_load_fpr64(ctx, fp0, fs);
11328 gen_load_fpr64(ctx, fp1, ft);
11329 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11330 tcg_temp_free_i64(fp1);
11331 gen_store_fpr64(ctx, fp0, fd);
11332 tcg_temp_free_i64(fp0);
11334 break;
11335 case OPC_CVT_S_PU:
11336 check_cp1_64bitmode(ctx);
11338 TCGv_i32 fp0 = tcg_temp_new_i32();
11340 gen_load_fpr32h(ctx, fp0, fs);
11341 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11342 gen_store_fpr32(ctx, fp0, fd);
11343 tcg_temp_free_i32(fp0);
11345 break;
11346 case OPC_CVT_PW_PS:
11347 check_ps(ctx);
11349 TCGv_i64 fp0 = tcg_temp_new_i64();
11351 gen_load_fpr64(ctx, fp0, fs);
11352 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11353 gen_store_fpr64(ctx, fp0, fd);
11354 tcg_temp_free_i64(fp0);
11356 break;
11357 case OPC_CVT_S_PL:
11358 check_cp1_64bitmode(ctx);
11360 TCGv_i32 fp0 = tcg_temp_new_i32();
11362 gen_load_fpr32(ctx, fp0, fs);
11363 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11364 gen_store_fpr32(ctx, fp0, fd);
11365 tcg_temp_free_i32(fp0);
11367 break;
11368 case OPC_PLL_PS:
11369 check_ps(ctx);
11371 TCGv_i32 fp0 = tcg_temp_new_i32();
11372 TCGv_i32 fp1 = tcg_temp_new_i32();
11374 gen_load_fpr32(ctx, fp0, fs);
11375 gen_load_fpr32(ctx, fp1, ft);
11376 gen_store_fpr32h(ctx, fp0, fd);
11377 gen_store_fpr32(ctx, fp1, fd);
11378 tcg_temp_free_i32(fp0);
11379 tcg_temp_free_i32(fp1);
11381 break;
11382 case OPC_PLU_PS:
11383 check_ps(ctx);
11385 TCGv_i32 fp0 = tcg_temp_new_i32();
11386 TCGv_i32 fp1 = tcg_temp_new_i32();
11388 gen_load_fpr32(ctx, fp0, fs);
11389 gen_load_fpr32h(ctx, fp1, ft);
11390 gen_store_fpr32(ctx, fp1, fd);
11391 gen_store_fpr32h(ctx, fp0, fd);
11392 tcg_temp_free_i32(fp0);
11393 tcg_temp_free_i32(fp1);
11395 break;
11396 case OPC_PUL_PS:
11397 check_ps(ctx);
11399 TCGv_i32 fp0 = tcg_temp_new_i32();
11400 TCGv_i32 fp1 = tcg_temp_new_i32();
11402 gen_load_fpr32h(ctx, fp0, fs);
11403 gen_load_fpr32(ctx, fp1, ft);
11404 gen_store_fpr32(ctx, fp1, fd);
11405 gen_store_fpr32h(ctx, fp0, fd);
11406 tcg_temp_free_i32(fp0);
11407 tcg_temp_free_i32(fp1);
11409 break;
11410 case OPC_PUU_PS:
11411 check_ps(ctx);
11413 TCGv_i32 fp0 = tcg_temp_new_i32();
11414 TCGv_i32 fp1 = tcg_temp_new_i32();
11416 gen_load_fpr32h(ctx, fp0, fs);
11417 gen_load_fpr32h(ctx, fp1, ft);
11418 gen_store_fpr32(ctx, fp1, fd);
11419 gen_store_fpr32h(ctx, fp0, fd);
11420 tcg_temp_free_i32(fp0);
11421 tcg_temp_free_i32(fp1);
11423 break;
11424 case OPC_CMP_F_PS:
11425 case OPC_CMP_UN_PS:
11426 case OPC_CMP_EQ_PS:
11427 case OPC_CMP_UEQ_PS:
11428 case OPC_CMP_OLT_PS:
11429 case OPC_CMP_ULT_PS:
11430 case OPC_CMP_OLE_PS:
11431 case OPC_CMP_ULE_PS:
11432 case OPC_CMP_SF_PS:
11433 case OPC_CMP_NGLE_PS:
11434 case OPC_CMP_SEQ_PS:
11435 case OPC_CMP_NGL_PS:
11436 case OPC_CMP_LT_PS:
11437 case OPC_CMP_NGE_PS:
11438 case OPC_CMP_LE_PS:
11439 case OPC_CMP_NGT_PS:
11440 if (ctx->opcode & (1 << 6)) {
11441 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
11442 } else {
11443 gen_cmp_ps(ctx, func-48, ft, fs, cc);
11445 break;
11446 default:
11447 MIPS_INVAL("farith");
11448 generate_exception_end(ctx, EXCP_RI);
11449 return;
11453 /* Coprocessor 3 (FPU) */
11454 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
11455 int fd, int fs, int base, int index)
11457 TCGv t0 = tcg_temp_new();
11459 if (base == 0) {
11460 gen_load_gpr(t0, index);
11461 } else if (index == 0) {
11462 gen_load_gpr(t0, base);
11463 } else {
11464 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11466 /* Don't do NOP if destination is zero: we must perform the actual
11467 memory access. */
11468 switch (opc) {
11469 case OPC_LWXC1:
11470 check_cop1x(ctx);
11472 TCGv_i32 fp0 = tcg_temp_new_i32();
11474 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11475 tcg_gen_trunc_tl_i32(fp0, t0);
11476 gen_store_fpr32(ctx, fp0, fd);
11477 tcg_temp_free_i32(fp0);
11479 break;
11480 case OPC_LDXC1:
11481 check_cop1x(ctx);
11482 check_cp1_registers(ctx, fd);
11484 TCGv_i64 fp0 = tcg_temp_new_i64();
11485 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11486 gen_store_fpr64(ctx, fp0, fd);
11487 tcg_temp_free_i64(fp0);
11489 break;
11490 case OPC_LUXC1:
11491 check_cp1_64bitmode(ctx);
11492 tcg_gen_andi_tl(t0, t0, ~0x7);
11494 TCGv_i64 fp0 = tcg_temp_new_i64();
11496 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11497 gen_store_fpr64(ctx, fp0, fd);
11498 tcg_temp_free_i64(fp0);
11500 break;
11501 case OPC_SWXC1:
11502 check_cop1x(ctx);
11504 TCGv_i32 fp0 = tcg_temp_new_i32();
11505 gen_load_fpr32(ctx, fp0, fs);
11506 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11507 tcg_temp_free_i32(fp0);
11509 break;
11510 case OPC_SDXC1:
11511 check_cop1x(ctx);
11512 check_cp1_registers(ctx, fs);
11514 TCGv_i64 fp0 = tcg_temp_new_i64();
11515 gen_load_fpr64(ctx, fp0, fs);
11516 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11517 tcg_temp_free_i64(fp0);
11519 break;
11520 case OPC_SUXC1:
11521 check_cp1_64bitmode(ctx);
11522 tcg_gen_andi_tl(t0, t0, ~0x7);
11524 TCGv_i64 fp0 = tcg_temp_new_i64();
11525 gen_load_fpr64(ctx, fp0, fs);
11526 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11527 tcg_temp_free_i64(fp0);
11529 break;
11531 tcg_temp_free(t0);
11534 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
11535 int fd, int fr, int fs, int ft)
11537 switch (opc) {
11538 case OPC_ALNV_PS:
11539 check_ps(ctx);
11541 TCGv t0 = tcg_temp_local_new();
11542 TCGv_i32 fp = tcg_temp_new_i32();
11543 TCGv_i32 fph = tcg_temp_new_i32();
11544 TCGLabel *l1 = gen_new_label();
11545 TCGLabel *l2 = gen_new_label();
11547 gen_load_gpr(t0, fr);
11548 tcg_gen_andi_tl(t0, t0, 0x7);
11550 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11551 gen_load_fpr32(ctx, fp, fs);
11552 gen_load_fpr32h(ctx, fph, fs);
11553 gen_store_fpr32(ctx, fp, fd);
11554 gen_store_fpr32h(ctx, fph, fd);
11555 tcg_gen_br(l2);
11556 gen_set_label(l1);
11557 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11558 tcg_temp_free(t0);
11559 #ifdef TARGET_WORDS_BIGENDIAN
11560 gen_load_fpr32(ctx, fp, fs);
11561 gen_load_fpr32h(ctx, fph, ft);
11562 gen_store_fpr32h(ctx, fp, fd);
11563 gen_store_fpr32(ctx, fph, fd);
11564 #else
11565 gen_load_fpr32h(ctx, fph, fs);
11566 gen_load_fpr32(ctx, fp, ft);
11567 gen_store_fpr32(ctx, fph, fd);
11568 gen_store_fpr32h(ctx, fp, fd);
11569 #endif
11570 gen_set_label(l2);
11571 tcg_temp_free_i32(fp);
11572 tcg_temp_free_i32(fph);
11574 break;
11575 case OPC_MADD_S:
11576 check_cop1x(ctx);
11578 TCGv_i32 fp0 = tcg_temp_new_i32();
11579 TCGv_i32 fp1 = tcg_temp_new_i32();
11580 TCGv_i32 fp2 = tcg_temp_new_i32();
11582 gen_load_fpr32(ctx, fp0, fs);
11583 gen_load_fpr32(ctx, fp1, ft);
11584 gen_load_fpr32(ctx, fp2, fr);
11585 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11586 tcg_temp_free_i32(fp0);
11587 tcg_temp_free_i32(fp1);
11588 gen_store_fpr32(ctx, fp2, fd);
11589 tcg_temp_free_i32(fp2);
11591 break;
11592 case OPC_MADD_D:
11593 check_cop1x(ctx);
11594 check_cp1_registers(ctx, fd | fs | ft | fr);
11596 TCGv_i64 fp0 = tcg_temp_new_i64();
11597 TCGv_i64 fp1 = tcg_temp_new_i64();
11598 TCGv_i64 fp2 = tcg_temp_new_i64();
11600 gen_load_fpr64(ctx, fp0, fs);
11601 gen_load_fpr64(ctx, fp1, ft);
11602 gen_load_fpr64(ctx, fp2, fr);
11603 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11604 tcg_temp_free_i64(fp0);
11605 tcg_temp_free_i64(fp1);
11606 gen_store_fpr64(ctx, fp2, fd);
11607 tcg_temp_free_i64(fp2);
11609 break;
11610 case OPC_MADD_PS:
11611 check_ps(ctx);
11613 TCGv_i64 fp0 = tcg_temp_new_i64();
11614 TCGv_i64 fp1 = tcg_temp_new_i64();
11615 TCGv_i64 fp2 = tcg_temp_new_i64();
11617 gen_load_fpr64(ctx, fp0, fs);
11618 gen_load_fpr64(ctx, fp1, ft);
11619 gen_load_fpr64(ctx, fp2, fr);
11620 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11621 tcg_temp_free_i64(fp0);
11622 tcg_temp_free_i64(fp1);
11623 gen_store_fpr64(ctx, fp2, fd);
11624 tcg_temp_free_i64(fp2);
11626 break;
11627 case OPC_MSUB_S:
11628 check_cop1x(ctx);
11630 TCGv_i32 fp0 = tcg_temp_new_i32();
11631 TCGv_i32 fp1 = tcg_temp_new_i32();
11632 TCGv_i32 fp2 = tcg_temp_new_i32();
11634 gen_load_fpr32(ctx, fp0, fs);
11635 gen_load_fpr32(ctx, fp1, ft);
11636 gen_load_fpr32(ctx, fp2, fr);
11637 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11638 tcg_temp_free_i32(fp0);
11639 tcg_temp_free_i32(fp1);
11640 gen_store_fpr32(ctx, fp2, fd);
11641 tcg_temp_free_i32(fp2);
11643 break;
11644 case OPC_MSUB_D:
11645 check_cop1x(ctx);
11646 check_cp1_registers(ctx, fd | fs | ft | fr);
11648 TCGv_i64 fp0 = tcg_temp_new_i64();
11649 TCGv_i64 fp1 = tcg_temp_new_i64();
11650 TCGv_i64 fp2 = tcg_temp_new_i64();
11652 gen_load_fpr64(ctx, fp0, fs);
11653 gen_load_fpr64(ctx, fp1, ft);
11654 gen_load_fpr64(ctx, fp2, fr);
11655 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11656 tcg_temp_free_i64(fp0);
11657 tcg_temp_free_i64(fp1);
11658 gen_store_fpr64(ctx, fp2, fd);
11659 tcg_temp_free_i64(fp2);
11661 break;
11662 case OPC_MSUB_PS:
11663 check_ps(ctx);
11665 TCGv_i64 fp0 = tcg_temp_new_i64();
11666 TCGv_i64 fp1 = tcg_temp_new_i64();
11667 TCGv_i64 fp2 = tcg_temp_new_i64();
11669 gen_load_fpr64(ctx, fp0, fs);
11670 gen_load_fpr64(ctx, fp1, ft);
11671 gen_load_fpr64(ctx, fp2, fr);
11672 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11673 tcg_temp_free_i64(fp0);
11674 tcg_temp_free_i64(fp1);
11675 gen_store_fpr64(ctx, fp2, fd);
11676 tcg_temp_free_i64(fp2);
11678 break;
11679 case OPC_NMADD_S:
11680 check_cop1x(ctx);
11682 TCGv_i32 fp0 = tcg_temp_new_i32();
11683 TCGv_i32 fp1 = tcg_temp_new_i32();
11684 TCGv_i32 fp2 = tcg_temp_new_i32();
11686 gen_load_fpr32(ctx, fp0, fs);
11687 gen_load_fpr32(ctx, fp1, ft);
11688 gen_load_fpr32(ctx, fp2, fr);
11689 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11690 tcg_temp_free_i32(fp0);
11691 tcg_temp_free_i32(fp1);
11692 gen_store_fpr32(ctx, fp2, fd);
11693 tcg_temp_free_i32(fp2);
11695 break;
11696 case OPC_NMADD_D:
11697 check_cop1x(ctx);
11698 check_cp1_registers(ctx, fd | fs | ft | fr);
11700 TCGv_i64 fp0 = tcg_temp_new_i64();
11701 TCGv_i64 fp1 = tcg_temp_new_i64();
11702 TCGv_i64 fp2 = tcg_temp_new_i64();
11704 gen_load_fpr64(ctx, fp0, fs);
11705 gen_load_fpr64(ctx, fp1, ft);
11706 gen_load_fpr64(ctx, fp2, fr);
11707 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11708 tcg_temp_free_i64(fp0);
11709 tcg_temp_free_i64(fp1);
11710 gen_store_fpr64(ctx, fp2, fd);
11711 tcg_temp_free_i64(fp2);
11713 break;
11714 case OPC_NMADD_PS:
11715 check_ps(ctx);
11717 TCGv_i64 fp0 = tcg_temp_new_i64();
11718 TCGv_i64 fp1 = tcg_temp_new_i64();
11719 TCGv_i64 fp2 = tcg_temp_new_i64();
11721 gen_load_fpr64(ctx, fp0, fs);
11722 gen_load_fpr64(ctx, fp1, ft);
11723 gen_load_fpr64(ctx, fp2, fr);
11724 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11725 tcg_temp_free_i64(fp0);
11726 tcg_temp_free_i64(fp1);
11727 gen_store_fpr64(ctx, fp2, fd);
11728 tcg_temp_free_i64(fp2);
11730 break;
11731 case OPC_NMSUB_S:
11732 check_cop1x(ctx);
11734 TCGv_i32 fp0 = tcg_temp_new_i32();
11735 TCGv_i32 fp1 = tcg_temp_new_i32();
11736 TCGv_i32 fp2 = tcg_temp_new_i32();
11738 gen_load_fpr32(ctx, fp0, fs);
11739 gen_load_fpr32(ctx, fp1, ft);
11740 gen_load_fpr32(ctx, fp2, fr);
11741 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11742 tcg_temp_free_i32(fp0);
11743 tcg_temp_free_i32(fp1);
11744 gen_store_fpr32(ctx, fp2, fd);
11745 tcg_temp_free_i32(fp2);
11747 break;
11748 case OPC_NMSUB_D:
11749 check_cop1x(ctx);
11750 check_cp1_registers(ctx, fd | fs | ft | fr);
11752 TCGv_i64 fp0 = tcg_temp_new_i64();
11753 TCGv_i64 fp1 = tcg_temp_new_i64();
11754 TCGv_i64 fp2 = tcg_temp_new_i64();
11756 gen_load_fpr64(ctx, fp0, fs);
11757 gen_load_fpr64(ctx, fp1, ft);
11758 gen_load_fpr64(ctx, fp2, fr);
11759 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11760 tcg_temp_free_i64(fp0);
11761 tcg_temp_free_i64(fp1);
11762 gen_store_fpr64(ctx, fp2, fd);
11763 tcg_temp_free_i64(fp2);
11765 break;
11766 case OPC_NMSUB_PS:
11767 check_ps(ctx);
11769 TCGv_i64 fp0 = tcg_temp_new_i64();
11770 TCGv_i64 fp1 = tcg_temp_new_i64();
11771 TCGv_i64 fp2 = tcg_temp_new_i64();
11773 gen_load_fpr64(ctx, fp0, fs);
11774 gen_load_fpr64(ctx, fp1, ft);
11775 gen_load_fpr64(ctx, fp2, fr);
11776 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11777 tcg_temp_free_i64(fp0);
11778 tcg_temp_free_i64(fp1);
11779 gen_store_fpr64(ctx, fp2, fd);
11780 tcg_temp_free_i64(fp2);
11782 break;
11783 default:
11784 MIPS_INVAL("flt3_arith");
11785 generate_exception_end(ctx, EXCP_RI);
11786 return;
11790 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
11792 TCGv t0;
11794 #if !defined(CONFIG_USER_ONLY)
11795 /* The Linux kernel will emulate rdhwr if it's not supported natively.
11796 Therefore only check the ISA in system mode. */
11797 check_insn(ctx, ISA_MIPS32R2);
11798 #endif
11799 t0 = tcg_temp_new();
11801 switch (rd) {
11802 case 0:
11803 gen_helper_rdhwr_cpunum(t0, cpu_env);
11804 gen_store_gpr(t0, rt);
11805 break;
11806 case 1:
11807 gen_helper_rdhwr_synci_step(t0, cpu_env);
11808 gen_store_gpr(t0, rt);
11809 break;
11810 case 2:
11811 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11812 gen_io_start();
11814 gen_helper_rdhwr_cc(t0, cpu_env);
11815 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
11816 gen_io_end();
11818 gen_store_gpr(t0, rt);
11819 /* Break the TB to be able to take timer interrupts immediately
11820 after reading count. DISAS_STOP isn't sufficient, we need to ensure
11821 we break completely out of translated code. */
11822 gen_save_pc(ctx->base.pc_next + 4);
11823 ctx->base.is_jmp = DISAS_EXIT;
11824 break;
11825 case 3:
11826 gen_helper_rdhwr_ccres(t0, cpu_env);
11827 gen_store_gpr(t0, rt);
11828 break;
11829 case 4:
11830 check_insn(ctx, ISA_MIPS32R6);
11831 if (sel != 0) {
11832 /* Performance counter registers are not implemented other than
11833 * control register 0.
11835 generate_exception(ctx, EXCP_RI);
11837 gen_helper_rdhwr_performance(t0, cpu_env);
11838 gen_store_gpr(t0, rt);
11839 break;
11840 case 5:
11841 check_insn(ctx, ISA_MIPS32R6);
11842 gen_helper_rdhwr_xnp(t0, cpu_env);
11843 gen_store_gpr(t0, rt);
11844 break;
11845 case 29:
11846 #if defined(CONFIG_USER_ONLY)
11847 tcg_gen_ld_tl(t0, cpu_env,
11848 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11849 gen_store_gpr(t0, rt);
11850 break;
11851 #else
11852 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
11853 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
11854 tcg_gen_ld_tl(t0, cpu_env,
11855 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
11856 gen_store_gpr(t0, rt);
11857 } else {
11858 generate_exception_end(ctx, EXCP_RI);
11860 break;
11861 #endif
11862 default: /* Invalid */
11863 MIPS_INVAL("rdhwr");
11864 generate_exception_end(ctx, EXCP_RI);
11865 break;
11867 tcg_temp_free(t0);
11870 static inline void clear_branch_hflags(DisasContext *ctx)
11872 ctx->hflags &= ~MIPS_HFLAG_BMASK;
11873 if (ctx->base.is_jmp == DISAS_NEXT) {
11874 save_cpu_state(ctx, 0);
11875 } else {
11876 /* it is not safe to save ctx->hflags as hflags may be changed
11877 in execution time by the instruction in delay / forbidden slot. */
11878 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
11882 static void gen_branch(DisasContext *ctx, int insn_bytes)
11884 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11885 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
11886 /* Branches completion */
11887 clear_branch_hflags(ctx);
11888 ctx->base.is_jmp = DISAS_NORETURN;
11889 /* FIXME: Need to clear can_do_io. */
11890 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
11891 case MIPS_HFLAG_FBNSLOT:
11892 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
11893 break;
11894 case MIPS_HFLAG_B:
11895 /* unconditional branch */
11896 if (proc_hflags & MIPS_HFLAG_BX) {
11897 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
11899 gen_goto_tb(ctx, 0, ctx->btarget);
11900 break;
11901 case MIPS_HFLAG_BL:
11902 /* blikely taken case */
11903 gen_goto_tb(ctx, 0, ctx->btarget);
11904 break;
11905 case MIPS_HFLAG_BC:
11906 /* Conditional branch */
11908 TCGLabel *l1 = gen_new_label();
11910 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11911 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
11912 gen_set_label(l1);
11913 gen_goto_tb(ctx, 0, ctx->btarget);
11915 break;
11916 case MIPS_HFLAG_BR:
11917 /* unconditional branch to register */
11918 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
11919 TCGv t0 = tcg_temp_new();
11920 TCGv_i32 t1 = tcg_temp_new_i32();
11922 tcg_gen_andi_tl(t0, btarget, 0x1);
11923 tcg_gen_trunc_tl_i32(t1, t0);
11924 tcg_temp_free(t0);
11925 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
11926 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
11927 tcg_gen_or_i32(hflags, hflags, t1);
11928 tcg_temp_free_i32(t1);
11930 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
11931 } else {
11932 tcg_gen_mov_tl(cpu_PC, btarget);
11934 if (ctx->base.singlestep_enabled) {
11935 save_cpu_state(ctx, 0);
11936 gen_helper_raise_exception_debug(cpu_env);
11938 tcg_gen_lookup_and_goto_ptr();
11939 break;
11940 default:
11941 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
11942 abort();
11947 /* Compact Branches */
11948 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
11949 int rs, int rt, int32_t offset)
11951 int bcond_compute = 0;
11952 TCGv t0 = tcg_temp_new();
11953 TCGv t1 = tcg_temp_new();
11954 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
11956 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11957 #ifdef MIPS_DEBUG_DISAS
11958 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11959 "\n", ctx->base.pc_next);
11960 #endif
11961 generate_exception_end(ctx, EXCP_RI);
11962 goto out;
11965 /* Load needed operands and calculate btarget */
11966 switch (opc) {
11967 /* compact branch */
11968 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11969 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11970 gen_load_gpr(t0, rs);
11971 gen_load_gpr(t1, rt);
11972 bcond_compute = 1;
11973 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11974 if (rs <= rt && rs == 0) {
11975 /* OPC_BEQZALC, OPC_BNEZALC */
11976 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11978 break;
11979 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11980 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11981 gen_load_gpr(t0, rs);
11982 gen_load_gpr(t1, rt);
11983 bcond_compute = 1;
11984 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11985 break;
11986 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11987 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11988 if (rs == 0 || rs == rt) {
11989 /* OPC_BLEZALC, OPC_BGEZALC */
11990 /* OPC_BGTZALC, OPC_BLTZALC */
11991 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11993 gen_load_gpr(t0, rs);
11994 gen_load_gpr(t1, rt);
11995 bcond_compute = 1;
11996 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11997 break;
11998 case OPC_BC:
11999 case OPC_BALC:
12000 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12001 break;
12002 case OPC_BEQZC:
12003 case OPC_BNEZC:
12004 if (rs != 0) {
12005 /* OPC_BEQZC, OPC_BNEZC */
12006 gen_load_gpr(t0, rs);
12007 bcond_compute = 1;
12008 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12009 } else {
12010 /* OPC_JIC, OPC_JIALC */
12011 TCGv tbase = tcg_temp_new();
12012 TCGv toffset = tcg_temp_new();
12014 gen_load_gpr(tbase, rt);
12015 tcg_gen_movi_tl(toffset, offset);
12016 gen_op_addr_add(ctx, btarget, tbase, toffset);
12017 tcg_temp_free(tbase);
12018 tcg_temp_free(toffset);
12020 break;
12021 default:
12022 MIPS_INVAL("Compact branch/jump");
12023 generate_exception_end(ctx, EXCP_RI);
12024 goto out;
12027 if (bcond_compute == 0) {
12028 /* Uncoditional compact branch */
12029 switch (opc) {
12030 case OPC_JIALC:
12031 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12032 /* Fallthrough */
12033 case OPC_JIC:
12034 ctx->hflags |= MIPS_HFLAG_BR;
12035 break;
12036 case OPC_BALC:
12037 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12038 /* Fallthrough */
12039 case OPC_BC:
12040 ctx->hflags |= MIPS_HFLAG_B;
12041 break;
12042 default:
12043 MIPS_INVAL("Compact branch/jump");
12044 generate_exception_end(ctx, EXCP_RI);
12045 goto out;
12048 /* Generating branch here as compact branches don't have delay slot */
12049 gen_branch(ctx, 4);
12050 } else {
12051 /* Conditional compact branch */
12052 TCGLabel *fs = gen_new_label();
12053 save_cpu_state(ctx, 0);
12055 switch (opc) {
12056 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12057 if (rs == 0 && rt != 0) {
12058 /* OPC_BLEZALC */
12059 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12060 } else if (rs != 0 && rt != 0 && rs == rt) {
12061 /* OPC_BGEZALC */
12062 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12063 } else {
12064 /* OPC_BGEUC */
12065 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12067 break;
12068 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12069 if (rs == 0 && rt != 0) {
12070 /* OPC_BGTZALC */
12071 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12072 } else if (rs != 0 && rt != 0 && rs == rt) {
12073 /* OPC_BLTZALC */
12074 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12075 } else {
12076 /* OPC_BLTUC */
12077 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12079 break;
12080 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12081 if (rs == 0 && rt != 0) {
12082 /* OPC_BLEZC */
12083 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12084 } else if (rs != 0 && rt != 0 && rs == rt) {
12085 /* OPC_BGEZC */
12086 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12087 } else {
12088 /* OPC_BGEC */
12089 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12091 break;
12092 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12093 if (rs == 0 && rt != 0) {
12094 /* OPC_BGTZC */
12095 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12096 } else if (rs != 0 && rt != 0 && rs == rt) {
12097 /* OPC_BLTZC */
12098 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12099 } else {
12100 /* OPC_BLTC */
12101 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12103 break;
12104 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12105 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12106 if (rs >= rt) {
12107 /* OPC_BOVC, OPC_BNVC */
12108 TCGv t2 = tcg_temp_new();
12109 TCGv t3 = tcg_temp_new();
12110 TCGv t4 = tcg_temp_new();
12111 TCGv input_overflow = tcg_temp_new();
12113 gen_load_gpr(t0, rs);
12114 gen_load_gpr(t1, rt);
12115 tcg_gen_ext32s_tl(t2, t0);
12116 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12117 tcg_gen_ext32s_tl(t3, t1);
12118 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12119 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12121 tcg_gen_add_tl(t4, t2, t3);
12122 tcg_gen_ext32s_tl(t4, t4);
12123 tcg_gen_xor_tl(t2, t2, t3);
12124 tcg_gen_xor_tl(t3, t4, t3);
12125 tcg_gen_andc_tl(t2, t3, t2);
12126 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12127 tcg_gen_or_tl(t4, t4, input_overflow);
12128 if (opc == OPC_BOVC) {
12129 /* OPC_BOVC */
12130 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12131 } else {
12132 /* OPC_BNVC */
12133 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12135 tcg_temp_free(input_overflow);
12136 tcg_temp_free(t4);
12137 tcg_temp_free(t3);
12138 tcg_temp_free(t2);
12139 } else if (rs < rt && rs == 0) {
12140 /* OPC_BEQZALC, OPC_BNEZALC */
12141 if (opc == OPC_BEQZALC) {
12142 /* OPC_BEQZALC */
12143 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12144 } else {
12145 /* OPC_BNEZALC */
12146 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12148 } else {
12149 /* OPC_BEQC, OPC_BNEC */
12150 if (opc == OPC_BEQC) {
12151 /* OPC_BEQC */
12152 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12153 } else {
12154 /* OPC_BNEC */
12155 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12158 break;
12159 case OPC_BEQZC:
12160 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12161 break;
12162 case OPC_BNEZC:
12163 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12164 break;
12165 default:
12166 MIPS_INVAL("Compact conditional branch/jump");
12167 generate_exception_end(ctx, EXCP_RI);
12168 goto out;
12171 /* Generating branch here as compact branches don't have delay slot */
12172 gen_goto_tb(ctx, 1, ctx->btarget);
12173 gen_set_label(fs);
12175 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12178 out:
12179 tcg_temp_free(t0);
12180 tcg_temp_free(t1);
12183 /* ISA extensions (ASEs) */
12184 /* MIPS16 extension to MIPS32 */
12186 /* MIPS16 major opcodes */
12187 enum {
12188 M16_OPC_ADDIUSP = 0x00,
12189 M16_OPC_ADDIUPC = 0x01,
12190 M16_OPC_B = 0x02,
12191 M16_OPC_JAL = 0x03,
12192 M16_OPC_BEQZ = 0x04,
12193 M16_OPC_BNEQZ = 0x05,
12194 M16_OPC_SHIFT = 0x06,
12195 M16_OPC_LD = 0x07,
12196 M16_OPC_RRIA = 0x08,
12197 M16_OPC_ADDIU8 = 0x09,
12198 M16_OPC_SLTI = 0x0a,
12199 M16_OPC_SLTIU = 0x0b,
12200 M16_OPC_I8 = 0x0c,
12201 M16_OPC_LI = 0x0d,
12202 M16_OPC_CMPI = 0x0e,
12203 M16_OPC_SD = 0x0f,
12204 M16_OPC_LB = 0x10,
12205 M16_OPC_LH = 0x11,
12206 M16_OPC_LWSP = 0x12,
12207 M16_OPC_LW = 0x13,
12208 M16_OPC_LBU = 0x14,
12209 M16_OPC_LHU = 0x15,
12210 M16_OPC_LWPC = 0x16,
12211 M16_OPC_LWU = 0x17,
12212 M16_OPC_SB = 0x18,
12213 M16_OPC_SH = 0x19,
12214 M16_OPC_SWSP = 0x1a,
12215 M16_OPC_SW = 0x1b,
12216 M16_OPC_RRR = 0x1c,
12217 M16_OPC_RR = 0x1d,
12218 M16_OPC_EXTEND = 0x1e,
12219 M16_OPC_I64 = 0x1f
12222 /* I8 funct field */
12223 enum {
12224 I8_BTEQZ = 0x0,
12225 I8_BTNEZ = 0x1,
12226 I8_SWRASP = 0x2,
12227 I8_ADJSP = 0x3,
12228 I8_SVRS = 0x4,
12229 I8_MOV32R = 0x5,
12230 I8_MOVR32 = 0x7
12233 /* RRR f field */
12234 enum {
12235 RRR_DADDU = 0x0,
12236 RRR_ADDU = 0x1,
12237 RRR_DSUBU = 0x2,
12238 RRR_SUBU = 0x3
12241 /* RR funct field */
12242 enum {
12243 RR_JR = 0x00,
12244 RR_SDBBP = 0x01,
12245 RR_SLT = 0x02,
12246 RR_SLTU = 0x03,
12247 RR_SLLV = 0x04,
12248 RR_BREAK = 0x05,
12249 RR_SRLV = 0x06,
12250 RR_SRAV = 0x07,
12251 RR_DSRL = 0x08,
12252 RR_CMP = 0x0a,
12253 RR_NEG = 0x0b,
12254 RR_AND = 0x0c,
12255 RR_OR = 0x0d,
12256 RR_XOR = 0x0e,
12257 RR_NOT = 0x0f,
12258 RR_MFHI = 0x10,
12259 RR_CNVT = 0x11,
12260 RR_MFLO = 0x12,
12261 RR_DSRA = 0x13,
12262 RR_DSLLV = 0x14,
12263 RR_DSRLV = 0x16,
12264 RR_DSRAV = 0x17,
12265 RR_MULT = 0x18,
12266 RR_MULTU = 0x19,
12267 RR_DIV = 0x1a,
12268 RR_DIVU = 0x1b,
12269 RR_DMULT = 0x1c,
12270 RR_DMULTU = 0x1d,
12271 RR_DDIV = 0x1e,
12272 RR_DDIVU = 0x1f
12275 /* I64 funct field */
12276 enum {
12277 I64_LDSP = 0x0,
12278 I64_SDSP = 0x1,
12279 I64_SDRASP = 0x2,
12280 I64_DADJSP = 0x3,
12281 I64_LDPC = 0x4,
12282 I64_DADDIU5 = 0x5,
12283 I64_DADDIUPC = 0x6,
12284 I64_DADDIUSP = 0x7
12287 /* RR ry field for CNVT */
12288 enum {
12289 RR_RY_CNVT_ZEB = 0x0,
12290 RR_RY_CNVT_ZEH = 0x1,
12291 RR_RY_CNVT_ZEW = 0x2,
12292 RR_RY_CNVT_SEB = 0x4,
12293 RR_RY_CNVT_SEH = 0x5,
12294 RR_RY_CNVT_SEW = 0x6,
12297 static int xlat (int r)
12299 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12301 return map[r];
12304 static void gen_mips16_save (DisasContext *ctx,
12305 int xsregs, int aregs,
12306 int do_ra, int do_s0, int do_s1,
12307 int framesize)
12309 TCGv t0 = tcg_temp_new();
12310 TCGv t1 = tcg_temp_new();
12311 TCGv t2 = tcg_temp_new();
12312 int args, astatic;
12314 switch (aregs) {
12315 case 0:
12316 case 1:
12317 case 2:
12318 case 3:
12319 case 11:
12320 args = 0;
12321 break;
12322 case 4:
12323 case 5:
12324 case 6:
12325 case 7:
12326 args = 1;
12327 break;
12328 case 8:
12329 case 9:
12330 case 10:
12331 args = 2;
12332 break;
12333 case 12:
12334 case 13:
12335 args = 3;
12336 break;
12337 case 14:
12338 args = 4;
12339 break;
12340 default:
12341 generate_exception_end(ctx, EXCP_RI);
12342 return;
12345 switch (args) {
12346 case 4:
12347 gen_base_offset_addr(ctx, t0, 29, 12);
12348 gen_load_gpr(t1, 7);
12349 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12350 /* Fall through */
12351 case 3:
12352 gen_base_offset_addr(ctx, t0, 29, 8);
12353 gen_load_gpr(t1, 6);
12354 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12355 /* Fall through */
12356 case 2:
12357 gen_base_offset_addr(ctx, t0, 29, 4);
12358 gen_load_gpr(t1, 5);
12359 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12360 /* Fall through */
12361 case 1:
12362 gen_base_offset_addr(ctx, t0, 29, 0);
12363 gen_load_gpr(t1, 4);
12364 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12367 gen_load_gpr(t0, 29);
12369 #define DECR_AND_STORE(reg) do { \
12370 tcg_gen_movi_tl(t2, -4); \
12371 gen_op_addr_add(ctx, t0, t0, t2); \
12372 gen_load_gpr(t1, reg); \
12373 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12374 } while (0)
12376 if (do_ra) {
12377 DECR_AND_STORE(31);
12380 switch (xsregs) {
12381 case 7:
12382 DECR_AND_STORE(30);
12383 /* Fall through */
12384 case 6:
12385 DECR_AND_STORE(23);
12386 /* Fall through */
12387 case 5:
12388 DECR_AND_STORE(22);
12389 /* Fall through */
12390 case 4:
12391 DECR_AND_STORE(21);
12392 /* Fall through */
12393 case 3:
12394 DECR_AND_STORE(20);
12395 /* Fall through */
12396 case 2:
12397 DECR_AND_STORE(19);
12398 /* Fall through */
12399 case 1:
12400 DECR_AND_STORE(18);
12403 if (do_s1) {
12404 DECR_AND_STORE(17);
12406 if (do_s0) {
12407 DECR_AND_STORE(16);
12410 switch (aregs) {
12411 case 0:
12412 case 4:
12413 case 8:
12414 case 12:
12415 case 14:
12416 astatic = 0;
12417 break;
12418 case 1:
12419 case 5:
12420 case 9:
12421 case 13:
12422 astatic = 1;
12423 break;
12424 case 2:
12425 case 6:
12426 case 10:
12427 astatic = 2;
12428 break;
12429 case 3:
12430 case 7:
12431 astatic = 3;
12432 break;
12433 case 11:
12434 astatic = 4;
12435 break;
12436 default:
12437 generate_exception_end(ctx, EXCP_RI);
12438 return;
12441 if (astatic > 0) {
12442 DECR_AND_STORE(7);
12443 if (astatic > 1) {
12444 DECR_AND_STORE(6);
12445 if (astatic > 2) {
12446 DECR_AND_STORE(5);
12447 if (astatic > 3) {
12448 DECR_AND_STORE(4);
12453 #undef DECR_AND_STORE
12455 tcg_gen_movi_tl(t2, -framesize);
12456 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12457 tcg_temp_free(t0);
12458 tcg_temp_free(t1);
12459 tcg_temp_free(t2);
12462 static void gen_mips16_restore (DisasContext *ctx,
12463 int xsregs, int aregs,
12464 int do_ra, int do_s0, int do_s1,
12465 int framesize)
12467 int astatic;
12468 TCGv t0 = tcg_temp_new();
12469 TCGv t1 = tcg_temp_new();
12470 TCGv t2 = tcg_temp_new();
12472 tcg_gen_movi_tl(t2, framesize);
12473 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12475 #define DECR_AND_LOAD(reg) do { \
12476 tcg_gen_movi_tl(t2, -4); \
12477 gen_op_addr_add(ctx, t0, t0, t2); \
12478 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12479 gen_store_gpr(t1, reg); \
12480 } while (0)
12482 if (do_ra) {
12483 DECR_AND_LOAD(31);
12486 switch (xsregs) {
12487 case 7:
12488 DECR_AND_LOAD(30);
12489 /* Fall through */
12490 case 6:
12491 DECR_AND_LOAD(23);
12492 /* Fall through */
12493 case 5:
12494 DECR_AND_LOAD(22);
12495 /* Fall through */
12496 case 4:
12497 DECR_AND_LOAD(21);
12498 /* Fall through */
12499 case 3:
12500 DECR_AND_LOAD(20);
12501 /* Fall through */
12502 case 2:
12503 DECR_AND_LOAD(19);
12504 /* Fall through */
12505 case 1:
12506 DECR_AND_LOAD(18);
12509 if (do_s1) {
12510 DECR_AND_LOAD(17);
12512 if (do_s0) {
12513 DECR_AND_LOAD(16);
12516 switch (aregs) {
12517 case 0:
12518 case 4:
12519 case 8:
12520 case 12:
12521 case 14:
12522 astatic = 0;
12523 break;
12524 case 1:
12525 case 5:
12526 case 9:
12527 case 13:
12528 astatic = 1;
12529 break;
12530 case 2:
12531 case 6:
12532 case 10:
12533 astatic = 2;
12534 break;
12535 case 3:
12536 case 7:
12537 astatic = 3;
12538 break;
12539 case 11:
12540 astatic = 4;
12541 break;
12542 default:
12543 generate_exception_end(ctx, EXCP_RI);
12544 return;
12547 if (astatic > 0) {
12548 DECR_AND_LOAD(7);
12549 if (astatic > 1) {
12550 DECR_AND_LOAD(6);
12551 if (astatic > 2) {
12552 DECR_AND_LOAD(5);
12553 if (astatic > 3) {
12554 DECR_AND_LOAD(4);
12559 #undef DECR_AND_LOAD
12561 tcg_gen_movi_tl(t2, framesize);
12562 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12563 tcg_temp_free(t0);
12564 tcg_temp_free(t1);
12565 tcg_temp_free(t2);
12568 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
12569 int is_64_bit, int extended)
12571 TCGv t0;
12573 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12574 generate_exception_end(ctx, EXCP_RI);
12575 return;
12578 t0 = tcg_temp_new();
12580 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12581 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12582 if (!is_64_bit) {
12583 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12586 tcg_temp_free(t0);
12589 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12590 int16_t offset)
12592 TCGv_i32 t0 = tcg_const_i32(op);
12593 TCGv t1 = tcg_temp_new();
12594 gen_base_offset_addr(ctx, t1, base, offset);
12595 gen_helper_cache(cpu_env, t1, t0);
12598 #if defined(TARGET_MIPS64)
12599 static void decode_i64_mips16 (DisasContext *ctx,
12600 int ry, int funct, int16_t offset,
12601 int extended)
12603 switch (funct) {
12604 case I64_LDSP:
12605 check_insn(ctx, ISA_MIPS3);
12606 check_mips_64(ctx);
12607 offset = extended ? offset : offset << 3;
12608 gen_ld(ctx, OPC_LD, ry, 29, offset);
12609 break;
12610 case I64_SDSP:
12611 check_insn(ctx, ISA_MIPS3);
12612 check_mips_64(ctx);
12613 offset = extended ? offset : offset << 3;
12614 gen_st(ctx, OPC_SD, ry, 29, offset);
12615 break;
12616 case I64_SDRASP:
12617 check_insn(ctx, ISA_MIPS3);
12618 check_mips_64(ctx);
12619 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
12620 gen_st(ctx, OPC_SD, 31, 29, offset);
12621 break;
12622 case I64_DADJSP:
12623 check_insn(ctx, ISA_MIPS3);
12624 check_mips_64(ctx);
12625 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
12626 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
12627 break;
12628 case I64_LDPC:
12629 check_insn(ctx, ISA_MIPS3);
12630 check_mips_64(ctx);
12631 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12632 generate_exception_end(ctx, EXCP_RI);
12633 } else {
12634 offset = extended ? offset : offset << 3;
12635 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
12637 break;
12638 case I64_DADDIU5:
12639 check_insn(ctx, ISA_MIPS3);
12640 check_mips_64(ctx);
12641 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
12642 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
12643 break;
12644 case I64_DADDIUPC:
12645 check_insn(ctx, ISA_MIPS3);
12646 check_mips_64(ctx);
12647 offset = extended ? offset : offset << 2;
12648 gen_addiupc(ctx, ry, offset, 1, extended);
12649 break;
12650 case I64_DADDIUSP:
12651 check_insn(ctx, ISA_MIPS3);
12652 check_mips_64(ctx);
12653 offset = extended ? offset : offset << 2;
12654 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12655 break;
12658 #endif
12660 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12662 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
12663 int op, rx, ry, funct, sa;
12664 int16_t imm, offset;
12666 ctx->opcode = (ctx->opcode << 16) | extend;
12667 op = (ctx->opcode >> 11) & 0x1f;
12668 sa = (ctx->opcode >> 22) & 0x1f;
12669 funct = (ctx->opcode >> 8) & 0x7;
12670 rx = xlat((ctx->opcode >> 8) & 0x7);
12671 ry = xlat((ctx->opcode >> 5) & 0x7);
12672 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12673 | ((ctx->opcode >> 21) & 0x3f) << 5
12674 | (ctx->opcode & 0x1f));
12676 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
12677 counterparts. */
12678 switch (op) {
12679 case M16_OPC_ADDIUSP:
12680 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12681 break;
12682 case M16_OPC_ADDIUPC:
12683 gen_addiupc(ctx, rx, imm, 0, 1);
12684 break;
12685 case M16_OPC_B:
12686 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12687 /* No delay slot, so just process as a normal instruction */
12688 break;
12689 case M16_OPC_BEQZ:
12690 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12691 /* No delay slot, so just process as a normal instruction */
12692 break;
12693 case M16_OPC_BNEQZ:
12694 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12695 /* No delay slot, so just process as a normal instruction */
12696 break;
12697 case M16_OPC_SHIFT:
12698 switch (ctx->opcode & 0x3) {
12699 case 0x0:
12700 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12701 break;
12702 case 0x1:
12703 #if defined(TARGET_MIPS64)
12704 check_mips_64(ctx);
12705 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12706 #else
12707 generate_exception_end(ctx, EXCP_RI);
12708 #endif
12709 break;
12710 case 0x2:
12711 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12712 break;
12713 case 0x3:
12714 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12715 break;
12717 break;
12718 #if defined(TARGET_MIPS64)
12719 case M16_OPC_LD:
12720 check_insn(ctx, ISA_MIPS3);
12721 check_mips_64(ctx);
12722 gen_ld(ctx, OPC_LD, ry, rx, offset);
12723 break;
12724 #endif
12725 case M16_OPC_RRIA:
12726 imm = ctx->opcode & 0xf;
12727 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12728 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12729 imm = (int16_t) (imm << 1) >> 1;
12730 if ((ctx->opcode >> 4) & 0x1) {
12731 #if defined(TARGET_MIPS64)
12732 check_mips_64(ctx);
12733 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12734 #else
12735 generate_exception_end(ctx, EXCP_RI);
12736 #endif
12737 } else {
12738 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12740 break;
12741 case M16_OPC_ADDIU8:
12742 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12743 break;
12744 case M16_OPC_SLTI:
12745 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12746 break;
12747 case M16_OPC_SLTIU:
12748 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12749 break;
12750 case M16_OPC_I8:
12751 switch (funct) {
12752 case I8_BTEQZ:
12753 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
12754 break;
12755 case I8_BTNEZ:
12756 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
12757 break;
12758 case I8_SWRASP:
12759 gen_st(ctx, OPC_SW, 31, 29, imm);
12760 break;
12761 case I8_ADJSP:
12762 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
12763 break;
12764 case I8_SVRS:
12765 check_insn(ctx, ISA_MIPS32);
12767 int xsregs = (ctx->opcode >> 24) & 0x7;
12768 int aregs = (ctx->opcode >> 16) & 0xf;
12769 int do_ra = (ctx->opcode >> 6) & 0x1;
12770 int do_s0 = (ctx->opcode >> 5) & 0x1;
12771 int do_s1 = (ctx->opcode >> 4) & 0x1;
12772 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12773 | (ctx->opcode & 0xf)) << 3;
12775 if (ctx->opcode & (1 << 7)) {
12776 gen_mips16_save(ctx, xsregs, aregs,
12777 do_ra, do_s0, do_s1,
12778 framesize);
12779 } else {
12780 gen_mips16_restore(ctx, xsregs, aregs,
12781 do_ra, do_s0, do_s1,
12782 framesize);
12785 break;
12786 default:
12787 generate_exception_end(ctx, EXCP_RI);
12788 break;
12790 break;
12791 case M16_OPC_LI:
12792 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
12793 break;
12794 case M16_OPC_CMPI:
12795 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
12796 break;
12797 #if defined(TARGET_MIPS64)
12798 case M16_OPC_SD:
12799 check_insn(ctx, ISA_MIPS3);
12800 check_mips_64(ctx);
12801 gen_st(ctx, OPC_SD, ry, rx, offset);
12802 break;
12803 #endif
12804 case M16_OPC_LB:
12805 gen_ld(ctx, OPC_LB, ry, rx, offset);
12806 break;
12807 case M16_OPC_LH:
12808 gen_ld(ctx, OPC_LH, ry, rx, offset);
12809 break;
12810 case M16_OPC_LWSP:
12811 gen_ld(ctx, OPC_LW, rx, 29, offset);
12812 break;
12813 case M16_OPC_LW:
12814 gen_ld(ctx, OPC_LW, ry, rx, offset);
12815 break;
12816 case M16_OPC_LBU:
12817 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12818 break;
12819 case M16_OPC_LHU:
12820 gen_ld(ctx, OPC_LHU, ry, rx, offset);
12821 break;
12822 case M16_OPC_LWPC:
12823 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
12824 break;
12825 #if defined(TARGET_MIPS64)
12826 case M16_OPC_LWU:
12827 check_insn(ctx, ISA_MIPS3);
12828 check_mips_64(ctx);
12829 gen_ld(ctx, OPC_LWU, ry, rx, offset);
12830 break;
12831 #endif
12832 case M16_OPC_SB:
12833 gen_st(ctx, OPC_SB, ry, rx, offset);
12834 break;
12835 case M16_OPC_SH:
12836 gen_st(ctx, OPC_SH, ry, rx, offset);
12837 break;
12838 case M16_OPC_SWSP:
12839 gen_st(ctx, OPC_SW, rx, 29, offset);
12840 break;
12841 case M16_OPC_SW:
12842 gen_st(ctx, OPC_SW, ry, rx, offset);
12843 break;
12844 #if defined(TARGET_MIPS64)
12845 case M16_OPC_I64:
12846 decode_i64_mips16(ctx, ry, funct, offset, 1);
12847 break;
12848 #endif
12849 default:
12850 generate_exception_end(ctx, EXCP_RI);
12851 break;
12854 return 4;
12857 static inline bool is_uhi(int sdbbp_code)
12859 #ifdef CONFIG_USER_ONLY
12860 return false;
12861 #else
12862 return semihosting_enabled() && sdbbp_code == 1;
12863 #endif
12866 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12868 int rx, ry;
12869 int sa;
12870 int op, cnvt_op, op1, offset;
12871 int funct;
12872 int n_bytes;
12874 op = (ctx->opcode >> 11) & 0x1f;
12875 sa = (ctx->opcode >> 2) & 0x7;
12876 sa = sa == 0 ? 8 : sa;
12877 rx = xlat((ctx->opcode >> 8) & 0x7);
12878 cnvt_op = (ctx->opcode >> 5) & 0x7;
12879 ry = xlat((ctx->opcode >> 5) & 0x7);
12880 op1 = offset = ctx->opcode & 0x1f;
12882 n_bytes = 2;
12884 switch (op) {
12885 case M16_OPC_ADDIUSP:
12887 int16_t imm = ((uint8_t) ctx->opcode) << 2;
12889 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12891 break;
12892 case M16_OPC_ADDIUPC:
12893 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
12894 break;
12895 case M16_OPC_B:
12896 offset = (ctx->opcode & 0x7ff) << 1;
12897 offset = (int16_t)(offset << 4) >> 4;
12898 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
12899 /* No delay slot, so just process as a normal instruction */
12900 break;
12901 case M16_OPC_JAL:
12902 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
12903 offset = (((ctx->opcode & 0x1f) << 21)
12904 | ((ctx->opcode >> 5) & 0x1f) << 16
12905 | offset) << 2;
12906 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
12907 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
12908 n_bytes = 4;
12909 break;
12910 case M16_OPC_BEQZ:
12911 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
12912 ((int8_t)ctx->opcode) << 1, 0);
12913 /* No delay slot, so just process as a normal instruction */
12914 break;
12915 case M16_OPC_BNEQZ:
12916 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
12917 ((int8_t)ctx->opcode) << 1, 0);
12918 /* No delay slot, so just process as a normal instruction */
12919 break;
12920 case M16_OPC_SHIFT:
12921 switch (ctx->opcode & 0x3) {
12922 case 0x0:
12923 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12924 break;
12925 case 0x1:
12926 #if defined(TARGET_MIPS64)
12927 check_insn(ctx, ISA_MIPS3);
12928 check_mips_64(ctx);
12929 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12930 #else
12931 generate_exception_end(ctx, EXCP_RI);
12932 #endif
12933 break;
12934 case 0x2:
12935 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12936 break;
12937 case 0x3:
12938 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12939 break;
12941 break;
12942 #if defined(TARGET_MIPS64)
12943 case M16_OPC_LD:
12944 check_insn(ctx, ISA_MIPS3);
12945 check_mips_64(ctx);
12946 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
12947 break;
12948 #endif
12949 case M16_OPC_RRIA:
12951 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
12953 if ((ctx->opcode >> 4) & 1) {
12954 #if defined(TARGET_MIPS64)
12955 check_insn(ctx, ISA_MIPS3);
12956 check_mips_64(ctx);
12957 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12958 #else
12959 generate_exception_end(ctx, EXCP_RI);
12960 #endif
12961 } else {
12962 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12965 break;
12966 case M16_OPC_ADDIU8:
12968 int16_t imm = (int8_t) ctx->opcode;
12970 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12972 break;
12973 case M16_OPC_SLTI:
12975 int16_t imm = (uint8_t) ctx->opcode;
12976 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12978 break;
12979 case M16_OPC_SLTIU:
12981 int16_t imm = (uint8_t) ctx->opcode;
12982 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12984 break;
12985 case M16_OPC_I8:
12987 int reg32;
12989 funct = (ctx->opcode >> 8) & 0x7;
12990 switch (funct) {
12991 case I8_BTEQZ:
12992 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
12993 ((int8_t)ctx->opcode) << 1, 0);
12994 break;
12995 case I8_BTNEZ:
12996 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
12997 ((int8_t)ctx->opcode) << 1, 0);
12998 break;
12999 case I8_SWRASP:
13000 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13001 break;
13002 case I8_ADJSP:
13003 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13004 ((int8_t)ctx->opcode) << 3);
13005 break;
13006 case I8_SVRS:
13007 check_insn(ctx, ISA_MIPS32);
13009 int do_ra = ctx->opcode & (1 << 6);
13010 int do_s0 = ctx->opcode & (1 << 5);
13011 int do_s1 = ctx->opcode & (1 << 4);
13012 int framesize = ctx->opcode & 0xf;
13014 if (framesize == 0) {
13015 framesize = 128;
13016 } else {
13017 framesize = framesize << 3;
13020 if (ctx->opcode & (1 << 7)) {
13021 gen_mips16_save(ctx, 0, 0,
13022 do_ra, do_s0, do_s1, framesize);
13023 } else {
13024 gen_mips16_restore(ctx, 0, 0,
13025 do_ra, do_s0, do_s1, framesize);
13028 break;
13029 case I8_MOV32R:
13031 int rz = xlat(ctx->opcode & 0x7);
13033 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13034 ((ctx->opcode >> 5) & 0x7);
13035 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13037 break;
13038 case I8_MOVR32:
13039 reg32 = ctx->opcode & 0x1f;
13040 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13041 break;
13042 default:
13043 generate_exception_end(ctx, EXCP_RI);
13044 break;
13047 break;
13048 case M16_OPC_LI:
13050 int16_t imm = (uint8_t) ctx->opcode;
13052 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13054 break;
13055 case M16_OPC_CMPI:
13057 int16_t imm = (uint8_t) ctx->opcode;
13058 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13060 break;
13061 #if defined(TARGET_MIPS64)
13062 case M16_OPC_SD:
13063 check_insn(ctx, ISA_MIPS3);
13064 check_mips_64(ctx);
13065 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13066 break;
13067 #endif
13068 case M16_OPC_LB:
13069 gen_ld(ctx, OPC_LB, ry, rx, offset);
13070 break;
13071 case M16_OPC_LH:
13072 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13073 break;
13074 case M16_OPC_LWSP:
13075 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13076 break;
13077 case M16_OPC_LW:
13078 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13079 break;
13080 case M16_OPC_LBU:
13081 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13082 break;
13083 case M16_OPC_LHU:
13084 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13085 break;
13086 case M16_OPC_LWPC:
13087 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13088 break;
13089 #if defined (TARGET_MIPS64)
13090 case M16_OPC_LWU:
13091 check_insn(ctx, ISA_MIPS3);
13092 check_mips_64(ctx);
13093 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13094 break;
13095 #endif
13096 case M16_OPC_SB:
13097 gen_st(ctx, OPC_SB, ry, rx, offset);
13098 break;
13099 case M16_OPC_SH:
13100 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13101 break;
13102 case M16_OPC_SWSP:
13103 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13104 break;
13105 case M16_OPC_SW:
13106 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13107 break;
13108 case M16_OPC_RRR:
13110 int rz = xlat((ctx->opcode >> 2) & 0x7);
13111 int mips32_op;
13113 switch (ctx->opcode & 0x3) {
13114 case RRR_ADDU:
13115 mips32_op = OPC_ADDU;
13116 break;
13117 case RRR_SUBU:
13118 mips32_op = OPC_SUBU;
13119 break;
13120 #if defined(TARGET_MIPS64)
13121 case RRR_DADDU:
13122 mips32_op = OPC_DADDU;
13123 check_insn(ctx, ISA_MIPS3);
13124 check_mips_64(ctx);
13125 break;
13126 case RRR_DSUBU:
13127 mips32_op = OPC_DSUBU;
13128 check_insn(ctx, ISA_MIPS3);
13129 check_mips_64(ctx);
13130 break;
13131 #endif
13132 default:
13133 generate_exception_end(ctx, EXCP_RI);
13134 goto done;
13137 gen_arith(ctx, mips32_op, rz, rx, ry);
13138 done:
13141 break;
13142 case M16_OPC_RR:
13143 switch (op1) {
13144 case RR_JR:
13146 int nd = (ctx->opcode >> 7) & 0x1;
13147 int link = (ctx->opcode >> 6) & 0x1;
13148 int ra = (ctx->opcode >> 5) & 0x1;
13150 if (nd) {
13151 check_insn(ctx, ISA_MIPS32);
13154 if (link) {
13155 op = OPC_JALR;
13156 } else {
13157 op = OPC_JR;
13160 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13161 (nd ? 0 : 2));
13163 break;
13164 case RR_SDBBP:
13165 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13166 gen_helper_do_semihosting(cpu_env);
13167 } else {
13168 /* XXX: not clear which exception should be raised
13169 * when in debug mode...
13171 check_insn(ctx, ISA_MIPS32);
13172 generate_exception_end(ctx, EXCP_DBp);
13174 break;
13175 case RR_SLT:
13176 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13177 break;
13178 case RR_SLTU:
13179 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13180 break;
13181 case RR_BREAK:
13182 generate_exception_end(ctx, EXCP_BREAK);
13183 break;
13184 case RR_SLLV:
13185 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13186 break;
13187 case RR_SRLV:
13188 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13189 break;
13190 case RR_SRAV:
13191 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13192 break;
13193 #if defined (TARGET_MIPS64)
13194 case RR_DSRL:
13195 check_insn(ctx, ISA_MIPS3);
13196 check_mips_64(ctx);
13197 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13198 break;
13199 #endif
13200 case RR_CMP:
13201 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13202 break;
13203 case RR_NEG:
13204 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13205 break;
13206 case RR_AND:
13207 gen_logic(ctx, OPC_AND, rx, rx, ry);
13208 break;
13209 case RR_OR:
13210 gen_logic(ctx, OPC_OR, rx, rx, ry);
13211 break;
13212 case RR_XOR:
13213 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13214 break;
13215 case RR_NOT:
13216 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13217 break;
13218 case RR_MFHI:
13219 gen_HILO(ctx, OPC_MFHI, 0, rx);
13220 break;
13221 case RR_CNVT:
13222 check_insn(ctx, ISA_MIPS32);
13223 switch (cnvt_op) {
13224 case RR_RY_CNVT_ZEB:
13225 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13226 break;
13227 case RR_RY_CNVT_ZEH:
13228 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13229 break;
13230 case RR_RY_CNVT_SEB:
13231 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13232 break;
13233 case RR_RY_CNVT_SEH:
13234 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13235 break;
13236 #if defined (TARGET_MIPS64)
13237 case RR_RY_CNVT_ZEW:
13238 check_insn(ctx, ISA_MIPS64);
13239 check_mips_64(ctx);
13240 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13241 break;
13242 case RR_RY_CNVT_SEW:
13243 check_insn(ctx, ISA_MIPS64);
13244 check_mips_64(ctx);
13245 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13246 break;
13247 #endif
13248 default:
13249 generate_exception_end(ctx, EXCP_RI);
13250 break;
13252 break;
13253 case RR_MFLO:
13254 gen_HILO(ctx, OPC_MFLO, 0, rx);
13255 break;
13256 #if defined (TARGET_MIPS64)
13257 case RR_DSRA:
13258 check_insn(ctx, ISA_MIPS3);
13259 check_mips_64(ctx);
13260 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13261 break;
13262 case RR_DSLLV:
13263 check_insn(ctx, ISA_MIPS3);
13264 check_mips_64(ctx);
13265 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13266 break;
13267 case RR_DSRLV:
13268 check_insn(ctx, ISA_MIPS3);
13269 check_mips_64(ctx);
13270 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13271 break;
13272 case RR_DSRAV:
13273 check_insn(ctx, ISA_MIPS3);
13274 check_mips_64(ctx);
13275 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13276 break;
13277 #endif
13278 case RR_MULT:
13279 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13280 break;
13281 case RR_MULTU:
13282 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13283 break;
13284 case RR_DIV:
13285 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13286 break;
13287 case RR_DIVU:
13288 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13289 break;
13290 #if defined (TARGET_MIPS64)
13291 case RR_DMULT:
13292 check_insn(ctx, ISA_MIPS3);
13293 check_mips_64(ctx);
13294 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13295 break;
13296 case RR_DMULTU:
13297 check_insn(ctx, ISA_MIPS3);
13298 check_mips_64(ctx);
13299 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13300 break;
13301 case RR_DDIV:
13302 check_insn(ctx, ISA_MIPS3);
13303 check_mips_64(ctx);
13304 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13305 break;
13306 case RR_DDIVU:
13307 check_insn(ctx, ISA_MIPS3);
13308 check_mips_64(ctx);
13309 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13310 break;
13311 #endif
13312 default:
13313 generate_exception_end(ctx, EXCP_RI);
13314 break;
13316 break;
13317 case M16_OPC_EXTEND:
13318 decode_extended_mips16_opc(env, ctx);
13319 n_bytes = 4;
13320 break;
13321 #if defined(TARGET_MIPS64)
13322 case M16_OPC_I64:
13323 funct = (ctx->opcode >> 8) & 0x7;
13324 decode_i64_mips16(ctx, ry, funct, offset, 0);
13325 break;
13326 #endif
13327 default:
13328 generate_exception_end(ctx, EXCP_RI);
13329 break;
13332 return n_bytes;
13335 /* microMIPS extension to MIPS32/MIPS64 */
13338 * microMIPS32/microMIPS64 major opcodes
13340 * 1. MIPS Architecture for Programmers Volume II-B:
13341 * The microMIPS32 Instruction Set (Revision 3.05)
13343 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13345 * 2. MIPS Architecture For Programmers Volume II-A:
13346 * The MIPS64 Instruction Set (Revision 3.51)
13349 enum {
13350 POOL32A = 0x00,
13351 POOL16A = 0x01,
13352 LBU16 = 0x02,
13353 MOVE16 = 0x03,
13354 ADDI32 = 0x04,
13355 R6_LUI = 0x04,
13356 AUI = 0x04,
13357 LBU32 = 0x05,
13358 SB32 = 0x06,
13359 LB32 = 0x07,
13361 POOL32B = 0x08,
13362 POOL16B = 0x09,
13363 LHU16 = 0x0a,
13364 ANDI16 = 0x0b,
13365 ADDIU32 = 0x0c,
13366 LHU32 = 0x0d,
13367 SH32 = 0x0e,
13368 LH32 = 0x0f,
13370 POOL32I = 0x10,
13371 POOL16C = 0x11,
13372 LWSP16 = 0x12,
13373 POOL16D = 0x13,
13374 ORI32 = 0x14,
13375 POOL32F = 0x15,
13376 POOL32S = 0x16, /* MIPS64 */
13377 DADDIU32 = 0x17, /* MIPS64 */
13379 POOL32C = 0x18,
13380 LWGP16 = 0x19,
13381 LW16 = 0x1a,
13382 POOL16E = 0x1b,
13383 XORI32 = 0x1c,
13384 JALS32 = 0x1d,
13385 BOVC = 0x1d,
13386 BEQC = 0x1d,
13387 BEQZALC = 0x1d,
13388 ADDIUPC = 0x1e,
13389 PCREL = 0x1e,
13390 BNVC = 0x1f,
13391 BNEC = 0x1f,
13392 BNEZALC = 0x1f,
13394 R6_BEQZC = 0x20,
13395 JIC = 0x20,
13396 POOL16F = 0x21,
13397 SB16 = 0x22,
13398 BEQZ16 = 0x23,
13399 BEQZC16 = 0x23,
13400 SLTI32 = 0x24,
13401 BEQ32 = 0x25,
13402 BC = 0x25,
13403 SWC132 = 0x26,
13404 LWC132 = 0x27,
13406 /* 0x29 is reserved */
13407 RES_29 = 0x29,
13408 R6_BNEZC = 0x28,
13409 JIALC = 0x28,
13410 SH16 = 0x2a,
13411 BNEZ16 = 0x2b,
13412 BNEZC16 = 0x2b,
13413 SLTIU32 = 0x2c,
13414 BNE32 = 0x2d,
13415 BALC = 0x2d,
13416 SDC132 = 0x2e,
13417 LDC132 = 0x2f,
13419 /* 0x31 is reserved */
13420 RES_31 = 0x31,
13421 BLEZALC = 0x30,
13422 BGEZALC = 0x30,
13423 BGEUC = 0x30,
13424 SWSP16 = 0x32,
13425 B16 = 0x33,
13426 BC16 = 0x33,
13427 ANDI32 = 0x34,
13428 J32 = 0x35,
13429 BGTZC = 0x35,
13430 BLTZC = 0x35,
13431 BLTC = 0x35,
13432 SD32 = 0x36, /* MIPS64 */
13433 LD32 = 0x37, /* MIPS64 */
13435 /* 0x39 is reserved */
13436 RES_39 = 0x39,
13437 BGTZALC = 0x38,
13438 BLTZALC = 0x38,
13439 BLTUC = 0x38,
13440 SW16 = 0x3a,
13441 LI16 = 0x3b,
13442 JALX32 = 0x3c,
13443 JAL32 = 0x3d,
13444 BLEZC = 0x3d,
13445 BGEZC = 0x3d,
13446 BGEC = 0x3d,
13447 SW32 = 0x3e,
13448 LW32 = 0x3f
13451 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13452 enum {
13453 ADDIUPC_00 = 0x00,
13454 ADDIUPC_01 = 0x01,
13455 ADDIUPC_02 = 0x02,
13456 ADDIUPC_03 = 0x03,
13457 ADDIUPC_04 = 0x04,
13458 ADDIUPC_05 = 0x05,
13459 ADDIUPC_06 = 0x06,
13460 ADDIUPC_07 = 0x07,
13461 AUIPC = 0x1e,
13462 ALUIPC = 0x1f,
13463 LWPC_08 = 0x08,
13464 LWPC_09 = 0x09,
13465 LWPC_0A = 0x0A,
13466 LWPC_0B = 0x0B,
13467 LWPC_0C = 0x0C,
13468 LWPC_0D = 0x0D,
13469 LWPC_0E = 0x0E,
13470 LWPC_0F = 0x0F,
13473 /* POOL32A encoding of minor opcode field */
13475 enum {
13476 /* These opcodes are distinguished only by bits 9..6; those bits are
13477 * what are recorded below. */
13478 SLL32 = 0x0,
13479 SRL32 = 0x1,
13480 SRA = 0x2,
13481 ROTR = 0x3,
13482 SELEQZ = 0x5,
13483 SELNEZ = 0x6,
13484 R6_RDHWR = 0x7,
13486 SLLV = 0x0,
13487 SRLV = 0x1,
13488 SRAV = 0x2,
13489 ROTRV = 0x3,
13490 ADD = 0x4,
13491 ADDU32 = 0x5,
13492 SUB = 0x6,
13493 SUBU32 = 0x7,
13494 MUL = 0x8,
13495 AND = 0x9,
13496 OR32 = 0xa,
13497 NOR = 0xb,
13498 XOR32 = 0xc,
13499 SLT = 0xd,
13500 SLTU = 0xe,
13502 MOVN = 0x0,
13503 R6_MUL = 0x0,
13504 MOVZ = 0x1,
13505 MUH = 0x1,
13506 MULU = 0x2,
13507 MUHU = 0x3,
13508 LWXS = 0x4,
13509 R6_DIV = 0x4,
13510 MOD = 0x5,
13511 R6_DIVU = 0x6,
13512 MODU = 0x7,
13514 /* The following can be distinguished by their lower 6 bits. */
13515 BREAK32 = 0x07,
13516 INS = 0x0c,
13517 LSA = 0x0f,
13518 ALIGN = 0x1f,
13519 EXT = 0x2c,
13520 POOL32AXF = 0x3c,
13521 SIGRIE = 0x3f
13524 /* POOL32AXF encoding of minor opcode field extension */
13527 * 1. MIPS Architecture for Programmers Volume II-B:
13528 * The microMIPS32 Instruction Set (Revision 3.05)
13530 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13532 * 2. MIPS Architecture for Programmers VolumeIV-e:
13533 * The MIPS DSP Application-Specific Extension
13534 * to the microMIPS32 Architecture (Revision 2.34)
13536 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13539 enum {
13540 /* bits 11..6 */
13541 TEQ = 0x00,
13542 TGE = 0x08,
13543 TGEU = 0x10,
13544 TLT = 0x20,
13545 TLTU = 0x28,
13546 TNE = 0x30,
13548 MFC0 = 0x03,
13549 MTC0 = 0x0b,
13551 /* begin of microMIPS32 DSP */
13553 /* bits 13..12 for 0x01 */
13554 MFHI_ACC = 0x0,
13555 MFLO_ACC = 0x1,
13556 MTHI_ACC = 0x2,
13557 MTLO_ACC = 0x3,
13559 /* bits 13..12 for 0x2a */
13560 MADD_ACC = 0x0,
13561 MADDU_ACC = 0x1,
13562 MSUB_ACC = 0x2,
13563 MSUBU_ACC = 0x3,
13565 /* bits 13..12 for 0x32 */
13566 MULT_ACC = 0x0,
13567 MULTU_ACC = 0x1,
13569 /* end of microMIPS32 DSP */
13571 /* bits 15..12 for 0x2c */
13572 BITSWAP = 0x0,
13573 SEB = 0x2,
13574 SEH = 0x3,
13575 CLO = 0x4,
13576 CLZ = 0x5,
13577 RDHWR = 0x6,
13578 WSBH = 0x7,
13579 MULT = 0x8,
13580 MULTU = 0x9,
13581 DIV = 0xa,
13582 DIVU = 0xb,
13583 MADD = 0xc,
13584 MADDU = 0xd,
13585 MSUB = 0xe,
13586 MSUBU = 0xf,
13588 /* bits 15..12 for 0x34 */
13589 MFC2 = 0x4,
13590 MTC2 = 0x5,
13591 MFHC2 = 0x8,
13592 MTHC2 = 0x9,
13593 CFC2 = 0xc,
13594 CTC2 = 0xd,
13596 /* bits 15..12 for 0x3c */
13597 JALR = 0x0,
13598 JR = 0x0, /* alias */
13599 JALRC = 0x0,
13600 JRC = 0x0,
13601 JALR_HB = 0x1,
13602 JALRC_HB = 0x1,
13603 JALRS = 0x4,
13604 JALRS_HB = 0x5,
13606 /* bits 15..12 for 0x05 */
13607 RDPGPR = 0xe,
13608 WRPGPR = 0xf,
13610 /* bits 15..12 for 0x0d */
13611 TLBP = 0x0,
13612 TLBR = 0x1,
13613 TLBWI = 0x2,
13614 TLBWR = 0x3,
13615 TLBINV = 0x4,
13616 TLBINVF = 0x5,
13617 WAIT = 0x9,
13618 IRET = 0xd,
13619 DERET = 0xe,
13620 ERET = 0xf,
13622 /* bits 15..12 for 0x15 */
13623 DMT = 0x0,
13624 DVPE = 0x1,
13625 EMT = 0x2,
13626 EVPE = 0x3,
13628 /* bits 15..12 for 0x1d */
13629 DI = 0x4,
13630 EI = 0x5,
13632 /* bits 15..12 for 0x2d */
13633 SYNC = 0x6,
13634 SYSCALL = 0x8,
13635 SDBBP = 0xd,
13637 /* bits 15..12 for 0x35 */
13638 MFHI32 = 0x0,
13639 MFLO32 = 0x1,
13640 MTHI32 = 0x2,
13641 MTLO32 = 0x3,
13644 /* POOL32B encoding of minor opcode field (bits 15..12) */
13646 enum {
13647 LWC2 = 0x0,
13648 LWP = 0x1,
13649 LDP = 0x4,
13650 LWM32 = 0x5,
13651 CACHE = 0x6,
13652 LDM = 0x7,
13653 SWC2 = 0x8,
13654 SWP = 0x9,
13655 SDP = 0xc,
13656 SWM32 = 0xd,
13657 SDM = 0xf
13660 /* POOL32C encoding of minor opcode field (bits 15..12) */
13662 enum {
13663 LWL = 0x0,
13664 SWL = 0x8,
13665 LWR = 0x1,
13666 SWR = 0x9,
13667 PREF = 0x2,
13668 ST_EVA = 0xa,
13669 LL = 0x3,
13670 SC = 0xb,
13671 LDL = 0x4,
13672 SDL = 0xc,
13673 LDR = 0x5,
13674 SDR = 0xd,
13675 LD_EVA = 0x6,
13676 LWU = 0xe,
13677 LLD = 0x7,
13678 SCD = 0xf
13681 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13683 enum {
13684 LBUE = 0x0,
13685 LHUE = 0x1,
13686 LWLE = 0x2,
13687 LWRE = 0x3,
13688 LBE = 0x4,
13689 LHE = 0x5,
13690 LLE = 0x6,
13691 LWE = 0x7,
13694 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13696 enum {
13697 SWLE = 0x0,
13698 SWRE = 0x1,
13699 PREFE = 0x2,
13700 CACHEE = 0x3,
13701 SBE = 0x4,
13702 SHE = 0x5,
13703 SCE = 0x6,
13704 SWE = 0x7,
13707 /* POOL32F encoding of minor opcode field (bits 5..0) */
13709 enum {
13710 /* These are the bit 7..6 values */
13711 ADD_FMT = 0x0,
13713 SUB_FMT = 0x1,
13715 MUL_FMT = 0x2,
13717 DIV_FMT = 0x3,
13719 /* These are the bit 8..6 values */
13720 MOVN_FMT = 0x0,
13721 RSQRT2_FMT = 0x0,
13722 MOVF_FMT = 0x0,
13723 RINT_FMT = 0x0,
13724 SELNEZ_FMT = 0x0,
13726 MOVZ_FMT = 0x1,
13727 LWXC1 = 0x1,
13728 MOVT_FMT = 0x1,
13729 CLASS_FMT = 0x1,
13730 SELEQZ_FMT = 0x1,
13732 PLL_PS = 0x2,
13733 SWXC1 = 0x2,
13734 SEL_FMT = 0x2,
13736 PLU_PS = 0x3,
13737 LDXC1 = 0x3,
13739 MOVN_FMT_04 = 0x4,
13740 PUL_PS = 0x4,
13741 SDXC1 = 0x4,
13742 RECIP2_FMT = 0x4,
13744 MOVZ_FMT_05 = 0x05,
13745 PUU_PS = 0x5,
13746 LUXC1 = 0x5,
13748 CVT_PS_S = 0x6,
13749 SUXC1 = 0x6,
13750 ADDR_PS = 0x6,
13751 PREFX = 0x6,
13752 MADDF_FMT = 0x6,
13754 MULR_PS = 0x7,
13755 MSUBF_FMT = 0x7,
13757 MADD_S = 0x01,
13758 MADD_D = 0x09,
13759 MADD_PS = 0x11,
13760 ALNV_PS = 0x19,
13761 MSUB_S = 0x21,
13762 MSUB_D = 0x29,
13763 MSUB_PS = 0x31,
13765 NMADD_S = 0x02,
13766 NMADD_D = 0x0a,
13767 NMADD_PS = 0x12,
13768 NMSUB_S = 0x22,
13769 NMSUB_D = 0x2a,
13770 NMSUB_PS = 0x32,
13772 MIN_FMT = 0x3,
13773 MAX_FMT = 0xb,
13774 MINA_FMT = 0x23,
13775 MAXA_FMT = 0x2b,
13776 POOL32FXF = 0x3b,
13778 CABS_COND_FMT = 0x1c, /* MIPS3D */
13779 C_COND_FMT = 0x3c,
13781 CMP_CONDN_S = 0x5,
13782 CMP_CONDN_D = 0x15
13785 /* POOL32Fxf encoding of minor opcode extension field */
13787 enum {
13788 CVT_L = 0x04,
13789 RSQRT_FMT = 0x08,
13790 FLOOR_L = 0x0c,
13791 CVT_PW_PS = 0x1c,
13792 CVT_W = 0x24,
13793 SQRT_FMT = 0x28,
13794 FLOOR_W = 0x2c,
13795 CVT_PS_PW = 0x3c,
13796 CFC1 = 0x40,
13797 RECIP_FMT = 0x48,
13798 CEIL_L = 0x4c,
13799 CTC1 = 0x60,
13800 CEIL_W = 0x6c,
13801 MFC1 = 0x80,
13802 CVT_S_PL = 0x84,
13803 TRUNC_L = 0x8c,
13804 MTC1 = 0xa0,
13805 CVT_S_PU = 0xa4,
13806 TRUNC_W = 0xac,
13807 MFHC1 = 0xc0,
13808 ROUND_L = 0xcc,
13809 MTHC1 = 0xe0,
13810 ROUND_W = 0xec,
13812 MOV_FMT = 0x01,
13813 MOVF = 0x05,
13814 ABS_FMT = 0x0d,
13815 RSQRT1_FMT = 0x1d,
13816 MOVT = 0x25,
13817 NEG_FMT = 0x2d,
13818 CVT_D = 0x4d,
13819 RECIP1_FMT = 0x5d,
13820 CVT_S = 0x6d
13823 /* POOL32I encoding of minor opcode field (bits 25..21) */
13825 enum {
13826 BLTZ = 0x00,
13827 BLTZAL = 0x01,
13828 BGEZ = 0x02,
13829 BGEZAL = 0x03,
13830 BLEZ = 0x04,
13831 BNEZC = 0x05,
13832 BGTZ = 0x06,
13833 BEQZC = 0x07,
13834 TLTI = 0x08,
13835 BC1EQZC = 0x08,
13836 TGEI = 0x09,
13837 BC1NEZC = 0x09,
13838 TLTIU = 0x0a,
13839 BC2EQZC = 0x0a,
13840 TGEIU = 0x0b,
13841 BC2NEZC = 0x0a,
13842 TNEI = 0x0c,
13843 R6_SYNCI = 0x0c,
13844 LUI = 0x0d,
13845 TEQI = 0x0e,
13846 SYNCI = 0x10,
13847 BLTZALS = 0x11,
13848 BGEZALS = 0x13,
13849 BC2F = 0x14,
13850 BC2T = 0x15,
13851 BPOSGE64 = 0x1a,
13852 BPOSGE32 = 0x1b,
13853 /* These overlap and are distinguished by bit16 of the instruction */
13854 BC1F = 0x1c,
13855 BC1T = 0x1d,
13856 BC1ANY2F = 0x1c,
13857 BC1ANY2T = 0x1d,
13858 BC1ANY4F = 0x1e,
13859 BC1ANY4T = 0x1f
13862 /* POOL16A encoding of minor opcode field */
13864 enum {
13865 ADDU16 = 0x0,
13866 SUBU16 = 0x1
13869 /* POOL16B encoding of minor opcode field */
13871 enum {
13872 SLL16 = 0x0,
13873 SRL16 = 0x1
13876 /* POOL16C encoding of minor opcode field */
13878 enum {
13879 NOT16 = 0x00,
13880 XOR16 = 0x04,
13881 AND16 = 0x08,
13882 OR16 = 0x0c,
13883 LWM16 = 0x10,
13884 SWM16 = 0x14,
13885 JR16 = 0x18,
13886 JRC16 = 0x1a,
13887 JALR16 = 0x1c,
13888 JALR16S = 0x1e,
13889 MFHI16 = 0x20,
13890 MFLO16 = 0x24,
13891 BREAK16 = 0x28,
13892 SDBBP16 = 0x2c,
13893 JRADDIUSP = 0x30
13896 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
13898 enum {
13899 R6_NOT16 = 0x00,
13900 R6_AND16 = 0x01,
13901 R6_LWM16 = 0x02,
13902 R6_JRC16 = 0x03,
13903 MOVEP = 0x04,
13904 MOVEP_05 = 0x05,
13905 MOVEP_06 = 0x06,
13906 MOVEP_07 = 0x07,
13907 R6_XOR16 = 0x08,
13908 R6_OR16 = 0x09,
13909 R6_SWM16 = 0x0a,
13910 JALRC16 = 0x0b,
13911 MOVEP_0C = 0x0c,
13912 MOVEP_0D = 0x0d,
13913 MOVEP_0E = 0x0e,
13914 MOVEP_0F = 0x0f,
13915 JRCADDIUSP = 0x13,
13916 R6_BREAK16 = 0x1b,
13917 R6_SDBBP16 = 0x3b
13920 /* POOL16D encoding of minor opcode field */
13922 enum {
13923 ADDIUS5 = 0x0,
13924 ADDIUSP = 0x1
13927 /* POOL16E encoding of minor opcode field */
13929 enum {
13930 ADDIUR2 = 0x0,
13931 ADDIUR1SP = 0x1
13934 static int mmreg (int r)
13936 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13938 return map[r];
13941 /* Used for 16-bit store instructions. */
13942 static int mmreg2 (int r)
13944 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
13946 return map[r];
13949 #define uMIPS_RD(op) ((op >> 7) & 0x7)
13950 #define uMIPS_RS(op) ((op >> 4) & 0x7)
13951 #define uMIPS_RS2(op) uMIPS_RS(op)
13952 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
13953 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
13954 #define uMIPS_RS5(op) (op & 0x1f)
13956 /* Signed immediate */
13957 #define SIMM(op, start, width) \
13958 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
13959 << (32-width)) \
13960 >> (32-width))
13961 /* Zero-extended immediate */
13962 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
13964 static void gen_addiur1sp(DisasContext *ctx)
13966 int rd = mmreg(uMIPS_RD(ctx->opcode));
13968 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
13971 static void gen_addiur2(DisasContext *ctx)
13973 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
13974 int rd = mmreg(uMIPS_RD(ctx->opcode));
13975 int rs = mmreg(uMIPS_RS(ctx->opcode));
13977 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
13980 static void gen_addiusp(DisasContext *ctx)
13982 int encoded = ZIMM(ctx->opcode, 1, 9);
13983 int decoded;
13985 if (encoded <= 1) {
13986 decoded = 256 + encoded;
13987 } else if (encoded <= 255) {
13988 decoded = encoded;
13989 } else if (encoded <= 509) {
13990 decoded = encoded - 512;
13991 } else {
13992 decoded = encoded - 768;
13995 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
13998 static void gen_addius5(DisasContext *ctx)
14000 int imm = SIMM(ctx->opcode, 1, 4);
14001 int rd = (ctx->opcode >> 5) & 0x1f;
14003 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14006 static void gen_andi16(DisasContext *ctx)
14008 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14009 31, 32, 63, 64, 255, 32768, 65535 };
14010 int rd = mmreg(uMIPS_RD(ctx->opcode));
14011 int rs = mmreg(uMIPS_RS(ctx->opcode));
14012 int encoded = ZIMM(ctx->opcode, 0, 4);
14014 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14017 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14018 int base, int16_t offset)
14020 TCGv t0, t1;
14021 TCGv_i32 t2;
14023 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14024 generate_exception_end(ctx, EXCP_RI);
14025 return;
14028 t0 = tcg_temp_new();
14030 gen_base_offset_addr(ctx, t0, base, offset);
14032 t1 = tcg_const_tl(reglist);
14033 t2 = tcg_const_i32(ctx->mem_idx);
14035 save_cpu_state(ctx, 1);
14036 switch (opc) {
14037 case LWM32:
14038 gen_helper_lwm(cpu_env, t0, t1, t2);
14039 break;
14040 case SWM32:
14041 gen_helper_swm(cpu_env, t0, t1, t2);
14042 break;
14043 #ifdef TARGET_MIPS64
14044 case LDM:
14045 gen_helper_ldm(cpu_env, t0, t1, t2);
14046 break;
14047 case SDM:
14048 gen_helper_sdm(cpu_env, t0, t1, t2);
14049 break;
14050 #endif
14052 tcg_temp_free(t0);
14053 tcg_temp_free(t1);
14054 tcg_temp_free_i32(t2);
14058 static void gen_pool16c_insn(DisasContext *ctx)
14060 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14061 int rs = mmreg(ctx->opcode & 0x7);
14063 switch (((ctx->opcode) >> 4) & 0x3f) {
14064 case NOT16 + 0:
14065 case NOT16 + 1:
14066 case NOT16 + 2:
14067 case NOT16 + 3:
14068 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14069 break;
14070 case XOR16 + 0:
14071 case XOR16 + 1:
14072 case XOR16 + 2:
14073 case XOR16 + 3:
14074 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14075 break;
14076 case AND16 + 0:
14077 case AND16 + 1:
14078 case AND16 + 2:
14079 case AND16 + 3:
14080 gen_logic(ctx, OPC_AND, rd, rd, rs);
14081 break;
14082 case OR16 + 0:
14083 case OR16 + 1:
14084 case OR16 + 2:
14085 case OR16 + 3:
14086 gen_logic(ctx, OPC_OR, rd, rd, rs);
14087 break;
14088 case LWM16 + 0:
14089 case LWM16 + 1:
14090 case LWM16 + 2:
14091 case LWM16 + 3:
14093 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14094 int offset = ZIMM(ctx->opcode, 0, 4);
14096 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14097 29, offset << 2);
14099 break;
14100 case SWM16 + 0:
14101 case SWM16 + 1:
14102 case SWM16 + 2:
14103 case SWM16 + 3:
14105 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14106 int offset = ZIMM(ctx->opcode, 0, 4);
14108 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14109 29, offset << 2);
14111 break;
14112 case JR16 + 0:
14113 case JR16 + 1:
14115 int reg = ctx->opcode & 0x1f;
14117 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14119 break;
14120 case JRC16 + 0:
14121 case JRC16 + 1:
14123 int reg = ctx->opcode & 0x1f;
14124 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14125 /* Let normal delay slot handling in our caller take us
14126 to the branch target. */
14128 break;
14129 case JALR16 + 0:
14130 case JALR16 + 1:
14131 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14132 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14133 break;
14134 case JALR16S + 0:
14135 case JALR16S + 1:
14136 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14137 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14138 break;
14139 case MFHI16 + 0:
14140 case MFHI16 + 1:
14141 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14142 break;
14143 case MFLO16 + 0:
14144 case MFLO16 + 1:
14145 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14146 break;
14147 case BREAK16:
14148 generate_exception_end(ctx, EXCP_BREAK);
14149 break;
14150 case SDBBP16:
14151 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14152 gen_helper_do_semihosting(cpu_env);
14153 } else {
14154 /* XXX: not clear which exception should be raised
14155 * when in debug mode...
14157 check_insn(ctx, ISA_MIPS32);
14158 generate_exception_end(ctx, EXCP_DBp);
14160 break;
14161 case JRADDIUSP + 0:
14162 case JRADDIUSP + 1:
14164 int imm = ZIMM(ctx->opcode, 0, 5);
14165 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14166 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14167 /* Let normal delay slot handling in our caller take us
14168 to the branch target. */
14170 break;
14171 default:
14172 generate_exception_end(ctx, EXCP_RI);
14173 break;
14177 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14178 int enc_rs)
14180 int rd, rs, re, rt;
14181 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14182 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14183 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14184 rd = rd_enc[enc_dest];
14185 re = re_enc[enc_dest];
14186 rs = rs_rt_enc[enc_rs];
14187 rt = rs_rt_enc[enc_rt];
14188 if (rs) {
14189 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14190 } else {
14191 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14193 if (rt) {
14194 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14195 } else {
14196 tcg_gen_movi_tl(cpu_gpr[re], 0);
14200 static void gen_pool16c_r6_insn(DisasContext *ctx)
14202 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14203 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14205 switch (ctx->opcode & 0xf) {
14206 case R6_NOT16:
14207 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14208 break;
14209 case R6_AND16:
14210 gen_logic(ctx, OPC_AND, rt, rt, rs);
14211 break;
14212 case R6_LWM16:
14214 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14215 int offset = extract32(ctx->opcode, 4, 4);
14216 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14218 break;
14219 case R6_JRC16: /* JRCADDIUSP */
14220 if ((ctx->opcode >> 4) & 1) {
14221 /* JRCADDIUSP */
14222 int imm = extract32(ctx->opcode, 5, 5);
14223 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14224 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14225 } else {
14226 /* JRC16 */
14227 rs = extract32(ctx->opcode, 5, 5);
14228 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14230 break;
14231 case MOVEP:
14232 case MOVEP_05:
14233 case MOVEP_06:
14234 case MOVEP_07:
14235 case MOVEP_0C:
14236 case MOVEP_0D:
14237 case MOVEP_0E:
14238 case MOVEP_0F:
14240 int enc_dest = uMIPS_RD(ctx->opcode);
14241 int enc_rt = uMIPS_RS2(ctx->opcode);
14242 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14243 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14245 break;
14246 case R6_XOR16:
14247 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14248 break;
14249 case R6_OR16:
14250 gen_logic(ctx, OPC_OR, rt, rt, rs);
14251 break;
14252 case R6_SWM16:
14254 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14255 int offset = extract32(ctx->opcode, 4, 4);
14256 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14258 break;
14259 case JALRC16: /* BREAK16, SDBBP16 */
14260 switch (ctx->opcode & 0x3f) {
14261 case JALRC16:
14262 case JALRC16 + 0x20:
14263 /* JALRC16 */
14264 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14265 31, 0, 0);
14266 break;
14267 case R6_BREAK16:
14268 /* BREAK16 */
14269 generate_exception(ctx, EXCP_BREAK);
14270 break;
14271 case R6_SDBBP16:
14272 /* SDBBP16 */
14273 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14274 gen_helper_do_semihosting(cpu_env);
14275 } else {
14276 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14277 generate_exception(ctx, EXCP_RI);
14278 } else {
14279 generate_exception(ctx, EXCP_DBp);
14282 break;
14284 break;
14285 default:
14286 generate_exception(ctx, EXCP_RI);
14287 break;
14291 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14293 TCGv t0 = tcg_temp_new();
14294 TCGv t1 = tcg_temp_new();
14296 gen_load_gpr(t0, base);
14298 if (index != 0) {
14299 gen_load_gpr(t1, index);
14300 tcg_gen_shli_tl(t1, t1, 2);
14301 gen_op_addr_add(ctx, t0, t1, t0);
14304 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14305 gen_store_gpr(t1, rd);
14307 tcg_temp_free(t0);
14308 tcg_temp_free(t1);
14311 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14312 int base, int16_t offset)
14314 TCGv t0, t1;
14316 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14317 generate_exception_end(ctx, EXCP_RI);
14318 return;
14321 t0 = tcg_temp_new();
14322 t1 = tcg_temp_new();
14324 gen_base_offset_addr(ctx, t0, base, offset);
14326 switch (opc) {
14327 case LWP:
14328 if (rd == base) {
14329 generate_exception_end(ctx, EXCP_RI);
14330 return;
14332 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14333 gen_store_gpr(t1, rd);
14334 tcg_gen_movi_tl(t1, 4);
14335 gen_op_addr_add(ctx, t0, t0, t1);
14336 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14337 gen_store_gpr(t1, rd+1);
14338 break;
14339 case SWP:
14340 gen_load_gpr(t1, rd);
14341 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14342 tcg_gen_movi_tl(t1, 4);
14343 gen_op_addr_add(ctx, t0, t0, t1);
14344 gen_load_gpr(t1, rd+1);
14345 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14346 break;
14347 #ifdef TARGET_MIPS64
14348 case LDP:
14349 if (rd == base) {
14350 generate_exception_end(ctx, EXCP_RI);
14351 return;
14353 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14354 gen_store_gpr(t1, rd);
14355 tcg_gen_movi_tl(t1, 8);
14356 gen_op_addr_add(ctx, t0, t0, t1);
14357 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14358 gen_store_gpr(t1, rd+1);
14359 break;
14360 case SDP:
14361 gen_load_gpr(t1, rd);
14362 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14363 tcg_gen_movi_tl(t1, 8);
14364 gen_op_addr_add(ctx, t0, t0, t1);
14365 gen_load_gpr(t1, rd+1);
14366 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14367 break;
14368 #endif
14370 tcg_temp_free(t0);
14371 tcg_temp_free(t1);
14374 static void gen_sync(int stype)
14376 TCGBar tcg_mo = TCG_BAR_SC;
14378 switch (stype) {
14379 case 0x4: /* SYNC_WMB */
14380 tcg_mo |= TCG_MO_ST_ST;
14381 break;
14382 case 0x10: /* SYNC_MB */
14383 tcg_mo |= TCG_MO_ALL;
14384 break;
14385 case 0x11: /* SYNC_ACQUIRE */
14386 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14387 break;
14388 case 0x12: /* SYNC_RELEASE */
14389 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14390 break;
14391 case 0x13: /* SYNC_RMB */
14392 tcg_mo |= TCG_MO_LD_LD;
14393 break;
14394 default:
14395 tcg_mo |= TCG_MO_ALL;
14396 break;
14399 tcg_gen_mb(tcg_mo);
14402 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14404 int extension = (ctx->opcode >> 6) & 0x3f;
14405 int minor = (ctx->opcode >> 12) & 0xf;
14406 uint32_t mips32_op;
14408 switch (extension) {
14409 case TEQ:
14410 mips32_op = OPC_TEQ;
14411 goto do_trap;
14412 case TGE:
14413 mips32_op = OPC_TGE;
14414 goto do_trap;
14415 case TGEU:
14416 mips32_op = OPC_TGEU;
14417 goto do_trap;
14418 case TLT:
14419 mips32_op = OPC_TLT;
14420 goto do_trap;
14421 case TLTU:
14422 mips32_op = OPC_TLTU;
14423 goto do_trap;
14424 case TNE:
14425 mips32_op = OPC_TNE;
14426 do_trap:
14427 gen_trap(ctx, mips32_op, rs, rt, -1);
14428 break;
14429 #ifndef CONFIG_USER_ONLY
14430 case MFC0:
14431 case MFC0 + 32:
14432 check_cp0_enabled(ctx);
14433 if (rt == 0) {
14434 /* Treat as NOP. */
14435 break;
14437 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14438 break;
14439 case MTC0:
14440 case MTC0 + 32:
14441 check_cp0_enabled(ctx);
14443 TCGv t0 = tcg_temp_new();
14445 gen_load_gpr(t0, rt);
14446 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14447 tcg_temp_free(t0);
14449 break;
14450 #endif
14451 case 0x2a:
14452 switch (minor & 3) {
14453 case MADD_ACC:
14454 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14455 break;
14456 case MADDU_ACC:
14457 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14458 break;
14459 case MSUB_ACC:
14460 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14461 break;
14462 case MSUBU_ACC:
14463 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14464 break;
14465 default:
14466 goto pool32axf_invalid;
14468 break;
14469 case 0x32:
14470 switch (minor & 3) {
14471 case MULT_ACC:
14472 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14473 break;
14474 case MULTU_ACC:
14475 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14476 break;
14477 default:
14478 goto pool32axf_invalid;
14480 break;
14481 case 0x2c:
14482 switch (minor) {
14483 case BITSWAP:
14484 check_insn(ctx, ISA_MIPS32R6);
14485 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14486 break;
14487 case SEB:
14488 gen_bshfl(ctx, OPC_SEB, rs, rt);
14489 break;
14490 case SEH:
14491 gen_bshfl(ctx, OPC_SEH, rs, rt);
14492 break;
14493 case CLO:
14494 mips32_op = OPC_CLO;
14495 goto do_cl;
14496 case CLZ:
14497 mips32_op = OPC_CLZ;
14498 do_cl:
14499 check_insn(ctx, ISA_MIPS32);
14500 gen_cl(ctx, mips32_op, rt, rs);
14501 break;
14502 case RDHWR:
14503 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14504 gen_rdhwr(ctx, rt, rs, 0);
14505 break;
14506 case WSBH:
14507 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14508 break;
14509 case MULT:
14510 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14511 mips32_op = OPC_MULT;
14512 goto do_mul;
14513 case MULTU:
14514 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14515 mips32_op = OPC_MULTU;
14516 goto do_mul;
14517 case DIV:
14518 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14519 mips32_op = OPC_DIV;
14520 goto do_div;
14521 case DIVU:
14522 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14523 mips32_op = OPC_DIVU;
14524 goto do_div;
14525 do_div:
14526 check_insn(ctx, ISA_MIPS32);
14527 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14528 break;
14529 case MADD:
14530 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14531 mips32_op = OPC_MADD;
14532 goto do_mul;
14533 case MADDU:
14534 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14535 mips32_op = OPC_MADDU;
14536 goto do_mul;
14537 case MSUB:
14538 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14539 mips32_op = OPC_MSUB;
14540 goto do_mul;
14541 case MSUBU:
14542 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14543 mips32_op = OPC_MSUBU;
14544 do_mul:
14545 check_insn(ctx, ISA_MIPS32);
14546 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14547 break;
14548 default:
14549 goto pool32axf_invalid;
14551 break;
14552 case 0x34:
14553 switch (minor) {
14554 case MFC2:
14555 case MTC2:
14556 case MFHC2:
14557 case MTHC2:
14558 case CFC2:
14559 case CTC2:
14560 generate_exception_err(ctx, EXCP_CpU, 2);
14561 break;
14562 default:
14563 goto pool32axf_invalid;
14565 break;
14566 case 0x3c:
14567 switch (minor) {
14568 case JALR: /* JALRC */
14569 case JALR_HB: /* JALRC_HB */
14570 if (ctx->insn_flags & ISA_MIPS32R6) {
14571 /* JALRC, JALRC_HB */
14572 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14573 } else {
14574 /* JALR, JALR_HB */
14575 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14576 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14578 break;
14579 case JALRS:
14580 case JALRS_HB:
14581 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14582 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14583 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14584 break;
14585 default:
14586 goto pool32axf_invalid;
14588 break;
14589 case 0x05:
14590 switch (minor) {
14591 case RDPGPR:
14592 check_cp0_enabled(ctx);
14593 check_insn(ctx, ISA_MIPS32R2);
14594 gen_load_srsgpr(rs, rt);
14595 break;
14596 case WRPGPR:
14597 check_cp0_enabled(ctx);
14598 check_insn(ctx, ISA_MIPS32R2);
14599 gen_store_srsgpr(rs, rt);
14600 break;
14601 default:
14602 goto pool32axf_invalid;
14604 break;
14605 #ifndef CONFIG_USER_ONLY
14606 case 0x0d:
14607 switch (minor) {
14608 case TLBP:
14609 mips32_op = OPC_TLBP;
14610 goto do_cp0;
14611 case TLBR:
14612 mips32_op = OPC_TLBR;
14613 goto do_cp0;
14614 case TLBWI:
14615 mips32_op = OPC_TLBWI;
14616 goto do_cp0;
14617 case TLBWR:
14618 mips32_op = OPC_TLBWR;
14619 goto do_cp0;
14620 case TLBINV:
14621 mips32_op = OPC_TLBINV;
14622 goto do_cp0;
14623 case TLBINVF:
14624 mips32_op = OPC_TLBINVF;
14625 goto do_cp0;
14626 case WAIT:
14627 mips32_op = OPC_WAIT;
14628 goto do_cp0;
14629 case DERET:
14630 mips32_op = OPC_DERET;
14631 goto do_cp0;
14632 case ERET:
14633 mips32_op = OPC_ERET;
14634 do_cp0:
14635 gen_cp0(env, ctx, mips32_op, rt, rs);
14636 break;
14637 default:
14638 goto pool32axf_invalid;
14640 break;
14641 case 0x1d:
14642 switch (minor) {
14643 case DI:
14644 check_cp0_enabled(ctx);
14646 TCGv t0 = tcg_temp_new();
14648 save_cpu_state(ctx, 1);
14649 gen_helper_di(t0, cpu_env);
14650 gen_store_gpr(t0, rs);
14651 /* Stop translation as we may have switched the execution mode */
14652 ctx->base.is_jmp = DISAS_STOP;
14653 tcg_temp_free(t0);
14655 break;
14656 case EI:
14657 check_cp0_enabled(ctx);
14659 TCGv t0 = tcg_temp_new();
14661 save_cpu_state(ctx, 1);
14662 gen_helper_ei(t0, cpu_env);
14663 gen_store_gpr(t0, rs);
14664 /* DISAS_STOP isn't sufficient, we need to ensure we break out
14665 of translated code to check for pending interrupts. */
14666 gen_save_pc(ctx->base.pc_next + 4);
14667 ctx->base.is_jmp = DISAS_EXIT;
14668 tcg_temp_free(t0);
14670 break;
14671 default:
14672 goto pool32axf_invalid;
14674 break;
14675 #endif
14676 case 0x2d:
14677 switch (minor) {
14678 case SYNC:
14679 gen_sync(extract32(ctx->opcode, 16, 5));
14680 break;
14681 case SYSCALL:
14682 generate_exception_end(ctx, EXCP_SYSCALL);
14683 break;
14684 case SDBBP:
14685 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14686 gen_helper_do_semihosting(cpu_env);
14687 } else {
14688 check_insn(ctx, ISA_MIPS32);
14689 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14690 generate_exception_end(ctx, EXCP_RI);
14691 } else {
14692 generate_exception_end(ctx, EXCP_DBp);
14695 break;
14696 default:
14697 goto pool32axf_invalid;
14699 break;
14700 case 0x01:
14701 switch (minor & 3) {
14702 case MFHI_ACC:
14703 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14704 break;
14705 case MFLO_ACC:
14706 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14707 break;
14708 case MTHI_ACC:
14709 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14710 break;
14711 case MTLO_ACC:
14712 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14713 break;
14714 default:
14715 goto pool32axf_invalid;
14717 break;
14718 case 0x35:
14719 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14720 switch (minor) {
14721 case MFHI32:
14722 gen_HILO(ctx, OPC_MFHI, 0, rs);
14723 break;
14724 case MFLO32:
14725 gen_HILO(ctx, OPC_MFLO, 0, rs);
14726 break;
14727 case MTHI32:
14728 gen_HILO(ctx, OPC_MTHI, 0, rs);
14729 break;
14730 case MTLO32:
14731 gen_HILO(ctx, OPC_MTLO, 0, rs);
14732 break;
14733 default:
14734 goto pool32axf_invalid;
14736 break;
14737 default:
14738 pool32axf_invalid:
14739 MIPS_INVAL("pool32axf");
14740 generate_exception_end(ctx, EXCP_RI);
14741 break;
14745 /* Values for microMIPS fmt field. Variable-width, depending on which
14746 formats the instruction supports. */
14748 enum {
14749 FMT_SD_S = 0,
14750 FMT_SD_D = 1,
14752 FMT_SDPS_S = 0,
14753 FMT_SDPS_D = 1,
14754 FMT_SDPS_PS = 2,
14756 FMT_SWL_S = 0,
14757 FMT_SWL_W = 1,
14758 FMT_SWL_L = 2,
14760 FMT_DWL_D = 0,
14761 FMT_DWL_W = 1,
14762 FMT_DWL_L = 2
14765 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
14767 int extension = (ctx->opcode >> 6) & 0x3ff;
14768 uint32_t mips32_op;
14770 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
14771 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
14772 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
14774 switch (extension) {
14775 case FLOAT_1BIT_FMT(CFC1, 0):
14776 mips32_op = OPC_CFC1;
14777 goto do_cp1;
14778 case FLOAT_1BIT_FMT(CTC1, 0):
14779 mips32_op = OPC_CTC1;
14780 goto do_cp1;
14781 case FLOAT_1BIT_FMT(MFC1, 0):
14782 mips32_op = OPC_MFC1;
14783 goto do_cp1;
14784 case FLOAT_1BIT_FMT(MTC1, 0):
14785 mips32_op = OPC_MTC1;
14786 goto do_cp1;
14787 case FLOAT_1BIT_FMT(MFHC1, 0):
14788 mips32_op = OPC_MFHC1;
14789 goto do_cp1;
14790 case FLOAT_1BIT_FMT(MTHC1, 0):
14791 mips32_op = OPC_MTHC1;
14792 do_cp1:
14793 gen_cp1(ctx, mips32_op, rt, rs);
14794 break;
14796 /* Reciprocal square root */
14797 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
14798 mips32_op = OPC_RSQRT_S;
14799 goto do_unaryfp;
14800 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
14801 mips32_op = OPC_RSQRT_D;
14802 goto do_unaryfp;
14804 /* Square root */
14805 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
14806 mips32_op = OPC_SQRT_S;
14807 goto do_unaryfp;
14808 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
14809 mips32_op = OPC_SQRT_D;
14810 goto do_unaryfp;
14812 /* Reciprocal */
14813 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
14814 mips32_op = OPC_RECIP_S;
14815 goto do_unaryfp;
14816 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
14817 mips32_op = OPC_RECIP_D;
14818 goto do_unaryfp;
14820 /* Floor */
14821 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
14822 mips32_op = OPC_FLOOR_L_S;
14823 goto do_unaryfp;
14824 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
14825 mips32_op = OPC_FLOOR_L_D;
14826 goto do_unaryfp;
14827 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
14828 mips32_op = OPC_FLOOR_W_S;
14829 goto do_unaryfp;
14830 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
14831 mips32_op = OPC_FLOOR_W_D;
14832 goto do_unaryfp;
14834 /* Ceiling */
14835 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
14836 mips32_op = OPC_CEIL_L_S;
14837 goto do_unaryfp;
14838 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
14839 mips32_op = OPC_CEIL_L_D;
14840 goto do_unaryfp;
14841 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
14842 mips32_op = OPC_CEIL_W_S;
14843 goto do_unaryfp;
14844 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
14845 mips32_op = OPC_CEIL_W_D;
14846 goto do_unaryfp;
14848 /* Truncation */
14849 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
14850 mips32_op = OPC_TRUNC_L_S;
14851 goto do_unaryfp;
14852 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
14853 mips32_op = OPC_TRUNC_L_D;
14854 goto do_unaryfp;
14855 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
14856 mips32_op = OPC_TRUNC_W_S;
14857 goto do_unaryfp;
14858 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
14859 mips32_op = OPC_TRUNC_W_D;
14860 goto do_unaryfp;
14862 /* Round */
14863 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
14864 mips32_op = OPC_ROUND_L_S;
14865 goto do_unaryfp;
14866 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
14867 mips32_op = OPC_ROUND_L_D;
14868 goto do_unaryfp;
14869 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
14870 mips32_op = OPC_ROUND_W_S;
14871 goto do_unaryfp;
14872 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
14873 mips32_op = OPC_ROUND_W_D;
14874 goto do_unaryfp;
14876 /* Integer to floating-point conversion */
14877 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
14878 mips32_op = OPC_CVT_L_S;
14879 goto do_unaryfp;
14880 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
14881 mips32_op = OPC_CVT_L_D;
14882 goto do_unaryfp;
14883 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
14884 mips32_op = OPC_CVT_W_S;
14885 goto do_unaryfp;
14886 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
14887 mips32_op = OPC_CVT_W_D;
14888 goto do_unaryfp;
14890 /* Paired-foo conversions */
14891 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
14892 mips32_op = OPC_CVT_S_PL;
14893 goto do_unaryfp;
14894 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
14895 mips32_op = OPC_CVT_S_PU;
14896 goto do_unaryfp;
14897 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
14898 mips32_op = OPC_CVT_PW_PS;
14899 goto do_unaryfp;
14900 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
14901 mips32_op = OPC_CVT_PS_PW;
14902 goto do_unaryfp;
14904 /* Floating-point moves */
14905 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
14906 mips32_op = OPC_MOV_S;
14907 goto do_unaryfp;
14908 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
14909 mips32_op = OPC_MOV_D;
14910 goto do_unaryfp;
14911 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
14912 mips32_op = OPC_MOV_PS;
14913 goto do_unaryfp;
14915 /* Absolute value */
14916 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
14917 mips32_op = OPC_ABS_S;
14918 goto do_unaryfp;
14919 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
14920 mips32_op = OPC_ABS_D;
14921 goto do_unaryfp;
14922 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
14923 mips32_op = OPC_ABS_PS;
14924 goto do_unaryfp;
14926 /* Negation */
14927 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
14928 mips32_op = OPC_NEG_S;
14929 goto do_unaryfp;
14930 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
14931 mips32_op = OPC_NEG_D;
14932 goto do_unaryfp;
14933 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
14934 mips32_op = OPC_NEG_PS;
14935 goto do_unaryfp;
14937 /* Reciprocal square root step */
14938 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
14939 mips32_op = OPC_RSQRT1_S;
14940 goto do_unaryfp;
14941 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
14942 mips32_op = OPC_RSQRT1_D;
14943 goto do_unaryfp;
14944 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
14945 mips32_op = OPC_RSQRT1_PS;
14946 goto do_unaryfp;
14948 /* Reciprocal step */
14949 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
14950 mips32_op = OPC_RECIP1_S;
14951 goto do_unaryfp;
14952 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
14953 mips32_op = OPC_RECIP1_S;
14954 goto do_unaryfp;
14955 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
14956 mips32_op = OPC_RECIP1_PS;
14957 goto do_unaryfp;
14959 /* Conversions from double */
14960 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
14961 mips32_op = OPC_CVT_D_S;
14962 goto do_unaryfp;
14963 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
14964 mips32_op = OPC_CVT_D_W;
14965 goto do_unaryfp;
14966 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
14967 mips32_op = OPC_CVT_D_L;
14968 goto do_unaryfp;
14970 /* Conversions from single */
14971 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
14972 mips32_op = OPC_CVT_S_D;
14973 goto do_unaryfp;
14974 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
14975 mips32_op = OPC_CVT_S_W;
14976 goto do_unaryfp;
14977 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
14978 mips32_op = OPC_CVT_S_L;
14979 do_unaryfp:
14980 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
14981 break;
14983 /* Conditional moves on floating-point codes */
14984 case COND_FLOAT_MOV(MOVT, 0):
14985 case COND_FLOAT_MOV(MOVT, 1):
14986 case COND_FLOAT_MOV(MOVT, 2):
14987 case COND_FLOAT_MOV(MOVT, 3):
14988 case COND_FLOAT_MOV(MOVT, 4):
14989 case COND_FLOAT_MOV(MOVT, 5):
14990 case COND_FLOAT_MOV(MOVT, 6):
14991 case COND_FLOAT_MOV(MOVT, 7):
14992 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14993 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
14994 break;
14995 case COND_FLOAT_MOV(MOVF, 0):
14996 case COND_FLOAT_MOV(MOVF, 1):
14997 case COND_FLOAT_MOV(MOVF, 2):
14998 case COND_FLOAT_MOV(MOVF, 3):
14999 case COND_FLOAT_MOV(MOVF, 4):
15000 case COND_FLOAT_MOV(MOVF, 5):
15001 case COND_FLOAT_MOV(MOVF, 6):
15002 case COND_FLOAT_MOV(MOVF, 7):
15003 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15004 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15005 break;
15006 default:
15007 MIPS_INVAL("pool32fxf");
15008 generate_exception_end(ctx, EXCP_RI);
15009 break;
15013 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15015 int32_t offset;
15016 uint16_t insn;
15017 int rt, rs, rd, rr;
15018 int16_t imm;
15019 uint32_t op, minor, minor2, mips32_op;
15020 uint32_t cond, fmt, cc;
15022 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15023 ctx->opcode = (ctx->opcode << 16) | insn;
15025 rt = (ctx->opcode >> 21) & 0x1f;
15026 rs = (ctx->opcode >> 16) & 0x1f;
15027 rd = (ctx->opcode >> 11) & 0x1f;
15028 rr = (ctx->opcode >> 6) & 0x1f;
15029 imm = (int16_t) ctx->opcode;
15031 op = (ctx->opcode >> 26) & 0x3f;
15032 switch (op) {
15033 case POOL32A:
15034 minor = ctx->opcode & 0x3f;
15035 switch (minor) {
15036 case 0x00:
15037 minor = (ctx->opcode >> 6) & 0xf;
15038 switch (minor) {
15039 case SLL32:
15040 mips32_op = OPC_SLL;
15041 goto do_shifti;
15042 case SRA:
15043 mips32_op = OPC_SRA;
15044 goto do_shifti;
15045 case SRL32:
15046 mips32_op = OPC_SRL;
15047 goto do_shifti;
15048 case ROTR:
15049 mips32_op = OPC_ROTR;
15050 do_shifti:
15051 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15052 break;
15053 case SELEQZ:
15054 check_insn(ctx, ISA_MIPS32R6);
15055 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15056 break;
15057 case SELNEZ:
15058 check_insn(ctx, ISA_MIPS32R6);
15059 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15060 break;
15061 case R6_RDHWR:
15062 check_insn(ctx, ISA_MIPS32R6);
15063 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15064 break;
15065 default:
15066 goto pool32a_invalid;
15068 break;
15069 case 0x10:
15070 minor = (ctx->opcode >> 6) & 0xf;
15071 switch (minor) {
15072 /* Arithmetic */
15073 case ADD:
15074 mips32_op = OPC_ADD;
15075 goto do_arith;
15076 case ADDU32:
15077 mips32_op = OPC_ADDU;
15078 goto do_arith;
15079 case SUB:
15080 mips32_op = OPC_SUB;
15081 goto do_arith;
15082 case SUBU32:
15083 mips32_op = OPC_SUBU;
15084 goto do_arith;
15085 case MUL:
15086 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15087 mips32_op = OPC_MUL;
15088 do_arith:
15089 gen_arith(ctx, mips32_op, rd, rs, rt);
15090 break;
15091 /* Shifts */
15092 case SLLV:
15093 mips32_op = OPC_SLLV;
15094 goto do_shift;
15095 case SRLV:
15096 mips32_op = OPC_SRLV;
15097 goto do_shift;
15098 case SRAV:
15099 mips32_op = OPC_SRAV;
15100 goto do_shift;
15101 case ROTRV:
15102 mips32_op = OPC_ROTRV;
15103 do_shift:
15104 gen_shift(ctx, mips32_op, rd, rs, rt);
15105 break;
15106 /* Logical operations */
15107 case AND:
15108 mips32_op = OPC_AND;
15109 goto do_logic;
15110 case OR32:
15111 mips32_op = OPC_OR;
15112 goto do_logic;
15113 case NOR:
15114 mips32_op = OPC_NOR;
15115 goto do_logic;
15116 case XOR32:
15117 mips32_op = OPC_XOR;
15118 do_logic:
15119 gen_logic(ctx, mips32_op, rd, rs, rt);
15120 break;
15121 /* Set less than */
15122 case SLT:
15123 mips32_op = OPC_SLT;
15124 goto do_slt;
15125 case SLTU:
15126 mips32_op = OPC_SLTU;
15127 do_slt:
15128 gen_slt(ctx, mips32_op, rd, rs, rt);
15129 break;
15130 default:
15131 goto pool32a_invalid;
15133 break;
15134 case 0x18:
15135 minor = (ctx->opcode >> 6) & 0xf;
15136 switch (minor) {
15137 /* Conditional moves */
15138 case MOVN: /* MUL */
15139 if (ctx->insn_flags & ISA_MIPS32R6) {
15140 /* MUL */
15141 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15142 } else {
15143 /* MOVN */
15144 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15146 break;
15147 case MOVZ: /* MUH */
15148 if (ctx->insn_flags & ISA_MIPS32R6) {
15149 /* MUH */
15150 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15151 } else {
15152 /* MOVZ */
15153 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15155 break;
15156 case MULU:
15157 check_insn(ctx, ISA_MIPS32R6);
15158 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15159 break;
15160 case MUHU:
15161 check_insn(ctx, ISA_MIPS32R6);
15162 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15163 break;
15164 case LWXS: /* DIV */
15165 if (ctx->insn_flags & ISA_MIPS32R6) {
15166 /* DIV */
15167 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15168 } else {
15169 /* LWXS */
15170 gen_ldxs(ctx, rs, rt, rd);
15172 break;
15173 case MOD:
15174 check_insn(ctx, ISA_MIPS32R6);
15175 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15176 break;
15177 case R6_DIVU:
15178 check_insn(ctx, ISA_MIPS32R6);
15179 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15180 break;
15181 case MODU:
15182 check_insn(ctx, ISA_MIPS32R6);
15183 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15184 break;
15185 default:
15186 goto pool32a_invalid;
15188 break;
15189 case INS:
15190 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15191 return;
15192 case LSA:
15193 check_insn(ctx, ISA_MIPS32R6);
15194 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15195 extract32(ctx->opcode, 9, 2));
15196 break;
15197 case ALIGN:
15198 check_insn(ctx, ISA_MIPS32R6);
15199 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15200 break;
15201 case EXT:
15202 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15203 return;
15204 case POOL32AXF:
15205 gen_pool32axf(env, ctx, rt, rs);
15206 break;
15207 case BREAK32:
15208 generate_exception_end(ctx, EXCP_BREAK);
15209 break;
15210 case SIGRIE:
15211 check_insn(ctx, ISA_MIPS32R6);
15212 generate_exception_end(ctx, EXCP_RI);
15213 break;
15214 default:
15215 pool32a_invalid:
15216 MIPS_INVAL("pool32a");
15217 generate_exception_end(ctx, EXCP_RI);
15218 break;
15220 break;
15221 case POOL32B:
15222 minor = (ctx->opcode >> 12) & 0xf;
15223 switch (minor) {
15224 case CACHE:
15225 check_cp0_enabled(ctx);
15226 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15227 gen_cache_operation(ctx, rt, rs, imm);
15229 break;
15230 case LWC2:
15231 case SWC2:
15232 /* COP2: Not implemented. */
15233 generate_exception_err(ctx, EXCP_CpU, 2);
15234 break;
15235 #ifdef TARGET_MIPS64
15236 case LDP:
15237 case SDP:
15238 check_insn(ctx, ISA_MIPS3);
15239 check_mips_64(ctx);
15240 #endif
15241 /* fall through */
15242 case LWP:
15243 case SWP:
15244 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15245 break;
15246 #ifdef TARGET_MIPS64
15247 case LDM:
15248 case SDM:
15249 check_insn(ctx, ISA_MIPS3);
15250 check_mips_64(ctx);
15251 #endif
15252 /* fall through */
15253 case LWM32:
15254 case SWM32:
15255 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15256 break;
15257 default:
15258 MIPS_INVAL("pool32b");
15259 generate_exception_end(ctx, EXCP_RI);
15260 break;
15262 break;
15263 case POOL32F:
15264 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15265 minor = ctx->opcode & 0x3f;
15266 check_cp1_enabled(ctx);
15267 switch (minor) {
15268 case ALNV_PS:
15269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15270 mips32_op = OPC_ALNV_PS;
15271 goto do_madd;
15272 case MADD_S:
15273 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15274 mips32_op = OPC_MADD_S;
15275 goto do_madd;
15276 case MADD_D:
15277 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15278 mips32_op = OPC_MADD_D;
15279 goto do_madd;
15280 case MADD_PS:
15281 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15282 mips32_op = OPC_MADD_PS;
15283 goto do_madd;
15284 case MSUB_S:
15285 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15286 mips32_op = OPC_MSUB_S;
15287 goto do_madd;
15288 case MSUB_D:
15289 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15290 mips32_op = OPC_MSUB_D;
15291 goto do_madd;
15292 case MSUB_PS:
15293 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15294 mips32_op = OPC_MSUB_PS;
15295 goto do_madd;
15296 case NMADD_S:
15297 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15298 mips32_op = OPC_NMADD_S;
15299 goto do_madd;
15300 case NMADD_D:
15301 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15302 mips32_op = OPC_NMADD_D;
15303 goto do_madd;
15304 case NMADD_PS:
15305 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15306 mips32_op = OPC_NMADD_PS;
15307 goto do_madd;
15308 case NMSUB_S:
15309 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15310 mips32_op = OPC_NMSUB_S;
15311 goto do_madd;
15312 case NMSUB_D:
15313 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15314 mips32_op = OPC_NMSUB_D;
15315 goto do_madd;
15316 case NMSUB_PS:
15317 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15318 mips32_op = OPC_NMSUB_PS;
15319 do_madd:
15320 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15321 break;
15322 case CABS_COND_FMT:
15323 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15324 cond = (ctx->opcode >> 6) & 0xf;
15325 cc = (ctx->opcode >> 13) & 0x7;
15326 fmt = (ctx->opcode >> 10) & 0x3;
15327 switch (fmt) {
15328 case 0x0:
15329 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15330 break;
15331 case 0x1:
15332 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15333 break;
15334 case 0x2:
15335 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15336 break;
15337 default:
15338 goto pool32f_invalid;
15340 break;
15341 case C_COND_FMT:
15342 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15343 cond = (ctx->opcode >> 6) & 0xf;
15344 cc = (ctx->opcode >> 13) & 0x7;
15345 fmt = (ctx->opcode >> 10) & 0x3;
15346 switch (fmt) {
15347 case 0x0:
15348 gen_cmp_s(ctx, cond, rt, rs, cc);
15349 break;
15350 case 0x1:
15351 gen_cmp_d(ctx, cond, rt, rs, cc);
15352 break;
15353 case 0x2:
15354 gen_cmp_ps(ctx, cond, rt, rs, cc);
15355 break;
15356 default:
15357 goto pool32f_invalid;
15359 break;
15360 case CMP_CONDN_S:
15361 check_insn(ctx, ISA_MIPS32R6);
15362 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15363 break;
15364 case CMP_CONDN_D:
15365 check_insn(ctx, ISA_MIPS32R6);
15366 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15367 break;
15368 case POOL32FXF:
15369 gen_pool32fxf(ctx, rt, rs);
15370 break;
15371 case 0x00:
15372 /* PLL foo */
15373 switch ((ctx->opcode >> 6) & 0x7) {
15374 case PLL_PS:
15375 mips32_op = OPC_PLL_PS;
15376 goto do_ps;
15377 case PLU_PS:
15378 mips32_op = OPC_PLU_PS;
15379 goto do_ps;
15380 case PUL_PS:
15381 mips32_op = OPC_PUL_PS;
15382 goto do_ps;
15383 case PUU_PS:
15384 mips32_op = OPC_PUU_PS;
15385 goto do_ps;
15386 case CVT_PS_S:
15387 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15388 mips32_op = OPC_CVT_PS_S;
15389 do_ps:
15390 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15391 break;
15392 default:
15393 goto pool32f_invalid;
15395 break;
15396 case MIN_FMT:
15397 check_insn(ctx, ISA_MIPS32R6);
15398 switch ((ctx->opcode >> 9) & 0x3) {
15399 case FMT_SDPS_S:
15400 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15401 break;
15402 case FMT_SDPS_D:
15403 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15404 break;
15405 default:
15406 goto pool32f_invalid;
15408 break;
15409 case 0x08:
15410 /* [LS][WDU]XC1 */
15411 switch ((ctx->opcode >> 6) & 0x7) {
15412 case LWXC1:
15413 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15414 mips32_op = OPC_LWXC1;
15415 goto do_ldst_cp1;
15416 case SWXC1:
15417 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15418 mips32_op = OPC_SWXC1;
15419 goto do_ldst_cp1;
15420 case LDXC1:
15421 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15422 mips32_op = OPC_LDXC1;
15423 goto do_ldst_cp1;
15424 case SDXC1:
15425 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15426 mips32_op = OPC_SDXC1;
15427 goto do_ldst_cp1;
15428 case LUXC1:
15429 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15430 mips32_op = OPC_LUXC1;
15431 goto do_ldst_cp1;
15432 case SUXC1:
15433 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15434 mips32_op = OPC_SUXC1;
15435 do_ldst_cp1:
15436 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15437 break;
15438 default:
15439 goto pool32f_invalid;
15441 break;
15442 case MAX_FMT:
15443 check_insn(ctx, ISA_MIPS32R6);
15444 switch ((ctx->opcode >> 9) & 0x3) {
15445 case FMT_SDPS_S:
15446 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15447 break;
15448 case FMT_SDPS_D:
15449 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15450 break;
15451 default:
15452 goto pool32f_invalid;
15454 break;
15455 case 0x18:
15456 /* 3D insns */
15457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15458 fmt = (ctx->opcode >> 9) & 0x3;
15459 switch ((ctx->opcode >> 6) & 0x7) {
15460 case RSQRT2_FMT:
15461 switch (fmt) {
15462 case FMT_SDPS_S:
15463 mips32_op = OPC_RSQRT2_S;
15464 goto do_3d;
15465 case FMT_SDPS_D:
15466 mips32_op = OPC_RSQRT2_D;
15467 goto do_3d;
15468 case FMT_SDPS_PS:
15469 mips32_op = OPC_RSQRT2_PS;
15470 goto do_3d;
15471 default:
15472 goto pool32f_invalid;
15474 break;
15475 case RECIP2_FMT:
15476 switch (fmt) {
15477 case FMT_SDPS_S:
15478 mips32_op = OPC_RECIP2_S;
15479 goto do_3d;
15480 case FMT_SDPS_D:
15481 mips32_op = OPC_RECIP2_D;
15482 goto do_3d;
15483 case FMT_SDPS_PS:
15484 mips32_op = OPC_RECIP2_PS;
15485 goto do_3d;
15486 default:
15487 goto pool32f_invalid;
15489 break;
15490 case ADDR_PS:
15491 mips32_op = OPC_ADDR_PS;
15492 goto do_3d;
15493 case MULR_PS:
15494 mips32_op = OPC_MULR_PS;
15495 do_3d:
15496 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15497 break;
15498 default:
15499 goto pool32f_invalid;
15501 break;
15502 case 0x20:
15503 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
15504 cc = (ctx->opcode >> 13) & 0x7;
15505 fmt = (ctx->opcode >> 9) & 0x3;
15506 switch ((ctx->opcode >> 6) & 0x7) {
15507 case MOVF_FMT: /* RINT_FMT */
15508 if (ctx->insn_flags & ISA_MIPS32R6) {
15509 /* RINT_FMT */
15510 switch (fmt) {
15511 case FMT_SDPS_S:
15512 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15513 break;
15514 case FMT_SDPS_D:
15515 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15516 break;
15517 default:
15518 goto pool32f_invalid;
15520 } else {
15521 /* MOVF_FMT */
15522 switch (fmt) {
15523 case FMT_SDPS_S:
15524 gen_movcf_s(ctx, rs, rt, cc, 0);
15525 break;
15526 case FMT_SDPS_D:
15527 gen_movcf_d(ctx, rs, rt, cc, 0);
15528 break;
15529 case FMT_SDPS_PS:
15530 check_ps(ctx);
15531 gen_movcf_ps(ctx, rs, rt, cc, 0);
15532 break;
15533 default:
15534 goto pool32f_invalid;
15537 break;
15538 case MOVT_FMT: /* CLASS_FMT */
15539 if (ctx->insn_flags & ISA_MIPS32R6) {
15540 /* CLASS_FMT */
15541 switch (fmt) {
15542 case FMT_SDPS_S:
15543 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15544 break;
15545 case FMT_SDPS_D:
15546 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15547 break;
15548 default:
15549 goto pool32f_invalid;
15551 } else {
15552 /* MOVT_FMT */
15553 switch (fmt) {
15554 case FMT_SDPS_S:
15555 gen_movcf_s(ctx, rs, rt, cc, 1);
15556 break;
15557 case FMT_SDPS_D:
15558 gen_movcf_d(ctx, rs, rt, cc, 1);
15559 break;
15560 case FMT_SDPS_PS:
15561 check_ps(ctx);
15562 gen_movcf_ps(ctx, rs, rt, cc, 1);
15563 break;
15564 default:
15565 goto pool32f_invalid;
15568 break;
15569 case PREFX:
15570 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15571 break;
15572 default:
15573 goto pool32f_invalid;
15575 break;
15576 #define FINSN_3ARG_SDPS(prfx) \
15577 switch ((ctx->opcode >> 8) & 0x3) { \
15578 case FMT_SDPS_S: \
15579 mips32_op = OPC_##prfx##_S; \
15580 goto do_fpop; \
15581 case FMT_SDPS_D: \
15582 mips32_op = OPC_##prfx##_D; \
15583 goto do_fpop; \
15584 case FMT_SDPS_PS: \
15585 check_ps(ctx); \
15586 mips32_op = OPC_##prfx##_PS; \
15587 goto do_fpop; \
15588 default: \
15589 goto pool32f_invalid; \
15591 case MINA_FMT:
15592 check_insn(ctx, ISA_MIPS32R6);
15593 switch ((ctx->opcode >> 9) & 0x3) {
15594 case FMT_SDPS_S:
15595 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15596 break;
15597 case FMT_SDPS_D:
15598 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15599 break;
15600 default:
15601 goto pool32f_invalid;
15603 break;
15604 case MAXA_FMT:
15605 check_insn(ctx, ISA_MIPS32R6);
15606 switch ((ctx->opcode >> 9) & 0x3) {
15607 case FMT_SDPS_S:
15608 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15609 break;
15610 case FMT_SDPS_D:
15611 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15612 break;
15613 default:
15614 goto pool32f_invalid;
15616 break;
15617 case 0x30:
15618 /* regular FP ops */
15619 switch ((ctx->opcode >> 6) & 0x3) {
15620 case ADD_FMT:
15621 FINSN_3ARG_SDPS(ADD);
15622 break;
15623 case SUB_FMT:
15624 FINSN_3ARG_SDPS(SUB);
15625 break;
15626 case MUL_FMT:
15627 FINSN_3ARG_SDPS(MUL);
15628 break;
15629 case DIV_FMT:
15630 fmt = (ctx->opcode >> 8) & 0x3;
15631 if (fmt == 1) {
15632 mips32_op = OPC_DIV_D;
15633 } else if (fmt == 0) {
15634 mips32_op = OPC_DIV_S;
15635 } else {
15636 goto pool32f_invalid;
15638 goto do_fpop;
15639 default:
15640 goto pool32f_invalid;
15642 break;
15643 case 0x38:
15644 /* cmovs */
15645 switch ((ctx->opcode >> 6) & 0x7) {
15646 case MOVN_FMT: /* SELEQZ_FMT */
15647 if (ctx->insn_flags & ISA_MIPS32R6) {
15648 /* SELEQZ_FMT */
15649 switch ((ctx->opcode >> 9) & 0x3) {
15650 case FMT_SDPS_S:
15651 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15652 break;
15653 case FMT_SDPS_D:
15654 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15655 break;
15656 default:
15657 goto pool32f_invalid;
15659 } else {
15660 /* MOVN_FMT */
15661 FINSN_3ARG_SDPS(MOVN);
15663 break;
15664 case MOVN_FMT_04:
15665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15666 FINSN_3ARG_SDPS(MOVN);
15667 break;
15668 case MOVZ_FMT: /* SELNEZ_FMT */
15669 if (ctx->insn_flags & ISA_MIPS32R6) {
15670 /* SELNEZ_FMT */
15671 switch ((ctx->opcode >> 9) & 0x3) {
15672 case FMT_SDPS_S:
15673 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15674 break;
15675 case FMT_SDPS_D:
15676 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15677 break;
15678 default:
15679 goto pool32f_invalid;
15681 } else {
15682 /* MOVZ_FMT */
15683 FINSN_3ARG_SDPS(MOVZ);
15685 break;
15686 case MOVZ_FMT_05:
15687 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15688 FINSN_3ARG_SDPS(MOVZ);
15689 break;
15690 case SEL_FMT:
15691 check_insn(ctx, ISA_MIPS32R6);
15692 switch ((ctx->opcode >> 9) & 0x3) {
15693 case FMT_SDPS_S:
15694 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15695 break;
15696 case FMT_SDPS_D:
15697 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15698 break;
15699 default:
15700 goto pool32f_invalid;
15702 break;
15703 case MADDF_FMT:
15704 check_insn(ctx, ISA_MIPS32R6);
15705 switch ((ctx->opcode >> 9) & 0x3) {
15706 case FMT_SDPS_S:
15707 mips32_op = OPC_MADDF_S;
15708 goto do_fpop;
15709 case FMT_SDPS_D:
15710 mips32_op = OPC_MADDF_D;
15711 goto do_fpop;
15712 default:
15713 goto pool32f_invalid;
15715 break;
15716 case MSUBF_FMT:
15717 check_insn(ctx, ISA_MIPS32R6);
15718 switch ((ctx->opcode >> 9) & 0x3) {
15719 case FMT_SDPS_S:
15720 mips32_op = OPC_MSUBF_S;
15721 goto do_fpop;
15722 case FMT_SDPS_D:
15723 mips32_op = OPC_MSUBF_D;
15724 goto do_fpop;
15725 default:
15726 goto pool32f_invalid;
15728 break;
15729 default:
15730 goto pool32f_invalid;
15732 break;
15733 do_fpop:
15734 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15735 break;
15736 default:
15737 pool32f_invalid:
15738 MIPS_INVAL("pool32f");
15739 generate_exception_end(ctx, EXCP_RI);
15740 break;
15742 } else {
15743 generate_exception_err(ctx, EXCP_CpU, 1);
15745 break;
15746 case POOL32I:
15747 minor = (ctx->opcode >> 21) & 0x1f;
15748 switch (minor) {
15749 case BLTZ:
15750 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15751 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15752 break;
15753 case BLTZAL:
15754 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15755 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15756 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15757 break;
15758 case BLTZALS:
15759 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15760 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15761 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15762 break;
15763 case BGEZ:
15764 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15765 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15766 break;
15767 case BGEZAL:
15768 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15769 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15770 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15771 break;
15772 case BGEZALS:
15773 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15774 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
15775 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15776 break;
15777 case BLEZ:
15778 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15779 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
15780 break;
15781 case BGTZ:
15782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15783 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
15784 break;
15786 /* Traps */
15787 case TLTI: /* BC1EQZC */
15788 if (ctx->insn_flags & ISA_MIPS32R6) {
15789 /* BC1EQZC */
15790 check_cp1_enabled(ctx);
15791 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
15792 } else {
15793 /* TLTI */
15794 mips32_op = OPC_TLTI;
15795 goto do_trapi;
15797 break;
15798 case TGEI: /* BC1NEZC */
15799 if (ctx->insn_flags & ISA_MIPS32R6) {
15800 /* BC1NEZC */
15801 check_cp1_enabled(ctx);
15802 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
15803 } else {
15804 /* TGEI */
15805 mips32_op = OPC_TGEI;
15806 goto do_trapi;
15808 break;
15809 case TLTIU:
15810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15811 mips32_op = OPC_TLTIU;
15812 goto do_trapi;
15813 case TGEIU:
15814 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15815 mips32_op = OPC_TGEIU;
15816 goto do_trapi;
15817 case TNEI: /* SYNCI */
15818 if (ctx->insn_flags & ISA_MIPS32R6) {
15819 /* SYNCI */
15820 /* Break the TB to be able to sync copied instructions
15821 immediately */
15822 ctx->base.is_jmp = DISAS_STOP;
15823 } else {
15824 /* TNEI */
15825 mips32_op = OPC_TNEI;
15826 goto do_trapi;
15828 break;
15829 case TEQI:
15830 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15831 mips32_op = OPC_TEQI;
15832 do_trapi:
15833 gen_trap(ctx, mips32_op, rs, -1, imm);
15834 break;
15836 case BNEZC:
15837 case BEQZC:
15838 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15839 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
15840 4, rs, 0, imm << 1, 0);
15841 /* Compact branches don't have a delay slot, so just let
15842 the normal delay slot handling take us to the branch
15843 target. */
15844 break;
15845 case LUI:
15846 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15847 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
15848 break;
15849 case SYNCI:
15850 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15851 /* Break the TB to be able to sync copied instructions
15852 immediately */
15853 ctx->base.is_jmp = DISAS_STOP;
15854 break;
15855 case BC2F:
15856 case BC2T:
15857 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15858 /* COP2: Not implemented. */
15859 generate_exception_err(ctx, EXCP_CpU, 2);
15860 break;
15861 case BC1F:
15862 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15863 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
15864 goto do_cp1branch;
15865 case BC1T:
15866 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15867 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
15868 goto do_cp1branch;
15869 case BC1ANY4F:
15870 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15871 mips32_op = OPC_BC1FANY4;
15872 goto do_cp1mips3d;
15873 case BC1ANY4T:
15874 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15875 mips32_op = OPC_BC1TANY4;
15876 do_cp1mips3d:
15877 check_cop1x(ctx);
15878 check_insn(ctx, ASE_MIPS3D);
15879 /* Fall through */
15880 do_cp1branch:
15881 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15882 check_cp1_enabled(ctx);
15883 gen_compute_branch1(ctx, mips32_op,
15884 (ctx->opcode >> 18) & 0x7, imm << 1);
15885 } else {
15886 generate_exception_err(ctx, EXCP_CpU, 1);
15888 break;
15889 case BPOSGE64:
15890 case BPOSGE32:
15891 /* MIPS DSP: not implemented */
15892 /* Fall through */
15893 default:
15894 MIPS_INVAL("pool32i");
15895 generate_exception_end(ctx, EXCP_RI);
15896 break;
15898 break;
15899 case POOL32C:
15900 minor = (ctx->opcode >> 12) & 0xf;
15901 offset = sextract32(ctx->opcode, 0,
15902 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
15903 switch (minor) {
15904 case LWL:
15905 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15906 mips32_op = OPC_LWL;
15907 goto do_ld_lr;
15908 case SWL:
15909 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15910 mips32_op = OPC_SWL;
15911 goto do_st_lr;
15912 case LWR:
15913 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15914 mips32_op = OPC_LWR;
15915 goto do_ld_lr;
15916 case SWR:
15917 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15918 mips32_op = OPC_SWR;
15919 goto do_st_lr;
15920 #if defined(TARGET_MIPS64)
15921 case LDL:
15922 check_insn(ctx, ISA_MIPS3);
15923 check_mips_64(ctx);
15924 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15925 mips32_op = OPC_LDL;
15926 goto do_ld_lr;
15927 case SDL:
15928 check_insn(ctx, ISA_MIPS3);
15929 check_mips_64(ctx);
15930 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15931 mips32_op = OPC_SDL;
15932 goto do_st_lr;
15933 case LDR:
15934 check_insn(ctx, ISA_MIPS3);
15935 check_mips_64(ctx);
15936 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15937 mips32_op = OPC_LDR;
15938 goto do_ld_lr;
15939 case SDR:
15940 check_insn(ctx, ISA_MIPS3);
15941 check_mips_64(ctx);
15942 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15943 mips32_op = OPC_SDR;
15944 goto do_st_lr;
15945 case LWU:
15946 check_insn(ctx, ISA_MIPS3);
15947 check_mips_64(ctx);
15948 mips32_op = OPC_LWU;
15949 goto do_ld_lr;
15950 case LLD:
15951 check_insn(ctx, ISA_MIPS3);
15952 check_mips_64(ctx);
15953 mips32_op = OPC_LLD;
15954 goto do_ld_lr;
15955 #endif
15956 case LL:
15957 mips32_op = OPC_LL;
15958 goto do_ld_lr;
15959 do_ld_lr:
15960 gen_ld(ctx, mips32_op, rt, rs, offset);
15961 break;
15962 do_st_lr:
15963 gen_st(ctx, mips32_op, rt, rs, offset);
15964 break;
15965 case SC:
15966 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
15967 break;
15968 #if defined(TARGET_MIPS64)
15969 case SCD:
15970 check_insn(ctx, ISA_MIPS3);
15971 check_mips_64(ctx);
15972 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
15973 break;
15974 #endif
15975 case LD_EVA:
15976 if (!ctx->eva) {
15977 MIPS_INVAL("pool32c ld-eva");
15978 generate_exception_end(ctx, EXCP_RI);
15979 break;
15981 check_cp0_enabled(ctx);
15983 minor2 = (ctx->opcode >> 9) & 0x7;
15984 offset = sextract32(ctx->opcode, 0, 9);
15985 switch (minor2) {
15986 case LBUE:
15987 mips32_op = OPC_LBUE;
15988 goto do_ld_lr;
15989 case LHUE:
15990 mips32_op = OPC_LHUE;
15991 goto do_ld_lr;
15992 case LWLE:
15993 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15994 mips32_op = OPC_LWLE;
15995 goto do_ld_lr;
15996 case LWRE:
15997 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15998 mips32_op = OPC_LWRE;
15999 goto do_ld_lr;
16000 case LBE:
16001 mips32_op = OPC_LBE;
16002 goto do_ld_lr;
16003 case LHE:
16004 mips32_op = OPC_LHE;
16005 goto do_ld_lr;
16006 case LLE:
16007 mips32_op = OPC_LLE;
16008 goto do_ld_lr;
16009 case LWE:
16010 mips32_op = OPC_LWE;
16011 goto do_ld_lr;
16013 break;
16014 case ST_EVA:
16015 if (!ctx->eva) {
16016 MIPS_INVAL("pool32c st-eva");
16017 generate_exception_end(ctx, EXCP_RI);
16018 break;
16020 check_cp0_enabled(ctx);
16022 minor2 = (ctx->opcode >> 9) & 0x7;
16023 offset = sextract32(ctx->opcode, 0, 9);
16024 switch (minor2) {
16025 case SWLE:
16026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16027 mips32_op = OPC_SWLE;
16028 goto do_st_lr;
16029 case SWRE:
16030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16031 mips32_op = OPC_SWRE;
16032 goto do_st_lr;
16033 case PREFE:
16034 /* Treat as no-op */
16035 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16036 /* hint codes 24-31 are reserved and signal RI */
16037 generate_exception(ctx, EXCP_RI);
16039 break;
16040 case CACHEE:
16041 /* Treat as no-op */
16042 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16043 gen_cache_operation(ctx, rt, rs, offset);
16045 break;
16046 case SBE:
16047 mips32_op = OPC_SBE;
16048 goto do_st_lr;
16049 case SHE:
16050 mips32_op = OPC_SHE;
16051 goto do_st_lr;
16052 case SCE:
16053 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16054 break;
16055 case SWE:
16056 mips32_op = OPC_SWE;
16057 goto do_st_lr;
16059 break;
16060 case PREF:
16061 /* Treat as no-op */
16062 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16063 /* hint codes 24-31 are reserved and signal RI */
16064 generate_exception(ctx, EXCP_RI);
16066 break;
16067 default:
16068 MIPS_INVAL("pool32c");
16069 generate_exception_end(ctx, EXCP_RI);
16070 break;
16072 break;
16073 case ADDI32: /* AUI, LUI */
16074 if (ctx->insn_flags & ISA_MIPS32R6) {
16075 /* AUI, LUI */
16076 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16077 } else {
16078 /* ADDI32 */
16079 mips32_op = OPC_ADDI;
16080 goto do_addi;
16082 break;
16083 case ADDIU32:
16084 mips32_op = OPC_ADDIU;
16085 do_addi:
16086 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16087 break;
16089 /* Logical operations */
16090 case ORI32:
16091 mips32_op = OPC_ORI;
16092 goto do_logici;
16093 case XORI32:
16094 mips32_op = OPC_XORI;
16095 goto do_logici;
16096 case ANDI32:
16097 mips32_op = OPC_ANDI;
16098 do_logici:
16099 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16100 break;
16102 /* Set less than immediate */
16103 case SLTI32:
16104 mips32_op = OPC_SLTI;
16105 goto do_slti;
16106 case SLTIU32:
16107 mips32_op = OPC_SLTIU;
16108 do_slti:
16109 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16110 break;
16111 case JALX32:
16112 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16113 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16114 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16115 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16116 break;
16117 case JALS32: /* BOVC, BEQC, BEQZALC */
16118 if (ctx->insn_flags & ISA_MIPS32R6) {
16119 if (rs >= rt) {
16120 /* BOVC */
16121 mips32_op = OPC_BOVC;
16122 } else if (rs < rt && rs == 0) {
16123 /* BEQZALC */
16124 mips32_op = OPC_BEQZALC;
16125 } else {
16126 /* BEQC */
16127 mips32_op = OPC_BEQC;
16129 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16130 } else {
16131 /* JALS32 */
16132 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16133 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16134 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16136 break;
16137 case BEQ32: /* BC */
16138 if (ctx->insn_flags & ISA_MIPS32R6) {
16139 /* BC */
16140 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16141 sextract32(ctx->opcode << 1, 0, 27));
16142 } else {
16143 /* BEQ32 */
16144 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16146 break;
16147 case BNE32: /* BALC */
16148 if (ctx->insn_flags & ISA_MIPS32R6) {
16149 /* BALC */
16150 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16151 sextract32(ctx->opcode << 1, 0, 27));
16152 } else {
16153 /* BNE32 */
16154 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16156 break;
16157 case J32: /* BGTZC, BLTZC, BLTC */
16158 if (ctx->insn_flags & ISA_MIPS32R6) {
16159 if (rs == 0 && rt != 0) {
16160 /* BGTZC */
16161 mips32_op = OPC_BGTZC;
16162 } else if (rs != 0 && rt != 0 && rs == rt) {
16163 /* BLTZC */
16164 mips32_op = OPC_BLTZC;
16165 } else {
16166 /* BLTC */
16167 mips32_op = OPC_BLTC;
16169 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16170 } else {
16171 /* J32 */
16172 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16173 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16175 break;
16176 case JAL32: /* BLEZC, BGEZC, BGEC */
16177 if (ctx->insn_flags & ISA_MIPS32R6) {
16178 if (rs == 0 && rt != 0) {
16179 /* BLEZC */
16180 mips32_op = OPC_BLEZC;
16181 } else if (rs != 0 && rt != 0 && rs == rt) {
16182 /* BGEZC */
16183 mips32_op = OPC_BGEZC;
16184 } else {
16185 /* BGEC */
16186 mips32_op = OPC_BGEC;
16188 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16189 } else {
16190 /* JAL32 */
16191 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16192 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16193 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16195 break;
16196 /* Floating point (COP1) */
16197 case LWC132:
16198 mips32_op = OPC_LWC1;
16199 goto do_cop1;
16200 case LDC132:
16201 mips32_op = OPC_LDC1;
16202 goto do_cop1;
16203 case SWC132:
16204 mips32_op = OPC_SWC1;
16205 goto do_cop1;
16206 case SDC132:
16207 mips32_op = OPC_SDC1;
16208 do_cop1:
16209 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16210 break;
16211 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16212 if (ctx->insn_flags & ISA_MIPS32R6) {
16213 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16214 switch ((ctx->opcode >> 16) & 0x1f) {
16215 case ADDIUPC_00:
16216 case ADDIUPC_01:
16217 case ADDIUPC_02:
16218 case ADDIUPC_03:
16219 case ADDIUPC_04:
16220 case ADDIUPC_05:
16221 case ADDIUPC_06:
16222 case ADDIUPC_07:
16223 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16224 break;
16225 case AUIPC:
16226 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16227 break;
16228 case ALUIPC:
16229 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16230 break;
16231 case LWPC_08:
16232 case LWPC_09:
16233 case LWPC_0A:
16234 case LWPC_0B:
16235 case LWPC_0C:
16236 case LWPC_0D:
16237 case LWPC_0E:
16238 case LWPC_0F:
16239 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16240 break;
16241 default:
16242 generate_exception(ctx, EXCP_RI);
16243 break;
16245 } else {
16246 /* ADDIUPC */
16247 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16248 offset = SIMM(ctx->opcode, 0, 23) << 2;
16250 gen_addiupc(ctx, reg, offset, 0, 0);
16252 break;
16253 case BNVC: /* BNEC, BNEZALC */
16254 check_insn(ctx, ISA_MIPS32R6);
16255 if (rs >= rt) {
16256 /* BNVC */
16257 mips32_op = OPC_BNVC;
16258 } else if (rs < rt && rs == 0) {
16259 /* BNEZALC */
16260 mips32_op = OPC_BNEZALC;
16261 } else {
16262 /* BNEC */
16263 mips32_op = OPC_BNEC;
16265 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16266 break;
16267 case R6_BNEZC: /* JIALC */
16268 check_insn(ctx, ISA_MIPS32R6);
16269 if (rt != 0) {
16270 /* BNEZC */
16271 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16272 sextract32(ctx->opcode << 1, 0, 22));
16273 } else {
16274 /* JIALC */
16275 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16277 break;
16278 case R6_BEQZC: /* JIC */
16279 check_insn(ctx, ISA_MIPS32R6);
16280 if (rt != 0) {
16281 /* BEQZC */
16282 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16283 sextract32(ctx->opcode << 1, 0, 22));
16284 } else {
16285 /* JIC */
16286 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16288 break;
16289 case BLEZALC: /* BGEZALC, BGEUC */
16290 check_insn(ctx, ISA_MIPS32R6);
16291 if (rs == 0 && rt != 0) {
16292 /* BLEZALC */
16293 mips32_op = OPC_BLEZALC;
16294 } else if (rs != 0 && rt != 0 && rs == rt) {
16295 /* BGEZALC */
16296 mips32_op = OPC_BGEZALC;
16297 } else {
16298 /* BGEUC */
16299 mips32_op = OPC_BGEUC;
16301 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16302 break;
16303 case BGTZALC: /* BLTZALC, BLTUC */
16304 check_insn(ctx, ISA_MIPS32R6);
16305 if (rs == 0 && rt != 0) {
16306 /* BGTZALC */
16307 mips32_op = OPC_BGTZALC;
16308 } else if (rs != 0 && rt != 0 && rs == rt) {
16309 /* BLTZALC */
16310 mips32_op = OPC_BLTZALC;
16311 } else {
16312 /* BLTUC */
16313 mips32_op = OPC_BLTUC;
16315 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16316 break;
16317 /* Loads and stores */
16318 case LB32:
16319 mips32_op = OPC_LB;
16320 goto do_ld;
16321 case LBU32:
16322 mips32_op = OPC_LBU;
16323 goto do_ld;
16324 case LH32:
16325 mips32_op = OPC_LH;
16326 goto do_ld;
16327 case LHU32:
16328 mips32_op = OPC_LHU;
16329 goto do_ld;
16330 case LW32:
16331 mips32_op = OPC_LW;
16332 goto do_ld;
16333 #ifdef TARGET_MIPS64
16334 case LD32:
16335 check_insn(ctx, ISA_MIPS3);
16336 check_mips_64(ctx);
16337 mips32_op = OPC_LD;
16338 goto do_ld;
16339 case SD32:
16340 check_insn(ctx, ISA_MIPS3);
16341 check_mips_64(ctx);
16342 mips32_op = OPC_SD;
16343 goto do_st;
16344 #endif
16345 case SB32:
16346 mips32_op = OPC_SB;
16347 goto do_st;
16348 case SH32:
16349 mips32_op = OPC_SH;
16350 goto do_st;
16351 case SW32:
16352 mips32_op = OPC_SW;
16353 goto do_st;
16354 do_ld:
16355 gen_ld(ctx, mips32_op, rt, rs, imm);
16356 break;
16357 do_st:
16358 gen_st(ctx, mips32_op, rt, rs, imm);
16359 break;
16360 default:
16361 generate_exception_end(ctx, EXCP_RI);
16362 break;
16366 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16368 uint32_t op;
16370 /* make sure instructions are on a halfword boundary */
16371 if (ctx->base.pc_next & 0x1) {
16372 env->CP0_BadVAddr = ctx->base.pc_next;
16373 generate_exception_end(ctx, EXCP_AdEL);
16374 return 2;
16377 op = (ctx->opcode >> 10) & 0x3f;
16378 /* Enforce properly-sized instructions in a delay slot */
16379 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16380 switch (op & 0x7) { /* MSB-3..MSB-5 */
16381 case 0:
16382 /* POOL32A, POOL32B, POOL32I, POOL32C */
16383 case 4:
16384 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16385 case 5:
16386 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16387 case 6:
16388 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16389 case 7:
16390 /* LB32, LH32, LWC132, LDC132, LW32 */
16391 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16392 generate_exception_end(ctx, EXCP_RI);
16393 return 2;
16395 break;
16396 case 1:
16397 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16398 case 2:
16399 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16400 case 3:
16401 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16402 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16403 generate_exception_end(ctx, EXCP_RI);
16404 return 2;
16406 break;
16410 switch (op) {
16411 case POOL16A:
16413 int rd = mmreg(uMIPS_RD(ctx->opcode));
16414 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16415 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16416 uint32_t opc = 0;
16418 switch (ctx->opcode & 0x1) {
16419 case ADDU16:
16420 opc = OPC_ADDU;
16421 break;
16422 case SUBU16:
16423 opc = OPC_SUBU;
16424 break;
16426 if (ctx->insn_flags & ISA_MIPS32R6) {
16427 /* In the Release 6 the register number location in
16428 * the instruction encoding has changed.
16430 gen_arith(ctx, opc, rs1, rd, rs2);
16431 } else {
16432 gen_arith(ctx, opc, rd, rs1, rs2);
16435 break;
16436 case POOL16B:
16438 int rd = mmreg(uMIPS_RD(ctx->opcode));
16439 int rs = mmreg(uMIPS_RS(ctx->opcode));
16440 int amount = (ctx->opcode >> 1) & 0x7;
16441 uint32_t opc = 0;
16442 amount = amount == 0 ? 8 : amount;
16444 switch (ctx->opcode & 0x1) {
16445 case SLL16:
16446 opc = OPC_SLL;
16447 break;
16448 case SRL16:
16449 opc = OPC_SRL;
16450 break;
16453 gen_shift_imm(ctx, opc, rd, rs, amount);
16455 break;
16456 case POOL16C:
16457 if (ctx->insn_flags & ISA_MIPS32R6) {
16458 gen_pool16c_r6_insn(ctx);
16459 } else {
16460 gen_pool16c_insn(ctx);
16462 break;
16463 case LWGP16:
16465 int rd = mmreg(uMIPS_RD(ctx->opcode));
16466 int rb = 28; /* GP */
16467 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16469 gen_ld(ctx, OPC_LW, rd, rb, offset);
16471 break;
16472 case POOL16F:
16473 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16474 if (ctx->opcode & 1) {
16475 generate_exception_end(ctx, EXCP_RI);
16476 } else {
16477 /* MOVEP */
16478 int enc_dest = uMIPS_RD(ctx->opcode);
16479 int enc_rt = uMIPS_RS2(ctx->opcode);
16480 int enc_rs = uMIPS_RS1(ctx->opcode);
16481 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
16483 break;
16484 case LBU16:
16486 int rd = mmreg(uMIPS_RD(ctx->opcode));
16487 int rb = mmreg(uMIPS_RS(ctx->opcode));
16488 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16489 offset = (offset == 0xf ? -1 : offset);
16491 gen_ld(ctx, OPC_LBU, rd, rb, offset);
16493 break;
16494 case LHU16:
16496 int rd = mmreg(uMIPS_RD(ctx->opcode));
16497 int rb = mmreg(uMIPS_RS(ctx->opcode));
16498 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16500 gen_ld(ctx, OPC_LHU, rd, rb, offset);
16502 break;
16503 case LWSP16:
16505 int rd = (ctx->opcode >> 5) & 0x1f;
16506 int rb = 29; /* SP */
16507 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16509 gen_ld(ctx, OPC_LW, rd, rb, offset);
16511 break;
16512 case LW16:
16514 int rd = mmreg(uMIPS_RD(ctx->opcode));
16515 int rb = mmreg(uMIPS_RS(ctx->opcode));
16516 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16518 gen_ld(ctx, OPC_LW, rd, rb, offset);
16520 break;
16521 case SB16:
16523 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16524 int rb = mmreg(uMIPS_RS(ctx->opcode));
16525 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16527 gen_st(ctx, OPC_SB, rd, rb, offset);
16529 break;
16530 case SH16:
16532 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16533 int rb = mmreg(uMIPS_RS(ctx->opcode));
16534 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16536 gen_st(ctx, OPC_SH, rd, rb, offset);
16538 break;
16539 case SWSP16:
16541 int rd = (ctx->opcode >> 5) & 0x1f;
16542 int rb = 29; /* SP */
16543 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16545 gen_st(ctx, OPC_SW, rd, rb, offset);
16547 break;
16548 case SW16:
16550 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16551 int rb = mmreg(uMIPS_RS(ctx->opcode));
16552 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16554 gen_st(ctx, OPC_SW, rd, rb, offset);
16556 break;
16557 case MOVE16:
16559 int rd = uMIPS_RD5(ctx->opcode);
16560 int rs = uMIPS_RS5(ctx->opcode);
16562 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
16564 break;
16565 case ANDI16:
16566 gen_andi16(ctx);
16567 break;
16568 case POOL16D:
16569 switch (ctx->opcode & 0x1) {
16570 case ADDIUS5:
16571 gen_addius5(ctx);
16572 break;
16573 case ADDIUSP:
16574 gen_addiusp(ctx);
16575 break;
16577 break;
16578 case POOL16E:
16579 switch (ctx->opcode & 0x1) {
16580 case ADDIUR2:
16581 gen_addiur2(ctx);
16582 break;
16583 case ADDIUR1SP:
16584 gen_addiur1sp(ctx);
16585 break;
16587 break;
16588 case B16: /* BC16 */
16589 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
16590 sextract32(ctx->opcode, 0, 10) << 1,
16591 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16592 break;
16593 case BNEZ16: /* BNEZC16 */
16594 case BEQZ16: /* BEQZC16 */
16595 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16596 mmreg(uMIPS_RD(ctx->opcode)),
16597 0, sextract32(ctx->opcode, 0, 7) << 1,
16598 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16600 break;
16601 case LI16:
16603 int reg = mmreg(uMIPS_RD(ctx->opcode));
16604 int imm = ZIMM(ctx->opcode, 0, 7);
16606 imm = (imm == 0x7f ? -1 : imm);
16607 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16609 break;
16610 case RES_29:
16611 case RES_31:
16612 case RES_39:
16613 generate_exception_end(ctx, EXCP_RI);
16614 break;
16615 default:
16616 decode_micromips32_opc(env, ctx);
16617 return 4;
16620 return 2;
16625 * nanoMIPS opcodes
16629 /* MAJOR, P16, and P32 pools opcodes */
16630 enum {
16631 NM_P_ADDIU = 0x00,
16632 NM_ADDIUPC = 0x01,
16633 NM_MOVE_BALC = 0x02,
16634 NM_P16_MV = 0x04,
16635 NM_LW16 = 0x05,
16636 NM_BC16 = 0x06,
16637 NM_P16_SR = 0x07,
16639 NM_POOL32A = 0x08,
16640 NM_P_BAL = 0x0a,
16641 NM_P16_SHIFT = 0x0c,
16642 NM_LWSP16 = 0x0d,
16643 NM_BALC16 = 0x0e,
16644 NM_P16_4X4 = 0x0f,
16646 NM_P_GP_W = 0x10,
16647 NM_P_GP_BH = 0x11,
16648 NM_P_J = 0x12,
16649 NM_P16C = 0x14,
16650 NM_LWGP16 = 0x15,
16651 NM_P16_LB = 0x17,
16653 NM_P48I = 0x18,
16654 NM_P16_A1 = 0x1c,
16655 NM_LW4X4 = 0x1d,
16656 NM_P16_LH = 0x1f,
16658 NM_P_U12 = 0x20,
16659 NM_P_LS_U12 = 0x21,
16660 NM_P_BR1 = 0x22,
16661 NM_P16_A2 = 0x24,
16662 NM_SW16 = 0x25,
16663 NM_BEQZC16 = 0x26,
16665 NM_POOL32F = 0x28,
16666 NM_P_LS_S9 = 0x29,
16667 NM_P_BR2 = 0x2a,
16669 NM_P16_ADDU = 0x2c,
16670 NM_SWSP16 = 0x2d,
16671 NM_BNEZC16 = 0x2e,
16672 NM_MOVEP = 0x2f,
16674 NM_POOL32S = 0x30,
16675 NM_P_BRI = 0x32,
16676 NM_LI16 = 0x34,
16677 NM_SWGP16 = 0x35,
16678 NM_P16_BR = 0x36,
16680 NM_P_LUI = 0x38,
16681 NM_ANDI16 = 0x3c,
16682 NM_SW4X4 = 0x3d,
16683 NM_MOVEPREV = 0x3f,
16686 /* POOL32A instruction pool */
16687 enum {
16688 NM_POOL32A0 = 0x00,
16689 NM_SPECIAL2 = 0x01,
16690 NM_COP2_1 = 0x02,
16691 NM_UDI = 0x03,
16692 NM_POOL32A5 = 0x05,
16693 NM_POOL32A7 = 0x07,
16696 /* P.GP.W instruction pool */
16697 enum {
16698 NM_ADDIUGP_W = 0x00,
16699 NM_LWGP = 0x02,
16700 NM_SWGP = 0x03,
16703 /* P48I instruction pool */
16704 enum {
16705 NM_LI48 = 0x00,
16706 NM_ADDIU48 = 0x01,
16707 NM_ADDIUGP48 = 0x02,
16708 NM_ADDIUPC48 = 0x03,
16709 NM_LWPC48 = 0x0b,
16710 NM_SWPC48 = 0x0f,
16713 /* P.U12 instruction pool */
16714 enum {
16715 NM_ORI = 0x00,
16716 NM_XORI = 0x01,
16717 NM_ANDI = 0x02,
16718 NM_P_SR = 0x03,
16719 NM_SLTI = 0x04,
16720 NM_SLTIU = 0x05,
16721 NM_SEQI = 0x06,
16722 NM_ADDIUNEG = 0x08,
16723 NM_P_SHIFT = 0x0c,
16724 NM_P_ROTX = 0x0d,
16725 NM_P_INS = 0x0e,
16726 NM_P_EXT = 0x0f,
16729 /* POOL32F instruction pool */
16730 enum {
16731 NM_POOL32F_0 = 0x00,
16732 NM_POOL32F_3 = 0x03,
16733 NM_POOL32F_5 = 0x05,
16736 /* POOL32S instruction pool */
16737 enum {
16738 NM_POOL32S_0 = 0x00,
16739 NM_POOL32S_4 = 0x04,
16742 /* P.LUI instruction pool */
16743 enum {
16744 NM_LUI = 0x00,
16745 NM_ALUIPC = 0x01,
16748 /* P.GP.BH instruction pool */
16749 enum {
16750 NM_LBGP = 0x00,
16751 NM_SBGP = 0x01,
16752 NM_LBUGP = 0x02,
16753 NM_ADDIUGP_B = 0x03,
16754 NM_P_GP_LH = 0x04,
16755 NM_P_GP_SH = 0x05,
16756 NM_P_GP_CP1 = 0x06,
16759 /* P.LS.U12 instruction pool */
16760 enum {
16761 NM_LB = 0x00,
16762 NM_SB = 0x01,
16763 NM_LBU = 0x02,
16764 NM_P_PREFU12 = 0x03,
16765 NM_LH = 0x04,
16766 NM_SH = 0x05,
16767 NM_LHU = 0x06,
16768 NM_LWU = 0x07,
16769 NM_LW = 0x08,
16770 NM_SW = 0x09,
16771 NM_LWC1 = 0x0a,
16772 NM_SWC1 = 0x0b,
16773 NM_LDC1 = 0x0e,
16774 NM_SDC1 = 0x0f,
16777 /* P.LS.S9 instruction pool */
16778 enum {
16779 NM_P_LS_S0 = 0x00,
16780 NM_P_LS_S1 = 0x01,
16781 NM_P_LS_E0 = 0x02,
16782 NM_P_LS_WM = 0x04,
16783 NM_P_LS_UAWM = 0x05,
16786 /* P.BAL instruction pool */
16787 enum {
16788 NM_BC = 0x00,
16789 NM_BALC = 0x01,
16792 /* P.J instruction pool */
16793 enum {
16794 NM_JALRC = 0x00,
16795 NM_JALRC_HB = 0x01,
16796 NM_P_BALRSC = 0x08,
16799 /* P.BR1 instruction pool */
16800 enum {
16801 NM_BEQC = 0x00,
16802 NM_P_BR3A = 0x01,
16803 NM_BGEC = 0x02,
16804 NM_BGEUC = 0x03,
16807 /* P.BR2 instruction pool */
16808 enum {
16809 NM_BNEC = 0x00,
16810 NM_BLTC = 0x02,
16811 NM_BLTUC = 0x03,
16814 /* P.BRI instruction pool */
16815 enum {
16816 NM_BEQIC = 0x00,
16817 NM_BBEQZC = 0x01,
16818 NM_BGEIC = 0x02,
16819 NM_BGEIUC = 0x03,
16820 NM_BNEIC = 0x04,
16821 NM_BBNEZC = 0x05,
16822 NM_BLTIC = 0x06,
16823 NM_BLTIUC = 0x07,
16826 /* P16.SHIFT instruction pool */
16827 enum {
16828 NM_SLL16 = 0x00,
16829 NM_SRL16 = 0x01,
16832 /* POOL16C instruction pool */
16833 enum {
16834 NM_POOL16C_0 = 0x00,
16835 NM_LWXS16 = 0x01,
16838 /* P16.A1 instruction pool */
16839 enum {
16840 NM_ADDIUR1SP = 0x01,
16843 /* P16.A2 instruction pool */
16844 enum {
16845 NM_ADDIUR2 = 0x00,
16846 NM_P_ADDIURS5 = 0x01,
16849 /* P16.ADDU instruction pool */
16850 enum {
16851 NM_ADDU16 = 0x00,
16852 NM_SUBU16 = 0x01,
16855 /* P16.SR instruction pool */
16856 enum {
16857 NM_SAVE16 = 0x00,
16858 NM_RESTORE_JRC16 = 0x01,
16861 /* P16.4X4 instruction pool */
16862 enum {
16863 NM_ADDU4X4 = 0x00,
16864 NM_MUL4X4 = 0x01,
16867 /* P16.LB instruction pool */
16868 enum {
16869 NM_LB16 = 0x00,
16870 NM_SB16 = 0x01,
16871 NM_LBU16 = 0x02,
16874 /* P16.LH instruction pool */
16875 enum {
16876 NM_LH16 = 0x00,
16877 NM_SH16 = 0x01,
16878 NM_LHU16 = 0x02,
16881 /* P.RI instruction pool */
16882 enum {
16883 NM_SIGRIE = 0x00,
16884 NM_P_SYSCALL = 0x01,
16885 NM_BREAK = 0x02,
16886 NM_SDBBP = 0x03,
16889 /* POOL32A0 instruction pool */
16890 enum {
16891 NM_P_TRAP = 0x00,
16892 NM_SEB = 0x01,
16893 NM_SLLV = 0x02,
16894 NM_MUL = 0x03,
16895 NM_MFC0 = 0x06,
16896 NM_MFHC0 = 0x07,
16897 NM_SEH = 0x09,
16898 NM_SRLV = 0x0a,
16899 NM_MUH = 0x0b,
16900 NM_MTC0 = 0x0e,
16901 NM_MTHC0 = 0x0f,
16902 NM_SRAV = 0x12,
16903 NM_MULU = 0x13,
16904 NM_ROTRV = 0x1a,
16905 NM_MUHU = 0x1b,
16906 NM_ADD = 0x22,
16907 NM_DIV = 0x23,
16908 NM_ADDU = 0x2a,
16909 NM_MOD = 0x2b,
16910 NM_SUB = 0x32,
16911 NM_DIVU = 0x33,
16912 NM_RDHWR = 0x38,
16913 NM_SUBU = 0x3a,
16914 NM_MODU = 0x3b,
16915 NM_P_CMOVE = 0x42,
16916 NM_FORK = 0x45,
16917 NM_MFTR = 0x46,
16918 NM_MFHTR = 0x47,
16919 NM_AND = 0x4a,
16920 NM_YIELD = 0x4d,
16921 NM_MTTR = 0x4e,
16922 NM_MTHTR = 0x4f,
16923 NM_OR = 0x52,
16924 NM_D_E_MT_VPE = 0x56,
16925 NM_NOR = 0x5a,
16926 NM_XOR = 0x62,
16927 NM_SLT = 0x6a,
16928 NM_P_SLTU = 0x72,
16929 NM_SOV = 0x7a,
16932 /* POOL32A5 instruction pool */
16933 enum {
16934 NM_CMP_EQ_PH = 0x00,
16935 NM_CMP_LT_PH = 0x08,
16936 NM_CMP_LE_PH = 0x10,
16937 NM_CMPGU_EQ_QB = 0x18,
16938 NM_CMPGU_LT_QB = 0x20,
16939 NM_CMPGU_LE_QB = 0x28,
16940 NM_CMPGDU_EQ_QB = 0x30,
16941 NM_CMPGDU_LT_QB = 0x38,
16942 NM_CMPGDU_LE_QB = 0x40,
16943 NM_CMPU_EQ_QB = 0x48,
16944 NM_CMPU_LT_QB = 0x50,
16945 NM_CMPU_LE_QB = 0x58,
16946 NM_ADDQ_S_W = 0x60,
16947 NM_SUBQ_S_W = 0x68,
16948 NM_ADDSC = 0x70,
16949 NM_ADDWC = 0x78,
16951 NM_ADDQ_S_PH = 0x01,
16952 NM_ADDQH_R_PH = 0x09,
16953 NM_ADDQH_R_W = 0x11,
16954 NM_ADDU_S_QB = 0x19,
16955 NM_ADDU_S_PH = 0x21,
16956 NM_ADDUH_R_QB = 0x29,
16957 NM_SHRAV_R_PH = 0x31,
16958 NM_SHRAV_R_QB = 0x39,
16959 NM_SUBQ_S_PH = 0x41,
16960 NM_SUBQH_R_PH = 0x49,
16961 NM_SUBQH_R_W = 0x51,
16962 NM_SUBU_S_QB = 0x59,
16963 NM_SUBU_S_PH = 0x61,
16964 NM_SUBUH_R_QB = 0x69,
16965 NM_SHLLV_S_PH = 0x71,
16966 NM_PRECR_SRA_R_PH_W = 0x79,
16968 NM_MULEU_S_PH_QBL = 0x12,
16969 NM_MULEU_S_PH_QBR = 0x1a,
16970 NM_MULQ_RS_PH = 0x22,
16971 NM_MULQ_S_PH = 0x2a,
16972 NM_MULQ_RS_W = 0x32,
16973 NM_MULQ_S_W = 0x3a,
16974 NM_APPEND = 0x42,
16975 NM_MODSUB = 0x52,
16976 NM_SHRAV_R_W = 0x5a,
16977 NM_SHRLV_PH = 0x62,
16978 NM_SHRLV_QB = 0x6a,
16979 NM_SHLLV_QB = 0x72,
16980 NM_SHLLV_S_W = 0x7a,
16982 NM_SHILO = 0x03,
16984 NM_MULEQ_S_W_PHL = 0x04,
16985 NM_MULEQ_S_W_PHR = 0x0c,
16987 NM_MUL_S_PH = 0x05,
16988 NM_PRECR_QB_PH = 0x0d,
16989 NM_PRECRQ_QB_PH = 0x15,
16990 NM_PRECRQ_PH_W = 0x1d,
16991 NM_PRECRQ_RS_PH_W = 0x25,
16992 NM_PRECRQU_S_QB_PH = 0x2d,
16993 NM_PACKRL_PH = 0x35,
16994 NM_PICK_QB = 0x3d,
16995 NM_PICK_PH = 0x45,
16997 NM_SHRA_R_W = 0x5e,
16998 NM_SHRA_R_PH = 0x66,
16999 NM_SHLL_S_PH = 0x76,
17000 NM_SHLL_S_W = 0x7e,
17002 NM_REPL_PH = 0x07
17005 /* POOL32A7 instruction pool */
17006 enum {
17007 NM_P_LSX = 0x00,
17008 NM_LSA = 0x01,
17009 NM_EXTW = 0x03,
17010 NM_POOL32AXF = 0x07,
17013 /* P.SR instruction pool */
17014 enum {
17015 NM_PP_SR = 0x00,
17016 NM_P_SR_F = 0x01,
17019 /* P.SHIFT instruction pool */
17020 enum {
17021 NM_P_SLL = 0x00,
17022 NM_SRL = 0x02,
17023 NM_SRA = 0x04,
17024 NM_ROTR = 0x06,
17027 /* P.ROTX instruction pool */
17028 enum {
17029 NM_ROTX = 0x00,
17032 /* P.INS instruction pool */
17033 enum {
17034 NM_INS = 0x00,
17037 /* P.EXT instruction pool */
17038 enum {
17039 NM_EXT = 0x00,
17042 /* POOL32F_0 (fmt) instruction pool */
17043 enum {
17044 NM_RINT_S = 0x04,
17045 NM_RINT_D = 0x44,
17046 NM_ADD_S = 0x06,
17047 NM_SELEQZ_S = 0x07,
17048 NM_SELEQZ_D = 0x47,
17049 NM_CLASS_S = 0x0c,
17050 NM_CLASS_D = 0x4c,
17051 NM_SUB_S = 0x0e,
17052 NM_SELNEZ_S = 0x0f,
17053 NM_SELNEZ_D = 0x4f,
17054 NM_MUL_S = 0x16,
17055 NM_SEL_S = 0x17,
17056 NM_SEL_D = 0x57,
17057 NM_DIV_S = 0x1e,
17058 NM_ADD_D = 0x26,
17059 NM_SUB_D = 0x2e,
17060 NM_MUL_D = 0x36,
17061 NM_MADDF_S = 0x37,
17062 NM_MADDF_D = 0x77,
17063 NM_DIV_D = 0x3e,
17064 NM_MSUBF_S = 0x3f,
17065 NM_MSUBF_D = 0x7f,
17068 /* POOL32F_3 instruction pool */
17069 enum {
17070 NM_MIN_FMT = 0x00,
17071 NM_MAX_FMT = 0x01,
17072 NM_MINA_FMT = 0x04,
17073 NM_MAXA_FMT = 0x05,
17074 NM_POOL32FXF = 0x07,
17077 /* POOL32F_5 instruction pool */
17078 enum {
17079 NM_CMP_CONDN_S = 0x00,
17080 NM_CMP_CONDN_D = 0x02,
17083 /* P.GP.LH instruction pool */
17084 enum {
17085 NM_LHGP = 0x00,
17086 NM_LHUGP = 0x01,
17089 /* P.GP.SH instruction pool */
17090 enum {
17091 NM_SHGP = 0x00,
17094 /* P.GP.CP1 instruction pool */
17095 enum {
17096 NM_LWC1GP = 0x00,
17097 NM_SWC1GP = 0x01,
17098 NM_LDC1GP = 0x02,
17099 NM_SDC1GP = 0x03,
17102 /* P.LS.S0 instruction pool */
17103 enum {
17104 NM_LBS9 = 0x00,
17105 NM_LHS9 = 0x04,
17106 NM_LWS9 = 0x08,
17107 NM_LDS9 = 0x0c,
17109 NM_SBS9 = 0x01,
17110 NM_SHS9 = 0x05,
17111 NM_SWS9 = 0x09,
17112 NM_SDS9 = 0x0d,
17114 NM_LBUS9 = 0x02,
17115 NM_LHUS9 = 0x06,
17116 NM_LWC1S9 = 0x0a,
17117 NM_LDC1S9 = 0x0e,
17119 NM_P_PREFS9 = 0x03,
17120 NM_LWUS9 = 0x07,
17121 NM_SWC1S9 = 0x0b,
17122 NM_SDC1S9 = 0x0f,
17125 /* P.LS.S1 instruction pool */
17126 enum {
17127 NM_ASET_ACLR = 0x02,
17128 NM_UALH = 0x04,
17129 NM_UASH = 0x05,
17130 NM_CACHE = 0x07,
17131 NM_P_LL = 0x0a,
17132 NM_P_SC = 0x0b,
17135 /* P.LS.E0 instruction pool */
17136 enum {
17137 NM_LBE = 0x00,
17138 NM_SBE = 0x01,
17139 NM_LBUE = 0x02,
17140 NM_P_PREFE = 0x03,
17141 NM_LHE = 0x04,
17142 NM_SHE = 0x05,
17143 NM_LHUE = 0x06,
17144 NM_CACHEE = 0x07,
17145 NM_LWE = 0x08,
17146 NM_SWE = 0x09,
17147 NM_P_LLE = 0x0a,
17148 NM_P_SCE = 0x0b,
17151 /* P.PREFE instruction pool */
17152 enum {
17153 NM_SYNCIE = 0x00,
17154 NM_PREFE = 0x01,
17157 /* P.LLE instruction pool */
17158 enum {
17159 NM_LLE = 0x00,
17160 NM_LLWPE = 0x01,
17163 /* P.SCE instruction pool */
17164 enum {
17165 NM_SCE = 0x00,
17166 NM_SCWPE = 0x01,
17169 /* P.LS.WM instruction pool */
17170 enum {
17171 NM_LWM = 0x00,
17172 NM_SWM = 0x01,
17175 /* P.LS.UAWM instruction pool */
17176 enum {
17177 NM_UALWM = 0x00,
17178 NM_UASWM = 0x01,
17181 /* P.BR3A instruction pool */
17182 enum {
17183 NM_BC1EQZC = 0x00,
17184 NM_BC1NEZC = 0x01,
17185 NM_BC2EQZC = 0x02,
17186 NM_BC2NEZC = 0x03,
17187 NM_BPOSGE32C = 0x04,
17190 /* P16.RI instruction pool */
17191 enum {
17192 NM_P16_SYSCALL = 0x01,
17193 NM_BREAK16 = 0x02,
17194 NM_SDBBP16 = 0x03,
17197 /* POOL16C_0 instruction pool */
17198 enum {
17199 NM_POOL16C_00 = 0x00,
17202 /* P16.JRC instruction pool */
17203 enum {
17204 NM_JRC = 0x00,
17205 NM_JALRC16 = 0x01,
17208 /* P.SYSCALL instruction pool */
17209 enum {
17210 NM_SYSCALL = 0x00,
17211 NM_HYPCALL = 0x01,
17214 /* P.TRAP instruction pool */
17215 enum {
17216 NM_TEQ = 0x00,
17217 NM_TNE = 0x01,
17220 /* P.CMOVE instruction pool */
17221 enum {
17222 NM_MOVZ = 0x00,
17223 NM_MOVN = 0x01,
17226 /* POOL32Axf instruction pool */
17227 enum {
17228 NM_POOL32AXF_1 = 0x01,
17229 NM_POOL32AXF_2 = 0x02,
17230 NM_POOL32AXF_4 = 0x04,
17231 NM_POOL32AXF_5 = 0x05,
17232 NM_POOL32AXF_7 = 0x07,
17235 /* POOL32Axf_1 instruction pool */
17236 enum {
17237 NM_POOL32AXF_1_0 = 0x00,
17238 NM_POOL32AXF_1_1 = 0x01,
17239 NM_POOL32AXF_1_3 = 0x03,
17240 NM_POOL32AXF_1_4 = 0x04,
17241 NM_POOL32AXF_1_5 = 0x05,
17242 NM_POOL32AXF_1_7 = 0x07,
17245 /* POOL32Axf_2 instruction pool */
17246 enum {
17247 NM_POOL32AXF_2_0_7 = 0x00,
17248 NM_POOL32AXF_2_8_15 = 0x01,
17249 NM_POOL32AXF_2_16_23 = 0x02,
17250 NM_POOL32AXF_2_24_31 = 0x03,
17253 /* POOL32Axf_7 instruction pool */
17254 enum {
17255 NM_SHRA_R_QB = 0x0,
17256 NM_SHRL_PH = 0x1,
17257 NM_REPL_QB = 0x2,
17260 /* POOL32Axf_1_0 instruction pool */
17261 enum {
17262 NM_MFHI = 0x0,
17263 NM_MFLO = 0x1,
17264 NM_MTHI = 0x2,
17265 NM_MTLO = 0x3,
17268 /* POOL32Axf_1_1 instruction pool */
17269 enum {
17270 NM_MTHLIP = 0x0,
17271 NM_SHILOV = 0x1,
17274 /* POOL32Axf_1_3 instruction pool */
17275 enum {
17276 NM_RDDSP = 0x0,
17277 NM_WRDSP = 0x1,
17278 NM_EXTP = 0x2,
17279 NM_EXTPDP = 0x3,
17282 /* POOL32Axf_1_4 instruction pool */
17283 enum {
17284 NM_SHLL_QB = 0x0,
17285 NM_SHRL_QB = 0x1,
17288 /* POOL32Axf_1_5 instruction pool */
17289 enum {
17290 NM_MAQ_S_W_PHR = 0x0,
17291 NM_MAQ_S_W_PHL = 0x1,
17292 NM_MAQ_SA_W_PHR = 0x2,
17293 NM_MAQ_SA_W_PHL = 0x3,
17296 /* POOL32Axf_1_7 instruction pool */
17297 enum {
17298 NM_EXTR_W = 0x0,
17299 NM_EXTR_R_W = 0x1,
17300 NM_EXTR_RS_W = 0x2,
17301 NM_EXTR_S_H = 0x3,
17304 /* POOL32Axf_2_0_7 instruction pool */
17305 enum {
17306 NM_DPA_W_PH = 0x0,
17307 NM_DPAQ_S_W_PH = 0x1,
17308 NM_DPS_W_PH = 0x2,
17309 NM_DPSQ_S_W_PH = 0x3,
17310 NM_BALIGN = 0x4,
17311 NM_MADD = 0x5,
17312 NM_MULT = 0x6,
17313 NM_EXTRV_W = 0x7,
17316 /* POOL32Axf_2_8_15 instruction pool */
17317 enum {
17318 NM_DPAX_W_PH = 0x0,
17319 NM_DPAQ_SA_L_W = 0x1,
17320 NM_DPSX_W_PH = 0x2,
17321 NM_DPSQ_SA_L_W = 0x3,
17322 NM_MADDU = 0x5,
17323 NM_MULTU = 0x6,
17324 NM_EXTRV_R_W = 0x7,
17327 /* POOL32Axf_2_16_23 instruction pool */
17328 enum {
17329 NM_DPAU_H_QBL = 0x0,
17330 NM_DPAQX_S_W_PH = 0x1,
17331 NM_DPSU_H_QBL = 0x2,
17332 NM_DPSQX_S_W_PH = 0x3,
17333 NM_EXTPV = 0x4,
17334 NM_MSUB = 0x5,
17335 NM_MULSA_W_PH = 0x6,
17336 NM_EXTRV_RS_W = 0x7,
17339 /* POOL32Axf_2_24_31 instruction pool */
17340 enum {
17341 NM_DPAU_H_QBR = 0x0,
17342 NM_DPAQX_SA_W_PH = 0x1,
17343 NM_DPSU_H_QBR = 0x2,
17344 NM_DPSQX_SA_W_PH = 0x3,
17345 NM_EXTPDPV = 0x4,
17346 NM_MSUBU = 0x5,
17347 NM_MULSAQ_S_W_PH = 0x6,
17348 NM_EXTRV_S_H = 0x7,
17351 /* POOL32Axf_{4, 5} instruction pool */
17352 enum {
17353 NM_CLO = 0x25,
17354 NM_CLZ = 0x2d,
17356 NM_TLBP = 0x01,
17357 NM_TLBR = 0x09,
17358 NM_TLBWI = 0x11,
17359 NM_TLBWR = 0x19,
17360 NM_TLBINV = 0x03,
17361 NM_TLBINVF = 0x0b,
17362 NM_DI = 0x23,
17363 NM_EI = 0x2b,
17364 NM_RDPGPR = 0x70,
17365 NM_WRPGPR = 0x78,
17366 NM_WAIT = 0x61,
17367 NM_DERET = 0x71,
17368 NM_ERETX = 0x79,
17370 /* nanoMIPS DSP instructions */
17371 NM_ABSQ_S_QB = 0x00,
17372 NM_ABSQ_S_PH = 0x08,
17373 NM_ABSQ_S_W = 0x10,
17374 NM_PRECEQ_W_PHL = 0x28,
17375 NM_PRECEQ_W_PHR = 0x30,
17376 NM_PRECEQU_PH_QBL = 0x38,
17377 NM_PRECEQU_PH_QBR = 0x48,
17378 NM_PRECEU_PH_QBL = 0x58,
17379 NM_PRECEU_PH_QBR = 0x68,
17380 NM_PRECEQU_PH_QBLA = 0x39,
17381 NM_PRECEQU_PH_QBRA = 0x49,
17382 NM_PRECEU_PH_QBLA = 0x59,
17383 NM_PRECEU_PH_QBRA = 0x69,
17384 NM_REPLV_PH = 0x01,
17385 NM_REPLV_QB = 0x09,
17386 NM_BITREV = 0x18,
17387 NM_INSV = 0x20,
17388 NM_RADDU_W_QB = 0x78,
17390 NM_BITSWAP = 0x05,
17391 NM_WSBH = 0x3d,
17394 /* PP.SR instruction pool */
17395 enum {
17396 NM_SAVE = 0x00,
17397 NM_RESTORE = 0x02,
17398 NM_RESTORE_JRC = 0x03,
17401 /* P.SR.F instruction pool */
17402 enum {
17403 NM_SAVEF = 0x00,
17404 NM_RESTOREF = 0x01,
17407 /* P16.SYSCALL instruction pool */
17408 enum {
17409 NM_SYSCALL16 = 0x00,
17410 NM_HYPCALL16 = 0x01,
17413 /* POOL16C_00 instruction pool */
17414 enum {
17415 NM_NOT16 = 0x00,
17416 NM_XOR16 = 0x01,
17417 NM_AND16 = 0x02,
17418 NM_OR16 = 0x03,
17421 /* PP.LSX and PP.LSXS instruction pool */
17422 enum {
17423 NM_LBX = 0x00,
17424 NM_LHX = 0x04,
17425 NM_LWX = 0x08,
17426 NM_LDX = 0x0c,
17428 NM_SBX = 0x01,
17429 NM_SHX = 0x05,
17430 NM_SWX = 0x09,
17431 NM_SDX = 0x0d,
17433 NM_LBUX = 0x02,
17434 NM_LHUX = 0x06,
17435 NM_LWC1X = 0x0a,
17436 NM_LDC1X = 0x0e,
17438 NM_LWUX = 0x07,
17439 NM_SWC1X = 0x0b,
17440 NM_SDC1X = 0x0f,
17442 NM_LHXS = 0x04,
17443 NM_LWXS = 0x08,
17444 NM_LDXS = 0x0c,
17446 NM_SHXS = 0x05,
17447 NM_SWXS = 0x09,
17448 NM_SDXS = 0x0d,
17450 NM_LHUXS = 0x06,
17451 NM_LWC1XS = 0x0a,
17452 NM_LDC1XS = 0x0e,
17454 NM_LWUXS = 0x07,
17455 NM_SWC1XS = 0x0b,
17456 NM_SDC1XS = 0x0f,
17459 /* ERETx instruction pool */
17460 enum {
17461 NM_ERET = 0x00,
17462 NM_ERETNC = 0x01,
17465 /* POOL32FxF_{0, 1} insturction pool */
17466 enum {
17467 NM_CFC1 = 0x40,
17468 NM_CTC1 = 0x60,
17469 NM_MFC1 = 0x80,
17470 NM_MTC1 = 0xa0,
17471 NM_MFHC1 = 0xc0,
17472 NM_MTHC1 = 0xe0,
17474 NM_CVT_S_PL = 0x84,
17475 NM_CVT_S_PU = 0xa4,
17477 NM_CVT_L_S = 0x004,
17478 NM_CVT_L_D = 0x104,
17479 NM_CVT_W_S = 0x024,
17480 NM_CVT_W_D = 0x124,
17482 NM_RSQRT_S = 0x008,
17483 NM_RSQRT_D = 0x108,
17485 NM_SQRT_S = 0x028,
17486 NM_SQRT_D = 0x128,
17488 NM_RECIP_S = 0x048,
17489 NM_RECIP_D = 0x148,
17491 NM_FLOOR_L_S = 0x00c,
17492 NM_FLOOR_L_D = 0x10c,
17494 NM_FLOOR_W_S = 0x02c,
17495 NM_FLOOR_W_D = 0x12c,
17497 NM_CEIL_L_S = 0x04c,
17498 NM_CEIL_L_D = 0x14c,
17499 NM_CEIL_W_S = 0x06c,
17500 NM_CEIL_W_D = 0x16c,
17501 NM_TRUNC_L_S = 0x08c,
17502 NM_TRUNC_L_D = 0x18c,
17503 NM_TRUNC_W_S = 0x0ac,
17504 NM_TRUNC_W_D = 0x1ac,
17505 NM_ROUND_L_S = 0x0cc,
17506 NM_ROUND_L_D = 0x1cc,
17507 NM_ROUND_W_S = 0x0ec,
17508 NM_ROUND_W_D = 0x1ec,
17510 NM_MOV_S = 0x01,
17511 NM_MOV_D = 0x81,
17512 NM_ABS_S = 0x0d,
17513 NM_ABS_D = 0x8d,
17514 NM_NEG_S = 0x2d,
17515 NM_NEG_D = 0xad,
17516 NM_CVT_D_S = 0x04d,
17517 NM_CVT_D_W = 0x0cd,
17518 NM_CVT_D_L = 0x14d,
17519 NM_CVT_S_D = 0x06d,
17520 NM_CVT_S_W = 0x0ed,
17521 NM_CVT_S_L = 0x16d,
17524 /* P.LL instruction pool */
17525 enum {
17526 NM_LL = 0x00,
17527 NM_LLWP = 0x01,
17530 /* P.SC instruction pool */
17531 enum {
17532 NM_SC = 0x00,
17533 NM_SCWP = 0x01,
17536 /* P.DVP instruction pool */
17537 enum {
17538 NM_DVP = 0x00,
17539 NM_EVP = 0x01,
17545 * nanoMIPS decoding engine
17550 /* extraction utilities */
17552 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17553 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17554 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17555 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17556 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17557 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17559 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17560 static inline int decode_gpr_gpr3(int r)
17562 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17564 return map[r & 0x7];
17567 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17568 static inline int decode_gpr_gpr3_src_store(int r)
17570 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17572 return map[r & 0x7];
17575 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17576 static inline int decode_gpr_gpr4(int r)
17578 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17579 16, 17, 18, 19, 20, 21, 22, 23 };
17581 return map[r & 0xf];
17584 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17585 static inline int decode_gpr_gpr4_zero(int r)
17587 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17588 16, 17, 18, 19, 20, 21, 22, 23 };
17590 return map[r & 0xf];
17594 /* extraction utilities */
17596 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17597 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17598 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17599 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17600 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17601 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17604 static void gen_adjust_sp(DisasContext *ctx, int u)
17606 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17609 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17610 uint8_t gp, uint16_t u)
17612 int counter = 0;
17613 TCGv va = tcg_temp_new();
17614 TCGv t0 = tcg_temp_new();
17616 while (counter != count) {
17617 bool use_gp = gp && (counter == count - 1);
17618 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17619 int this_offset = -((counter + 1) << 2);
17620 gen_base_offset_addr(ctx, va, 29, this_offset);
17621 gen_load_gpr(t0, this_rt);
17622 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17623 (MO_TEUL | ctx->default_tcg_memop_mask));
17624 counter++;
17627 /* adjust stack pointer */
17628 gen_adjust_sp(ctx, -u);
17630 tcg_temp_free(t0);
17631 tcg_temp_free(va);
17634 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17635 uint8_t gp, uint16_t u)
17637 int counter = 0;
17638 TCGv va = tcg_temp_new();
17639 TCGv t0 = tcg_temp_new();
17641 while (counter != count) {
17642 bool use_gp = gp && (counter == count - 1);
17643 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17644 int this_offset = u - ((counter + 1) << 2);
17645 gen_base_offset_addr(ctx, va, 29, this_offset);
17646 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17647 ctx->default_tcg_memop_mask);
17648 tcg_gen_ext32s_tl(t0, t0);
17649 gen_store_gpr(t0, this_rt);
17650 counter++;
17653 /* adjust stack pointer */
17654 gen_adjust_sp(ctx, u);
17656 tcg_temp_free(t0);
17657 tcg_temp_free(va);
17660 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17662 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
17663 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
17665 switch (extract32(ctx->opcode, 2, 2)) {
17666 case NM_NOT16:
17667 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17668 break;
17669 case NM_AND16:
17670 gen_logic(ctx, OPC_AND, rt, rt, rs);
17671 break;
17672 case NM_XOR16:
17673 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17674 break;
17675 case NM_OR16:
17676 gen_logic(ctx, OPC_OR, rt, rt, rs);
17677 break;
17681 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17683 int rt = extract32(ctx->opcode, 21, 5);
17684 int rs = extract32(ctx->opcode, 16, 5);
17685 int rd = extract32(ctx->opcode, 11, 5);
17687 switch (extract32(ctx->opcode, 3, 7)) {
17688 case NM_P_TRAP:
17689 switch (extract32(ctx->opcode, 10, 1)) {
17690 case NM_TEQ:
17691 check_nms(ctx);
17692 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17693 break;
17694 case NM_TNE:
17695 check_nms(ctx);
17696 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17697 break;
17699 break;
17700 case NM_RDHWR:
17701 check_nms(ctx);
17702 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17703 break;
17704 case NM_SEB:
17705 check_nms(ctx);
17706 gen_bshfl(ctx, OPC_SEB, rs, rt);
17707 break;
17708 case NM_SEH:
17709 gen_bshfl(ctx, OPC_SEH, rs, rt);
17710 break;
17711 case NM_SLLV:
17712 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17713 break;
17714 case NM_SRLV:
17715 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17716 break;
17717 case NM_SRAV:
17718 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17719 break;
17720 case NM_ROTRV:
17721 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17722 break;
17723 case NM_ADD:
17724 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17725 break;
17726 case NM_ADDU:
17727 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17728 break;
17729 case NM_SUB:
17730 check_nms(ctx);
17731 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17732 break;
17733 case NM_SUBU:
17734 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17735 break;
17736 case NM_P_CMOVE:
17737 switch (extract32(ctx->opcode, 10, 1)) {
17738 case NM_MOVZ:
17739 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17740 break;
17741 case NM_MOVN:
17742 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17743 break;
17745 break;
17746 case NM_AND:
17747 gen_logic(ctx, OPC_AND, rd, rs, rt);
17748 break;
17749 case NM_OR:
17750 gen_logic(ctx, OPC_OR, rd, rs, rt);
17751 break;
17752 case NM_NOR:
17753 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17754 break;
17755 case NM_XOR:
17756 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17757 break;
17758 case NM_SLT:
17759 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17760 break;
17761 case NM_P_SLTU:
17762 if (rd == 0) {
17763 /* P_DVP */
17764 #ifndef CONFIG_USER_ONLY
17765 TCGv t0 = tcg_temp_new();
17766 switch (extract32(ctx->opcode, 10, 1)) {
17767 case NM_DVP:
17768 if (ctx->vp) {
17769 check_cp0_enabled(ctx);
17770 gen_helper_dvp(t0, cpu_env);
17771 gen_store_gpr(t0, rt);
17773 break;
17774 case NM_EVP:
17775 if (ctx->vp) {
17776 check_cp0_enabled(ctx);
17777 gen_helper_evp(t0, cpu_env);
17778 gen_store_gpr(t0, rt);
17780 break;
17782 tcg_temp_free(t0);
17783 #endif
17784 } else {
17785 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
17787 break;
17788 case NM_SOV:
17790 TCGv t0 = tcg_temp_new();
17791 TCGv t1 = tcg_temp_new();
17792 TCGv t2 = tcg_temp_new();
17794 gen_load_gpr(t1, rs);
17795 gen_load_gpr(t2, rt);
17796 tcg_gen_add_tl(t0, t1, t2);
17797 tcg_gen_ext32s_tl(t0, t0);
17798 tcg_gen_xor_tl(t1, t1, t2);
17799 tcg_gen_xor_tl(t2, t0, t2);
17800 tcg_gen_andc_tl(t1, t2, t1);
17802 /* operands of same sign, result different sign */
17803 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
17804 gen_store_gpr(t0, rd);
17806 tcg_temp_free(t0);
17807 tcg_temp_free(t1);
17808 tcg_temp_free(t2);
17810 break;
17811 case NM_MUL:
17812 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
17813 break;
17814 case NM_MUH:
17815 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
17816 break;
17817 case NM_MULU:
17818 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
17819 break;
17820 case NM_MUHU:
17821 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
17822 break;
17823 case NM_DIV:
17824 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
17825 break;
17826 case NM_MOD:
17827 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
17828 break;
17829 case NM_DIVU:
17830 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
17831 break;
17832 case NM_MODU:
17833 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
17834 break;
17835 #ifndef CONFIG_USER_ONLY
17836 case NM_MFC0:
17837 check_cp0_enabled(ctx);
17838 if (rt == 0) {
17839 /* Treat as NOP. */
17840 break;
17842 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
17843 break;
17844 case NM_MTC0:
17845 check_cp0_enabled(ctx);
17847 TCGv t0 = tcg_temp_new();
17849 gen_load_gpr(t0, rt);
17850 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
17851 tcg_temp_free(t0);
17853 break;
17854 case NM_D_E_MT_VPE:
17856 uint8_t sc = extract32(ctx->opcode, 10, 1);
17857 TCGv t0 = tcg_temp_new();
17859 switch (sc) {
17860 case 0:
17861 if (rs == 1) {
17862 /* DMT */
17863 check_cp0_mt(ctx);
17864 gen_helper_dmt(t0);
17865 gen_store_gpr(t0, rt);
17866 } else if (rs == 0) {
17867 /* DVPE */
17868 check_cp0_mt(ctx);
17869 gen_helper_dvpe(t0, cpu_env);
17870 gen_store_gpr(t0, rt);
17871 } else {
17872 generate_exception_end(ctx, EXCP_RI);
17874 break;
17875 case 1:
17876 if (rs == 1) {
17877 /* EMT */
17878 check_cp0_mt(ctx);
17879 gen_helper_emt(t0);
17880 gen_store_gpr(t0, rt);
17881 } else if (rs == 0) {
17882 /* EVPE */
17883 check_cp0_mt(ctx);
17884 gen_helper_evpe(t0, cpu_env);
17885 gen_store_gpr(t0, rt);
17886 } else {
17887 generate_exception_end(ctx, EXCP_RI);
17889 break;
17892 tcg_temp_free(t0);
17894 break;
17895 case NM_FORK:
17896 check_mt(ctx);
17898 TCGv t0 = tcg_temp_new();
17899 TCGv t1 = tcg_temp_new();
17901 gen_load_gpr(t0, rt);
17902 gen_load_gpr(t1, rs);
17903 gen_helper_fork(t0, t1);
17904 tcg_temp_free(t0);
17905 tcg_temp_free(t1);
17907 break;
17908 case NM_MFTR:
17909 case NM_MFHTR:
17910 check_cp0_enabled(ctx);
17911 if (rd == 0) {
17912 /* Treat as NOP. */
17913 return;
17915 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17916 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17917 break;
17918 case NM_MTTR:
17919 case NM_MTHTR:
17920 check_cp0_enabled(ctx);
17921 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
17922 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
17923 break;
17924 case NM_YIELD:
17925 check_mt(ctx);
17927 TCGv t0 = tcg_temp_new();
17929 gen_load_gpr(t0, rs);
17930 gen_helper_yield(t0, cpu_env, t0);
17931 gen_store_gpr(t0, rt);
17932 tcg_temp_free(t0);
17934 break;
17935 #endif
17936 default:
17937 generate_exception_end(ctx, EXCP_RI);
17938 break;
17942 /* dsp */
17943 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
17944 int ret, int v1, int v2)
17946 TCGv_i32 t0;
17947 TCGv v0_t;
17948 TCGv v1_t;
17950 t0 = tcg_temp_new_i32();
17952 v0_t = tcg_temp_new();
17953 v1_t = tcg_temp_new();
17955 tcg_gen_movi_i32(t0, v2 >> 3);
17957 gen_load_gpr(v0_t, ret);
17958 gen_load_gpr(v1_t, v1);
17960 switch (opc) {
17961 case NM_MAQ_S_W_PHR:
17962 check_dsp(ctx);
17963 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
17964 break;
17965 case NM_MAQ_S_W_PHL:
17966 check_dsp(ctx);
17967 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
17968 break;
17969 case NM_MAQ_SA_W_PHR:
17970 check_dsp(ctx);
17971 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
17972 break;
17973 case NM_MAQ_SA_W_PHL:
17974 check_dsp(ctx);
17975 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
17976 break;
17977 default:
17978 generate_exception_end(ctx, EXCP_RI);
17979 break;
17982 tcg_temp_free_i32(t0);
17984 tcg_temp_free(v0_t);
17985 tcg_temp_free(v1_t);
17989 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
17990 int ret, int v1, int v2)
17992 int16_t imm;
17993 TCGv t0 = tcg_temp_new();
17994 TCGv t1 = tcg_temp_new();
17995 TCGv v0_t = tcg_temp_new();
17997 gen_load_gpr(v0_t, v1);
17999 switch (opc) {
18000 case NM_POOL32AXF_1_0:
18001 check_dsp(ctx);
18002 switch (extract32(ctx->opcode, 12, 2)) {
18003 case NM_MFHI:
18004 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18005 break;
18006 case NM_MFLO:
18007 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18008 break;
18009 case NM_MTHI:
18010 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18011 break;
18012 case NM_MTLO:
18013 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18014 break;
18016 break;
18017 case NM_POOL32AXF_1_1:
18018 check_dsp(ctx);
18019 switch (extract32(ctx->opcode, 12, 2)) {
18020 case NM_MTHLIP:
18021 tcg_gen_movi_tl(t0, v2);
18022 gen_helper_mthlip(t0, v0_t, cpu_env);
18023 break;
18024 case NM_SHILOV:
18025 tcg_gen_movi_tl(t0, v2 >> 3);
18026 gen_helper_shilo(t0, v0_t, cpu_env);
18027 break;
18028 default:
18029 generate_exception_end(ctx, EXCP_RI);
18030 break;
18032 break;
18033 case NM_POOL32AXF_1_3:
18034 check_dsp(ctx);
18035 imm = extract32(ctx->opcode, 14, 7);
18036 switch (extract32(ctx->opcode, 12, 2)) {
18037 case NM_RDDSP:
18038 tcg_gen_movi_tl(t0, imm);
18039 gen_helper_rddsp(t0, t0, cpu_env);
18040 gen_store_gpr(t0, ret);
18041 break;
18042 case NM_WRDSP:
18043 gen_load_gpr(t0, ret);
18044 tcg_gen_movi_tl(t1, imm);
18045 gen_helper_wrdsp(t0, t1, cpu_env);
18046 break;
18047 case NM_EXTP:
18048 tcg_gen_movi_tl(t0, v2 >> 3);
18049 tcg_gen_movi_tl(t1, v1);
18050 gen_helper_extp(t0, t0, t1, cpu_env);
18051 gen_store_gpr(t0, ret);
18052 break;
18053 case NM_EXTPDP:
18054 tcg_gen_movi_tl(t0, v2 >> 3);
18055 tcg_gen_movi_tl(t1, v1);
18056 gen_helper_extpdp(t0, t0, t1, cpu_env);
18057 gen_store_gpr(t0, ret);
18058 break;
18060 break;
18061 case NM_POOL32AXF_1_4:
18062 check_dsp(ctx);
18063 tcg_gen_movi_tl(t0, v2 >> 2);
18064 switch (extract32(ctx->opcode, 12, 1)) {
18065 case NM_SHLL_QB:
18066 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18067 gen_store_gpr(t0, ret);
18068 break;
18069 case NM_SHRL_QB:
18070 gen_helper_shrl_qb(t0, t0, v0_t);
18071 gen_store_gpr(t0, ret);
18072 break;
18074 break;
18075 case NM_POOL32AXF_1_5:
18076 opc = extract32(ctx->opcode, 12, 2);
18077 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18078 break;
18079 case NM_POOL32AXF_1_7:
18080 check_dsp(ctx);
18081 tcg_gen_movi_tl(t0, v2 >> 3);
18082 tcg_gen_movi_tl(t1, v1);
18083 switch (extract32(ctx->opcode, 12, 2)) {
18084 case NM_EXTR_W:
18085 gen_helper_extr_w(t0, t0, t1, cpu_env);
18086 gen_store_gpr(t0, ret);
18087 break;
18088 case NM_EXTR_R_W:
18089 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18090 gen_store_gpr(t0, ret);
18091 break;
18092 case NM_EXTR_RS_W:
18093 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18094 gen_store_gpr(t0, ret);
18095 break;
18096 case NM_EXTR_S_H:
18097 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18098 gen_store_gpr(t0, ret);
18099 break;
18101 break;
18102 default:
18103 generate_exception_end(ctx, EXCP_RI);
18104 break;
18107 tcg_temp_free(t0);
18108 tcg_temp_free(t1);
18109 tcg_temp_free(v0_t);
18112 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18113 TCGv v0, TCGv v1, int rd)
18115 TCGv_i32 t0;
18117 t0 = tcg_temp_new_i32();
18119 tcg_gen_movi_i32(t0, rd >> 3);
18121 switch (opc) {
18122 case NM_POOL32AXF_2_0_7:
18123 switch (extract32(ctx->opcode, 9, 3)) {
18124 case NM_DPA_W_PH:
18125 check_dsp_r2(ctx);
18126 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18127 break;
18128 case NM_DPAQ_S_W_PH:
18129 check_dsp(ctx);
18130 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18131 break;
18132 case NM_DPS_W_PH:
18133 check_dsp_r2(ctx);
18134 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18135 break;
18136 case NM_DPSQ_S_W_PH:
18137 check_dsp(ctx);
18138 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18139 break;
18140 default:
18141 generate_exception_end(ctx, EXCP_RI);
18142 break;
18144 break;
18145 case NM_POOL32AXF_2_8_15:
18146 switch (extract32(ctx->opcode, 9, 3)) {
18147 case NM_DPAX_W_PH:
18148 check_dsp_r2(ctx);
18149 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18150 break;
18151 case NM_DPAQ_SA_L_W:
18152 check_dsp(ctx);
18153 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18154 break;
18155 case NM_DPSX_W_PH:
18156 check_dsp_r2(ctx);
18157 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18158 break;
18159 case NM_DPSQ_SA_L_W:
18160 check_dsp(ctx);
18161 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18162 break;
18163 default:
18164 generate_exception_end(ctx, EXCP_RI);
18165 break;
18167 break;
18168 case NM_POOL32AXF_2_16_23:
18169 switch (extract32(ctx->opcode, 9, 3)) {
18170 case NM_DPAU_H_QBL:
18171 check_dsp(ctx);
18172 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18173 break;
18174 case NM_DPAQX_S_W_PH:
18175 check_dsp_r2(ctx);
18176 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18177 break;
18178 case NM_DPSU_H_QBL:
18179 check_dsp(ctx);
18180 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18181 break;
18182 case NM_DPSQX_S_W_PH:
18183 check_dsp_r2(ctx);
18184 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18185 break;
18186 case NM_MULSA_W_PH:
18187 check_dsp_r2(ctx);
18188 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18189 break;
18190 default:
18191 generate_exception_end(ctx, EXCP_RI);
18192 break;
18194 break;
18195 case NM_POOL32AXF_2_24_31:
18196 switch (extract32(ctx->opcode, 9, 3)) {
18197 case NM_DPAU_H_QBR:
18198 check_dsp(ctx);
18199 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18200 break;
18201 case NM_DPAQX_SA_W_PH:
18202 check_dsp_r2(ctx);
18203 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18204 break;
18205 case NM_DPSU_H_QBR:
18206 check_dsp(ctx);
18207 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18208 break;
18209 case NM_DPSQX_SA_W_PH:
18210 check_dsp_r2(ctx);
18211 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18212 break;
18213 case NM_MULSAQ_S_W_PH:
18214 check_dsp(ctx);
18215 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18216 break;
18217 default:
18218 generate_exception_end(ctx, EXCP_RI);
18219 break;
18221 break;
18222 default:
18223 generate_exception_end(ctx, EXCP_RI);
18224 break;
18227 tcg_temp_free_i32(t0);
18230 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18231 int rt, int rs, int rd)
18233 int ret = rt;
18234 TCGv t0 = tcg_temp_new();
18235 TCGv t1 = tcg_temp_new();
18236 TCGv v0_t = tcg_temp_new();
18237 TCGv v1_t = tcg_temp_new();
18239 gen_load_gpr(v0_t, rt);
18240 gen_load_gpr(v1_t, rs);
18242 switch (opc) {
18243 case NM_POOL32AXF_2_0_7:
18244 switch (extract32(ctx->opcode, 9, 3)) {
18245 case NM_DPA_W_PH:
18246 case NM_DPAQ_S_W_PH:
18247 case NM_DPS_W_PH:
18248 case NM_DPSQ_S_W_PH:
18249 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18250 break;
18251 case NM_BALIGN:
18252 check_dsp_r2(ctx);
18253 if (rt != 0) {
18254 gen_load_gpr(t0, rs);
18255 rd &= 3;
18256 if (rd != 0 && rd != 2) {
18257 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18258 tcg_gen_ext32u_tl(t0, t0);
18259 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18260 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18262 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18264 break;
18265 case NM_MADD:
18266 check_dsp(ctx);
18268 int acc = extract32(ctx->opcode, 14, 2);
18269 TCGv_i64 t2 = tcg_temp_new_i64();
18270 TCGv_i64 t3 = tcg_temp_new_i64();
18272 gen_load_gpr(t0, rt);
18273 gen_load_gpr(t1, rs);
18274 tcg_gen_ext_tl_i64(t2, t0);
18275 tcg_gen_ext_tl_i64(t3, t1);
18276 tcg_gen_mul_i64(t2, t2, t3);
18277 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18278 tcg_gen_add_i64(t2, t2, t3);
18279 tcg_temp_free_i64(t3);
18280 gen_move_low32(cpu_LO[acc], t2);
18281 gen_move_high32(cpu_HI[acc], t2);
18282 tcg_temp_free_i64(t2);
18284 break;
18285 case NM_MULT:
18286 check_dsp(ctx);
18288 int acc = extract32(ctx->opcode, 14, 2);
18289 TCGv_i32 t2 = tcg_temp_new_i32();
18290 TCGv_i32 t3 = tcg_temp_new_i32();
18292 gen_load_gpr(t0, rs);
18293 gen_load_gpr(t1, rt);
18294 tcg_gen_trunc_tl_i32(t2, t0);
18295 tcg_gen_trunc_tl_i32(t3, t1);
18296 tcg_gen_muls2_i32(t2, t3, t2, t3);
18297 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18298 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18299 tcg_temp_free_i32(t2);
18300 tcg_temp_free_i32(t3);
18302 break;
18303 case NM_EXTRV_W:
18304 check_dsp(ctx);
18305 gen_load_gpr(v1_t, rs);
18306 tcg_gen_movi_tl(t0, rd >> 3);
18307 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18308 gen_store_gpr(t0, ret);
18309 break;
18311 break;
18312 case NM_POOL32AXF_2_8_15:
18313 switch (extract32(ctx->opcode, 9, 3)) {
18314 case NM_DPAX_W_PH:
18315 case NM_DPAQ_SA_L_W:
18316 case NM_DPSX_W_PH:
18317 case NM_DPSQ_SA_L_W:
18318 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18319 break;
18320 case NM_MADDU:
18321 check_dsp(ctx);
18323 int acc = extract32(ctx->opcode, 14, 2);
18324 TCGv_i64 t2 = tcg_temp_new_i64();
18325 TCGv_i64 t3 = tcg_temp_new_i64();
18327 gen_load_gpr(t0, rs);
18328 gen_load_gpr(t1, rt);
18329 tcg_gen_ext32u_tl(t0, t0);
18330 tcg_gen_ext32u_tl(t1, t1);
18331 tcg_gen_extu_tl_i64(t2, t0);
18332 tcg_gen_extu_tl_i64(t3, t1);
18333 tcg_gen_mul_i64(t2, t2, t3);
18334 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18335 tcg_gen_add_i64(t2, t2, t3);
18336 tcg_temp_free_i64(t3);
18337 gen_move_low32(cpu_LO[acc], t2);
18338 gen_move_high32(cpu_HI[acc], t2);
18339 tcg_temp_free_i64(t2);
18341 break;
18342 case NM_MULTU:
18343 check_dsp(ctx);
18345 int acc = extract32(ctx->opcode, 14, 2);
18346 TCGv_i32 t2 = tcg_temp_new_i32();
18347 TCGv_i32 t3 = tcg_temp_new_i32();
18349 gen_load_gpr(t0, rs);
18350 gen_load_gpr(t1, rt);
18351 tcg_gen_trunc_tl_i32(t2, t0);
18352 tcg_gen_trunc_tl_i32(t3, t1);
18353 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18354 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18355 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18356 tcg_temp_free_i32(t2);
18357 tcg_temp_free_i32(t3);
18359 break;
18360 case NM_EXTRV_R_W:
18361 check_dsp(ctx);
18362 tcg_gen_movi_tl(t0, rd >> 3);
18363 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18364 gen_store_gpr(t0, ret);
18365 break;
18366 default:
18367 generate_exception_end(ctx, EXCP_RI);
18368 break;
18370 break;
18371 case NM_POOL32AXF_2_16_23:
18372 switch (extract32(ctx->opcode, 9, 3)) {
18373 case NM_DPAU_H_QBL:
18374 case NM_DPAQX_S_W_PH:
18375 case NM_DPSU_H_QBL:
18376 case NM_DPSQX_S_W_PH:
18377 case NM_MULSA_W_PH:
18378 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18379 break;
18380 case NM_EXTPV:
18381 check_dsp(ctx);
18382 tcg_gen_movi_tl(t0, rd >> 3);
18383 gen_helper_extp(t0, t0, v1_t, cpu_env);
18384 gen_store_gpr(t0, ret);
18385 break;
18386 case NM_MSUB:
18387 check_dsp(ctx);
18389 int acc = extract32(ctx->opcode, 14, 2);
18390 TCGv_i64 t2 = tcg_temp_new_i64();
18391 TCGv_i64 t3 = tcg_temp_new_i64();
18393 gen_load_gpr(t0, rs);
18394 gen_load_gpr(t1, rt);
18395 tcg_gen_ext_tl_i64(t2, t0);
18396 tcg_gen_ext_tl_i64(t3, t1);
18397 tcg_gen_mul_i64(t2, t2, t3);
18398 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18399 tcg_gen_sub_i64(t2, t3, t2);
18400 tcg_temp_free_i64(t3);
18401 gen_move_low32(cpu_LO[acc], t2);
18402 gen_move_high32(cpu_HI[acc], t2);
18403 tcg_temp_free_i64(t2);
18405 break;
18406 case NM_EXTRV_RS_W:
18407 check_dsp(ctx);
18408 tcg_gen_movi_tl(t0, rd >> 3);
18409 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18410 gen_store_gpr(t0, ret);
18411 break;
18413 break;
18414 case NM_POOL32AXF_2_24_31:
18415 switch (extract32(ctx->opcode, 9, 3)) {
18416 case NM_DPAU_H_QBR:
18417 case NM_DPAQX_SA_W_PH:
18418 case NM_DPSU_H_QBR:
18419 case NM_DPSQX_SA_W_PH:
18420 case NM_MULSAQ_S_W_PH:
18421 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18422 break;
18423 case NM_EXTPDPV:
18424 check_dsp(ctx);
18425 tcg_gen_movi_tl(t0, rd >> 3);
18426 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18427 gen_store_gpr(t0, ret);
18428 break;
18429 case NM_MSUBU:
18430 check_dsp(ctx);
18432 int acc = extract32(ctx->opcode, 14, 2);
18433 TCGv_i64 t2 = tcg_temp_new_i64();
18434 TCGv_i64 t3 = tcg_temp_new_i64();
18436 gen_load_gpr(t0, rs);
18437 gen_load_gpr(t1, rt);
18438 tcg_gen_ext32u_tl(t0, t0);
18439 tcg_gen_ext32u_tl(t1, t1);
18440 tcg_gen_extu_tl_i64(t2, t0);
18441 tcg_gen_extu_tl_i64(t3, t1);
18442 tcg_gen_mul_i64(t2, t2, t3);
18443 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18444 tcg_gen_sub_i64(t2, t3, t2);
18445 tcg_temp_free_i64(t3);
18446 gen_move_low32(cpu_LO[acc], t2);
18447 gen_move_high32(cpu_HI[acc], t2);
18448 tcg_temp_free_i64(t2);
18450 break;
18451 case NM_EXTRV_S_H:
18452 check_dsp(ctx);
18453 tcg_gen_movi_tl(t0, rd >> 3);
18454 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18455 gen_store_gpr(t0, ret);
18456 break;
18458 break;
18459 default:
18460 generate_exception_end(ctx, EXCP_RI);
18461 break;
18464 tcg_temp_free(t0);
18465 tcg_temp_free(t1);
18467 tcg_temp_free(v0_t);
18468 tcg_temp_free(v1_t);
18471 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18472 int rt, int rs)
18474 int ret = rt;
18475 TCGv t0 = tcg_temp_new();
18476 TCGv v0_t = tcg_temp_new();
18478 gen_load_gpr(v0_t, rs);
18480 switch (opc) {
18481 case NM_ABSQ_S_QB:
18482 check_dsp_r2(ctx);
18483 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18484 gen_store_gpr(v0_t, ret);
18485 break;
18486 case NM_ABSQ_S_PH:
18487 check_dsp(ctx);
18488 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18489 gen_store_gpr(v0_t, ret);
18490 break;
18491 case NM_ABSQ_S_W:
18492 check_dsp(ctx);
18493 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18494 gen_store_gpr(v0_t, ret);
18495 break;
18496 case NM_PRECEQ_W_PHL:
18497 check_dsp(ctx);
18498 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18499 tcg_gen_ext32s_tl(v0_t, v0_t);
18500 gen_store_gpr(v0_t, ret);
18501 break;
18502 case NM_PRECEQ_W_PHR:
18503 check_dsp(ctx);
18504 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18505 tcg_gen_shli_tl(v0_t, v0_t, 16);
18506 tcg_gen_ext32s_tl(v0_t, v0_t);
18507 gen_store_gpr(v0_t, ret);
18508 break;
18509 case NM_PRECEQU_PH_QBL:
18510 check_dsp(ctx);
18511 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18512 gen_store_gpr(v0_t, ret);
18513 break;
18514 case NM_PRECEQU_PH_QBR:
18515 check_dsp(ctx);
18516 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18517 gen_store_gpr(v0_t, ret);
18518 break;
18519 case NM_PRECEQU_PH_QBLA:
18520 check_dsp(ctx);
18521 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18522 gen_store_gpr(v0_t, ret);
18523 break;
18524 case NM_PRECEQU_PH_QBRA:
18525 check_dsp(ctx);
18526 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18527 gen_store_gpr(v0_t, ret);
18528 break;
18529 case NM_PRECEU_PH_QBL:
18530 check_dsp(ctx);
18531 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18532 gen_store_gpr(v0_t, ret);
18533 break;
18534 case NM_PRECEU_PH_QBR:
18535 check_dsp(ctx);
18536 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18537 gen_store_gpr(v0_t, ret);
18538 break;
18539 case NM_PRECEU_PH_QBLA:
18540 check_dsp(ctx);
18541 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18542 gen_store_gpr(v0_t, ret);
18543 break;
18544 case NM_PRECEU_PH_QBRA:
18545 check_dsp(ctx);
18546 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18547 gen_store_gpr(v0_t, ret);
18548 break;
18549 case NM_REPLV_PH:
18550 check_dsp(ctx);
18551 tcg_gen_ext16u_tl(v0_t, v0_t);
18552 tcg_gen_shli_tl(t0, v0_t, 16);
18553 tcg_gen_or_tl(v0_t, v0_t, t0);
18554 tcg_gen_ext32s_tl(v0_t, v0_t);
18555 gen_store_gpr(v0_t, ret);
18556 break;
18557 case NM_REPLV_QB:
18558 check_dsp(ctx);
18559 tcg_gen_ext8u_tl(v0_t, v0_t);
18560 tcg_gen_shli_tl(t0, v0_t, 8);
18561 tcg_gen_or_tl(v0_t, v0_t, t0);
18562 tcg_gen_shli_tl(t0, v0_t, 16);
18563 tcg_gen_or_tl(v0_t, v0_t, t0);
18564 tcg_gen_ext32s_tl(v0_t, v0_t);
18565 gen_store_gpr(v0_t, ret);
18566 break;
18567 case NM_BITREV:
18568 check_dsp(ctx);
18569 gen_helper_bitrev(v0_t, v0_t);
18570 gen_store_gpr(v0_t, ret);
18571 break;
18572 case NM_INSV:
18573 check_dsp(ctx);
18575 TCGv tv0 = tcg_temp_new();
18577 gen_load_gpr(tv0, rt);
18578 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18579 gen_store_gpr(v0_t, ret);
18580 tcg_temp_free(tv0);
18582 break;
18583 case NM_RADDU_W_QB:
18584 check_dsp(ctx);
18585 gen_helper_raddu_w_qb(v0_t, v0_t);
18586 gen_store_gpr(v0_t, ret);
18587 break;
18588 case NM_BITSWAP:
18589 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18590 break;
18591 case NM_CLO:
18592 check_nms(ctx);
18593 gen_cl(ctx, OPC_CLO, ret, rs);
18594 break;
18595 case NM_CLZ:
18596 check_nms(ctx);
18597 gen_cl(ctx, OPC_CLZ, ret, rs);
18598 break;
18599 case NM_WSBH:
18600 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18601 break;
18602 default:
18603 generate_exception_end(ctx, EXCP_RI);
18604 break;
18607 tcg_temp_free(v0_t);
18608 tcg_temp_free(t0);
18611 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18612 int rt, int rs, int rd)
18614 TCGv t0 = tcg_temp_new();
18615 TCGv rs_t = tcg_temp_new();
18617 gen_load_gpr(rs_t, rs);
18619 switch (opc) {
18620 case NM_SHRA_R_QB:
18621 check_dsp_r2(ctx);
18622 tcg_gen_movi_tl(t0, rd >> 2);
18623 switch (extract32(ctx->opcode, 12, 1)) {
18624 case 0:
18625 /* NM_SHRA_QB */
18626 gen_helper_shra_qb(t0, t0, rs_t);
18627 gen_store_gpr(t0, rt);
18628 break;
18629 case 1:
18630 /* NM_SHRA_R_QB */
18631 gen_helper_shra_r_qb(t0, t0, rs_t);
18632 gen_store_gpr(t0, rt);
18633 break;
18635 break;
18636 case NM_SHRL_PH:
18637 check_dsp_r2(ctx);
18638 tcg_gen_movi_tl(t0, rd >> 1);
18639 gen_helper_shrl_ph(t0, t0, rs_t);
18640 gen_store_gpr(t0, rt);
18641 break;
18642 case NM_REPL_QB:
18643 check_dsp(ctx);
18645 int16_t imm;
18646 target_long result;
18647 imm = extract32(ctx->opcode, 13, 8);
18648 result = (uint32_t)imm << 24 |
18649 (uint32_t)imm << 16 |
18650 (uint32_t)imm << 8 |
18651 (uint32_t)imm;
18652 result = (int32_t)result;
18653 tcg_gen_movi_tl(t0, result);
18654 gen_store_gpr(t0, rt);
18656 break;
18657 default:
18658 generate_exception_end(ctx, EXCP_RI);
18659 break;
18661 tcg_temp_free(t0);
18662 tcg_temp_free(rs_t);
18666 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18668 int rt = extract32(ctx->opcode, 21, 5);
18669 int rs = extract32(ctx->opcode, 16, 5);
18670 int rd = extract32(ctx->opcode, 11, 5);
18672 switch (extract32(ctx->opcode, 6, 3)) {
18673 case NM_POOL32AXF_1:
18675 int32_t op1 = extract32(ctx->opcode, 9, 3);
18676 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18678 break;
18679 case NM_POOL32AXF_2:
18681 int32_t op1 = extract32(ctx->opcode, 12, 2);
18682 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18684 break;
18685 case NM_POOL32AXF_4:
18687 int32_t op1 = extract32(ctx->opcode, 9, 7);
18688 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18690 break;
18691 case NM_POOL32AXF_5:
18692 switch (extract32(ctx->opcode, 9, 7)) {
18693 #ifndef CONFIG_USER_ONLY
18694 case NM_TLBP:
18695 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18696 break;
18697 case NM_TLBR:
18698 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18699 break;
18700 case NM_TLBWI:
18701 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18702 break;
18703 case NM_TLBWR:
18704 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18705 break;
18706 case NM_TLBINV:
18707 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18708 break;
18709 case NM_TLBINVF:
18710 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18711 break;
18712 case NM_DI:
18713 check_cp0_enabled(ctx);
18715 TCGv t0 = tcg_temp_new();
18717 save_cpu_state(ctx, 1);
18718 gen_helper_di(t0, cpu_env);
18719 gen_store_gpr(t0, rt);
18720 /* Stop translation as we may have switched the execution mode */
18721 ctx->base.is_jmp = DISAS_STOP;
18722 tcg_temp_free(t0);
18724 break;
18725 case NM_EI:
18726 check_cp0_enabled(ctx);
18728 TCGv t0 = tcg_temp_new();
18730 save_cpu_state(ctx, 1);
18731 gen_helper_ei(t0, cpu_env);
18732 gen_store_gpr(t0, rt);
18733 /* Stop translation as we may have switched the execution mode */
18734 ctx->base.is_jmp = DISAS_STOP;
18735 tcg_temp_free(t0);
18737 break;
18738 case NM_RDPGPR:
18739 gen_load_srsgpr(rs, rt);
18740 break;
18741 case NM_WRPGPR:
18742 gen_store_srsgpr(rs, rt);
18743 break;
18744 case NM_WAIT:
18745 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18746 break;
18747 case NM_DERET:
18748 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18749 break;
18750 case NM_ERETX:
18751 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18752 break;
18753 #endif
18754 default:
18755 generate_exception_end(ctx, EXCP_RI);
18756 break;
18758 break;
18759 case NM_POOL32AXF_7:
18761 int32_t op1 = extract32(ctx->opcode, 9, 3);
18762 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18764 break;
18765 default:
18766 generate_exception_end(ctx, EXCP_RI);
18767 break;
18771 /* Immediate Value Compact Branches */
18772 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
18773 int rt, int32_t imm, int32_t offset)
18775 TCGCond cond;
18776 int bcond_compute = 0;
18777 TCGv t0 = tcg_temp_new();
18778 TCGv t1 = tcg_temp_new();
18780 gen_load_gpr(t0, rt);
18781 tcg_gen_movi_tl(t1, imm);
18782 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18784 /* Load needed operands and calculate btarget */
18785 switch (opc) {
18786 case NM_BEQIC:
18787 if (rt == 0 && imm == 0) {
18788 /* Unconditional branch */
18789 } else if (rt == 0 && imm != 0) {
18790 /* Treat as NOP */
18791 goto out;
18792 } else {
18793 bcond_compute = 1;
18794 cond = TCG_COND_EQ;
18796 break;
18797 case NM_BBEQZC:
18798 case NM_BBNEZC:
18799 check_nms(ctx);
18800 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
18801 generate_exception_end(ctx, EXCP_RI);
18802 goto out;
18803 } else if (rt == 0 && opc == NM_BBEQZC) {
18804 /* Unconditional branch */
18805 } else if (rt == 0 && opc == NM_BBNEZC) {
18806 /* Treat as NOP */
18807 goto out;
18808 } else {
18809 tcg_gen_shri_tl(t0, t0, imm);
18810 tcg_gen_andi_tl(t0, t0, 1);
18811 tcg_gen_movi_tl(t1, 0);
18812 bcond_compute = 1;
18813 if (opc == NM_BBEQZC) {
18814 cond = TCG_COND_EQ;
18815 } else {
18816 cond = TCG_COND_NE;
18819 break;
18820 case NM_BNEIC:
18821 if (rt == 0 && imm == 0) {
18822 /* Treat as NOP */
18823 goto out;
18824 } else if (rt == 0 && imm != 0) {
18825 /* Unconditional branch */
18826 } else {
18827 bcond_compute = 1;
18828 cond = TCG_COND_NE;
18830 break;
18831 case NM_BGEIC:
18832 if (rt == 0 && imm == 0) {
18833 /* Unconditional branch */
18834 } else {
18835 bcond_compute = 1;
18836 cond = TCG_COND_GE;
18838 break;
18839 case NM_BLTIC:
18840 bcond_compute = 1;
18841 cond = TCG_COND_LT;
18842 break;
18843 case NM_BGEIUC:
18844 if (rt == 0 && imm == 0) {
18845 /* Unconditional branch */
18846 } else {
18847 bcond_compute = 1;
18848 cond = TCG_COND_GEU;
18850 break;
18851 case NM_BLTIUC:
18852 bcond_compute = 1;
18853 cond = TCG_COND_LTU;
18854 break;
18855 default:
18856 MIPS_INVAL("Immediate Value Compact branch");
18857 generate_exception_end(ctx, EXCP_RI);
18858 goto out;
18861 if (bcond_compute == 0) {
18862 /* Uncoditional compact branch */
18863 gen_goto_tb(ctx, 0, ctx->btarget);
18864 } else {
18865 /* Conditional compact branch */
18866 TCGLabel *fs = gen_new_label();
18868 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
18870 gen_goto_tb(ctx, 1, ctx->btarget);
18871 gen_set_label(fs);
18873 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
18876 out:
18877 tcg_temp_free(t0);
18878 tcg_temp_free(t1);
18881 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
18882 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
18883 int rt)
18885 TCGv t0 = tcg_temp_new();
18886 TCGv t1 = tcg_temp_new();
18888 /* load rs */
18889 gen_load_gpr(t0, rs);
18891 /* link */
18892 if (rt != 0) {
18893 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
18896 /* calculate btarget */
18897 tcg_gen_shli_tl(t0, t0, 1);
18898 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
18899 gen_op_addr_add(ctx, btarget, t1, t0);
18901 /* unconditional branch to register */
18902 tcg_gen_mov_tl(cpu_PC, btarget);
18903 tcg_gen_lookup_and_goto_ptr();
18905 tcg_temp_free(t0);
18906 tcg_temp_free(t1);
18909 /* nanoMIPS Branches */
18910 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
18911 int rs, int rt, int32_t offset)
18913 int bcond_compute = 0;
18914 TCGv t0 = tcg_temp_new();
18915 TCGv t1 = tcg_temp_new();
18917 /* Load needed operands and calculate btarget */
18918 switch (opc) {
18919 /* compact branch */
18920 case OPC_BGEC:
18921 case OPC_BLTC:
18922 gen_load_gpr(t0, rs);
18923 gen_load_gpr(t1, rt);
18924 bcond_compute = 1;
18925 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18926 break;
18927 case OPC_BGEUC:
18928 case OPC_BLTUC:
18929 if (rs == 0 || rs == rt) {
18930 /* OPC_BLEZALC, OPC_BGEZALC */
18931 /* OPC_BGTZALC, OPC_BLTZALC */
18932 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
18934 gen_load_gpr(t0, rs);
18935 gen_load_gpr(t1, rt);
18936 bcond_compute = 1;
18937 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18938 break;
18939 case OPC_BC:
18940 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18941 break;
18942 case OPC_BEQZC:
18943 if (rs != 0) {
18944 /* OPC_BEQZC, OPC_BNEZC */
18945 gen_load_gpr(t0, rs);
18946 bcond_compute = 1;
18947 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
18948 } else {
18949 /* OPC_JIC, OPC_JIALC */
18950 TCGv tbase = tcg_temp_new();
18951 TCGv toffset = tcg_temp_new();
18953 gen_load_gpr(tbase, rt);
18954 tcg_gen_movi_tl(toffset, offset);
18955 gen_op_addr_add(ctx, btarget, tbase, toffset);
18956 tcg_temp_free(tbase);
18957 tcg_temp_free(toffset);
18959 break;
18960 default:
18961 MIPS_INVAL("Compact branch/jump");
18962 generate_exception_end(ctx, EXCP_RI);
18963 goto out;
18966 if (bcond_compute == 0) {
18967 /* Uncoditional compact branch */
18968 switch (opc) {
18969 case OPC_BC:
18970 gen_goto_tb(ctx, 0, ctx->btarget);
18971 break;
18972 default:
18973 MIPS_INVAL("Compact branch/jump");
18974 generate_exception_end(ctx, EXCP_RI);
18975 goto out;
18977 } else {
18978 /* Conditional compact branch */
18979 TCGLabel *fs = gen_new_label();
18981 switch (opc) {
18982 case OPC_BGEUC:
18983 if (rs == 0 && rt != 0) {
18984 /* OPC_BLEZALC */
18985 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
18986 } else if (rs != 0 && rt != 0 && rs == rt) {
18987 /* OPC_BGEZALC */
18988 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
18989 } else {
18990 /* OPC_BGEUC */
18991 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
18993 break;
18994 case OPC_BLTUC:
18995 if (rs == 0 && rt != 0) {
18996 /* OPC_BGTZALC */
18997 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
18998 } else if (rs != 0 && rt != 0 && rs == rt) {
18999 /* OPC_BLTZALC */
19000 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19001 } else {
19002 /* OPC_BLTUC */
19003 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19005 break;
19006 case OPC_BGEC:
19007 if (rs == 0 && rt != 0) {
19008 /* OPC_BLEZC */
19009 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19010 } else if (rs != 0 && rt != 0 && rs == rt) {
19011 /* OPC_BGEZC */
19012 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19013 } else {
19014 /* OPC_BGEC */
19015 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19017 break;
19018 case OPC_BLTC:
19019 if (rs == 0 && rt != 0) {
19020 /* OPC_BGTZC */
19021 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19022 } else if (rs != 0 && rt != 0 && rs == rt) {
19023 /* OPC_BLTZC */
19024 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19025 } else {
19026 /* OPC_BLTC */
19027 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19029 break;
19030 case OPC_BEQZC:
19031 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19032 break;
19033 default:
19034 MIPS_INVAL("Compact conditional branch/jump");
19035 generate_exception_end(ctx, EXCP_RI);
19036 goto out;
19039 /* Generating branch here as compact branches don't have delay slot */
19040 gen_goto_tb(ctx, 1, ctx->btarget);
19041 gen_set_label(fs);
19043 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19046 out:
19047 tcg_temp_free(t0);
19048 tcg_temp_free(t1);
19052 /* nanoMIPS CP1 Branches */
19053 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19054 int32_t ft, int32_t offset)
19056 target_ulong btarget;
19057 TCGv_i64 t0 = tcg_temp_new_i64();
19059 gen_load_fpr64(ctx, t0, ft);
19060 tcg_gen_andi_i64(t0, t0, 1);
19062 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19064 switch (op) {
19065 case NM_BC1EQZC:
19066 tcg_gen_xori_i64(t0, t0, 1);
19067 ctx->hflags |= MIPS_HFLAG_BC;
19068 break;
19069 case NM_BC1NEZC:
19070 /* t0 already set */
19071 ctx->hflags |= MIPS_HFLAG_BC;
19072 break;
19073 default:
19074 MIPS_INVAL("cp1 cond branch");
19075 generate_exception_end(ctx, EXCP_RI);
19076 goto out;
19079 tcg_gen_trunc_i64_tl(bcond, t0);
19081 ctx->btarget = btarget;
19083 out:
19084 tcg_temp_free_i64(t0);
19088 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19090 TCGv t0, t1;
19091 t0 = tcg_temp_new();
19092 t1 = tcg_temp_new();
19094 gen_load_gpr(t0, rs);
19095 gen_load_gpr(t1, rt);
19097 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19098 /* PP.LSXS instructions require shifting */
19099 switch (extract32(ctx->opcode, 7, 4)) {
19100 case NM_SHXS:
19101 check_nms(ctx);
19102 case NM_LHXS:
19103 case NM_LHUXS:
19104 tcg_gen_shli_tl(t0, t0, 1);
19105 break;
19106 case NM_SWXS:
19107 check_nms(ctx);
19108 case NM_LWXS:
19109 case NM_LWC1XS:
19110 case NM_SWC1XS:
19111 tcg_gen_shli_tl(t0, t0, 2);
19112 break;
19113 case NM_LDC1XS:
19114 case NM_SDC1XS:
19115 tcg_gen_shli_tl(t0, t0, 3);
19116 break;
19119 gen_op_addr_add(ctx, t0, t0, t1);
19121 switch (extract32(ctx->opcode, 7, 4)) {
19122 case NM_LBX:
19123 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19124 MO_SB);
19125 gen_store_gpr(t0, rd);
19126 break;
19127 case NM_LHX:
19128 /*case NM_LHXS:*/
19129 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19130 MO_TESW);
19131 gen_store_gpr(t0, rd);
19132 break;
19133 case NM_LWX:
19134 /*case NM_LWXS:*/
19135 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19136 MO_TESL);
19137 gen_store_gpr(t0, rd);
19138 break;
19139 case NM_LBUX:
19140 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19141 MO_UB);
19142 gen_store_gpr(t0, rd);
19143 break;
19144 case NM_LHUX:
19145 /*case NM_LHUXS:*/
19146 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19147 MO_TEUW);
19148 gen_store_gpr(t0, rd);
19149 break;
19150 case NM_SBX:
19151 check_nms(ctx);
19152 gen_load_gpr(t1, rd);
19153 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19154 MO_8);
19155 break;
19156 case NM_SHX:
19157 /*case NM_SHXS:*/
19158 check_nms(ctx);
19159 gen_load_gpr(t1, rd);
19160 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19161 MO_TEUW);
19162 break;
19163 case NM_SWX:
19164 /*case NM_SWXS:*/
19165 check_nms(ctx);
19166 gen_load_gpr(t1, rd);
19167 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19168 MO_TEUL);
19169 break;
19170 case NM_LWC1X:
19171 /*case NM_LWC1XS:*/
19172 case NM_LDC1X:
19173 /*case NM_LDC1XS:*/
19174 case NM_SWC1X:
19175 /*case NM_SWC1XS:*/
19176 case NM_SDC1X:
19177 /*case NM_SDC1XS:*/
19178 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19179 check_cp1_enabled(ctx);
19180 switch (extract32(ctx->opcode, 7, 4)) {
19181 case NM_LWC1X:
19182 /*case NM_LWC1XS:*/
19183 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19184 break;
19185 case NM_LDC1X:
19186 /*case NM_LDC1XS:*/
19187 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19188 break;
19189 case NM_SWC1X:
19190 /*case NM_SWC1XS:*/
19191 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19192 break;
19193 case NM_SDC1X:
19194 /*case NM_SDC1XS:*/
19195 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19196 break;
19198 } else {
19199 generate_exception_err(ctx, EXCP_CpU, 1);
19201 break;
19202 default:
19203 generate_exception_end(ctx, EXCP_RI);
19204 break;
19207 tcg_temp_free(t0);
19208 tcg_temp_free(t1);
19211 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19213 int rt, rs, rd;
19215 rt = extract32(ctx->opcode, 21, 5);
19216 rs = extract32(ctx->opcode, 16, 5);
19217 rd = extract32(ctx->opcode, 11, 5);
19219 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19220 generate_exception_end(ctx, EXCP_RI);
19221 return;
19223 check_cp1_enabled(ctx);
19224 switch (extract32(ctx->opcode, 0, 3)) {
19225 case NM_POOL32F_0:
19226 switch (extract32(ctx->opcode, 3, 7)) {
19227 case NM_RINT_S:
19228 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19229 break;
19230 case NM_RINT_D:
19231 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19232 break;
19233 case NM_CLASS_S:
19234 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19235 break;
19236 case NM_CLASS_D:
19237 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19238 break;
19239 case NM_ADD_S:
19240 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19241 break;
19242 case NM_ADD_D:
19243 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19244 break;
19245 case NM_SUB_S:
19246 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19247 break;
19248 case NM_SUB_D:
19249 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19250 break;
19251 case NM_MUL_S:
19252 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19253 break;
19254 case NM_MUL_D:
19255 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19256 break;
19257 case NM_DIV_S:
19258 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19259 break;
19260 case NM_DIV_D:
19261 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19262 break;
19263 case NM_SELEQZ_S:
19264 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19265 break;
19266 case NM_SELEQZ_D:
19267 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19268 break;
19269 case NM_SELNEZ_S:
19270 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19271 break;
19272 case NM_SELNEZ_D:
19273 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19274 break;
19275 case NM_SEL_S:
19276 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19277 break;
19278 case NM_SEL_D:
19279 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19280 break;
19281 case NM_MADDF_S:
19282 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19283 break;
19284 case NM_MADDF_D:
19285 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19286 break;
19287 case NM_MSUBF_S:
19288 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19289 break;
19290 case NM_MSUBF_D:
19291 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19292 break;
19293 default:
19294 generate_exception_end(ctx, EXCP_RI);
19295 break;
19297 break;
19298 case NM_POOL32F_3:
19299 switch (extract32(ctx->opcode, 3, 3)) {
19300 case NM_MIN_FMT:
19301 switch (extract32(ctx->opcode, 9, 1)) {
19302 case FMT_SDPS_S:
19303 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19304 break;
19305 case FMT_SDPS_D:
19306 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19307 break;
19309 break;
19310 case NM_MAX_FMT:
19311 switch (extract32(ctx->opcode, 9, 1)) {
19312 case FMT_SDPS_S:
19313 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19314 break;
19315 case FMT_SDPS_D:
19316 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19317 break;
19319 break;
19320 case NM_MINA_FMT:
19321 switch (extract32(ctx->opcode, 9, 1)) {
19322 case FMT_SDPS_S:
19323 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19324 break;
19325 case FMT_SDPS_D:
19326 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19327 break;
19329 break;
19330 case NM_MAXA_FMT:
19331 switch (extract32(ctx->opcode, 9, 1)) {
19332 case FMT_SDPS_S:
19333 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19334 break;
19335 case FMT_SDPS_D:
19336 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19337 break;
19339 break;
19340 case NM_POOL32FXF:
19341 switch (extract32(ctx->opcode, 6, 8)) {
19342 case NM_CFC1:
19343 gen_cp1(ctx, OPC_CFC1, rt, rs);
19344 break;
19345 case NM_CTC1:
19346 gen_cp1(ctx, OPC_CTC1, rt, rs);
19347 break;
19348 case NM_MFC1:
19349 gen_cp1(ctx, OPC_MFC1, rt, rs);
19350 break;
19351 case NM_MTC1:
19352 gen_cp1(ctx, OPC_MTC1, rt, rs);
19353 break;
19354 case NM_MFHC1:
19355 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19356 break;
19357 case NM_MTHC1:
19358 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19359 break;
19360 case NM_CVT_S_PL:
19361 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19362 break;
19363 case NM_CVT_S_PU:
19364 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19365 break;
19366 default:
19367 switch (extract32(ctx->opcode, 6, 9)) {
19368 case NM_CVT_L_S:
19369 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19370 break;
19371 case NM_CVT_L_D:
19372 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19373 break;
19374 case NM_CVT_W_S:
19375 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19376 break;
19377 case NM_CVT_W_D:
19378 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19379 break;
19380 case NM_RSQRT_S:
19381 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19382 break;
19383 case NM_RSQRT_D:
19384 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19385 break;
19386 case NM_SQRT_S:
19387 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19388 break;
19389 case NM_SQRT_D:
19390 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19391 break;
19392 case NM_RECIP_S:
19393 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19394 break;
19395 case NM_RECIP_D:
19396 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19397 break;
19398 case NM_FLOOR_L_S:
19399 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19400 break;
19401 case NM_FLOOR_L_D:
19402 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19403 break;
19404 case NM_FLOOR_W_S:
19405 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19406 break;
19407 case NM_FLOOR_W_D:
19408 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19409 break;
19410 case NM_CEIL_L_S:
19411 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19412 break;
19413 case NM_CEIL_L_D:
19414 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19415 break;
19416 case NM_CEIL_W_S:
19417 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19418 break;
19419 case NM_CEIL_W_D:
19420 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19421 break;
19422 case NM_TRUNC_L_S:
19423 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19424 break;
19425 case NM_TRUNC_L_D:
19426 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19427 break;
19428 case NM_TRUNC_W_S:
19429 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19430 break;
19431 case NM_TRUNC_W_D:
19432 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19433 break;
19434 case NM_ROUND_L_S:
19435 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19436 break;
19437 case NM_ROUND_L_D:
19438 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19439 break;
19440 case NM_ROUND_W_S:
19441 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19442 break;
19443 case NM_ROUND_W_D:
19444 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19445 break;
19446 case NM_MOV_S:
19447 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19448 break;
19449 case NM_MOV_D:
19450 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19451 break;
19452 case NM_ABS_S:
19453 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19454 break;
19455 case NM_ABS_D:
19456 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19457 break;
19458 case NM_NEG_S:
19459 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19460 break;
19461 case NM_NEG_D:
19462 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19463 break;
19464 case NM_CVT_D_S:
19465 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19466 break;
19467 case NM_CVT_D_W:
19468 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19469 break;
19470 case NM_CVT_D_L:
19471 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19472 break;
19473 case NM_CVT_S_D:
19474 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19475 break;
19476 case NM_CVT_S_W:
19477 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19478 break;
19479 case NM_CVT_S_L:
19480 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19481 break;
19482 default:
19483 generate_exception_end(ctx, EXCP_RI);
19484 break;
19486 break;
19488 break;
19490 break;
19491 case NM_POOL32F_5:
19492 switch (extract32(ctx->opcode, 3, 3)) {
19493 case NM_CMP_CONDN_S:
19494 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19495 break;
19496 case NM_CMP_CONDN_D:
19497 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19498 break;
19499 default:
19500 generate_exception_end(ctx, EXCP_RI);
19501 break;
19503 break;
19504 default:
19505 generate_exception_end(ctx, EXCP_RI);
19506 break;
19510 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19511 int rd, int rs, int rt)
19513 int ret = rd;
19514 TCGv t0 = tcg_temp_new();
19515 TCGv v1_t = tcg_temp_new();
19516 TCGv v2_t = tcg_temp_new();
19518 gen_load_gpr(v1_t, rs);
19519 gen_load_gpr(v2_t, rt);
19521 switch (opc) {
19522 case NM_CMP_EQ_PH:
19523 check_dsp(ctx);
19524 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19525 break;
19526 case NM_CMP_LT_PH:
19527 check_dsp(ctx);
19528 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19529 break;
19530 case NM_CMP_LE_PH:
19531 check_dsp(ctx);
19532 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19533 break;
19534 case NM_CMPU_EQ_QB:
19535 check_dsp(ctx);
19536 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19537 break;
19538 case NM_CMPU_LT_QB:
19539 check_dsp(ctx);
19540 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19541 break;
19542 case NM_CMPU_LE_QB:
19543 check_dsp(ctx);
19544 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19545 break;
19546 case NM_CMPGU_EQ_QB:
19547 check_dsp(ctx);
19548 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19549 gen_store_gpr(v1_t, ret);
19550 break;
19551 case NM_CMPGU_LT_QB:
19552 check_dsp(ctx);
19553 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19554 gen_store_gpr(v1_t, ret);
19555 break;
19556 case NM_CMPGU_LE_QB:
19557 check_dsp(ctx);
19558 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19559 gen_store_gpr(v1_t, ret);
19560 break;
19561 case NM_CMPGDU_EQ_QB:
19562 check_dsp_r2(ctx);
19563 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19564 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19565 gen_store_gpr(v1_t, ret);
19566 break;
19567 case NM_CMPGDU_LT_QB:
19568 check_dsp_r2(ctx);
19569 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19570 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19571 gen_store_gpr(v1_t, ret);
19572 break;
19573 case NM_CMPGDU_LE_QB:
19574 check_dsp_r2(ctx);
19575 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19576 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19577 gen_store_gpr(v1_t, ret);
19578 break;
19579 case NM_PACKRL_PH:
19580 check_dsp(ctx);
19581 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19582 gen_store_gpr(v1_t, ret);
19583 break;
19584 case NM_PICK_QB:
19585 check_dsp(ctx);
19586 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19587 gen_store_gpr(v1_t, ret);
19588 break;
19589 case NM_PICK_PH:
19590 check_dsp(ctx);
19591 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19592 gen_store_gpr(v1_t, ret);
19593 break;
19594 case NM_ADDQ_S_W:
19595 check_dsp(ctx);
19596 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19597 gen_store_gpr(v1_t, ret);
19598 break;
19599 case NM_SUBQ_S_W:
19600 check_dsp(ctx);
19601 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19602 gen_store_gpr(v1_t, ret);
19603 break;
19604 case NM_ADDSC:
19605 check_dsp(ctx);
19606 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19607 gen_store_gpr(v1_t, ret);
19608 break;
19609 case NM_ADDWC:
19610 check_dsp(ctx);
19611 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19612 gen_store_gpr(v1_t, ret);
19613 break;
19614 case NM_ADDQ_S_PH:
19615 check_dsp(ctx);
19616 switch (extract32(ctx->opcode, 10, 1)) {
19617 case 0:
19618 /* ADDQ_PH */
19619 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19620 gen_store_gpr(v1_t, ret);
19621 break;
19622 case 1:
19623 /* ADDQ_S_PH */
19624 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19625 gen_store_gpr(v1_t, ret);
19626 break;
19628 break;
19629 case NM_ADDQH_R_PH:
19630 check_dsp_r2(ctx);
19631 switch (extract32(ctx->opcode, 10, 1)) {
19632 case 0:
19633 /* ADDQH_PH */
19634 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19635 gen_store_gpr(v1_t, ret);
19636 break;
19637 case 1:
19638 /* ADDQH_R_PH */
19639 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19640 gen_store_gpr(v1_t, ret);
19641 break;
19643 break;
19644 case NM_ADDQH_R_W:
19645 check_dsp_r2(ctx);
19646 switch (extract32(ctx->opcode, 10, 1)) {
19647 case 0:
19648 /* ADDQH_W */
19649 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19650 gen_store_gpr(v1_t, ret);
19651 break;
19652 case 1:
19653 /* ADDQH_R_W */
19654 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19655 gen_store_gpr(v1_t, ret);
19656 break;
19658 break;
19659 case NM_ADDU_S_QB:
19660 check_dsp(ctx);
19661 switch (extract32(ctx->opcode, 10, 1)) {
19662 case 0:
19663 /* ADDU_QB */
19664 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19665 gen_store_gpr(v1_t, ret);
19666 break;
19667 case 1:
19668 /* ADDU_S_QB */
19669 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19670 gen_store_gpr(v1_t, ret);
19671 break;
19673 break;
19674 case NM_ADDU_S_PH:
19675 check_dsp_r2(ctx);
19676 switch (extract32(ctx->opcode, 10, 1)) {
19677 case 0:
19678 /* ADDU_PH */
19679 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19680 gen_store_gpr(v1_t, ret);
19681 break;
19682 case 1:
19683 /* ADDU_S_PH */
19684 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19685 gen_store_gpr(v1_t, ret);
19686 break;
19688 break;
19689 case NM_ADDUH_R_QB:
19690 check_dsp_r2(ctx);
19691 switch (extract32(ctx->opcode, 10, 1)) {
19692 case 0:
19693 /* ADDUH_QB */
19694 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19695 gen_store_gpr(v1_t, ret);
19696 break;
19697 case 1:
19698 /* ADDUH_R_QB */
19699 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19700 gen_store_gpr(v1_t, ret);
19701 break;
19703 break;
19704 case NM_SHRAV_R_PH:
19705 check_dsp(ctx);
19706 switch (extract32(ctx->opcode, 10, 1)) {
19707 case 0:
19708 /* SHRAV_PH */
19709 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19710 gen_store_gpr(v1_t, ret);
19711 break;
19712 case 1:
19713 /* SHRAV_R_PH */
19714 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19715 gen_store_gpr(v1_t, ret);
19716 break;
19718 break;
19719 case NM_SHRAV_R_QB:
19720 check_dsp_r2(ctx);
19721 switch (extract32(ctx->opcode, 10, 1)) {
19722 case 0:
19723 /* SHRAV_QB */
19724 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19725 gen_store_gpr(v1_t, ret);
19726 break;
19727 case 1:
19728 /* SHRAV_R_QB */
19729 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19730 gen_store_gpr(v1_t, ret);
19731 break;
19733 break;
19734 case NM_SUBQ_S_PH:
19735 check_dsp(ctx);
19736 switch (extract32(ctx->opcode, 10, 1)) {
19737 case 0:
19738 /* SUBQ_PH */
19739 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19740 gen_store_gpr(v1_t, ret);
19741 break;
19742 case 1:
19743 /* SUBQ_S_PH */
19744 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19745 gen_store_gpr(v1_t, ret);
19746 break;
19748 break;
19749 case NM_SUBQH_R_PH:
19750 check_dsp_r2(ctx);
19751 switch (extract32(ctx->opcode, 10, 1)) {
19752 case 0:
19753 /* SUBQH_PH */
19754 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19755 gen_store_gpr(v1_t, ret);
19756 break;
19757 case 1:
19758 /* SUBQH_R_PH */
19759 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19760 gen_store_gpr(v1_t, ret);
19761 break;
19763 break;
19764 case NM_SUBQH_R_W:
19765 check_dsp_r2(ctx);
19766 switch (extract32(ctx->opcode, 10, 1)) {
19767 case 0:
19768 /* SUBQH_W */
19769 gen_helper_subqh_w(v1_t, v1_t, v2_t);
19770 gen_store_gpr(v1_t, ret);
19771 break;
19772 case 1:
19773 /* SUBQH_R_W */
19774 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
19775 gen_store_gpr(v1_t, ret);
19776 break;
19778 break;
19779 case NM_SUBU_S_QB:
19780 check_dsp(ctx);
19781 switch (extract32(ctx->opcode, 10, 1)) {
19782 case 0:
19783 /* SUBU_QB */
19784 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
19785 gen_store_gpr(v1_t, ret);
19786 break;
19787 case 1:
19788 /* SUBU_S_QB */
19789 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19790 gen_store_gpr(v1_t, ret);
19791 break;
19793 break;
19794 case NM_SUBU_S_PH:
19795 check_dsp_r2(ctx);
19796 switch (extract32(ctx->opcode, 10, 1)) {
19797 case 0:
19798 /* SUBU_PH */
19799 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
19800 gen_store_gpr(v1_t, ret);
19801 break;
19802 case 1:
19803 /* SUBU_S_PH */
19804 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19805 gen_store_gpr(v1_t, ret);
19806 break;
19808 break;
19809 case NM_SUBUH_R_QB:
19810 check_dsp_r2(ctx);
19811 switch (extract32(ctx->opcode, 10, 1)) {
19812 case 0:
19813 /* SUBUH_QB */
19814 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
19815 gen_store_gpr(v1_t, ret);
19816 break;
19817 case 1:
19818 /* SUBUH_R_QB */
19819 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
19820 gen_store_gpr(v1_t, ret);
19821 break;
19823 break;
19824 case NM_SHLLV_S_PH:
19825 check_dsp(ctx);
19826 switch (extract32(ctx->opcode, 10, 1)) {
19827 case 0:
19828 /* SHLLV_PH */
19829 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
19830 gen_store_gpr(v1_t, ret);
19831 break;
19832 case 1:
19833 /* SHLLV_S_PH */
19834 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
19835 gen_store_gpr(v1_t, ret);
19836 break;
19838 break;
19839 case NM_PRECR_SRA_R_PH_W:
19840 check_dsp_r2(ctx);
19841 switch (extract32(ctx->opcode, 10, 1)) {
19842 case 0:
19843 /* PRECR_SRA_PH_W */
19845 TCGv_i32 sa_t = tcg_const_i32(rd);
19846 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
19847 cpu_gpr[rt]);
19848 gen_store_gpr(v1_t, rt);
19849 tcg_temp_free_i32(sa_t);
19851 break;
19852 case 1:
19853 /* PRECR_SRA_R_PH_W */
19855 TCGv_i32 sa_t = tcg_const_i32(rd);
19856 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
19857 cpu_gpr[rt]);
19858 gen_store_gpr(v1_t, rt);
19859 tcg_temp_free_i32(sa_t);
19861 break;
19863 break;
19864 case NM_MULEU_S_PH_QBL:
19865 check_dsp(ctx);
19866 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
19867 gen_store_gpr(v1_t, ret);
19868 break;
19869 case NM_MULEU_S_PH_QBR:
19870 check_dsp(ctx);
19871 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
19872 gen_store_gpr(v1_t, ret);
19873 break;
19874 case NM_MULQ_RS_PH:
19875 check_dsp(ctx);
19876 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
19877 gen_store_gpr(v1_t, ret);
19878 break;
19879 case NM_MULQ_S_PH:
19880 check_dsp_r2(ctx);
19881 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19882 gen_store_gpr(v1_t, ret);
19883 break;
19884 case NM_MULQ_RS_W:
19885 check_dsp_r2(ctx);
19886 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
19887 gen_store_gpr(v1_t, ret);
19888 break;
19889 case NM_MULQ_S_W:
19890 check_dsp_r2(ctx);
19891 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
19892 gen_store_gpr(v1_t, ret);
19893 break;
19894 case NM_APPEND:
19895 check_dsp_r2(ctx);
19896 gen_load_gpr(t0, rs);
19897 if (rd != 0) {
19898 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
19900 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
19901 break;
19902 case NM_MODSUB:
19903 check_dsp(ctx);
19904 gen_helper_modsub(v1_t, v1_t, v2_t);
19905 gen_store_gpr(v1_t, ret);
19906 break;
19907 case NM_SHRAV_R_W:
19908 check_dsp(ctx);
19909 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
19910 gen_store_gpr(v1_t, ret);
19911 break;
19912 case NM_SHRLV_PH:
19913 check_dsp_r2(ctx);
19914 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
19915 gen_store_gpr(v1_t, ret);
19916 break;
19917 case NM_SHRLV_QB:
19918 check_dsp(ctx);
19919 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
19920 gen_store_gpr(v1_t, ret);
19921 break;
19922 case NM_SHLLV_QB:
19923 check_dsp(ctx);
19924 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
19925 gen_store_gpr(v1_t, ret);
19926 break;
19927 case NM_SHLLV_S_W:
19928 check_dsp(ctx);
19929 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
19930 gen_store_gpr(v1_t, ret);
19931 break;
19932 case NM_SHILO:
19933 check_dsp(ctx);
19935 TCGv tv0 = tcg_temp_new();
19936 TCGv tv1 = tcg_temp_new();
19937 int16_t imm = extract32(ctx->opcode, 16, 7);
19939 tcg_gen_movi_tl(tv0, rd >> 3);
19940 tcg_gen_movi_tl(tv1, imm);
19941 gen_helper_shilo(tv0, tv1, cpu_env);
19943 break;
19944 case NM_MULEQ_S_W_PHL:
19945 check_dsp(ctx);
19946 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
19947 gen_store_gpr(v1_t, ret);
19948 break;
19949 case NM_MULEQ_S_W_PHR:
19950 check_dsp(ctx);
19951 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
19952 gen_store_gpr(v1_t, ret);
19953 break;
19954 case NM_MUL_S_PH:
19955 check_dsp_r2(ctx);
19956 switch (extract32(ctx->opcode, 10, 1)) {
19957 case 0:
19958 /* MUL_PH */
19959 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
19960 gen_store_gpr(v1_t, ret);
19961 break;
19962 case 1:
19963 /* MUL_S_PH */
19964 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
19965 gen_store_gpr(v1_t, ret);
19966 break;
19968 break;
19969 case NM_PRECR_QB_PH:
19970 check_dsp_r2(ctx);
19971 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
19972 gen_store_gpr(v1_t, ret);
19973 break;
19974 case NM_PRECRQ_QB_PH:
19975 check_dsp(ctx);
19976 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
19977 gen_store_gpr(v1_t, ret);
19978 break;
19979 case NM_PRECRQ_PH_W:
19980 check_dsp(ctx);
19981 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
19982 gen_store_gpr(v1_t, ret);
19983 break;
19984 case NM_PRECRQ_RS_PH_W:
19985 check_dsp(ctx);
19986 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
19987 gen_store_gpr(v1_t, ret);
19988 break;
19989 case NM_PRECRQU_S_QB_PH:
19990 check_dsp(ctx);
19991 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
19992 gen_store_gpr(v1_t, ret);
19993 break;
19994 case NM_SHRA_R_W:
19995 check_dsp(ctx);
19996 tcg_gen_movi_tl(t0, rd);
19997 gen_helper_shra_r_w(v1_t, t0, v1_t);
19998 gen_store_gpr(v1_t, rt);
19999 break;
20000 case NM_SHRA_R_PH:
20001 check_dsp(ctx);
20002 tcg_gen_movi_tl(t0, rd >> 1);
20003 switch (extract32(ctx->opcode, 10, 1)) {
20004 case 0:
20005 /* SHRA_PH */
20006 gen_helper_shra_ph(v1_t, t0, v1_t);
20007 gen_store_gpr(v1_t, rt);
20008 break;
20009 case 1:
20010 /* SHRA_R_PH */
20011 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20012 gen_store_gpr(v1_t, rt);
20013 break;
20015 break;
20016 case NM_SHLL_S_PH:
20017 check_dsp(ctx);
20018 tcg_gen_movi_tl(t0, rd >> 1);
20019 switch (extract32(ctx->opcode, 10, 2)) {
20020 case 0:
20021 /* SHLL_PH */
20022 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20023 gen_store_gpr(v1_t, rt);
20024 break;
20025 case 2:
20026 /* SHLL_S_PH */
20027 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20028 gen_store_gpr(v1_t, rt);
20029 break;
20030 default:
20031 generate_exception_end(ctx, EXCP_RI);
20032 break;
20034 break;
20035 case NM_SHLL_S_W:
20036 check_dsp(ctx);
20037 tcg_gen_movi_tl(t0, rd);
20038 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20039 gen_store_gpr(v1_t, rt);
20040 break;
20041 case NM_REPL_PH:
20042 check_dsp(ctx);
20044 int16_t imm;
20045 imm = sextract32(ctx->opcode, 11, 11);
20046 imm = (int16_t)(imm << 6) >> 6;
20047 if (rt != 0) {
20048 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20051 break;
20052 default:
20053 generate_exception_end(ctx, EXCP_RI);
20054 break;
20058 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20060 uint16_t insn;
20061 uint32_t op;
20062 int rt, rs, rd;
20063 int offset;
20064 int imm;
20066 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20067 ctx->opcode = (ctx->opcode << 16) | insn;
20069 rt = extract32(ctx->opcode, 21, 5);
20070 rs = extract32(ctx->opcode, 16, 5);
20071 rd = extract32(ctx->opcode, 11, 5);
20073 op = extract32(ctx->opcode, 26, 6);
20074 switch (op) {
20075 case NM_P_ADDIU:
20076 if (rt == 0) {
20077 /* P.RI */
20078 switch (extract32(ctx->opcode, 19, 2)) {
20079 case NM_SIGRIE:
20080 default:
20081 generate_exception_end(ctx, EXCP_RI);
20082 break;
20083 case NM_P_SYSCALL:
20084 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20085 generate_exception_end(ctx, EXCP_SYSCALL);
20086 } else {
20087 generate_exception_end(ctx, EXCP_RI);
20089 break;
20090 case NM_BREAK:
20091 generate_exception_end(ctx, EXCP_BREAK);
20092 break;
20093 case NM_SDBBP:
20094 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20095 gen_helper_do_semihosting(cpu_env);
20096 } else {
20097 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20098 generate_exception_end(ctx, EXCP_RI);
20099 } else {
20100 generate_exception_end(ctx, EXCP_DBp);
20103 break;
20105 } else {
20106 /* NM_ADDIU */
20107 imm = extract32(ctx->opcode, 0, 16);
20108 if (rs != 0) {
20109 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20110 } else {
20111 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20113 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20115 break;
20116 case NM_ADDIUPC:
20117 if (rt != 0) {
20118 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20119 extract32(ctx->opcode, 1, 20) << 1;
20120 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20121 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20123 break;
20124 case NM_POOL32A:
20125 switch (ctx->opcode & 0x07) {
20126 case NM_POOL32A0:
20127 gen_pool32a0_nanomips_insn(env, ctx);
20128 break;
20129 case NM_POOL32A5:
20131 int32_t op1 = extract32(ctx->opcode, 3, 7);
20132 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20134 break;
20135 case NM_POOL32A7:
20136 switch (extract32(ctx->opcode, 3, 3)) {
20137 case NM_P_LSX:
20138 gen_p_lsx(ctx, rd, rs, rt);
20139 break;
20140 case NM_LSA:
20141 /* In nanoMIPS, the shift field directly encodes the shift
20142 * amount, meaning that the supported shift values are in
20143 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20144 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20145 extract32(ctx->opcode, 9, 2) - 1);
20146 break;
20147 case NM_EXTW:
20148 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20149 break;
20150 case NM_POOL32AXF:
20151 gen_pool32axf_nanomips_insn(env, ctx);
20152 break;
20153 default:
20154 generate_exception_end(ctx, EXCP_RI);
20155 break;
20157 break;
20158 default:
20159 generate_exception_end(ctx, EXCP_RI);
20160 break;
20162 break;
20163 case NM_P_GP_W:
20164 switch (ctx->opcode & 0x03) {
20165 case NM_ADDIUGP_W:
20166 if (rt != 0) {
20167 offset = extract32(ctx->opcode, 0, 21);
20168 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20170 break;
20171 case NM_LWGP:
20172 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20173 break;
20174 case NM_SWGP:
20175 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20176 break;
20177 default:
20178 generate_exception_end(ctx, EXCP_RI);
20179 break;
20181 break;
20182 case NM_P48I:
20184 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20185 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20186 switch (extract32(ctx->opcode, 16, 5)) {
20187 case NM_LI48:
20188 check_nms(ctx);
20189 if (rt != 0) {
20190 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20192 break;
20193 case NM_ADDIU48:
20194 check_nms(ctx);
20195 if (rt != 0) {
20196 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20197 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20199 break;
20200 case NM_ADDIUGP48:
20201 check_nms(ctx);
20202 if (rt != 0) {
20203 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20205 break;
20206 case NM_ADDIUPC48:
20207 check_nms(ctx);
20208 if (rt != 0) {
20209 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20210 addr_off);
20212 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20214 break;
20215 case NM_LWPC48:
20216 check_nms(ctx);
20217 if (rt != 0) {
20218 TCGv t0;
20219 t0 = tcg_temp_new();
20221 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20222 addr_off);
20224 tcg_gen_movi_tl(t0, addr);
20225 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20226 tcg_temp_free(t0);
20228 break;
20229 case NM_SWPC48:
20230 check_nms(ctx);
20232 TCGv t0, t1;
20233 t0 = tcg_temp_new();
20234 t1 = tcg_temp_new();
20236 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20237 addr_off);
20239 tcg_gen_movi_tl(t0, addr);
20240 gen_load_gpr(t1, rt);
20242 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20244 tcg_temp_free(t0);
20245 tcg_temp_free(t1);
20247 break;
20248 default:
20249 generate_exception_end(ctx, EXCP_RI);
20250 break;
20252 return 6;
20254 case NM_P_U12:
20255 switch (extract32(ctx->opcode, 12, 4)) {
20256 case NM_ORI:
20257 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20258 break;
20259 case NM_XORI:
20260 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20261 break;
20262 case NM_ANDI:
20263 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20264 break;
20265 case NM_P_SR:
20266 switch (extract32(ctx->opcode, 20, 1)) {
20267 case NM_PP_SR:
20268 switch (ctx->opcode & 3) {
20269 case NM_SAVE:
20270 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20271 extract32(ctx->opcode, 2, 1),
20272 extract32(ctx->opcode, 3, 9) << 3);
20273 break;
20274 case NM_RESTORE:
20275 case NM_RESTORE_JRC:
20276 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20277 extract32(ctx->opcode, 2, 1),
20278 extract32(ctx->opcode, 3, 9) << 3);
20279 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20280 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20282 break;
20283 default:
20284 generate_exception_end(ctx, EXCP_RI);
20285 break;
20287 break;
20288 case NM_P_SR_F:
20289 generate_exception_end(ctx, EXCP_RI);
20290 break;
20292 break;
20293 case NM_SLTI:
20294 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20295 break;
20296 case NM_SLTIU:
20297 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20298 break;
20299 case NM_SEQI:
20301 TCGv t0 = tcg_temp_new();
20303 imm = extract32(ctx->opcode, 0, 12);
20304 gen_load_gpr(t0, rs);
20305 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20306 gen_store_gpr(t0, rt);
20308 tcg_temp_free(t0);
20310 break;
20311 case NM_ADDIUNEG:
20312 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20313 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20314 break;
20315 case NM_P_SHIFT:
20317 int shift = extract32(ctx->opcode, 0, 5);
20318 switch (extract32(ctx->opcode, 5, 4)) {
20319 case NM_P_SLL:
20320 if (rt == 0 && shift == 0) {
20321 /* NOP */
20322 } else if (rt == 0 && shift == 3) {
20323 /* EHB - treat as NOP */
20324 } else if (rt == 0 && shift == 5) {
20325 /* PAUSE - treat as NOP */
20326 } else if (rt == 0 && shift == 6) {
20327 /* SYNC */
20328 gen_sync(extract32(ctx->opcode, 16, 5));
20329 } else {
20330 /* SLL */
20331 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20332 extract32(ctx->opcode, 0, 5));
20334 break;
20335 case NM_SRL:
20336 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20337 extract32(ctx->opcode, 0, 5));
20338 break;
20339 case NM_SRA:
20340 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20341 extract32(ctx->opcode, 0, 5));
20342 break;
20343 case NM_ROTR:
20344 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20345 extract32(ctx->opcode, 0, 5));
20346 break;
20349 break;
20350 case NM_P_ROTX:
20351 check_nms(ctx);
20352 if (rt != 0) {
20353 TCGv t0 = tcg_temp_new();
20354 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20355 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20356 << 1);
20357 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20359 gen_load_gpr(t0, rs);
20360 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20361 tcg_temp_free(t0);
20363 tcg_temp_free_i32(shift);
20364 tcg_temp_free_i32(shiftx);
20365 tcg_temp_free_i32(stripe);
20367 break;
20368 case NM_P_INS:
20369 switch (((ctx->opcode >> 10) & 2) |
20370 (extract32(ctx->opcode, 5, 1))) {
20371 case NM_INS:
20372 check_nms(ctx);
20373 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20374 extract32(ctx->opcode, 6, 5));
20375 break;
20376 default:
20377 generate_exception_end(ctx, EXCP_RI);
20378 break;
20380 break;
20381 case NM_P_EXT:
20382 switch (((ctx->opcode >> 10) & 2) |
20383 (extract32(ctx->opcode, 5, 1))) {
20384 case NM_EXT:
20385 check_nms(ctx);
20386 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20387 extract32(ctx->opcode, 6, 5));
20388 break;
20389 default:
20390 generate_exception_end(ctx, EXCP_RI);
20391 break;
20393 break;
20394 default:
20395 generate_exception_end(ctx, EXCP_RI);
20396 break;
20398 break;
20399 case NM_POOL32F:
20400 gen_pool32f_nanomips_insn(ctx);
20401 break;
20402 case NM_POOL32S:
20403 break;
20404 case NM_P_LUI:
20405 switch (extract32(ctx->opcode, 1, 1)) {
20406 case NM_LUI:
20407 if (rt != 0) {
20408 tcg_gen_movi_tl(cpu_gpr[rt],
20409 sextract32(ctx->opcode, 0, 1) << 31 |
20410 extract32(ctx->opcode, 2, 10) << 21 |
20411 extract32(ctx->opcode, 12, 9) << 12);
20413 break;
20414 case NM_ALUIPC:
20415 if (rt != 0) {
20416 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20417 extract32(ctx->opcode, 2, 10) << 21 |
20418 extract32(ctx->opcode, 12, 9) << 12;
20419 target_long addr;
20420 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20421 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20423 break;
20425 break;
20426 case NM_P_GP_BH:
20428 uint32_t u = extract32(ctx->opcode, 0, 18);
20430 switch (extract32(ctx->opcode, 18, 3)) {
20431 case NM_LBGP:
20432 gen_ld(ctx, OPC_LB, rt, 28, u);
20433 break;
20434 case NM_SBGP:
20435 gen_st(ctx, OPC_SB, rt, 28, u);
20436 break;
20437 case NM_LBUGP:
20438 gen_ld(ctx, OPC_LBU, rt, 28, u);
20439 break;
20440 case NM_ADDIUGP_B:
20441 if (rt != 0) {
20442 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20444 break;
20445 case NM_P_GP_LH:
20446 u &= ~1;
20447 switch (ctx->opcode & 1) {
20448 case NM_LHGP:
20449 gen_ld(ctx, OPC_LH, rt, 28, u);
20450 break;
20451 case NM_LHUGP:
20452 gen_ld(ctx, OPC_LHU, rt, 28, u);
20453 break;
20455 break;
20456 case NM_P_GP_SH:
20457 u &= ~1;
20458 switch (ctx->opcode & 1) {
20459 case NM_SHGP:
20460 gen_st(ctx, OPC_SH, rt, 28, u);
20461 break;
20462 default:
20463 generate_exception_end(ctx, EXCP_RI);
20464 break;
20466 break;
20467 case NM_P_GP_CP1:
20468 u &= ~0x3;
20469 switch (ctx->opcode & 0x3) {
20470 case NM_LWC1GP:
20471 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20472 break;
20473 case NM_LDC1GP:
20474 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20475 break;
20476 case NM_SWC1GP:
20477 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20478 break;
20479 case NM_SDC1GP:
20480 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20481 break;
20483 break;
20484 default:
20485 generate_exception_end(ctx, EXCP_RI);
20486 break;
20489 break;
20490 case NM_P_LS_U12:
20492 uint32_t u = extract32(ctx->opcode, 0, 12);
20494 switch (extract32(ctx->opcode, 12, 4)) {
20495 case NM_P_PREFU12:
20496 if (rt == 31) {
20497 /* SYNCI */
20498 /* Break the TB to be able to sync copied instructions
20499 immediately */
20500 ctx->base.is_jmp = DISAS_STOP;
20501 } else {
20502 /* PREF */
20503 /* Treat as NOP. */
20505 break;
20506 case NM_LB:
20507 gen_ld(ctx, OPC_LB, rt, rs, u);
20508 break;
20509 case NM_LH:
20510 gen_ld(ctx, OPC_LH, rt, rs, u);
20511 break;
20512 case NM_LW:
20513 gen_ld(ctx, OPC_LW, rt, rs, u);
20514 break;
20515 case NM_LBU:
20516 gen_ld(ctx, OPC_LBU, rt, rs, u);
20517 break;
20518 case NM_LHU:
20519 gen_ld(ctx, OPC_LHU, rt, rs, u);
20520 break;
20521 case NM_SB:
20522 gen_st(ctx, OPC_SB, rt, rs, u);
20523 break;
20524 case NM_SH:
20525 gen_st(ctx, OPC_SH, rt, rs, u);
20526 break;
20527 case NM_SW:
20528 gen_st(ctx, OPC_SW, rt, rs, u);
20529 break;
20530 case NM_LWC1:
20531 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20532 break;
20533 case NM_LDC1:
20534 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20535 break;
20536 case NM_SWC1:
20537 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20538 break;
20539 case NM_SDC1:
20540 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20541 break;
20542 default:
20543 generate_exception_end(ctx, EXCP_RI);
20544 break;
20547 break;
20548 case NM_P_LS_S9:
20550 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20551 extract32(ctx->opcode, 0, 8);
20553 switch (extract32(ctx->opcode, 8, 3)) {
20554 case NM_P_LS_S0:
20555 switch (extract32(ctx->opcode, 11, 4)) {
20556 case NM_LBS9:
20557 gen_ld(ctx, OPC_LB, rt, rs, s);
20558 break;
20559 case NM_LHS9:
20560 gen_ld(ctx, OPC_LH, rt, rs, s);
20561 break;
20562 case NM_LWS9:
20563 gen_ld(ctx, OPC_LW, rt, rs, s);
20564 break;
20565 case NM_LBUS9:
20566 gen_ld(ctx, OPC_LBU, rt, rs, s);
20567 break;
20568 case NM_LHUS9:
20569 gen_ld(ctx, OPC_LHU, rt, rs, s);
20570 break;
20571 case NM_SBS9:
20572 gen_st(ctx, OPC_SB, rt, rs, s);
20573 break;
20574 case NM_SHS9:
20575 gen_st(ctx, OPC_SH, rt, rs, s);
20576 break;
20577 case NM_SWS9:
20578 gen_st(ctx, OPC_SW, rt, rs, s);
20579 break;
20580 case NM_LWC1S9:
20581 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20582 break;
20583 case NM_LDC1S9:
20584 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20585 break;
20586 case NM_SWC1S9:
20587 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20588 break;
20589 case NM_SDC1S9:
20590 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20591 break;
20592 case NM_P_PREFS9:
20593 if (rt == 31) {
20594 /* SYNCI */
20595 /* Break the TB to be able to sync copied instructions
20596 immediately */
20597 ctx->base.is_jmp = DISAS_STOP;
20598 } else {
20599 /* PREF */
20600 /* Treat as NOP. */
20602 break;
20603 default:
20604 generate_exception_end(ctx, EXCP_RI);
20605 break;
20607 break;
20608 case NM_P_LS_S1:
20609 switch (extract32(ctx->opcode, 11, 4)) {
20610 case NM_UALH:
20611 case NM_UASH:
20612 check_nms(ctx);
20614 TCGv t0 = tcg_temp_new();
20615 TCGv t1 = tcg_temp_new();
20617 gen_base_offset_addr(ctx, t0, rs, s);
20619 switch (extract32(ctx->opcode, 11, 4)) {
20620 case NM_UALH:
20621 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20622 MO_UNALN);
20623 gen_store_gpr(t0, rt);
20624 break;
20625 case NM_UASH:
20626 gen_load_gpr(t1, rt);
20627 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20628 MO_UNALN);
20629 break;
20631 tcg_temp_free(t0);
20632 tcg_temp_free(t1);
20634 break;
20635 case NM_P_LL:
20636 switch (ctx->opcode & 0x03) {
20637 case NM_LL:
20638 gen_ld(ctx, OPC_LL, rt, rs, s);
20639 break;
20640 case NM_LLWP:
20641 check_xnp(ctx);
20642 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20643 break;
20645 break;
20646 case NM_P_SC:
20647 switch (ctx->opcode & 0x03) {
20648 case NM_SC:
20649 gen_st_cond(ctx, OPC_SC, rt, rs, s);
20650 break;
20651 case NM_SCWP:
20652 check_xnp(ctx);
20653 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20654 break;
20656 break;
20657 case NM_CACHE:
20658 check_cp0_enabled(ctx);
20659 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20660 gen_cache_operation(ctx, rt, rs, s);
20662 break;
20664 break;
20665 case NM_P_LS_WM:
20666 case NM_P_LS_UAWM:
20667 check_nms(ctx);
20669 int count = extract32(ctx->opcode, 12, 3);
20670 int counter = 0;
20672 offset = sextract32(ctx->opcode, 15, 1) << 8 |
20673 extract32(ctx->opcode, 0, 8);
20674 TCGv va = tcg_temp_new();
20675 TCGv t1 = tcg_temp_new();
20676 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
20677 NM_P_LS_UAWM ? MO_UNALN : 0;
20679 count = (count == 0) ? 8 : count;
20680 while (counter != count) {
20681 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
20682 int this_offset = offset + (counter << 2);
20684 gen_base_offset_addr(ctx, va, rs, this_offset);
20686 switch (extract32(ctx->opcode, 11, 1)) {
20687 case NM_LWM:
20688 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
20689 memop | MO_TESL);
20690 gen_store_gpr(t1, this_rt);
20691 if ((this_rt == rs) &&
20692 (counter != (count - 1))) {
20693 /* UNPREDICTABLE */
20695 break;
20696 case NM_SWM:
20697 this_rt = (rt == 0) ? 0 : this_rt;
20698 gen_load_gpr(t1, this_rt);
20699 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
20700 memop | MO_TEUL);
20701 break;
20703 counter++;
20705 tcg_temp_free(va);
20706 tcg_temp_free(t1);
20708 break;
20709 default:
20710 generate_exception_end(ctx, EXCP_RI);
20711 break;
20714 break;
20715 case NM_MOVE_BALC:
20716 check_nms(ctx);
20718 TCGv t0 = tcg_temp_new();
20719 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
20720 extract32(ctx->opcode, 1, 20) << 1;
20721 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
20722 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
20723 extract32(ctx->opcode, 21, 3));
20724 gen_load_gpr(t0, rt);
20725 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20726 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20727 tcg_temp_free(t0);
20729 break;
20730 case NM_P_BAL:
20732 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
20733 extract32(ctx->opcode, 1, 24) << 1;
20735 if ((extract32(ctx->opcode, 25, 1)) == 0) {
20736 /* BC */
20737 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
20738 } else {
20739 /* BALC */
20740 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20743 break;
20744 case NM_P_J:
20745 switch (extract32(ctx->opcode, 12, 4)) {
20746 case NM_JALRC:
20747 case NM_JALRC_HB:
20748 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
20749 break;
20750 case NM_P_BALRSC:
20751 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
20752 break;
20753 default:
20754 generate_exception_end(ctx, EXCP_RI);
20755 break;
20757 break;
20758 case NM_P_BR1:
20760 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20761 extract32(ctx->opcode, 1, 13) << 1;
20762 switch (extract32(ctx->opcode, 14, 2)) {
20763 case NM_BEQC:
20764 check_nms(ctx);
20765 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
20766 break;
20767 case NM_P_BR3A:
20768 s = sextract32(ctx->opcode, 0, 1) << 14 |
20769 extract32(ctx->opcode, 1, 13) << 1;
20770 check_cp1_enabled(ctx);
20771 switch (extract32(ctx->opcode, 16, 5)) {
20772 case NM_BC1EQZC:
20773 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
20774 break;
20775 case NM_BC1NEZC:
20776 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
20777 break;
20778 case NM_BPOSGE32C:
20779 check_dsp_r3(ctx);
20781 int32_t imm = extract32(ctx->opcode, 1, 13) |
20782 extract32(ctx->opcode, 0, 1) << 13;
20784 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
20785 imm);
20787 break;
20788 default:
20789 generate_exception_end(ctx, EXCP_RI);
20790 break;
20792 break;
20793 case NM_BGEC:
20794 if (rs == rt) {
20795 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
20796 } else {
20797 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
20799 break;
20800 case NM_BGEUC:
20801 if (rs == rt || rt == 0) {
20802 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
20803 } else if (rs == 0) {
20804 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
20805 } else {
20806 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
20808 break;
20811 break;
20812 case NM_P_BR2:
20814 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
20815 extract32(ctx->opcode, 1, 13) << 1;
20816 switch (extract32(ctx->opcode, 14, 2)) {
20817 case NM_BNEC:
20818 check_nms(ctx);
20819 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
20820 break;
20821 case NM_BLTC:
20822 if (rs != 0 && rt != 0 && rs == rt) {
20823 /* NOP */
20824 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
20825 } else {
20826 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
20828 break;
20829 case NM_BLTUC:
20830 if (rs == 0 || rs == rt) {
20831 /* NOP */
20832 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
20833 } else {
20834 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
20836 break;
20837 default:
20838 generate_exception_end(ctx, EXCP_RI);
20839 break;
20842 break;
20843 case NM_P_BRI:
20845 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
20846 extract32(ctx->opcode, 1, 10) << 1;
20847 uint32_t u = extract32(ctx->opcode, 11, 7);
20849 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
20850 rt, u, s);
20852 break;
20853 default:
20854 generate_exception_end(ctx, EXCP_RI);
20855 break;
20857 return 4;
20860 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
20862 uint32_t op;
20863 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
20864 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
20865 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
20866 int offset;
20867 int imm;
20869 /* make sure instructions are on a halfword boundary */
20870 if (ctx->base.pc_next & 0x1) {
20871 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
20872 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
20873 tcg_temp_free(tmp);
20874 generate_exception_end(ctx, EXCP_AdEL);
20875 return 2;
20878 op = extract32(ctx->opcode, 10, 6);
20879 switch (op) {
20880 case NM_P16_MV:
20881 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
20882 if (rt != 0) {
20883 /* MOVE */
20884 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
20885 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
20886 } else {
20887 /* P16.RI */
20888 switch (extract32(ctx->opcode, 3, 2)) {
20889 case NM_P16_SYSCALL:
20890 if (extract32(ctx->opcode, 2, 1) == 0) {
20891 generate_exception_end(ctx, EXCP_SYSCALL);
20892 } else {
20893 generate_exception_end(ctx, EXCP_RI);
20895 break;
20896 case NM_BREAK16:
20897 generate_exception_end(ctx, EXCP_BREAK);
20898 break;
20899 case NM_SDBBP16:
20900 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
20901 gen_helper_do_semihosting(cpu_env);
20902 } else {
20903 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20904 generate_exception_end(ctx, EXCP_RI);
20905 } else {
20906 generate_exception_end(ctx, EXCP_DBp);
20909 break;
20910 default:
20911 generate_exception_end(ctx, EXCP_RI);
20912 break;
20915 break;
20916 case NM_P16_SHIFT:
20918 int shift = extract32(ctx->opcode, 0, 3);
20919 uint32_t opc = 0;
20920 shift = (shift == 0) ? 8 : shift;
20922 switch (extract32(ctx->opcode, 3, 1)) {
20923 case NM_SLL16:
20924 opc = OPC_SLL;
20925 break;
20926 case NM_SRL16:
20927 opc = OPC_SRL;
20928 break;
20930 gen_shift_imm(ctx, opc, rt, rs, shift);
20932 break;
20933 case NM_P16C:
20934 switch (ctx->opcode & 1) {
20935 case NM_POOL16C_0:
20936 gen_pool16c_nanomips_insn(ctx);
20937 break;
20938 case NM_LWXS16:
20939 gen_ldxs(ctx, rt, rs, rd);
20940 break;
20942 break;
20943 case NM_P16_A1:
20944 switch (extract32(ctx->opcode, 6, 1)) {
20945 case NM_ADDIUR1SP:
20946 imm = extract32(ctx->opcode, 0, 6) << 2;
20947 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
20948 break;
20949 default:
20950 generate_exception_end(ctx, EXCP_RI);
20951 break;
20953 break;
20954 case NM_P16_A2:
20955 switch (extract32(ctx->opcode, 3, 1)) {
20956 case NM_ADDIUR2:
20957 imm = extract32(ctx->opcode, 0, 3) << 2;
20958 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
20959 break;
20960 case NM_P_ADDIURS5:
20961 rt = extract32(ctx->opcode, 5, 5);
20962 if (rt != 0) {
20963 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
20964 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
20965 (extract32(ctx->opcode, 0, 3));
20966 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
20968 break;
20970 break;
20971 case NM_P16_ADDU:
20972 switch (ctx->opcode & 0x1) {
20973 case NM_ADDU16:
20974 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
20975 break;
20976 case NM_SUBU16:
20977 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
20978 break;
20980 break;
20981 case NM_P16_4X4:
20982 rt = (extract32(ctx->opcode, 9, 1) << 3) |
20983 extract32(ctx->opcode, 5, 3);
20984 rs = (extract32(ctx->opcode, 4, 1) << 3) |
20985 extract32(ctx->opcode, 0, 3);
20986 rt = decode_gpr_gpr4(rt);
20987 rs = decode_gpr_gpr4(rs);
20988 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
20989 (extract32(ctx->opcode, 3, 1))) {
20990 case NM_ADDU4X4:
20991 check_nms(ctx);
20992 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
20993 break;
20994 case NM_MUL4X4:
20995 check_nms(ctx);
20996 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
20997 break;
20998 default:
20999 generate_exception_end(ctx, EXCP_RI);
21000 break;
21002 break;
21003 case NM_LI16:
21005 int imm = extract32(ctx->opcode, 0, 7);
21006 imm = (imm == 0x7f ? -1 : imm);
21007 if (rt != 0) {
21008 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21011 break;
21012 case NM_ANDI16:
21014 uint32_t u = extract32(ctx->opcode, 0, 4);
21015 u = (u == 12) ? 0xff :
21016 (u == 13) ? 0xffff : u;
21017 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21019 break;
21020 case NM_P16_LB:
21021 offset = extract32(ctx->opcode, 0, 2);
21022 switch (extract32(ctx->opcode, 2, 2)) {
21023 case NM_LB16:
21024 gen_ld(ctx, OPC_LB, rt, rs, offset);
21025 break;
21026 case NM_SB16:
21027 rt = decode_gpr_gpr3_src_store(
21028 NANOMIPS_EXTRACT_RD(ctx->opcode));
21029 gen_st(ctx, OPC_SB, rt, rs, offset);
21030 break;
21031 case NM_LBU16:
21032 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21033 break;
21034 default:
21035 generate_exception_end(ctx, EXCP_RI);
21036 break;
21038 break;
21039 case NM_P16_LH:
21040 offset = extract32(ctx->opcode, 1, 2) << 1;
21041 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21042 case NM_LH16:
21043 gen_ld(ctx, OPC_LH, rt, rs, offset);
21044 break;
21045 case NM_SH16:
21046 rt = decode_gpr_gpr3_src_store(
21047 NANOMIPS_EXTRACT_RD(ctx->opcode));
21048 gen_st(ctx, OPC_SH, rt, rs, offset);
21049 break;
21050 case NM_LHU16:
21051 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21052 break;
21053 default:
21054 generate_exception_end(ctx, EXCP_RI);
21055 break;
21057 break;
21058 case NM_LW16:
21059 offset = extract32(ctx->opcode, 0, 4) << 2;
21060 gen_ld(ctx, OPC_LW, rt, rs, offset);
21061 break;
21062 case NM_LWSP16:
21063 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21064 offset = extract32(ctx->opcode, 0, 5) << 2;
21065 gen_ld(ctx, OPC_LW, rt, 29, offset);
21066 break;
21067 case NM_LW4X4:
21068 check_nms(ctx);
21069 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21070 extract32(ctx->opcode, 5, 3);
21071 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21072 extract32(ctx->opcode, 0, 3);
21073 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21074 (extract32(ctx->opcode, 8, 1) << 2);
21075 rt = decode_gpr_gpr4(rt);
21076 rs = decode_gpr_gpr4(rs);
21077 gen_ld(ctx, OPC_LW, rt, rs, offset);
21078 break;
21079 case NM_SW4X4:
21080 check_nms(ctx);
21081 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21082 extract32(ctx->opcode, 5, 3);
21083 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21084 extract32(ctx->opcode, 0, 3);
21085 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21086 (extract32(ctx->opcode, 8, 1) << 2);
21087 rt = decode_gpr_gpr4_zero(rt);
21088 rs = decode_gpr_gpr4(rs);
21089 gen_st(ctx, OPC_SW, rt, rs, offset);
21090 break;
21091 case NM_LWGP16:
21092 offset = extract32(ctx->opcode, 0, 7) << 2;
21093 gen_ld(ctx, OPC_LW, rt, 28, offset);
21094 break;
21095 case NM_SWSP16:
21096 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21097 offset = extract32(ctx->opcode, 0, 5) << 2;
21098 gen_st(ctx, OPC_SW, rt, 29, offset);
21099 break;
21100 case NM_SW16:
21101 rt = decode_gpr_gpr3_src_store(
21102 NANOMIPS_EXTRACT_RD(ctx->opcode));
21103 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21104 offset = extract32(ctx->opcode, 0, 4) << 2;
21105 gen_st(ctx, OPC_SW, rt, rs, offset);
21106 break;
21107 case NM_SWGP16:
21108 rt = decode_gpr_gpr3_src_store(
21109 NANOMIPS_EXTRACT_RD(ctx->opcode));
21110 offset = extract32(ctx->opcode, 0, 7) << 2;
21111 gen_st(ctx, OPC_SW, rt, 28, offset);
21112 break;
21113 case NM_BC16:
21114 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21115 (sextract32(ctx->opcode, 0, 1) << 10) |
21116 (extract32(ctx->opcode, 1, 9) << 1));
21117 break;
21118 case NM_BALC16:
21119 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21120 (sextract32(ctx->opcode, 0, 1) << 10) |
21121 (extract32(ctx->opcode, 1, 9) << 1));
21122 break;
21123 case NM_BEQZC16:
21124 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21125 (sextract32(ctx->opcode, 0, 1) << 7) |
21126 (extract32(ctx->opcode, 1, 6) << 1));
21127 break;
21128 case NM_BNEZC16:
21129 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21130 (sextract32(ctx->opcode, 0, 1) << 7) |
21131 (extract32(ctx->opcode, 1, 6) << 1));
21132 break;
21133 case NM_P16_BR:
21134 switch (ctx->opcode & 0xf) {
21135 case 0:
21136 /* P16.JRC */
21137 switch (extract32(ctx->opcode, 4, 1)) {
21138 case NM_JRC:
21139 gen_compute_branch_nm(ctx, OPC_JR, 2,
21140 extract32(ctx->opcode, 5, 5), 0, 0);
21141 break;
21142 case NM_JALRC16:
21143 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21144 extract32(ctx->opcode, 5, 5), 31, 0);
21145 break;
21147 break;
21148 default:
21150 /* P16.BRI */
21151 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21152 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21153 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21154 extract32(ctx->opcode, 0, 4) << 1);
21156 break;
21158 break;
21159 case NM_P16_SR:
21161 int count = extract32(ctx->opcode, 0, 4);
21162 int u = extract32(ctx->opcode, 4, 4) << 4;
21164 rt = 30 + extract32(ctx->opcode, 9, 1);
21165 switch (extract32(ctx->opcode, 8, 1)) {
21166 case NM_SAVE16:
21167 gen_save(ctx, rt, count, 0, u);
21168 break;
21169 case NM_RESTORE_JRC16:
21170 gen_restore(ctx, rt, count, 0, u);
21171 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21172 break;
21175 break;
21176 case NM_MOVEP:
21177 case NM_MOVEPREV:
21178 check_nms(ctx);
21180 static const int gpr2reg1[] = {4, 5, 6, 7};
21181 static const int gpr2reg2[] = {5, 6, 7, 8};
21182 int re;
21183 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21184 extract32(ctx->opcode, 8, 1);
21185 int r1 = gpr2reg1[rd2];
21186 int r2 = gpr2reg2[rd2];
21187 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21188 extract32(ctx->opcode, 0, 3);
21189 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21190 extract32(ctx->opcode, 5, 3);
21191 TCGv t0 = tcg_temp_new();
21192 TCGv t1 = tcg_temp_new();
21193 if (op == NM_MOVEP) {
21194 rd = r1;
21195 re = r2;
21196 rs = decode_gpr_gpr4_zero(r3);
21197 rt = decode_gpr_gpr4_zero(r4);
21198 } else {
21199 rd = decode_gpr_gpr4(r3);
21200 re = decode_gpr_gpr4(r4);
21201 rs = r1;
21202 rt = r2;
21204 gen_load_gpr(t0, rs);
21205 gen_load_gpr(t1, rt);
21206 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21207 tcg_gen_mov_tl(cpu_gpr[re], t1);
21208 tcg_temp_free(t0);
21209 tcg_temp_free(t1);
21211 break;
21212 default:
21213 return decode_nanomips_32_48_opc(env, ctx);
21216 return 2;
21220 /* SmartMIPS extension to MIPS32 */
21222 #if defined(TARGET_MIPS64)
21224 /* MDMX extension to MIPS64 */
21226 #endif
21228 /* MIPSDSP functions. */
21229 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21230 int rd, int base, int offset)
21232 TCGv t0;
21234 check_dsp(ctx);
21235 t0 = tcg_temp_new();
21237 if (base == 0) {
21238 gen_load_gpr(t0, offset);
21239 } else if (offset == 0) {
21240 gen_load_gpr(t0, base);
21241 } else {
21242 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21245 switch (opc) {
21246 case OPC_LBUX:
21247 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21248 gen_store_gpr(t0, rd);
21249 break;
21250 case OPC_LHX:
21251 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21252 gen_store_gpr(t0, rd);
21253 break;
21254 case OPC_LWX:
21255 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21256 gen_store_gpr(t0, rd);
21257 break;
21258 #if defined(TARGET_MIPS64)
21259 case OPC_LDX:
21260 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21261 gen_store_gpr(t0, rd);
21262 break;
21263 #endif
21265 tcg_temp_free(t0);
21268 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21269 int ret, int v1, int v2)
21271 TCGv v1_t;
21272 TCGv v2_t;
21274 if (ret == 0) {
21275 /* Treat as NOP. */
21276 return;
21279 v1_t = tcg_temp_new();
21280 v2_t = tcg_temp_new();
21282 gen_load_gpr(v1_t, v1);
21283 gen_load_gpr(v2_t, v2);
21285 switch (op1) {
21286 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21287 case OPC_MULT_G_2E:
21288 check_dsp_r2(ctx);
21289 switch (op2) {
21290 case OPC_ADDUH_QB:
21291 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21292 break;
21293 case OPC_ADDUH_R_QB:
21294 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21295 break;
21296 case OPC_ADDQH_PH:
21297 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21298 break;
21299 case OPC_ADDQH_R_PH:
21300 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21301 break;
21302 case OPC_ADDQH_W:
21303 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21304 break;
21305 case OPC_ADDQH_R_W:
21306 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21307 break;
21308 case OPC_SUBUH_QB:
21309 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21310 break;
21311 case OPC_SUBUH_R_QB:
21312 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21313 break;
21314 case OPC_SUBQH_PH:
21315 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21316 break;
21317 case OPC_SUBQH_R_PH:
21318 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21319 break;
21320 case OPC_SUBQH_W:
21321 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21322 break;
21323 case OPC_SUBQH_R_W:
21324 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21325 break;
21327 break;
21328 case OPC_ABSQ_S_PH_DSP:
21329 switch (op2) {
21330 case OPC_ABSQ_S_QB:
21331 check_dsp_r2(ctx);
21332 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21333 break;
21334 case OPC_ABSQ_S_PH:
21335 check_dsp(ctx);
21336 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21337 break;
21338 case OPC_ABSQ_S_W:
21339 check_dsp(ctx);
21340 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21341 break;
21342 case OPC_PRECEQ_W_PHL:
21343 check_dsp(ctx);
21344 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21345 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21346 break;
21347 case OPC_PRECEQ_W_PHR:
21348 check_dsp(ctx);
21349 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21350 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21351 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21352 break;
21353 case OPC_PRECEQU_PH_QBL:
21354 check_dsp(ctx);
21355 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21356 break;
21357 case OPC_PRECEQU_PH_QBR:
21358 check_dsp(ctx);
21359 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21360 break;
21361 case OPC_PRECEQU_PH_QBLA:
21362 check_dsp(ctx);
21363 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21364 break;
21365 case OPC_PRECEQU_PH_QBRA:
21366 check_dsp(ctx);
21367 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21368 break;
21369 case OPC_PRECEU_PH_QBL:
21370 check_dsp(ctx);
21371 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21372 break;
21373 case OPC_PRECEU_PH_QBR:
21374 check_dsp(ctx);
21375 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21376 break;
21377 case OPC_PRECEU_PH_QBLA:
21378 check_dsp(ctx);
21379 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21380 break;
21381 case OPC_PRECEU_PH_QBRA:
21382 check_dsp(ctx);
21383 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21384 break;
21386 break;
21387 case OPC_ADDU_QB_DSP:
21388 switch (op2) {
21389 case OPC_ADDQ_PH:
21390 check_dsp(ctx);
21391 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21392 break;
21393 case OPC_ADDQ_S_PH:
21394 check_dsp(ctx);
21395 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21396 break;
21397 case OPC_ADDQ_S_W:
21398 check_dsp(ctx);
21399 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21400 break;
21401 case OPC_ADDU_QB:
21402 check_dsp(ctx);
21403 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21404 break;
21405 case OPC_ADDU_S_QB:
21406 check_dsp(ctx);
21407 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21408 break;
21409 case OPC_ADDU_PH:
21410 check_dsp_r2(ctx);
21411 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21412 break;
21413 case OPC_ADDU_S_PH:
21414 check_dsp_r2(ctx);
21415 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21416 break;
21417 case OPC_SUBQ_PH:
21418 check_dsp(ctx);
21419 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21420 break;
21421 case OPC_SUBQ_S_PH:
21422 check_dsp(ctx);
21423 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21424 break;
21425 case OPC_SUBQ_S_W:
21426 check_dsp(ctx);
21427 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21428 break;
21429 case OPC_SUBU_QB:
21430 check_dsp(ctx);
21431 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21432 break;
21433 case OPC_SUBU_S_QB:
21434 check_dsp(ctx);
21435 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21436 break;
21437 case OPC_SUBU_PH:
21438 check_dsp_r2(ctx);
21439 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21440 break;
21441 case OPC_SUBU_S_PH:
21442 check_dsp_r2(ctx);
21443 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21444 break;
21445 case OPC_ADDSC:
21446 check_dsp(ctx);
21447 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21448 break;
21449 case OPC_ADDWC:
21450 check_dsp(ctx);
21451 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21452 break;
21453 case OPC_MODSUB:
21454 check_dsp(ctx);
21455 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21456 break;
21457 case OPC_RADDU_W_QB:
21458 check_dsp(ctx);
21459 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21460 break;
21462 break;
21463 case OPC_CMPU_EQ_QB_DSP:
21464 switch (op2) {
21465 case OPC_PRECR_QB_PH:
21466 check_dsp_r2(ctx);
21467 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21468 break;
21469 case OPC_PRECRQ_QB_PH:
21470 check_dsp(ctx);
21471 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21472 break;
21473 case OPC_PRECR_SRA_PH_W:
21474 check_dsp_r2(ctx);
21476 TCGv_i32 sa_t = tcg_const_i32(v2);
21477 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21478 cpu_gpr[ret]);
21479 tcg_temp_free_i32(sa_t);
21480 break;
21482 case OPC_PRECR_SRA_R_PH_W:
21483 check_dsp_r2(ctx);
21485 TCGv_i32 sa_t = tcg_const_i32(v2);
21486 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21487 cpu_gpr[ret]);
21488 tcg_temp_free_i32(sa_t);
21489 break;
21491 case OPC_PRECRQ_PH_W:
21492 check_dsp(ctx);
21493 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21494 break;
21495 case OPC_PRECRQ_RS_PH_W:
21496 check_dsp(ctx);
21497 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21498 break;
21499 case OPC_PRECRQU_S_QB_PH:
21500 check_dsp(ctx);
21501 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21502 break;
21504 break;
21505 #ifdef TARGET_MIPS64
21506 case OPC_ABSQ_S_QH_DSP:
21507 switch (op2) {
21508 case OPC_PRECEQ_L_PWL:
21509 check_dsp(ctx);
21510 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21511 break;
21512 case OPC_PRECEQ_L_PWR:
21513 check_dsp(ctx);
21514 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21515 break;
21516 case OPC_PRECEQ_PW_QHL:
21517 check_dsp(ctx);
21518 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21519 break;
21520 case OPC_PRECEQ_PW_QHR:
21521 check_dsp(ctx);
21522 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21523 break;
21524 case OPC_PRECEQ_PW_QHLA:
21525 check_dsp(ctx);
21526 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21527 break;
21528 case OPC_PRECEQ_PW_QHRA:
21529 check_dsp(ctx);
21530 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21531 break;
21532 case OPC_PRECEQU_QH_OBL:
21533 check_dsp(ctx);
21534 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21535 break;
21536 case OPC_PRECEQU_QH_OBR:
21537 check_dsp(ctx);
21538 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21539 break;
21540 case OPC_PRECEQU_QH_OBLA:
21541 check_dsp(ctx);
21542 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21543 break;
21544 case OPC_PRECEQU_QH_OBRA:
21545 check_dsp(ctx);
21546 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21547 break;
21548 case OPC_PRECEU_QH_OBL:
21549 check_dsp(ctx);
21550 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21551 break;
21552 case OPC_PRECEU_QH_OBR:
21553 check_dsp(ctx);
21554 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21555 break;
21556 case OPC_PRECEU_QH_OBLA:
21557 check_dsp(ctx);
21558 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21559 break;
21560 case OPC_PRECEU_QH_OBRA:
21561 check_dsp(ctx);
21562 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21563 break;
21564 case OPC_ABSQ_S_OB:
21565 check_dsp_r2(ctx);
21566 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21567 break;
21568 case OPC_ABSQ_S_PW:
21569 check_dsp(ctx);
21570 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21571 break;
21572 case OPC_ABSQ_S_QH:
21573 check_dsp(ctx);
21574 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21575 break;
21577 break;
21578 case OPC_ADDU_OB_DSP:
21579 switch (op2) {
21580 case OPC_RADDU_L_OB:
21581 check_dsp(ctx);
21582 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21583 break;
21584 case OPC_SUBQ_PW:
21585 check_dsp(ctx);
21586 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21587 break;
21588 case OPC_SUBQ_S_PW:
21589 check_dsp(ctx);
21590 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21591 break;
21592 case OPC_SUBQ_QH:
21593 check_dsp(ctx);
21594 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21595 break;
21596 case OPC_SUBQ_S_QH:
21597 check_dsp(ctx);
21598 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21599 break;
21600 case OPC_SUBU_OB:
21601 check_dsp(ctx);
21602 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21603 break;
21604 case OPC_SUBU_S_OB:
21605 check_dsp(ctx);
21606 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21607 break;
21608 case OPC_SUBU_QH:
21609 check_dsp_r2(ctx);
21610 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21611 break;
21612 case OPC_SUBU_S_QH:
21613 check_dsp_r2(ctx);
21614 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21615 break;
21616 case OPC_SUBUH_OB:
21617 check_dsp_r2(ctx);
21618 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21619 break;
21620 case OPC_SUBUH_R_OB:
21621 check_dsp_r2(ctx);
21622 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21623 break;
21624 case OPC_ADDQ_PW:
21625 check_dsp(ctx);
21626 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21627 break;
21628 case OPC_ADDQ_S_PW:
21629 check_dsp(ctx);
21630 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21631 break;
21632 case OPC_ADDQ_QH:
21633 check_dsp(ctx);
21634 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21635 break;
21636 case OPC_ADDQ_S_QH:
21637 check_dsp(ctx);
21638 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21639 break;
21640 case OPC_ADDU_OB:
21641 check_dsp(ctx);
21642 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21643 break;
21644 case OPC_ADDU_S_OB:
21645 check_dsp(ctx);
21646 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21647 break;
21648 case OPC_ADDU_QH:
21649 check_dsp_r2(ctx);
21650 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21651 break;
21652 case OPC_ADDU_S_QH:
21653 check_dsp_r2(ctx);
21654 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21655 break;
21656 case OPC_ADDUH_OB:
21657 check_dsp_r2(ctx);
21658 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
21659 break;
21660 case OPC_ADDUH_R_OB:
21661 check_dsp_r2(ctx);
21662 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21663 break;
21665 break;
21666 case OPC_CMPU_EQ_OB_DSP:
21667 switch (op2) {
21668 case OPC_PRECR_OB_QH:
21669 check_dsp_r2(ctx);
21670 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21671 break;
21672 case OPC_PRECR_SRA_QH_PW:
21673 check_dsp_r2(ctx);
21675 TCGv_i32 ret_t = tcg_const_i32(ret);
21676 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
21677 tcg_temp_free_i32(ret_t);
21678 break;
21680 case OPC_PRECR_SRA_R_QH_PW:
21681 check_dsp_r2(ctx);
21683 TCGv_i32 sa_v = tcg_const_i32(ret);
21684 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
21685 tcg_temp_free_i32(sa_v);
21686 break;
21688 case OPC_PRECRQ_OB_QH:
21689 check_dsp(ctx);
21690 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21691 break;
21692 case OPC_PRECRQ_PW_L:
21693 check_dsp(ctx);
21694 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
21695 break;
21696 case OPC_PRECRQ_QH_PW:
21697 check_dsp(ctx);
21698 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
21699 break;
21700 case OPC_PRECRQ_RS_QH_PW:
21701 check_dsp(ctx);
21702 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21703 break;
21704 case OPC_PRECRQU_S_OB_QH:
21705 check_dsp(ctx);
21706 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21707 break;
21709 break;
21710 #endif
21713 tcg_temp_free(v1_t);
21714 tcg_temp_free(v2_t);
21717 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
21718 int ret, int v1, int v2)
21720 uint32_t op2;
21721 TCGv t0;
21722 TCGv v1_t;
21723 TCGv v2_t;
21725 if (ret == 0) {
21726 /* Treat as NOP. */
21727 return;
21730 t0 = tcg_temp_new();
21731 v1_t = tcg_temp_new();
21732 v2_t = tcg_temp_new();
21734 tcg_gen_movi_tl(t0, v1);
21735 gen_load_gpr(v1_t, v1);
21736 gen_load_gpr(v2_t, v2);
21738 switch (opc) {
21739 case OPC_SHLL_QB_DSP:
21741 op2 = MASK_SHLL_QB(ctx->opcode);
21742 switch (op2) {
21743 case OPC_SHLL_QB:
21744 check_dsp(ctx);
21745 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
21746 break;
21747 case OPC_SHLLV_QB:
21748 check_dsp(ctx);
21749 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21750 break;
21751 case OPC_SHLL_PH:
21752 check_dsp(ctx);
21753 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21754 break;
21755 case OPC_SHLLV_PH:
21756 check_dsp(ctx);
21757 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21758 break;
21759 case OPC_SHLL_S_PH:
21760 check_dsp(ctx);
21761 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
21762 break;
21763 case OPC_SHLLV_S_PH:
21764 check_dsp(ctx);
21765 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21766 break;
21767 case OPC_SHLL_S_W:
21768 check_dsp(ctx);
21769 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
21770 break;
21771 case OPC_SHLLV_S_W:
21772 check_dsp(ctx);
21773 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21774 break;
21775 case OPC_SHRL_QB:
21776 check_dsp(ctx);
21777 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
21778 break;
21779 case OPC_SHRLV_QB:
21780 check_dsp(ctx);
21781 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
21782 break;
21783 case OPC_SHRL_PH:
21784 check_dsp_r2(ctx);
21785 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
21786 break;
21787 case OPC_SHRLV_PH:
21788 check_dsp_r2(ctx);
21789 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
21790 break;
21791 case OPC_SHRA_QB:
21792 check_dsp_r2(ctx);
21793 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
21794 break;
21795 case OPC_SHRA_R_QB:
21796 check_dsp_r2(ctx);
21797 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
21798 break;
21799 case OPC_SHRAV_QB:
21800 check_dsp_r2(ctx);
21801 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
21802 break;
21803 case OPC_SHRAV_R_QB:
21804 check_dsp_r2(ctx);
21805 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
21806 break;
21807 case OPC_SHRA_PH:
21808 check_dsp(ctx);
21809 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
21810 break;
21811 case OPC_SHRA_R_PH:
21812 check_dsp(ctx);
21813 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
21814 break;
21815 case OPC_SHRAV_PH:
21816 check_dsp(ctx);
21817 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
21818 break;
21819 case OPC_SHRAV_R_PH:
21820 check_dsp(ctx);
21821 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
21822 break;
21823 case OPC_SHRA_R_W:
21824 check_dsp(ctx);
21825 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
21826 break;
21827 case OPC_SHRAV_R_W:
21828 check_dsp(ctx);
21829 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
21830 break;
21831 default: /* Invalid */
21832 MIPS_INVAL("MASK SHLL.QB");
21833 generate_exception_end(ctx, EXCP_RI);
21834 break;
21836 break;
21838 #ifdef TARGET_MIPS64
21839 case OPC_SHLL_OB_DSP:
21840 op2 = MASK_SHLL_OB(ctx->opcode);
21841 switch (op2) {
21842 case OPC_SHLL_PW:
21843 check_dsp(ctx);
21844 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
21845 break;
21846 case OPC_SHLLV_PW:
21847 check_dsp(ctx);
21848 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21849 break;
21850 case OPC_SHLL_S_PW:
21851 check_dsp(ctx);
21852 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
21853 break;
21854 case OPC_SHLLV_S_PW:
21855 check_dsp(ctx);
21856 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21857 break;
21858 case OPC_SHLL_OB:
21859 check_dsp(ctx);
21860 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
21861 break;
21862 case OPC_SHLLV_OB:
21863 check_dsp(ctx);
21864 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21865 break;
21866 case OPC_SHLL_QH:
21867 check_dsp(ctx);
21868 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
21869 break;
21870 case OPC_SHLLV_QH:
21871 check_dsp(ctx);
21872 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21873 break;
21874 case OPC_SHLL_S_QH:
21875 check_dsp(ctx);
21876 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
21877 break;
21878 case OPC_SHLLV_S_QH:
21879 check_dsp(ctx);
21880 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
21881 break;
21882 case OPC_SHRA_OB:
21883 check_dsp_r2(ctx);
21884 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
21885 break;
21886 case OPC_SHRAV_OB:
21887 check_dsp_r2(ctx);
21888 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
21889 break;
21890 case OPC_SHRA_R_OB:
21891 check_dsp_r2(ctx);
21892 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
21893 break;
21894 case OPC_SHRAV_R_OB:
21895 check_dsp_r2(ctx);
21896 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
21897 break;
21898 case OPC_SHRA_PW:
21899 check_dsp(ctx);
21900 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
21901 break;
21902 case OPC_SHRAV_PW:
21903 check_dsp(ctx);
21904 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
21905 break;
21906 case OPC_SHRA_R_PW:
21907 check_dsp(ctx);
21908 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
21909 break;
21910 case OPC_SHRAV_R_PW:
21911 check_dsp(ctx);
21912 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
21913 break;
21914 case OPC_SHRA_QH:
21915 check_dsp(ctx);
21916 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
21917 break;
21918 case OPC_SHRAV_QH:
21919 check_dsp(ctx);
21920 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
21921 break;
21922 case OPC_SHRA_R_QH:
21923 check_dsp(ctx);
21924 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
21925 break;
21926 case OPC_SHRAV_R_QH:
21927 check_dsp(ctx);
21928 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
21929 break;
21930 case OPC_SHRL_OB:
21931 check_dsp(ctx);
21932 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
21933 break;
21934 case OPC_SHRLV_OB:
21935 check_dsp(ctx);
21936 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
21937 break;
21938 case OPC_SHRL_QH:
21939 check_dsp_r2(ctx);
21940 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
21941 break;
21942 case OPC_SHRLV_QH:
21943 check_dsp_r2(ctx);
21944 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
21945 break;
21946 default: /* Invalid */
21947 MIPS_INVAL("MASK SHLL.OB");
21948 generate_exception_end(ctx, EXCP_RI);
21949 break;
21951 break;
21952 #endif
21955 tcg_temp_free(t0);
21956 tcg_temp_free(v1_t);
21957 tcg_temp_free(v2_t);
21960 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
21961 int ret, int v1, int v2, int check_ret)
21963 TCGv_i32 t0;
21964 TCGv v1_t;
21965 TCGv v2_t;
21967 if ((ret == 0) && (check_ret == 1)) {
21968 /* Treat as NOP. */
21969 return;
21972 t0 = tcg_temp_new_i32();
21973 v1_t = tcg_temp_new();
21974 v2_t = tcg_temp_new();
21976 tcg_gen_movi_i32(t0, ret);
21977 gen_load_gpr(v1_t, v1);
21978 gen_load_gpr(v2_t, v2);
21980 switch (op1) {
21981 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
21982 * the same mask and op1. */
21983 case OPC_MULT_G_2E:
21984 check_dsp_r2(ctx);
21985 switch (op2) {
21986 case OPC_MUL_PH:
21987 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21988 break;
21989 case OPC_MUL_S_PH:
21990 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21991 break;
21992 case OPC_MULQ_S_W:
21993 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21994 break;
21995 case OPC_MULQ_RS_W:
21996 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21997 break;
21999 break;
22000 case OPC_DPA_W_PH_DSP:
22001 switch (op2) {
22002 case OPC_DPAU_H_QBL:
22003 check_dsp(ctx);
22004 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22005 break;
22006 case OPC_DPAU_H_QBR:
22007 check_dsp(ctx);
22008 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22009 break;
22010 case OPC_DPSU_H_QBL:
22011 check_dsp(ctx);
22012 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22013 break;
22014 case OPC_DPSU_H_QBR:
22015 check_dsp(ctx);
22016 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22017 break;
22018 case OPC_DPA_W_PH:
22019 check_dsp_r2(ctx);
22020 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22021 break;
22022 case OPC_DPAX_W_PH:
22023 check_dsp_r2(ctx);
22024 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22025 break;
22026 case OPC_DPAQ_S_W_PH:
22027 check_dsp(ctx);
22028 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22029 break;
22030 case OPC_DPAQX_S_W_PH:
22031 check_dsp_r2(ctx);
22032 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22033 break;
22034 case OPC_DPAQX_SA_W_PH:
22035 check_dsp_r2(ctx);
22036 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22037 break;
22038 case OPC_DPS_W_PH:
22039 check_dsp_r2(ctx);
22040 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22041 break;
22042 case OPC_DPSX_W_PH:
22043 check_dsp_r2(ctx);
22044 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22045 break;
22046 case OPC_DPSQ_S_W_PH:
22047 check_dsp(ctx);
22048 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22049 break;
22050 case OPC_DPSQX_S_W_PH:
22051 check_dsp_r2(ctx);
22052 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22053 break;
22054 case OPC_DPSQX_SA_W_PH:
22055 check_dsp_r2(ctx);
22056 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22057 break;
22058 case OPC_MULSAQ_S_W_PH:
22059 check_dsp(ctx);
22060 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22061 break;
22062 case OPC_DPAQ_SA_L_W:
22063 check_dsp(ctx);
22064 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22065 break;
22066 case OPC_DPSQ_SA_L_W:
22067 check_dsp(ctx);
22068 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22069 break;
22070 case OPC_MAQ_S_W_PHL:
22071 check_dsp(ctx);
22072 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22073 break;
22074 case OPC_MAQ_S_W_PHR:
22075 check_dsp(ctx);
22076 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22077 break;
22078 case OPC_MAQ_SA_W_PHL:
22079 check_dsp(ctx);
22080 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22081 break;
22082 case OPC_MAQ_SA_W_PHR:
22083 check_dsp(ctx);
22084 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22085 break;
22086 case OPC_MULSA_W_PH:
22087 check_dsp_r2(ctx);
22088 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22089 break;
22091 break;
22092 #ifdef TARGET_MIPS64
22093 case OPC_DPAQ_W_QH_DSP:
22095 int ac = ret & 0x03;
22096 tcg_gen_movi_i32(t0, ac);
22098 switch (op2) {
22099 case OPC_DMADD:
22100 check_dsp(ctx);
22101 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22102 break;
22103 case OPC_DMADDU:
22104 check_dsp(ctx);
22105 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22106 break;
22107 case OPC_DMSUB:
22108 check_dsp(ctx);
22109 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22110 break;
22111 case OPC_DMSUBU:
22112 check_dsp(ctx);
22113 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22114 break;
22115 case OPC_DPA_W_QH:
22116 check_dsp_r2(ctx);
22117 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22118 break;
22119 case OPC_DPAQ_S_W_QH:
22120 check_dsp(ctx);
22121 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22122 break;
22123 case OPC_DPAQ_SA_L_PW:
22124 check_dsp(ctx);
22125 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22126 break;
22127 case OPC_DPAU_H_OBL:
22128 check_dsp(ctx);
22129 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22130 break;
22131 case OPC_DPAU_H_OBR:
22132 check_dsp(ctx);
22133 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22134 break;
22135 case OPC_DPS_W_QH:
22136 check_dsp_r2(ctx);
22137 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22138 break;
22139 case OPC_DPSQ_S_W_QH:
22140 check_dsp(ctx);
22141 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22142 break;
22143 case OPC_DPSQ_SA_L_PW:
22144 check_dsp(ctx);
22145 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22146 break;
22147 case OPC_DPSU_H_OBL:
22148 check_dsp(ctx);
22149 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22150 break;
22151 case OPC_DPSU_H_OBR:
22152 check_dsp(ctx);
22153 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22154 break;
22155 case OPC_MAQ_S_L_PWL:
22156 check_dsp(ctx);
22157 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22158 break;
22159 case OPC_MAQ_S_L_PWR:
22160 check_dsp(ctx);
22161 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22162 break;
22163 case OPC_MAQ_S_W_QHLL:
22164 check_dsp(ctx);
22165 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22166 break;
22167 case OPC_MAQ_SA_W_QHLL:
22168 check_dsp(ctx);
22169 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22170 break;
22171 case OPC_MAQ_S_W_QHLR:
22172 check_dsp(ctx);
22173 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22174 break;
22175 case OPC_MAQ_SA_W_QHLR:
22176 check_dsp(ctx);
22177 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22178 break;
22179 case OPC_MAQ_S_W_QHRL:
22180 check_dsp(ctx);
22181 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22182 break;
22183 case OPC_MAQ_SA_W_QHRL:
22184 check_dsp(ctx);
22185 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22186 break;
22187 case OPC_MAQ_S_W_QHRR:
22188 check_dsp(ctx);
22189 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22190 break;
22191 case OPC_MAQ_SA_W_QHRR:
22192 check_dsp(ctx);
22193 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22194 break;
22195 case OPC_MULSAQ_S_L_PW:
22196 check_dsp(ctx);
22197 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22198 break;
22199 case OPC_MULSAQ_S_W_QH:
22200 check_dsp(ctx);
22201 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22202 break;
22205 break;
22206 #endif
22207 case OPC_ADDU_QB_DSP:
22208 switch (op2) {
22209 case OPC_MULEU_S_PH_QBL:
22210 check_dsp(ctx);
22211 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22212 break;
22213 case OPC_MULEU_S_PH_QBR:
22214 check_dsp(ctx);
22215 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22216 break;
22217 case OPC_MULQ_RS_PH:
22218 check_dsp(ctx);
22219 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22220 break;
22221 case OPC_MULEQ_S_W_PHL:
22222 check_dsp(ctx);
22223 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22224 break;
22225 case OPC_MULEQ_S_W_PHR:
22226 check_dsp(ctx);
22227 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22228 break;
22229 case OPC_MULQ_S_PH:
22230 check_dsp_r2(ctx);
22231 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22232 break;
22234 break;
22235 #ifdef TARGET_MIPS64
22236 case OPC_ADDU_OB_DSP:
22237 switch (op2) {
22238 case OPC_MULEQ_S_PW_QHL:
22239 check_dsp(ctx);
22240 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22241 break;
22242 case OPC_MULEQ_S_PW_QHR:
22243 check_dsp(ctx);
22244 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22245 break;
22246 case OPC_MULEU_S_QH_OBL:
22247 check_dsp(ctx);
22248 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22249 break;
22250 case OPC_MULEU_S_QH_OBR:
22251 check_dsp(ctx);
22252 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22253 break;
22254 case OPC_MULQ_RS_QH:
22255 check_dsp(ctx);
22256 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22257 break;
22259 break;
22260 #endif
22263 tcg_temp_free_i32(t0);
22264 tcg_temp_free(v1_t);
22265 tcg_temp_free(v2_t);
22268 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22269 int ret, int val)
22271 int16_t imm;
22272 TCGv t0;
22273 TCGv val_t;
22275 if (ret == 0) {
22276 /* Treat as NOP. */
22277 return;
22280 t0 = tcg_temp_new();
22281 val_t = tcg_temp_new();
22282 gen_load_gpr(val_t, val);
22284 switch (op1) {
22285 case OPC_ABSQ_S_PH_DSP:
22286 switch (op2) {
22287 case OPC_BITREV:
22288 check_dsp(ctx);
22289 gen_helper_bitrev(cpu_gpr[ret], val_t);
22290 break;
22291 case OPC_REPL_QB:
22292 check_dsp(ctx);
22294 target_long result;
22295 imm = (ctx->opcode >> 16) & 0xFF;
22296 result = (uint32_t)imm << 24 |
22297 (uint32_t)imm << 16 |
22298 (uint32_t)imm << 8 |
22299 (uint32_t)imm;
22300 result = (int32_t)result;
22301 tcg_gen_movi_tl(cpu_gpr[ret], result);
22303 break;
22304 case OPC_REPLV_QB:
22305 check_dsp(ctx);
22306 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22307 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22308 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22309 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22310 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22311 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22312 break;
22313 case OPC_REPL_PH:
22314 check_dsp(ctx);
22316 imm = (ctx->opcode >> 16) & 0x03FF;
22317 imm = (int16_t)(imm << 6) >> 6;
22318 tcg_gen_movi_tl(cpu_gpr[ret], \
22319 (target_long)((int32_t)imm << 16 | \
22320 (uint16_t)imm));
22322 break;
22323 case OPC_REPLV_PH:
22324 check_dsp(ctx);
22325 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22326 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22327 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22328 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22329 break;
22331 break;
22332 #ifdef TARGET_MIPS64
22333 case OPC_ABSQ_S_QH_DSP:
22334 switch (op2) {
22335 case OPC_REPL_OB:
22336 check_dsp(ctx);
22338 target_long temp;
22340 imm = (ctx->opcode >> 16) & 0xFF;
22341 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22342 temp = (temp << 16) | temp;
22343 temp = (temp << 32) | temp;
22344 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22345 break;
22347 case OPC_REPL_PW:
22348 check_dsp(ctx);
22350 target_long temp;
22352 imm = (ctx->opcode >> 16) & 0x03FF;
22353 imm = (int16_t)(imm << 6) >> 6;
22354 temp = ((target_long)imm << 32) \
22355 | ((target_long)imm & 0xFFFFFFFF);
22356 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22357 break;
22359 case OPC_REPL_QH:
22360 check_dsp(ctx);
22362 target_long temp;
22364 imm = (ctx->opcode >> 16) & 0x03FF;
22365 imm = (int16_t)(imm << 6) >> 6;
22367 temp = ((uint64_t)(uint16_t)imm << 48) |
22368 ((uint64_t)(uint16_t)imm << 32) |
22369 ((uint64_t)(uint16_t)imm << 16) |
22370 (uint64_t)(uint16_t)imm;
22371 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22372 break;
22374 case OPC_REPLV_OB:
22375 check_dsp(ctx);
22376 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22377 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22378 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22379 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22380 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22381 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22382 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22383 break;
22384 case OPC_REPLV_PW:
22385 check_dsp(ctx);
22386 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22387 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22388 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22389 break;
22390 case OPC_REPLV_QH:
22391 check_dsp(ctx);
22392 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22393 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22394 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22395 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22396 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22397 break;
22399 break;
22400 #endif
22402 tcg_temp_free(t0);
22403 tcg_temp_free(val_t);
22406 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22407 uint32_t op1, uint32_t op2,
22408 int ret, int v1, int v2, int check_ret)
22410 TCGv t1;
22411 TCGv v1_t;
22412 TCGv v2_t;
22414 if ((ret == 0) && (check_ret == 1)) {
22415 /* Treat as NOP. */
22416 return;
22419 t1 = tcg_temp_new();
22420 v1_t = tcg_temp_new();
22421 v2_t = tcg_temp_new();
22423 gen_load_gpr(v1_t, v1);
22424 gen_load_gpr(v2_t, v2);
22426 switch (op1) {
22427 case OPC_CMPU_EQ_QB_DSP:
22428 switch (op2) {
22429 case OPC_CMPU_EQ_QB:
22430 check_dsp(ctx);
22431 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22432 break;
22433 case OPC_CMPU_LT_QB:
22434 check_dsp(ctx);
22435 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22436 break;
22437 case OPC_CMPU_LE_QB:
22438 check_dsp(ctx);
22439 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22440 break;
22441 case OPC_CMPGU_EQ_QB:
22442 check_dsp(ctx);
22443 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22444 break;
22445 case OPC_CMPGU_LT_QB:
22446 check_dsp(ctx);
22447 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22448 break;
22449 case OPC_CMPGU_LE_QB:
22450 check_dsp(ctx);
22451 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22452 break;
22453 case OPC_CMPGDU_EQ_QB:
22454 check_dsp_r2(ctx);
22455 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22456 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22457 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22458 tcg_gen_shli_tl(t1, t1, 24);
22459 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22460 break;
22461 case OPC_CMPGDU_LT_QB:
22462 check_dsp_r2(ctx);
22463 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22464 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22465 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22466 tcg_gen_shli_tl(t1, t1, 24);
22467 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22468 break;
22469 case OPC_CMPGDU_LE_QB:
22470 check_dsp_r2(ctx);
22471 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22472 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22473 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22474 tcg_gen_shli_tl(t1, t1, 24);
22475 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22476 break;
22477 case OPC_CMP_EQ_PH:
22478 check_dsp(ctx);
22479 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22480 break;
22481 case OPC_CMP_LT_PH:
22482 check_dsp(ctx);
22483 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22484 break;
22485 case OPC_CMP_LE_PH:
22486 check_dsp(ctx);
22487 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22488 break;
22489 case OPC_PICK_QB:
22490 check_dsp(ctx);
22491 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22492 break;
22493 case OPC_PICK_PH:
22494 check_dsp(ctx);
22495 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22496 break;
22497 case OPC_PACKRL_PH:
22498 check_dsp(ctx);
22499 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22500 break;
22502 break;
22503 #ifdef TARGET_MIPS64
22504 case OPC_CMPU_EQ_OB_DSP:
22505 switch (op2) {
22506 case OPC_CMP_EQ_PW:
22507 check_dsp(ctx);
22508 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22509 break;
22510 case OPC_CMP_LT_PW:
22511 check_dsp(ctx);
22512 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22513 break;
22514 case OPC_CMP_LE_PW:
22515 check_dsp(ctx);
22516 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22517 break;
22518 case OPC_CMP_EQ_QH:
22519 check_dsp(ctx);
22520 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22521 break;
22522 case OPC_CMP_LT_QH:
22523 check_dsp(ctx);
22524 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22525 break;
22526 case OPC_CMP_LE_QH:
22527 check_dsp(ctx);
22528 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22529 break;
22530 case OPC_CMPGDU_EQ_OB:
22531 check_dsp_r2(ctx);
22532 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22533 break;
22534 case OPC_CMPGDU_LT_OB:
22535 check_dsp_r2(ctx);
22536 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22537 break;
22538 case OPC_CMPGDU_LE_OB:
22539 check_dsp_r2(ctx);
22540 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22541 break;
22542 case OPC_CMPGU_EQ_OB:
22543 check_dsp(ctx);
22544 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22545 break;
22546 case OPC_CMPGU_LT_OB:
22547 check_dsp(ctx);
22548 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22549 break;
22550 case OPC_CMPGU_LE_OB:
22551 check_dsp(ctx);
22552 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22553 break;
22554 case OPC_CMPU_EQ_OB:
22555 check_dsp(ctx);
22556 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22557 break;
22558 case OPC_CMPU_LT_OB:
22559 check_dsp(ctx);
22560 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22561 break;
22562 case OPC_CMPU_LE_OB:
22563 check_dsp(ctx);
22564 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22565 break;
22566 case OPC_PACKRL_PW:
22567 check_dsp(ctx);
22568 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22569 break;
22570 case OPC_PICK_OB:
22571 check_dsp(ctx);
22572 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22573 break;
22574 case OPC_PICK_PW:
22575 check_dsp(ctx);
22576 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22577 break;
22578 case OPC_PICK_QH:
22579 check_dsp(ctx);
22580 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22581 break;
22583 break;
22584 #endif
22587 tcg_temp_free(t1);
22588 tcg_temp_free(v1_t);
22589 tcg_temp_free(v2_t);
22592 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22593 uint32_t op1, int rt, int rs, int sa)
22595 TCGv t0;
22597 check_dsp_r2(ctx);
22599 if (rt == 0) {
22600 /* Treat as NOP. */
22601 return;
22604 t0 = tcg_temp_new();
22605 gen_load_gpr(t0, rs);
22607 switch (op1) {
22608 case OPC_APPEND_DSP:
22609 switch (MASK_APPEND(ctx->opcode)) {
22610 case OPC_APPEND:
22611 if (sa != 0) {
22612 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22614 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22615 break;
22616 case OPC_PREPEND:
22617 if (sa != 0) {
22618 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22619 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22620 tcg_gen_shli_tl(t0, t0, 32 - sa);
22621 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22623 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22624 break;
22625 case OPC_BALIGN:
22626 sa &= 3;
22627 if (sa != 0 && sa != 2) {
22628 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22629 tcg_gen_ext32u_tl(t0, t0);
22630 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22631 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22633 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22634 break;
22635 default: /* Invalid */
22636 MIPS_INVAL("MASK APPEND");
22637 generate_exception_end(ctx, EXCP_RI);
22638 break;
22640 break;
22641 #ifdef TARGET_MIPS64
22642 case OPC_DAPPEND_DSP:
22643 switch (MASK_DAPPEND(ctx->opcode)) {
22644 case OPC_DAPPEND:
22645 if (sa != 0) {
22646 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22648 break;
22649 case OPC_PREPENDD:
22650 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
22651 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
22652 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
22653 break;
22654 case OPC_PREPENDW:
22655 if (sa != 0) {
22656 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22657 tcg_gen_shli_tl(t0, t0, 64 - sa);
22658 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22660 break;
22661 case OPC_DBALIGN:
22662 sa &= 7;
22663 if (sa != 0 && sa != 2 && sa != 4) {
22664 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22665 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
22666 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22668 break;
22669 default: /* Invalid */
22670 MIPS_INVAL("MASK DAPPEND");
22671 generate_exception_end(ctx, EXCP_RI);
22672 break;
22674 break;
22675 #endif
22677 tcg_temp_free(t0);
22680 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22681 int ret, int v1, int v2, int check_ret)
22684 TCGv t0;
22685 TCGv t1;
22686 TCGv v1_t;
22687 TCGv v2_t;
22688 int16_t imm;
22690 if ((ret == 0) && (check_ret == 1)) {
22691 /* Treat as NOP. */
22692 return;
22695 t0 = tcg_temp_new();
22696 t1 = tcg_temp_new();
22697 v1_t = tcg_temp_new();
22698 v2_t = tcg_temp_new();
22700 gen_load_gpr(v1_t, v1);
22701 gen_load_gpr(v2_t, v2);
22703 switch (op1) {
22704 case OPC_EXTR_W_DSP:
22705 check_dsp(ctx);
22706 switch (op2) {
22707 case OPC_EXTR_W:
22708 tcg_gen_movi_tl(t0, v2);
22709 tcg_gen_movi_tl(t1, v1);
22710 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
22711 break;
22712 case OPC_EXTR_R_W:
22713 tcg_gen_movi_tl(t0, v2);
22714 tcg_gen_movi_tl(t1, v1);
22715 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22716 break;
22717 case OPC_EXTR_RS_W:
22718 tcg_gen_movi_tl(t0, v2);
22719 tcg_gen_movi_tl(t1, v1);
22720 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22721 break;
22722 case OPC_EXTR_S_H:
22723 tcg_gen_movi_tl(t0, v2);
22724 tcg_gen_movi_tl(t1, v1);
22725 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22726 break;
22727 case OPC_EXTRV_S_H:
22728 tcg_gen_movi_tl(t0, v2);
22729 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
22730 break;
22731 case OPC_EXTRV_W:
22732 tcg_gen_movi_tl(t0, v2);
22733 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22734 break;
22735 case OPC_EXTRV_R_W:
22736 tcg_gen_movi_tl(t0, v2);
22737 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22738 break;
22739 case OPC_EXTRV_RS_W:
22740 tcg_gen_movi_tl(t0, v2);
22741 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22742 break;
22743 case OPC_EXTP:
22744 tcg_gen_movi_tl(t0, v2);
22745 tcg_gen_movi_tl(t1, v1);
22746 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
22747 break;
22748 case OPC_EXTPV:
22749 tcg_gen_movi_tl(t0, v2);
22750 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
22751 break;
22752 case OPC_EXTPDP:
22753 tcg_gen_movi_tl(t0, v2);
22754 tcg_gen_movi_tl(t1, v1);
22755 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
22756 break;
22757 case OPC_EXTPDPV:
22758 tcg_gen_movi_tl(t0, v2);
22759 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22760 break;
22761 case OPC_SHILO:
22762 imm = (ctx->opcode >> 20) & 0x3F;
22763 tcg_gen_movi_tl(t0, ret);
22764 tcg_gen_movi_tl(t1, imm);
22765 gen_helper_shilo(t0, t1, cpu_env);
22766 break;
22767 case OPC_SHILOV:
22768 tcg_gen_movi_tl(t0, ret);
22769 gen_helper_shilo(t0, v1_t, cpu_env);
22770 break;
22771 case OPC_MTHLIP:
22772 tcg_gen_movi_tl(t0, ret);
22773 gen_helper_mthlip(t0, v1_t, cpu_env);
22774 break;
22775 case OPC_WRDSP:
22776 imm = (ctx->opcode >> 11) & 0x3FF;
22777 tcg_gen_movi_tl(t0, imm);
22778 gen_helper_wrdsp(v1_t, t0, cpu_env);
22779 break;
22780 case OPC_RDDSP:
22781 imm = (ctx->opcode >> 16) & 0x03FF;
22782 tcg_gen_movi_tl(t0, imm);
22783 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
22784 break;
22786 break;
22787 #ifdef TARGET_MIPS64
22788 case OPC_DEXTR_W_DSP:
22789 check_dsp(ctx);
22790 switch (op2) {
22791 case OPC_DMTHLIP:
22792 tcg_gen_movi_tl(t0, ret);
22793 gen_helper_dmthlip(v1_t, t0, cpu_env);
22794 break;
22795 case OPC_DSHILO:
22797 int shift = (ctx->opcode >> 19) & 0x7F;
22798 int ac = (ctx->opcode >> 11) & 0x03;
22799 tcg_gen_movi_tl(t0, shift);
22800 tcg_gen_movi_tl(t1, ac);
22801 gen_helper_dshilo(t0, t1, cpu_env);
22802 break;
22804 case OPC_DSHILOV:
22806 int ac = (ctx->opcode >> 11) & 0x03;
22807 tcg_gen_movi_tl(t0, ac);
22808 gen_helper_dshilo(v1_t, t0, cpu_env);
22809 break;
22811 case OPC_DEXTP:
22812 tcg_gen_movi_tl(t0, v2);
22813 tcg_gen_movi_tl(t1, v1);
22815 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
22816 break;
22817 case OPC_DEXTPV:
22818 tcg_gen_movi_tl(t0, v2);
22819 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
22820 break;
22821 case OPC_DEXTPDP:
22822 tcg_gen_movi_tl(t0, v2);
22823 tcg_gen_movi_tl(t1, v1);
22824 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
22825 break;
22826 case OPC_DEXTPDPV:
22827 tcg_gen_movi_tl(t0, v2);
22828 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
22829 break;
22830 case OPC_DEXTR_L:
22831 tcg_gen_movi_tl(t0, v2);
22832 tcg_gen_movi_tl(t1, v1);
22833 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
22834 break;
22835 case OPC_DEXTR_R_L:
22836 tcg_gen_movi_tl(t0, v2);
22837 tcg_gen_movi_tl(t1, v1);
22838 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
22839 break;
22840 case OPC_DEXTR_RS_L:
22841 tcg_gen_movi_tl(t0, v2);
22842 tcg_gen_movi_tl(t1, v1);
22843 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
22844 break;
22845 case OPC_DEXTR_W:
22846 tcg_gen_movi_tl(t0, v2);
22847 tcg_gen_movi_tl(t1, v1);
22848 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
22849 break;
22850 case OPC_DEXTR_R_W:
22851 tcg_gen_movi_tl(t0, v2);
22852 tcg_gen_movi_tl(t1, v1);
22853 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22854 break;
22855 case OPC_DEXTR_RS_W:
22856 tcg_gen_movi_tl(t0, v2);
22857 tcg_gen_movi_tl(t1, v1);
22858 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22859 break;
22860 case OPC_DEXTR_S_H:
22861 tcg_gen_movi_tl(t0, v2);
22862 tcg_gen_movi_tl(t1, v1);
22863 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22864 break;
22865 case OPC_DEXTRV_S_H:
22866 tcg_gen_movi_tl(t0, v2);
22867 tcg_gen_movi_tl(t1, v1);
22868 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22869 break;
22870 case OPC_DEXTRV_L:
22871 tcg_gen_movi_tl(t0, v2);
22872 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22873 break;
22874 case OPC_DEXTRV_R_L:
22875 tcg_gen_movi_tl(t0, v2);
22876 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22877 break;
22878 case OPC_DEXTRV_RS_L:
22879 tcg_gen_movi_tl(t0, v2);
22880 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
22881 break;
22882 case OPC_DEXTRV_W:
22883 tcg_gen_movi_tl(t0, v2);
22884 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22885 break;
22886 case OPC_DEXTRV_R_W:
22887 tcg_gen_movi_tl(t0, v2);
22888 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22889 break;
22890 case OPC_DEXTRV_RS_W:
22891 tcg_gen_movi_tl(t0, v2);
22892 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22893 break;
22895 break;
22896 #endif
22899 tcg_temp_free(t0);
22900 tcg_temp_free(t1);
22901 tcg_temp_free(v1_t);
22902 tcg_temp_free(v2_t);
22905 /* End MIPSDSP functions. */
22907 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
22909 int rs, rt, rd, sa;
22910 uint32_t op1, op2;
22912 rs = (ctx->opcode >> 21) & 0x1f;
22913 rt = (ctx->opcode >> 16) & 0x1f;
22914 rd = (ctx->opcode >> 11) & 0x1f;
22915 sa = (ctx->opcode >> 6) & 0x1f;
22917 op1 = MASK_SPECIAL(ctx->opcode);
22918 switch (op1) {
22919 case OPC_LSA:
22920 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
22921 break;
22922 case OPC_MULT:
22923 case OPC_MULTU:
22924 case OPC_DIV:
22925 case OPC_DIVU:
22926 op2 = MASK_R6_MULDIV(ctx->opcode);
22927 switch (op2) {
22928 case R6_OPC_MUL:
22929 case R6_OPC_MUH:
22930 case R6_OPC_MULU:
22931 case R6_OPC_MUHU:
22932 case R6_OPC_DIV:
22933 case R6_OPC_MOD:
22934 case R6_OPC_DIVU:
22935 case R6_OPC_MODU:
22936 gen_r6_muldiv(ctx, op2, rd, rs, rt);
22937 break;
22938 default:
22939 MIPS_INVAL("special_r6 muldiv");
22940 generate_exception_end(ctx, EXCP_RI);
22941 break;
22943 break;
22944 case OPC_SELEQZ:
22945 case OPC_SELNEZ:
22946 gen_cond_move(ctx, op1, rd, rs, rt);
22947 break;
22948 case R6_OPC_CLO:
22949 case R6_OPC_CLZ:
22950 if (rt == 0 && sa == 1) {
22951 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22952 We need additionally to check other fields */
22953 gen_cl(ctx, op1, rd, rs);
22954 } else {
22955 generate_exception_end(ctx, EXCP_RI);
22957 break;
22958 case R6_OPC_SDBBP:
22959 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
22960 gen_helper_do_semihosting(cpu_env);
22961 } else {
22962 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22963 generate_exception_end(ctx, EXCP_RI);
22964 } else {
22965 generate_exception_end(ctx, EXCP_DBp);
22968 break;
22969 #if defined(TARGET_MIPS64)
22970 case OPC_DLSA:
22971 check_mips_64(ctx);
22972 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
22973 break;
22974 case R6_OPC_DCLO:
22975 case R6_OPC_DCLZ:
22976 if (rt == 0 && sa == 1) {
22977 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
22978 We need additionally to check other fields */
22979 check_mips_64(ctx);
22980 gen_cl(ctx, op1, rd, rs);
22981 } else {
22982 generate_exception_end(ctx, EXCP_RI);
22984 break;
22985 case OPC_DMULT:
22986 case OPC_DMULTU:
22987 case OPC_DDIV:
22988 case OPC_DDIVU:
22990 op2 = MASK_R6_MULDIV(ctx->opcode);
22991 switch (op2) {
22992 case R6_OPC_DMUL:
22993 case R6_OPC_DMUH:
22994 case R6_OPC_DMULU:
22995 case R6_OPC_DMUHU:
22996 case R6_OPC_DDIV:
22997 case R6_OPC_DMOD:
22998 case R6_OPC_DDIVU:
22999 case R6_OPC_DMODU:
23000 check_mips_64(ctx);
23001 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23002 break;
23003 default:
23004 MIPS_INVAL("special_r6 muldiv");
23005 generate_exception_end(ctx, EXCP_RI);
23006 break;
23008 break;
23009 #endif
23010 default: /* Invalid */
23011 MIPS_INVAL("special_r6");
23012 generate_exception_end(ctx, EXCP_RI);
23013 break;
23017 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23019 int rs, rt, rd, sa;
23020 uint32_t op1;
23022 rs = (ctx->opcode >> 21) & 0x1f;
23023 rt = (ctx->opcode >> 16) & 0x1f;
23024 rd = (ctx->opcode >> 11) & 0x1f;
23025 sa = (ctx->opcode >> 6) & 0x1f;
23027 op1 = MASK_SPECIAL(ctx->opcode);
23028 switch (op1) {
23029 case OPC_MOVN: /* Conditional move */
23030 case OPC_MOVZ:
23031 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23032 INSN_LOONGSON2E | INSN_LOONGSON2F);
23033 gen_cond_move(ctx, op1, rd, rs, rt);
23034 break;
23035 case OPC_MFHI: /* Move from HI/LO */
23036 case OPC_MFLO:
23037 gen_HILO(ctx, op1, rs & 3, rd);
23038 break;
23039 case OPC_MTHI:
23040 case OPC_MTLO: /* Move to HI/LO */
23041 gen_HILO(ctx, op1, rd & 3, rs);
23042 break;
23043 case OPC_MOVCI:
23044 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23045 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23046 check_cp1_enabled(ctx);
23047 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23048 (ctx->opcode >> 16) & 1);
23049 } else {
23050 generate_exception_err(ctx, EXCP_CpU, 1);
23052 break;
23053 case OPC_MULT:
23054 case OPC_MULTU:
23055 if (sa) {
23056 check_insn(ctx, INSN_VR54XX);
23057 op1 = MASK_MUL_VR54XX(ctx->opcode);
23058 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23059 } else {
23060 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23062 break;
23063 case OPC_DIV:
23064 case OPC_DIVU:
23065 gen_muldiv(ctx, op1, 0, rs, rt);
23066 break;
23067 #if defined(TARGET_MIPS64)
23068 case OPC_DMULT:
23069 case OPC_DMULTU:
23070 case OPC_DDIV:
23071 case OPC_DDIVU:
23072 check_insn(ctx, ISA_MIPS3);
23073 check_mips_64(ctx);
23074 gen_muldiv(ctx, op1, 0, rs, rt);
23075 break;
23076 #endif
23077 case OPC_JR:
23078 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23079 break;
23080 case OPC_SPIM:
23081 #ifdef MIPS_STRICT_STANDARD
23082 MIPS_INVAL("SPIM");
23083 generate_exception_end(ctx, EXCP_RI);
23084 #else
23085 /* Implemented as RI exception for now. */
23086 MIPS_INVAL("spim (unofficial)");
23087 generate_exception_end(ctx, EXCP_RI);
23088 #endif
23089 break;
23090 default: /* Invalid */
23091 MIPS_INVAL("special_legacy");
23092 generate_exception_end(ctx, EXCP_RI);
23093 break;
23097 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23099 int rs, rt, rd, sa;
23100 uint32_t op1;
23102 rs = (ctx->opcode >> 21) & 0x1f;
23103 rt = (ctx->opcode >> 16) & 0x1f;
23104 rd = (ctx->opcode >> 11) & 0x1f;
23105 sa = (ctx->opcode >> 6) & 0x1f;
23107 op1 = MASK_SPECIAL(ctx->opcode);
23108 switch (op1) {
23109 case OPC_SLL: /* Shift with immediate */
23110 if (sa == 5 && rd == 0 &&
23111 rs == 0 && rt == 0) { /* PAUSE */
23112 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23113 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23114 generate_exception_end(ctx, EXCP_RI);
23115 break;
23118 /* Fallthrough */
23119 case OPC_SRA:
23120 gen_shift_imm(ctx, op1, rd, rt, sa);
23121 break;
23122 case OPC_SRL:
23123 switch ((ctx->opcode >> 21) & 0x1f) {
23124 case 1:
23125 /* rotr is decoded as srl on non-R2 CPUs */
23126 if (ctx->insn_flags & ISA_MIPS32R2) {
23127 op1 = OPC_ROTR;
23129 /* Fallthrough */
23130 case 0:
23131 gen_shift_imm(ctx, op1, rd, rt, sa);
23132 break;
23133 default:
23134 generate_exception_end(ctx, EXCP_RI);
23135 break;
23137 break;
23138 case OPC_ADD:
23139 case OPC_ADDU:
23140 case OPC_SUB:
23141 case OPC_SUBU:
23142 gen_arith(ctx, op1, rd, rs, rt);
23143 break;
23144 case OPC_SLLV: /* Shifts */
23145 case OPC_SRAV:
23146 gen_shift(ctx, op1, rd, rs, rt);
23147 break;
23148 case OPC_SRLV:
23149 switch ((ctx->opcode >> 6) & 0x1f) {
23150 case 1:
23151 /* rotrv is decoded as srlv on non-R2 CPUs */
23152 if (ctx->insn_flags & ISA_MIPS32R2) {
23153 op1 = OPC_ROTRV;
23155 /* Fallthrough */
23156 case 0:
23157 gen_shift(ctx, op1, rd, rs, rt);
23158 break;
23159 default:
23160 generate_exception_end(ctx, EXCP_RI);
23161 break;
23163 break;
23164 case OPC_SLT: /* Set on less than */
23165 case OPC_SLTU:
23166 gen_slt(ctx, op1, rd, rs, rt);
23167 break;
23168 case OPC_AND: /* Logic*/
23169 case OPC_OR:
23170 case OPC_NOR:
23171 case OPC_XOR:
23172 gen_logic(ctx, op1, rd, rs, rt);
23173 break;
23174 case OPC_JALR:
23175 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23176 break;
23177 case OPC_TGE: /* Traps */
23178 case OPC_TGEU:
23179 case OPC_TLT:
23180 case OPC_TLTU:
23181 case OPC_TEQ:
23182 case OPC_TNE:
23183 check_insn(ctx, ISA_MIPS2);
23184 gen_trap(ctx, op1, rs, rt, -1);
23185 break;
23186 case OPC_LSA: /* OPC_PMON */
23187 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23188 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23189 decode_opc_special_r6(env, ctx);
23190 } else {
23191 /* Pmon entry point, also R4010 selsl */
23192 #ifdef MIPS_STRICT_STANDARD
23193 MIPS_INVAL("PMON / selsl");
23194 generate_exception_end(ctx, EXCP_RI);
23195 #else
23196 gen_helper_0e0i(pmon, sa);
23197 #endif
23199 break;
23200 case OPC_SYSCALL:
23201 generate_exception_end(ctx, EXCP_SYSCALL);
23202 break;
23203 case OPC_BREAK:
23204 generate_exception_end(ctx, EXCP_BREAK);
23205 break;
23206 case OPC_SYNC:
23207 check_insn(ctx, ISA_MIPS2);
23208 gen_sync(extract32(ctx->opcode, 6, 5));
23209 break;
23211 #if defined(TARGET_MIPS64)
23212 /* MIPS64 specific opcodes */
23213 case OPC_DSLL:
23214 case OPC_DSRA:
23215 case OPC_DSLL32:
23216 case OPC_DSRA32:
23217 check_insn(ctx, ISA_MIPS3);
23218 check_mips_64(ctx);
23219 gen_shift_imm(ctx, op1, rd, rt, sa);
23220 break;
23221 case OPC_DSRL:
23222 switch ((ctx->opcode >> 21) & 0x1f) {
23223 case 1:
23224 /* drotr is decoded as dsrl on non-R2 CPUs */
23225 if (ctx->insn_flags & ISA_MIPS32R2) {
23226 op1 = OPC_DROTR;
23228 /* Fallthrough */
23229 case 0:
23230 check_insn(ctx, ISA_MIPS3);
23231 check_mips_64(ctx);
23232 gen_shift_imm(ctx, op1, rd, rt, sa);
23233 break;
23234 default:
23235 generate_exception_end(ctx, EXCP_RI);
23236 break;
23238 break;
23239 case OPC_DSRL32:
23240 switch ((ctx->opcode >> 21) & 0x1f) {
23241 case 1:
23242 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23243 if (ctx->insn_flags & ISA_MIPS32R2) {
23244 op1 = OPC_DROTR32;
23246 /* Fallthrough */
23247 case 0:
23248 check_insn(ctx, ISA_MIPS3);
23249 check_mips_64(ctx);
23250 gen_shift_imm(ctx, op1, rd, rt, sa);
23251 break;
23252 default:
23253 generate_exception_end(ctx, EXCP_RI);
23254 break;
23256 break;
23257 case OPC_DADD:
23258 case OPC_DADDU:
23259 case OPC_DSUB:
23260 case OPC_DSUBU:
23261 check_insn(ctx, ISA_MIPS3);
23262 check_mips_64(ctx);
23263 gen_arith(ctx, op1, rd, rs, rt);
23264 break;
23265 case OPC_DSLLV:
23266 case OPC_DSRAV:
23267 check_insn(ctx, ISA_MIPS3);
23268 check_mips_64(ctx);
23269 gen_shift(ctx, op1, rd, rs, rt);
23270 break;
23271 case OPC_DSRLV:
23272 switch ((ctx->opcode >> 6) & 0x1f) {
23273 case 1:
23274 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23275 if (ctx->insn_flags & ISA_MIPS32R2) {
23276 op1 = OPC_DROTRV;
23278 /* Fallthrough */
23279 case 0:
23280 check_insn(ctx, ISA_MIPS3);
23281 check_mips_64(ctx);
23282 gen_shift(ctx, op1, rd, rs, rt);
23283 break;
23284 default:
23285 generate_exception_end(ctx, EXCP_RI);
23286 break;
23288 break;
23289 case OPC_DLSA:
23290 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23291 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23292 decode_opc_special_r6(env, ctx);
23294 break;
23295 #endif
23296 default:
23297 if (ctx->insn_flags & ISA_MIPS32R6) {
23298 decode_opc_special_r6(env, ctx);
23299 } else {
23300 decode_opc_special_legacy(env, ctx);
23305 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23307 int rs, rt, rd;
23308 uint32_t op1;
23310 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23312 rs = (ctx->opcode >> 21) & 0x1f;
23313 rt = (ctx->opcode >> 16) & 0x1f;
23314 rd = (ctx->opcode >> 11) & 0x1f;
23316 op1 = MASK_SPECIAL2(ctx->opcode);
23317 switch (op1) {
23318 case OPC_MADD: /* Multiply and add/sub */
23319 case OPC_MADDU:
23320 case OPC_MSUB:
23321 case OPC_MSUBU:
23322 check_insn(ctx, ISA_MIPS32);
23323 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23324 break;
23325 case OPC_MUL:
23326 gen_arith(ctx, op1, rd, rs, rt);
23327 break;
23328 case OPC_DIV_G_2F:
23329 case OPC_DIVU_G_2F:
23330 case OPC_MULT_G_2F:
23331 case OPC_MULTU_G_2F:
23332 case OPC_MOD_G_2F:
23333 case OPC_MODU_G_2F:
23334 check_insn(ctx, INSN_LOONGSON2F);
23335 gen_loongson_integer(ctx, op1, rd, rs, rt);
23336 break;
23337 case OPC_CLO:
23338 case OPC_CLZ:
23339 check_insn(ctx, ISA_MIPS32);
23340 gen_cl(ctx, op1, rd, rs);
23341 break;
23342 case OPC_SDBBP:
23343 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23344 gen_helper_do_semihosting(cpu_env);
23345 } else {
23346 /* XXX: not clear which exception should be raised
23347 * when in debug mode...
23349 check_insn(ctx, ISA_MIPS32);
23350 generate_exception_end(ctx, EXCP_DBp);
23352 break;
23353 #if defined(TARGET_MIPS64)
23354 case OPC_DCLO:
23355 case OPC_DCLZ:
23356 check_insn(ctx, ISA_MIPS64);
23357 check_mips_64(ctx);
23358 gen_cl(ctx, op1, rd, rs);
23359 break;
23360 case OPC_DMULT_G_2F:
23361 case OPC_DMULTU_G_2F:
23362 case OPC_DDIV_G_2F:
23363 case OPC_DDIVU_G_2F:
23364 case OPC_DMOD_G_2F:
23365 case OPC_DMODU_G_2F:
23366 check_insn(ctx, INSN_LOONGSON2F);
23367 gen_loongson_integer(ctx, op1, rd, rs, rt);
23368 break;
23369 #endif
23370 default: /* Invalid */
23371 MIPS_INVAL("special2_legacy");
23372 generate_exception_end(ctx, EXCP_RI);
23373 break;
23377 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23379 int rs, rt, rd, sa;
23380 uint32_t op1, op2;
23381 int16_t imm;
23383 rs = (ctx->opcode >> 21) & 0x1f;
23384 rt = (ctx->opcode >> 16) & 0x1f;
23385 rd = (ctx->opcode >> 11) & 0x1f;
23386 sa = (ctx->opcode >> 6) & 0x1f;
23387 imm = (int16_t)ctx->opcode >> 7;
23389 op1 = MASK_SPECIAL3(ctx->opcode);
23390 switch (op1) {
23391 case R6_OPC_PREF:
23392 if (rt >= 24) {
23393 /* hint codes 24-31 are reserved and signal RI */
23394 generate_exception_end(ctx, EXCP_RI);
23396 /* Treat as NOP. */
23397 break;
23398 case R6_OPC_CACHE:
23399 check_cp0_enabled(ctx);
23400 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23401 gen_cache_operation(ctx, rt, rs, imm);
23403 break;
23404 case R6_OPC_SC:
23405 gen_st_cond(ctx, op1, rt, rs, imm);
23406 break;
23407 case R6_OPC_LL:
23408 gen_ld(ctx, op1, rt, rs, imm);
23409 break;
23410 case OPC_BSHFL:
23412 if (rd == 0) {
23413 /* Treat as NOP. */
23414 break;
23416 op2 = MASK_BSHFL(ctx->opcode);
23417 switch (op2) {
23418 case OPC_ALIGN:
23419 case OPC_ALIGN_END:
23420 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23421 break;
23422 case OPC_BITSWAP:
23423 gen_bitswap(ctx, op2, rd, rt);
23424 break;
23427 break;
23428 #if defined(TARGET_MIPS64)
23429 case R6_OPC_SCD:
23430 gen_st_cond(ctx, op1, rt, rs, imm);
23431 break;
23432 case R6_OPC_LLD:
23433 gen_ld(ctx, op1, rt, rs, imm);
23434 break;
23435 case OPC_DBSHFL:
23436 check_mips_64(ctx);
23438 if (rd == 0) {
23439 /* Treat as NOP. */
23440 break;
23442 op2 = MASK_DBSHFL(ctx->opcode);
23443 switch (op2) {
23444 case OPC_DALIGN:
23445 case OPC_DALIGN_END:
23446 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23447 break;
23448 case OPC_DBITSWAP:
23449 gen_bitswap(ctx, op2, rd, rt);
23450 break;
23454 break;
23455 #endif
23456 default: /* Invalid */
23457 MIPS_INVAL("special3_r6");
23458 generate_exception_end(ctx, EXCP_RI);
23459 break;
23463 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23465 int rs, rt, rd;
23466 uint32_t op1, op2;
23468 rs = (ctx->opcode >> 21) & 0x1f;
23469 rt = (ctx->opcode >> 16) & 0x1f;
23470 rd = (ctx->opcode >> 11) & 0x1f;
23472 op1 = MASK_SPECIAL3(ctx->opcode);
23473 switch (op1) {
23474 case OPC_DIV_G_2E:
23475 case OPC_DIVU_G_2E:
23476 case OPC_MOD_G_2E:
23477 case OPC_MODU_G_2E:
23478 case OPC_MULT_G_2E:
23479 case OPC_MULTU_G_2E:
23480 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23481 * the same mask and op1. */
23482 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
23483 op2 = MASK_ADDUH_QB(ctx->opcode);
23484 switch (op2) {
23485 case OPC_ADDUH_QB:
23486 case OPC_ADDUH_R_QB:
23487 case OPC_ADDQH_PH:
23488 case OPC_ADDQH_R_PH:
23489 case OPC_ADDQH_W:
23490 case OPC_ADDQH_R_W:
23491 case OPC_SUBUH_QB:
23492 case OPC_SUBUH_R_QB:
23493 case OPC_SUBQH_PH:
23494 case OPC_SUBQH_R_PH:
23495 case OPC_SUBQH_W:
23496 case OPC_SUBQH_R_W:
23497 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23498 break;
23499 case OPC_MUL_PH:
23500 case OPC_MUL_S_PH:
23501 case OPC_MULQ_S_W:
23502 case OPC_MULQ_RS_W:
23503 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23504 break;
23505 default:
23506 MIPS_INVAL("MASK ADDUH.QB");
23507 generate_exception_end(ctx, EXCP_RI);
23508 break;
23510 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23511 gen_loongson_integer(ctx, op1, rd, rs, rt);
23512 } else {
23513 generate_exception_end(ctx, EXCP_RI);
23515 break;
23516 case OPC_LX_DSP:
23517 op2 = MASK_LX(ctx->opcode);
23518 switch (op2) {
23519 #if defined(TARGET_MIPS64)
23520 case OPC_LDX:
23521 #endif
23522 case OPC_LBUX:
23523 case OPC_LHX:
23524 case OPC_LWX:
23525 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23526 break;
23527 default: /* Invalid */
23528 MIPS_INVAL("MASK LX");
23529 generate_exception_end(ctx, EXCP_RI);
23530 break;
23532 break;
23533 case OPC_ABSQ_S_PH_DSP:
23534 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23535 switch (op2) {
23536 case OPC_ABSQ_S_QB:
23537 case OPC_ABSQ_S_PH:
23538 case OPC_ABSQ_S_W:
23539 case OPC_PRECEQ_W_PHL:
23540 case OPC_PRECEQ_W_PHR:
23541 case OPC_PRECEQU_PH_QBL:
23542 case OPC_PRECEQU_PH_QBR:
23543 case OPC_PRECEQU_PH_QBLA:
23544 case OPC_PRECEQU_PH_QBRA:
23545 case OPC_PRECEU_PH_QBL:
23546 case OPC_PRECEU_PH_QBR:
23547 case OPC_PRECEU_PH_QBLA:
23548 case OPC_PRECEU_PH_QBRA:
23549 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23550 break;
23551 case OPC_BITREV:
23552 case OPC_REPL_QB:
23553 case OPC_REPLV_QB:
23554 case OPC_REPL_PH:
23555 case OPC_REPLV_PH:
23556 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23557 break;
23558 default:
23559 MIPS_INVAL("MASK ABSQ_S.PH");
23560 generate_exception_end(ctx, EXCP_RI);
23561 break;
23563 break;
23564 case OPC_ADDU_QB_DSP:
23565 op2 = MASK_ADDU_QB(ctx->opcode);
23566 switch (op2) {
23567 case OPC_ADDQ_PH:
23568 case OPC_ADDQ_S_PH:
23569 case OPC_ADDQ_S_W:
23570 case OPC_ADDU_QB:
23571 case OPC_ADDU_S_QB:
23572 case OPC_ADDU_PH:
23573 case OPC_ADDU_S_PH:
23574 case OPC_SUBQ_PH:
23575 case OPC_SUBQ_S_PH:
23576 case OPC_SUBQ_S_W:
23577 case OPC_SUBU_QB:
23578 case OPC_SUBU_S_QB:
23579 case OPC_SUBU_PH:
23580 case OPC_SUBU_S_PH:
23581 case OPC_ADDSC:
23582 case OPC_ADDWC:
23583 case OPC_MODSUB:
23584 case OPC_RADDU_W_QB:
23585 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23586 break;
23587 case OPC_MULEU_S_PH_QBL:
23588 case OPC_MULEU_S_PH_QBR:
23589 case OPC_MULQ_RS_PH:
23590 case OPC_MULEQ_S_W_PHL:
23591 case OPC_MULEQ_S_W_PHR:
23592 case OPC_MULQ_S_PH:
23593 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23594 break;
23595 default: /* Invalid */
23596 MIPS_INVAL("MASK ADDU.QB");
23597 generate_exception_end(ctx, EXCP_RI);
23598 break;
23601 break;
23602 case OPC_CMPU_EQ_QB_DSP:
23603 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
23604 switch (op2) {
23605 case OPC_PRECR_SRA_PH_W:
23606 case OPC_PRECR_SRA_R_PH_W:
23607 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
23608 break;
23609 case OPC_PRECR_QB_PH:
23610 case OPC_PRECRQ_QB_PH:
23611 case OPC_PRECRQ_PH_W:
23612 case OPC_PRECRQ_RS_PH_W:
23613 case OPC_PRECRQU_S_QB_PH:
23614 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23615 break;
23616 case OPC_CMPU_EQ_QB:
23617 case OPC_CMPU_LT_QB:
23618 case OPC_CMPU_LE_QB:
23619 case OPC_CMP_EQ_PH:
23620 case OPC_CMP_LT_PH:
23621 case OPC_CMP_LE_PH:
23622 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
23623 break;
23624 case OPC_CMPGU_EQ_QB:
23625 case OPC_CMPGU_LT_QB:
23626 case OPC_CMPGU_LE_QB:
23627 case OPC_CMPGDU_EQ_QB:
23628 case OPC_CMPGDU_LT_QB:
23629 case OPC_CMPGDU_LE_QB:
23630 case OPC_PICK_QB:
23631 case OPC_PICK_PH:
23632 case OPC_PACKRL_PH:
23633 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
23634 break;
23635 default: /* Invalid */
23636 MIPS_INVAL("MASK CMPU.EQ.QB");
23637 generate_exception_end(ctx, EXCP_RI);
23638 break;
23640 break;
23641 case OPC_SHLL_QB_DSP:
23642 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23643 break;
23644 case OPC_DPA_W_PH_DSP:
23645 op2 = MASK_DPA_W_PH(ctx->opcode);
23646 switch (op2) {
23647 case OPC_DPAU_H_QBL:
23648 case OPC_DPAU_H_QBR:
23649 case OPC_DPSU_H_QBL:
23650 case OPC_DPSU_H_QBR:
23651 case OPC_DPA_W_PH:
23652 case OPC_DPAX_W_PH:
23653 case OPC_DPAQ_S_W_PH:
23654 case OPC_DPAQX_S_W_PH:
23655 case OPC_DPAQX_SA_W_PH:
23656 case OPC_DPS_W_PH:
23657 case OPC_DPSX_W_PH:
23658 case OPC_DPSQ_S_W_PH:
23659 case OPC_DPSQX_S_W_PH:
23660 case OPC_DPSQX_SA_W_PH:
23661 case OPC_MULSAQ_S_W_PH:
23662 case OPC_DPAQ_SA_L_W:
23663 case OPC_DPSQ_SA_L_W:
23664 case OPC_MAQ_S_W_PHL:
23665 case OPC_MAQ_S_W_PHR:
23666 case OPC_MAQ_SA_W_PHL:
23667 case OPC_MAQ_SA_W_PHR:
23668 case OPC_MULSA_W_PH:
23669 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23670 break;
23671 default: /* Invalid */
23672 MIPS_INVAL("MASK DPAW.PH");
23673 generate_exception_end(ctx, EXCP_RI);
23674 break;
23676 break;
23677 case OPC_INSV_DSP:
23678 op2 = MASK_INSV(ctx->opcode);
23679 switch (op2) {
23680 case OPC_INSV:
23681 check_dsp(ctx);
23683 TCGv t0, t1;
23685 if (rt == 0) {
23686 break;
23689 t0 = tcg_temp_new();
23690 t1 = tcg_temp_new();
23692 gen_load_gpr(t0, rt);
23693 gen_load_gpr(t1, rs);
23695 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
23697 tcg_temp_free(t0);
23698 tcg_temp_free(t1);
23699 break;
23701 default: /* Invalid */
23702 MIPS_INVAL("MASK INSV");
23703 generate_exception_end(ctx, EXCP_RI);
23704 break;
23706 break;
23707 case OPC_APPEND_DSP:
23708 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23709 break;
23710 case OPC_EXTR_W_DSP:
23711 op2 = MASK_EXTR_W(ctx->opcode);
23712 switch (op2) {
23713 case OPC_EXTR_W:
23714 case OPC_EXTR_R_W:
23715 case OPC_EXTR_RS_W:
23716 case OPC_EXTR_S_H:
23717 case OPC_EXTRV_S_H:
23718 case OPC_EXTRV_W:
23719 case OPC_EXTRV_R_W:
23720 case OPC_EXTRV_RS_W:
23721 case OPC_EXTP:
23722 case OPC_EXTPV:
23723 case OPC_EXTPDP:
23724 case OPC_EXTPDPV:
23725 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23726 break;
23727 case OPC_RDDSP:
23728 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
23729 break;
23730 case OPC_SHILO:
23731 case OPC_SHILOV:
23732 case OPC_MTHLIP:
23733 case OPC_WRDSP:
23734 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23735 break;
23736 default: /* Invalid */
23737 MIPS_INVAL("MASK EXTR.W");
23738 generate_exception_end(ctx, EXCP_RI);
23739 break;
23741 break;
23742 #if defined(TARGET_MIPS64)
23743 case OPC_DDIV_G_2E:
23744 case OPC_DDIVU_G_2E:
23745 case OPC_DMULT_G_2E:
23746 case OPC_DMULTU_G_2E:
23747 case OPC_DMOD_G_2E:
23748 case OPC_DMODU_G_2E:
23749 check_insn(ctx, INSN_LOONGSON2E);
23750 gen_loongson_integer(ctx, op1, rd, rs, rt);
23751 break;
23752 case OPC_ABSQ_S_QH_DSP:
23753 op2 = MASK_ABSQ_S_QH(ctx->opcode);
23754 switch (op2) {
23755 case OPC_PRECEQ_L_PWL:
23756 case OPC_PRECEQ_L_PWR:
23757 case OPC_PRECEQ_PW_QHL:
23758 case OPC_PRECEQ_PW_QHR:
23759 case OPC_PRECEQ_PW_QHLA:
23760 case OPC_PRECEQ_PW_QHRA:
23761 case OPC_PRECEQU_QH_OBL:
23762 case OPC_PRECEQU_QH_OBR:
23763 case OPC_PRECEQU_QH_OBLA:
23764 case OPC_PRECEQU_QH_OBRA:
23765 case OPC_PRECEU_QH_OBL:
23766 case OPC_PRECEU_QH_OBR:
23767 case OPC_PRECEU_QH_OBLA:
23768 case OPC_PRECEU_QH_OBRA:
23769 case OPC_ABSQ_S_OB:
23770 case OPC_ABSQ_S_PW:
23771 case OPC_ABSQ_S_QH:
23772 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23773 break;
23774 case OPC_REPL_OB:
23775 case OPC_REPL_PW:
23776 case OPC_REPL_QH:
23777 case OPC_REPLV_OB:
23778 case OPC_REPLV_PW:
23779 case OPC_REPLV_QH:
23780 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23781 break;
23782 default: /* Invalid */
23783 MIPS_INVAL("MASK ABSQ_S.QH");
23784 generate_exception_end(ctx, EXCP_RI);
23785 break;
23787 break;
23788 case OPC_ADDU_OB_DSP:
23789 op2 = MASK_ADDU_OB(ctx->opcode);
23790 switch (op2) {
23791 case OPC_RADDU_L_OB:
23792 case OPC_SUBQ_PW:
23793 case OPC_SUBQ_S_PW:
23794 case OPC_SUBQ_QH:
23795 case OPC_SUBQ_S_QH:
23796 case OPC_SUBU_OB:
23797 case OPC_SUBU_S_OB:
23798 case OPC_SUBU_QH:
23799 case OPC_SUBU_S_QH:
23800 case OPC_SUBUH_OB:
23801 case OPC_SUBUH_R_OB:
23802 case OPC_ADDQ_PW:
23803 case OPC_ADDQ_S_PW:
23804 case OPC_ADDQ_QH:
23805 case OPC_ADDQ_S_QH:
23806 case OPC_ADDU_OB:
23807 case OPC_ADDU_S_OB:
23808 case OPC_ADDU_QH:
23809 case OPC_ADDU_S_QH:
23810 case OPC_ADDUH_OB:
23811 case OPC_ADDUH_R_OB:
23812 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23813 break;
23814 case OPC_MULEQ_S_PW_QHL:
23815 case OPC_MULEQ_S_PW_QHR:
23816 case OPC_MULEU_S_QH_OBL:
23817 case OPC_MULEU_S_QH_OBR:
23818 case OPC_MULQ_RS_QH:
23819 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23820 break;
23821 default: /* Invalid */
23822 MIPS_INVAL("MASK ADDU.OB");
23823 generate_exception_end(ctx, EXCP_RI);
23824 break;
23826 break;
23827 case OPC_CMPU_EQ_OB_DSP:
23828 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
23829 switch (op2) {
23830 case OPC_PRECR_SRA_QH_PW:
23831 case OPC_PRECR_SRA_R_QH_PW:
23832 /* Return value is rt. */
23833 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
23834 break;
23835 case OPC_PRECR_OB_QH:
23836 case OPC_PRECRQ_OB_QH:
23837 case OPC_PRECRQ_PW_L:
23838 case OPC_PRECRQ_QH_PW:
23839 case OPC_PRECRQ_RS_QH_PW:
23840 case OPC_PRECRQU_S_OB_QH:
23841 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23842 break;
23843 case OPC_CMPU_EQ_OB:
23844 case OPC_CMPU_LT_OB:
23845 case OPC_CMPU_LE_OB:
23846 case OPC_CMP_EQ_QH:
23847 case OPC_CMP_LT_QH:
23848 case OPC_CMP_LE_QH:
23849 case OPC_CMP_EQ_PW:
23850 case OPC_CMP_LT_PW:
23851 case OPC_CMP_LE_PW:
23852 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
23853 break;
23854 case OPC_CMPGDU_EQ_OB:
23855 case OPC_CMPGDU_LT_OB:
23856 case OPC_CMPGDU_LE_OB:
23857 case OPC_CMPGU_EQ_OB:
23858 case OPC_CMPGU_LT_OB:
23859 case OPC_CMPGU_LE_OB:
23860 case OPC_PACKRL_PW:
23861 case OPC_PICK_OB:
23862 case OPC_PICK_PW:
23863 case OPC_PICK_QH:
23864 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
23865 break;
23866 default: /* Invalid */
23867 MIPS_INVAL("MASK CMPU_EQ.OB");
23868 generate_exception_end(ctx, EXCP_RI);
23869 break;
23871 break;
23872 case OPC_DAPPEND_DSP:
23873 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23874 break;
23875 case OPC_DEXTR_W_DSP:
23876 op2 = MASK_DEXTR_W(ctx->opcode);
23877 switch (op2) {
23878 case OPC_DEXTP:
23879 case OPC_DEXTPDP:
23880 case OPC_DEXTPDPV:
23881 case OPC_DEXTPV:
23882 case OPC_DEXTR_L:
23883 case OPC_DEXTR_R_L:
23884 case OPC_DEXTR_RS_L:
23885 case OPC_DEXTR_W:
23886 case OPC_DEXTR_R_W:
23887 case OPC_DEXTR_RS_W:
23888 case OPC_DEXTR_S_H:
23889 case OPC_DEXTRV_L:
23890 case OPC_DEXTRV_R_L:
23891 case OPC_DEXTRV_RS_L:
23892 case OPC_DEXTRV_S_H:
23893 case OPC_DEXTRV_W:
23894 case OPC_DEXTRV_R_W:
23895 case OPC_DEXTRV_RS_W:
23896 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23897 break;
23898 case OPC_DMTHLIP:
23899 case OPC_DSHILO:
23900 case OPC_DSHILOV:
23901 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23902 break;
23903 default: /* Invalid */
23904 MIPS_INVAL("MASK EXTR.W");
23905 generate_exception_end(ctx, EXCP_RI);
23906 break;
23908 break;
23909 case OPC_DPAQ_W_QH_DSP:
23910 op2 = MASK_DPAQ_W_QH(ctx->opcode);
23911 switch (op2) {
23912 case OPC_DPAU_H_OBL:
23913 case OPC_DPAU_H_OBR:
23914 case OPC_DPSU_H_OBL:
23915 case OPC_DPSU_H_OBR:
23916 case OPC_DPA_W_QH:
23917 case OPC_DPAQ_S_W_QH:
23918 case OPC_DPS_W_QH:
23919 case OPC_DPSQ_S_W_QH:
23920 case OPC_MULSAQ_S_W_QH:
23921 case OPC_DPAQ_SA_L_PW:
23922 case OPC_DPSQ_SA_L_PW:
23923 case OPC_MULSAQ_S_L_PW:
23924 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23925 break;
23926 case OPC_MAQ_S_W_QHLL:
23927 case OPC_MAQ_S_W_QHLR:
23928 case OPC_MAQ_S_W_QHRL:
23929 case OPC_MAQ_S_W_QHRR:
23930 case OPC_MAQ_SA_W_QHLL:
23931 case OPC_MAQ_SA_W_QHLR:
23932 case OPC_MAQ_SA_W_QHRL:
23933 case OPC_MAQ_SA_W_QHRR:
23934 case OPC_MAQ_S_L_PWL:
23935 case OPC_MAQ_S_L_PWR:
23936 case OPC_DMADD:
23937 case OPC_DMADDU:
23938 case OPC_DMSUB:
23939 case OPC_DMSUBU:
23940 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23941 break;
23942 default: /* Invalid */
23943 MIPS_INVAL("MASK DPAQ.W.QH");
23944 generate_exception_end(ctx, EXCP_RI);
23945 break;
23947 break;
23948 case OPC_DINSV_DSP:
23949 op2 = MASK_INSV(ctx->opcode);
23950 switch (op2) {
23951 case OPC_DINSV:
23953 TCGv t0, t1;
23955 if (rt == 0) {
23956 break;
23958 check_dsp(ctx);
23960 t0 = tcg_temp_new();
23961 t1 = tcg_temp_new();
23963 gen_load_gpr(t0, rt);
23964 gen_load_gpr(t1, rs);
23966 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
23968 tcg_temp_free(t0);
23969 tcg_temp_free(t1);
23970 break;
23972 default: /* Invalid */
23973 MIPS_INVAL("MASK DINSV");
23974 generate_exception_end(ctx, EXCP_RI);
23975 break;
23977 break;
23978 case OPC_SHLL_OB_DSP:
23979 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23980 break;
23981 #endif
23982 default: /* Invalid */
23983 MIPS_INVAL("special3_legacy");
23984 generate_exception_end(ctx, EXCP_RI);
23985 break;
23989 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
23991 int rs, rt, rd, sa;
23992 uint32_t op1, op2;
23993 int16_t imm;
23995 rs = (ctx->opcode >> 21) & 0x1f;
23996 rt = (ctx->opcode >> 16) & 0x1f;
23997 rd = (ctx->opcode >> 11) & 0x1f;
23998 sa = (ctx->opcode >> 6) & 0x1f;
23999 imm = sextract32(ctx->opcode, 7, 9);
24001 op1 = MASK_SPECIAL3(ctx->opcode);
24004 * EVA loads and stores overlap Loongson 2E instructions decoded by
24005 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24006 * EVA is absent.
24008 if (ctx->eva) {
24009 switch (op1) {
24010 case OPC_LWLE:
24011 case OPC_LWRE:
24012 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24013 /* fall through */
24014 case OPC_LBUE:
24015 case OPC_LHUE:
24016 case OPC_LBE:
24017 case OPC_LHE:
24018 case OPC_LLE:
24019 case OPC_LWE:
24020 check_cp0_enabled(ctx);
24021 gen_ld(ctx, op1, rt, rs, imm);
24022 return;
24023 case OPC_SWLE:
24024 case OPC_SWRE:
24025 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24026 /* fall through */
24027 case OPC_SBE:
24028 case OPC_SHE:
24029 case OPC_SWE:
24030 check_cp0_enabled(ctx);
24031 gen_st(ctx, op1, rt, rs, imm);
24032 return;
24033 case OPC_SCE:
24034 check_cp0_enabled(ctx);
24035 gen_st_cond(ctx, op1, rt, rs, imm);
24036 return;
24037 case OPC_CACHEE:
24038 check_cp0_enabled(ctx);
24039 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24040 gen_cache_operation(ctx, rt, rs, imm);
24042 /* Treat as NOP. */
24043 return;
24044 case OPC_PREFE:
24045 check_cp0_enabled(ctx);
24046 /* Treat as NOP. */
24047 return;
24051 switch (op1) {
24052 case OPC_EXT:
24053 case OPC_INS:
24054 check_insn(ctx, ISA_MIPS32R2);
24055 gen_bitops(ctx, op1, rt, rs, sa, rd);
24056 break;
24057 case OPC_BSHFL:
24058 op2 = MASK_BSHFL(ctx->opcode);
24059 switch (op2) {
24060 case OPC_ALIGN:
24061 case OPC_ALIGN_END:
24062 case OPC_BITSWAP:
24063 check_insn(ctx, ISA_MIPS32R6);
24064 decode_opc_special3_r6(env, ctx);
24065 break;
24066 default:
24067 check_insn(ctx, ISA_MIPS32R2);
24068 gen_bshfl(ctx, op2, rt, rd);
24069 break;
24071 break;
24072 #if defined(TARGET_MIPS64)
24073 case OPC_DEXTM:
24074 case OPC_DEXTU:
24075 case OPC_DEXT:
24076 case OPC_DINSM:
24077 case OPC_DINSU:
24078 case OPC_DINS:
24079 check_insn(ctx, ISA_MIPS64R2);
24080 check_mips_64(ctx);
24081 gen_bitops(ctx, op1, rt, rs, sa, rd);
24082 break;
24083 case OPC_DBSHFL:
24084 op2 = MASK_DBSHFL(ctx->opcode);
24085 switch (op2) {
24086 case OPC_DALIGN:
24087 case OPC_DALIGN_END:
24088 case OPC_DBITSWAP:
24089 check_insn(ctx, ISA_MIPS32R6);
24090 decode_opc_special3_r6(env, ctx);
24091 break;
24092 default:
24093 check_insn(ctx, ISA_MIPS64R2);
24094 check_mips_64(ctx);
24095 op2 = MASK_DBSHFL(ctx->opcode);
24096 gen_bshfl(ctx, op2, rt, rd);
24097 break;
24099 break;
24100 #endif
24101 case OPC_RDHWR:
24102 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24103 break;
24104 case OPC_FORK:
24105 check_mt(ctx);
24107 TCGv t0 = tcg_temp_new();
24108 TCGv t1 = tcg_temp_new();
24110 gen_load_gpr(t0, rt);
24111 gen_load_gpr(t1, rs);
24112 gen_helper_fork(t0, t1);
24113 tcg_temp_free(t0);
24114 tcg_temp_free(t1);
24116 break;
24117 case OPC_YIELD:
24118 check_mt(ctx);
24120 TCGv t0 = tcg_temp_new();
24122 gen_load_gpr(t0, rs);
24123 gen_helper_yield(t0, cpu_env, t0);
24124 gen_store_gpr(t0, rd);
24125 tcg_temp_free(t0);
24127 break;
24128 default:
24129 if (ctx->insn_flags & ISA_MIPS32R6) {
24130 decode_opc_special3_r6(env, ctx);
24131 } else {
24132 decode_opc_special3_legacy(env, ctx);
24137 /* MIPS SIMD Architecture (MSA) */
24138 static inline int check_msa_access(DisasContext *ctx)
24140 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
24141 !(ctx->hflags & MIPS_HFLAG_F64))) {
24142 generate_exception_end(ctx, EXCP_RI);
24143 return 0;
24146 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
24147 if (ctx->insn_flags & ASE_MSA) {
24148 generate_exception_end(ctx, EXCP_MSADIS);
24149 return 0;
24150 } else {
24151 generate_exception_end(ctx, EXCP_RI);
24152 return 0;
24155 return 1;
24158 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
24160 /* generates tcg ops to check if any element is 0 */
24161 /* Note this function only works with MSA_WRLEN = 128 */
24162 uint64_t eval_zero_or_big = 0;
24163 uint64_t eval_big = 0;
24164 TCGv_i64 t0 = tcg_temp_new_i64();
24165 TCGv_i64 t1 = tcg_temp_new_i64();
24166 switch (df) {
24167 case DF_BYTE:
24168 eval_zero_or_big = 0x0101010101010101ULL;
24169 eval_big = 0x8080808080808080ULL;
24170 break;
24171 case DF_HALF:
24172 eval_zero_or_big = 0x0001000100010001ULL;
24173 eval_big = 0x8000800080008000ULL;
24174 break;
24175 case DF_WORD:
24176 eval_zero_or_big = 0x0000000100000001ULL;
24177 eval_big = 0x8000000080000000ULL;
24178 break;
24179 case DF_DOUBLE:
24180 eval_zero_or_big = 0x0000000000000001ULL;
24181 eval_big = 0x8000000000000000ULL;
24182 break;
24184 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
24185 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
24186 tcg_gen_andi_i64(t0, t0, eval_big);
24187 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
24188 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
24189 tcg_gen_andi_i64(t1, t1, eval_big);
24190 tcg_gen_or_i64(t0, t0, t1);
24191 /* if all bits are zero then all elements are not zero */
24192 /* if some bit is non-zero then some element is zero */
24193 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
24194 tcg_gen_trunc_i64_tl(tresult, t0);
24195 tcg_temp_free_i64(t0);
24196 tcg_temp_free_i64(t1);
24199 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
24201 uint8_t df = (ctx->opcode >> 21) & 0x3;
24202 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24203 int64_t s16 = (int16_t)ctx->opcode;
24205 check_msa_access(ctx);
24207 if (ctx->hflags & MIPS_HFLAG_BMASK) {
24208 generate_exception_end(ctx, EXCP_RI);
24209 return;
24211 switch (op1) {
24212 case OPC_BZ_V:
24213 case OPC_BNZ_V:
24215 TCGv_i64 t0 = tcg_temp_new_i64();
24216 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
24217 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
24218 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
24219 tcg_gen_trunc_i64_tl(bcond, t0);
24220 tcg_temp_free_i64(t0);
24222 break;
24223 case OPC_BZ_B:
24224 case OPC_BZ_H:
24225 case OPC_BZ_W:
24226 case OPC_BZ_D:
24227 gen_check_zero_element(bcond, df, wt);
24228 break;
24229 case OPC_BNZ_B:
24230 case OPC_BNZ_H:
24231 case OPC_BNZ_W:
24232 case OPC_BNZ_D:
24233 gen_check_zero_element(bcond, df, wt);
24234 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
24235 break;
24238 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
24240 ctx->hflags |= MIPS_HFLAG_BC;
24241 ctx->hflags |= MIPS_HFLAG_BDS32;
24244 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
24246 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
24247 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
24248 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24249 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24251 TCGv_i32 twd = tcg_const_i32(wd);
24252 TCGv_i32 tws = tcg_const_i32(ws);
24253 TCGv_i32 ti8 = tcg_const_i32(i8);
24255 switch (MASK_MSA_I8(ctx->opcode)) {
24256 case OPC_ANDI_B:
24257 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
24258 break;
24259 case OPC_ORI_B:
24260 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
24261 break;
24262 case OPC_NORI_B:
24263 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
24264 break;
24265 case OPC_XORI_B:
24266 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
24267 break;
24268 case OPC_BMNZI_B:
24269 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
24270 break;
24271 case OPC_BMZI_B:
24272 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
24273 break;
24274 case OPC_BSELI_B:
24275 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
24276 break;
24277 case OPC_SHF_B:
24278 case OPC_SHF_H:
24279 case OPC_SHF_W:
24281 uint8_t df = (ctx->opcode >> 24) & 0x3;
24282 if (df == DF_DOUBLE) {
24283 generate_exception_end(ctx, EXCP_RI);
24284 } else {
24285 TCGv_i32 tdf = tcg_const_i32(df);
24286 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
24287 tcg_temp_free_i32(tdf);
24290 break;
24291 default:
24292 MIPS_INVAL("MSA instruction");
24293 generate_exception_end(ctx, EXCP_RI);
24294 break;
24297 tcg_temp_free_i32(twd);
24298 tcg_temp_free_i32(tws);
24299 tcg_temp_free_i32(ti8);
24302 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
24304 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24305 uint8_t df = (ctx->opcode >> 21) & 0x3;
24306 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
24307 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
24308 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24309 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24311 TCGv_i32 tdf = tcg_const_i32(df);
24312 TCGv_i32 twd = tcg_const_i32(wd);
24313 TCGv_i32 tws = tcg_const_i32(ws);
24314 TCGv_i32 timm = tcg_temp_new_i32();
24315 tcg_gen_movi_i32(timm, u5);
24317 switch (MASK_MSA_I5(ctx->opcode)) {
24318 case OPC_ADDVI_df:
24319 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
24320 break;
24321 case OPC_SUBVI_df:
24322 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
24323 break;
24324 case OPC_MAXI_S_df:
24325 tcg_gen_movi_i32(timm, s5);
24326 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
24327 break;
24328 case OPC_MAXI_U_df:
24329 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
24330 break;
24331 case OPC_MINI_S_df:
24332 tcg_gen_movi_i32(timm, s5);
24333 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
24334 break;
24335 case OPC_MINI_U_df:
24336 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
24337 break;
24338 case OPC_CEQI_df:
24339 tcg_gen_movi_i32(timm, s5);
24340 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
24341 break;
24342 case OPC_CLTI_S_df:
24343 tcg_gen_movi_i32(timm, s5);
24344 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
24345 break;
24346 case OPC_CLTI_U_df:
24347 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
24348 break;
24349 case OPC_CLEI_S_df:
24350 tcg_gen_movi_i32(timm, s5);
24351 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
24352 break;
24353 case OPC_CLEI_U_df:
24354 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
24355 break;
24356 case OPC_LDI_df:
24358 int32_t s10 = sextract32(ctx->opcode, 11, 10);
24359 tcg_gen_movi_i32(timm, s10);
24360 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
24362 break;
24363 default:
24364 MIPS_INVAL("MSA instruction");
24365 generate_exception_end(ctx, EXCP_RI);
24366 break;
24369 tcg_temp_free_i32(tdf);
24370 tcg_temp_free_i32(twd);
24371 tcg_temp_free_i32(tws);
24372 tcg_temp_free_i32(timm);
24375 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
24377 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24378 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
24379 uint32_t df = 0, m = 0;
24380 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24381 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24383 TCGv_i32 tdf;
24384 TCGv_i32 tm;
24385 TCGv_i32 twd;
24386 TCGv_i32 tws;
24388 if ((dfm & 0x40) == 0x00) {
24389 m = dfm & 0x3f;
24390 df = DF_DOUBLE;
24391 } else if ((dfm & 0x60) == 0x40) {
24392 m = dfm & 0x1f;
24393 df = DF_WORD;
24394 } else if ((dfm & 0x70) == 0x60) {
24395 m = dfm & 0x0f;
24396 df = DF_HALF;
24397 } else if ((dfm & 0x78) == 0x70) {
24398 m = dfm & 0x7;
24399 df = DF_BYTE;
24400 } else {
24401 generate_exception_end(ctx, EXCP_RI);
24402 return;
24405 tdf = tcg_const_i32(df);
24406 tm = tcg_const_i32(m);
24407 twd = tcg_const_i32(wd);
24408 tws = tcg_const_i32(ws);
24410 switch (MASK_MSA_BIT(ctx->opcode)) {
24411 case OPC_SLLI_df:
24412 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
24413 break;
24414 case OPC_SRAI_df:
24415 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
24416 break;
24417 case OPC_SRLI_df:
24418 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
24419 break;
24420 case OPC_BCLRI_df:
24421 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
24422 break;
24423 case OPC_BSETI_df:
24424 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
24425 break;
24426 case OPC_BNEGI_df:
24427 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
24428 break;
24429 case OPC_BINSLI_df:
24430 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
24431 break;
24432 case OPC_BINSRI_df:
24433 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
24434 break;
24435 case OPC_SAT_S_df:
24436 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
24437 break;
24438 case OPC_SAT_U_df:
24439 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
24440 break;
24441 case OPC_SRARI_df:
24442 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
24443 break;
24444 case OPC_SRLRI_df:
24445 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
24446 break;
24447 default:
24448 MIPS_INVAL("MSA instruction");
24449 generate_exception_end(ctx, EXCP_RI);
24450 break;
24453 tcg_temp_free_i32(tdf);
24454 tcg_temp_free_i32(tm);
24455 tcg_temp_free_i32(twd);
24456 tcg_temp_free_i32(tws);
24459 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
24461 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24462 uint8_t df = (ctx->opcode >> 21) & 0x3;
24463 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24464 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24465 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24467 TCGv_i32 tdf = tcg_const_i32(df);
24468 TCGv_i32 twd = tcg_const_i32(wd);
24469 TCGv_i32 tws = tcg_const_i32(ws);
24470 TCGv_i32 twt = tcg_const_i32(wt);
24472 switch (MASK_MSA_3R(ctx->opcode)) {
24473 case OPC_SLL_df:
24474 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
24475 break;
24476 case OPC_ADDV_df:
24477 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
24478 break;
24479 case OPC_CEQ_df:
24480 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
24481 break;
24482 case OPC_ADD_A_df:
24483 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
24484 break;
24485 case OPC_SUBS_S_df:
24486 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
24487 break;
24488 case OPC_MULV_df:
24489 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
24490 break;
24491 case OPC_SLD_df:
24492 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
24493 break;
24494 case OPC_VSHF_df:
24495 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
24496 break;
24497 case OPC_SRA_df:
24498 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
24499 break;
24500 case OPC_SUBV_df:
24501 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
24502 break;
24503 case OPC_ADDS_A_df:
24504 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
24505 break;
24506 case OPC_SUBS_U_df:
24507 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
24508 break;
24509 case OPC_MADDV_df:
24510 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
24511 break;
24512 case OPC_SPLAT_df:
24513 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
24514 break;
24515 case OPC_SRAR_df:
24516 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
24517 break;
24518 case OPC_SRL_df:
24519 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
24520 break;
24521 case OPC_MAX_S_df:
24522 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
24523 break;
24524 case OPC_CLT_S_df:
24525 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
24526 break;
24527 case OPC_ADDS_S_df:
24528 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
24529 break;
24530 case OPC_SUBSUS_U_df:
24531 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
24532 break;
24533 case OPC_MSUBV_df:
24534 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
24535 break;
24536 case OPC_PCKEV_df:
24537 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
24538 break;
24539 case OPC_SRLR_df:
24540 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
24541 break;
24542 case OPC_BCLR_df:
24543 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
24544 break;
24545 case OPC_MAX_U_df:
24546 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
24547 break;
24548 case OPC_CLT_U_df:
24549 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
24550 break;
24551 case OPC_ADDS_U_df:
24552 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
24553 break;
24554 case OPC_SUBSUU_S_df:
24555 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
24556 break;
24557 case OPC_PCKOD_df:
24558 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
24559 break;
24560 case OPC_BSET_df:
24561 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
24562 break;
24563 case OPC_MIN_S_df:
24564 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
24565 break;
24566 case OPC_CLE_S_df:
24567 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
24568 break;
24569 case OPC_AVE_S_df:
24570 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
24571 break;
24572 case OPC_ASUB_S_df:
24573 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
24574 break;
24575 case OPC_DIV_S_df:
24576 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
24577 break;
24578 case OPC_ILVL_df:
24579 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
24580 break;
24581 case OPC_BNEG_df:
24582 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
24583 break;
24584 case OPC_MIN_U_df:
24585 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
24586 break;
24587 case OPC_CLE_U_df:
24588 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
24589 break;
24590 case OPC_AVE_U_df:
24591 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
24592 break;
24593 case OPC_ASUB_U_df:
24594 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
24595 break;
24596 case OPC_DIV_U_df:
24597 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
24598 break;
24599 case OPC_ILVR_df:
24600 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
24601 break;
24602 case OPC_BINSL_df:
24603 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
24604 break;
24605 case OPC_MAX_A_df:
24606 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
24607 break;
24608 case OPC_AVER_S_df:
24609 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
24610 break;
24611 case OPC_MOD_S_df:
24612 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
24613 break;
24614 case OPC_ILVEV_df:
24615 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
24616 break;
24617 case OPC_BINSR_df:
24618 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
24619 break;
24620 case OPC_MIN_A_df:
24621 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
24622 break;
24623 case OPC_AVER_U_df:
24624 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
24625 break;
24626 case OPC_MOD_U_df:
24627 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
24628 break;
24629 case OPC_ILVOD_df:
24630 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
24631 break;
24633 case OPC_DOTP_S_df:
24634 case OPC_DOTP_U_df:
24635 case OPC_DPADD_S_df:
24636 case OPC_DPADD_U_df:
24637 case OPC_DPSUB_S_df:
24638 case OPC_HADD_S_df:
24639 case OPC_DPSUB_U_df:
24640 case OPC_HADD_U_df:
24641 case OPC_HSUB_S_df:
24642 case OPC_HSUB_U_df:
24643 if (df == DF_BYTE) {
24644 generate_exception_end(ctx, EXCP_RI);
24645 break;
24647 switch (MASK_MSA_3R(ctx->opcode)) {
24648 case OPC_DOTP_S_df:
24649 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
24650 break;
24651 case OPC_DOTP_U_df:
24652 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
24653 break;
24654 case OPC_DPADD_S_df:
24655 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
24656 break;
24657 case OPC_DPADD_U_df:
24658 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
24659 break;
24660 case OPC_DPSUB_S_df:
24661 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
24662 break;
24663 case OPC_HADD_S_df:
24664 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
24665 break;
24666 case OPC_DPSUB_U_df:
24667 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
24668 break;
24669 case OPC_HADD_U_df:
24670 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
24671 break;
24672 case OPC_HSUB_S_df:
24673 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
24674 break;
24675 case OPC_HSUB_U_df:
24676 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
24677 break;
24679 break;
24680 default:
24681 MIPS_INVAL("MSA instruction");
24682 generate_exception_end(ctx, EXCP_RI);
24683 break;
24685 tcg_temp_free_i32(twd);
24686 tcg_temp_free_i32(tws);
24687 tcg_temp_free_i32(twt);
24688 tcg_temp_free_i32(tdf);
24691 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
24693 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
24694 uint8_t source = (ctx->opcode >> 11) & 0x1f;
24695 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
24696 TCGv telm = tcg_temp_new();
24697 TCGv_i32 tsr = tcg_const_i32(source);
24698 TCGv_i32 tdt = tcg_const_i32(dest);
24700 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
24701 case OPC_CTCMSA:
24702 gen_load_gpr(telm, source);
24703 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
24704 break;
24705 case OPC_CFCMSA:
24706 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
24707 gen_store_gpr(telm, dest);
24708 break;
24709 case OPC_MOVE_V:
24710 gen_helper_msa_move_v(cpu_env, tdt, tsr);
24711 break;
24712 default:
24713 MIPS_INVAL("MSA instruction");
24714 generate_exception_end(ctx, EXCP_RI);
24715 break;
24718 tcg_temp_free(telm);
24719 tcg_temp_free_i32(tdt);
24720 tcg_temp_free_i32(tsr);
24723 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
24724 uint32_t n)
24726 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24727 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24728 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24730 TCGv_i32 tws = tcg_const_i32(ws);
24731 TCGv_i32 twd = tcg_const_i32(wd);
24732 TCGv_i32 tn = tcg_const_i32(n);
24733 TCGv_i32 tdf = tcg_const_i32(df);
24735 switch (MASK_MSA_ELM(ctx->opcode)) {
24736 case OPC_SLDI_df:
24737 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
24738 break;
24739 case OPC_SPLATI_df:
24740 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
24741 break;
24742 case OPC_INSVE_df:
24743 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
24744 break;
24745 case OPC_COPY_S_df:
24746 case OPC_COPY_U_df:
24747 case OPC_INSERT_df:
24748 #if !defined(TARGET_MIPS64)
24749 /* Double format valid only for MIPS64 */
24750 if (df == DF_DOUBLE) {
24751 generate_exception_end(ctx, EXCP_RI);
24752 break;
24754 #endif
24755 switch (MASK_MSA_ELM(ctx->opcode)) {
24756 case OPC_COPY_S_df:
24757 if (likely(wd != 0)) {
24758 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
24760 break;
24761 case OPC_COPY_U_df:
24762 if (likely(wd != 0)) {
24763 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
24765 break;
24766 case OPC_INSERT_df:
24767 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
24768 break;
24770 break;
24771 default:
24772 MIPS_INVAL("MSA instruction");
24773 generate_exception_end(ctx, EXCP_RI);
24775 tcg_temp_free_i32(twd);
24776 tcg_temp_free_i32(tws);
24777 tcg_temp_free_i32(tn);
24778 tcg_temp_free_i32(tdf);
24781 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
24783 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
24784 uint32_t df = 0, n = 0;
24786 if ((dfn & 0x30) == 0x00) {
24787 n = dfn & 0x0f;
24788 df = DF_BYTE;
24789 } else if ((dfn & 0x38) == 0x20) {
24790 n = dfn & 0x07;
24791 df = DF_HALF;
24792 } else if ((dfn & 0x3c) == 0x30) {
24793 n = dfn & 0x03;
24794 df = DF_WORD;
24795 } else if ((dfn & 0x3e) == 0x38) {
24796 n = dfn & 0x01;
24797 df = DF_DOUBLE;
24798 } else if (dfn == 0x3E) {
24799 /* CTCMSA, CFCMSA, MOVE.V */
24800 gen_msa_elm_3e(env, ctx);
24801 return;
24802 } else {
24803 generate_exception_end(ctx, EXCP_RI);
24804 return;
24807 gen_msa_elm_df(env, ctx, df, n);
24810 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
24812 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24813 uint8_t df = (ctx->opcode >> 21) & 0x1;
24814 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24815 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24816 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24818 TCGv_i32 twd = tcg_const_i32(wd);
24819 TCGv_i32 tws = tcg_const_i32(ws);
24820 TCGv_i32 twt = tcg_const_i32(wt);
24821 TCGv_i32 tdf = tcg_temp_new_i32();
24823 /* adjust df value for floating-point instruction */
24824 tcg_gen_movi_i32(tdf, df + 2);
24826 switch (MASK_MSA_3RF(ctx->opcode)) {
24827 case OPC_FCAF_df:
24828 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
24829 break;
24830 case OPC_FADD_df:
24831 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
24832 break;
24833 case OPC_FCUN_df:
24834 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
24835 break;
24836 case OPC_FSUB_df:
24837 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
24838 break;
24839 case OPC_FCOR_df:
24840 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
24841 break;
24842 case OPC_FCEQ_df:
24843 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
24844 break;
24845 case OPC_FMUL_df:
24846 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
24847 break;
24848 case OPC_FCUNE_df:
24849 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
24850 break;
24851 case OPC_FCUEQ_df:
24852 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
24853 break;
24854 case OPC_FDIV_df:
24855 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
24856 break;
24857 case OPC_FCNE_df:
24858 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
24859 break;
24860 case OPC_FCLT_df:
24861 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
24862 break;
24863 case OPC_FMADD_df:
24864 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
24865 break;
24866 case OPC_MUL_Q_df:
24867 tcg_gen_movi_i32(tdf, df + 1);
24868 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
24869 break;
24870 case OPC_FCULT_df:
24871 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
24872 break;
24873 case OPC_FMSUB_df:
24874 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
24875 break;
24876 case OPC_MADD_Q_df:
24877 tcg_gen_movi_i32(tdf, df + 1);
24878 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
24879 break;
24880 case OPC_FCLE_df:
24881 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
24882 break;
24883 case OPC_MSUB_Q_df:
24884 tcg_gen_movi_i32(tdf, df + 1);
24885 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
24886 break;
24887 case OPC_FCULE_df:
24888 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
24889 break;
24890 case OPC_FEXP2_df:
24891 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
24892 break;
24893 case OPC_FSAF_df:
24894 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
24895 break;
24896 case OPC_FEXDO_df:
24897 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
24898 break;
24899 case OPC_FSUN_df:
24900 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
24901 break;
24902 case OPC_FSOR_df:
24903 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
24904 break;
24905 case OPC_FSEQ_df:
24906 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
24907 break;
24908 case OPC_FTQ_df:
24909 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
24910 break;
24911 case OPC_FSUNE_df:
24912 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
24913 break;
24914 case OPC_FSUEQ_df:
24915 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
24916 break;
24917 case OPC_FSNE_df:
24918 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
24919 break;
24920 case OPC_FSLT_df:
24921 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
24922 break;
24923 case OPC_FMIN_df:
24924 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
24925 break;
24926 case OPC_MULR_Q_df:
24927 tcg_gen_movi_i32(tdf, df + 1);
24928 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
24929 break;
24930 case OPC_FSULT_df:
24931 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
24932 break;
24933 case OPC_FMIN_A_df:
24934 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
24935 break;
24936 case OPC_MADDR_Q_df:
24937 tcg_gen_movi_i32(tdf, df + 1);
24938 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
24939 break;
24940 case OPC_FSLE_df:
24941 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
24942 break;
24943 case OPC_FMAX_df:
24944 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
24945 break;
24946 case OPC_MSUBR_Q_df:
24947 tcg_gen_movi_i32(tdf, df + 1);
24948 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
24949 break;
24950 case OPC_FSULE_df:
24951 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
24952 break;
24953 case OPC_FMAX_A_df:
24954 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
24955 break;
24956 default:
24957 MIPS_INVAL("MSA instruction");
24958 generate_exception_end(ctx, EXCP_RI);
24959 break;
24962 tcg_temp_free_i32(twd);
24963 tcg_temp_free_i32(tws);
24964 tcg_temp_free_i32(twt);
24965 tcg_temp_free_i32(tdf);
24968 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
24970 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
24971 (op & (0x7 << 18)))
24972 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24973 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24974 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24975 uint8_t df = (ctx->opcode >> 16) & 0x3;
24976 TCGv_i32 twd = tcg_const_i32(wd);
24977 TCGv_i32 tws = tcg_const_i32(ws);
24978 TCGv_i32 twt = tcg_const_i32(wt);
24979 TCGv_i32 tdf = tcg_const_i32(df);
24981 switch (MASK_MSA_2R(ctx->opcode)) {
24982 case OPC_FILL_df:
24983 #if !defined(TARGET_MIPS64)
24984 /* Double format valid only for MIPS64 */
24985 if (df == DF_DOUBLE) {
24986 generate_exception_end(ctx, EXCP_RI);
24987 break;
24989 #endif
24990 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
24991 break;
24992 case OPC_PCNT_df:
24993 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
24994 break;
24995 case OPC_NLOC_df:
24996 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
24997 break;
24998 case OPC_NLZC_df:
24999 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
25000 break;
25001 default:
25002 MIPS_INVAL("MSA instruction");
25003 generate_exception_end(ctx, EXCP_RI);
25004 break;
25007 tcg_temp_free_i32(twd);
25008 tcg_temp_free_i32(tws);
25009 tcg_temp_free_i32(twt);
25010 tcg_temp_free_i32(tdf);
25013 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
25015 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25016 (op & (0xf << 17)))
25017 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25018 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25019 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25020 uint8_t df = (ctx->opcode >> 16) & 0x1;
25021 TCGv_i32 twd = tcg_const_i32(wd);
25022 TCGv_i32 tws = tcg_const_i32(ws);
25023 TCGv_i32 twt = tcg_const_i32(wt);
25024 /* adjust df value for floating-point instruction */
25025 TCGv_i32 tdf = tcg_const_i32(df + 2);
25027 switch (MASK_MSA_2RF(ctx->opcode)) {
25028 case OPC_FCLASS_df:
25029 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
25030 break;
25031 case OPC_FTRUNC_S_df:
25032 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
25033 break;
25034 case OPC_FTRUNC_U_df:
25035 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25036 break;
25037 case OPC_FSQRT_df:
25038 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25039 break;
25040 case OPC_FRSQRT_df:
25041 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
25042 break;
25043 case OPC_FRCP_df:
25044 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
25045 break;
25046 case OPC_FRINT_df:
25047 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
25048 break;
25049 case OPC_FLOG2_df:
25050 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
25051 break;
25052 case OPC_FEXUPL_df:
25053 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
25054 break;
25055 case OPC_FEXUPR_df:
25056 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
25057 break;
25058 case OPC_FFQL_df:
25059 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
25060 break;
25061 case OPC_FFQR_df:
25062 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
25063 break;
25064 case OPC_FTINT_S_df:
25065 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
25066 break;
25067 case OPC_FTINT_U_df:
25068 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
25069 break;
25070 case OPC_FFINT_S_df:
25071 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
25072 break;
25073 case OPC_FFINT_U_df:
25074 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
25075 break;
25078 tcg_temp_free_i32(twd);
25079 tcg_temp_free_i32(tws);
25080 tcg_temp_free_i32(twt);
25081 tcg_temp_free_i32(tdf);
25084 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
25086 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
25087 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25088 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25089 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25090 TCGv_i32 twd = tcg_const_i32(wd);
25091 TCGv_i32 tws = tcg_const_i32(ws);
25092 TCGv_i32 twt = tcg_const_i32(wt);
25094 switch (MASK_MSA_VEC(ctx->opcode)) {
25095 case OPC_AND_V:
25096 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
25097 break;
25098 case OPC_OR_V:
25099 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
25100 break;
25101 case OPC_NOR_V:
25102 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
25103 break;
25104 case OPC_XOR_V:
25105 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
25106 break;
25107 case OPC_BMNZ_V:
25108 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
25109 break;
25110 case OPC_BMZ_V:
25111 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
25112 break;
25113 case OPC_BSEL_V:
25114 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
25115 break;
25116 default:
25117 MIPS_INVAL("MSA instruction");
25118 generate_exception_end(ctx, EXCP_RI);
25119 break;
25122 tcg_temp_free_i32(twd);
25123 tcg_temp_free_i32(tws);
25124 tcg_temp_free_i32(twt);
25127 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
25129 switch (MASK_MSA_VEC(ctx->opcode)) {
25130 case OPC_AND_V:
25131 case OPC_OR_V:
25132 case OPC_NOR_V:
25133 case OPC_XOR_V:
25134 case OPC_BMNZ_V:
25135 case OPC_BMZ_V:
25136 case OPC_BSEL_V:
25137 gen_msa_vec_v(env, ctx);
25138 break;
25139 case OPC_MSA_2R:
25140 gen_msa_2r(env, ctx);
25141 break;
25142 case OPC_MSA_2RF:
25143 gen_msa_2rf(env, ctx);
25144 break;
25145 default:
25146 MIPS_INVAL("MSA instruction");
25147 generate_exception_end(ctx, EXCP_RI);
25148 break;
25152 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
25154 uint32_t opcode = ctx->opcode;
25155 check_insn(ctx, ASE_MSA);
25156 check_msa_access(ctx);
25158 switch (MASK_MSA_MINOR(opcode)) {
25159 case OPC_MSA_I8_00:
25160 case OPC_MSA_I8_01:
25161 case OPC_MSA_I8_02:
25162 gen_msa_i8(env, ctx);
25163 break;
25164 case OPC_MSA_I5_06:
25165 case OPC_MSA_I5_07:
25166 gen_msa_i5(env, ctx);
25167 break;
25168 case OPC_MSA_BIT_09:
25169 case OPC_MSA_BIT_0A:
25170 gen_msa_bit(env, ctx);
25171 break;
25172 case OPC_MSA_3R_0D:
25173 case OPC_MSA_3R_0E:
25174 case OPC_MSA_3R_0F:
25175 case OPC_MSA_3R_10:
25176 case OPC_MSA_3R_11:
25177 case OPC_MSA_3R_12:
25178 case OPC_MSA_3R_13:
25179 case OPC_MSA_3R_14:
25180 case OPC_MSA_3R_15:
25181 gen_msa_3r(env, ctx);
25182 break;
25183 case OPC_MSA_ELM:
25184 gen_msa_elm(env, ctx);
25185 break;
25186 case OPC_MSA_3RF_1A:
25187 case OPC_MSA_3RF_1B:
25188 case OPC_MSA_3RF_1C:
25189 gen_msa_3rf(env, ctx);
25190 break;
25191 case OPC_MSA_VEC:
25192 gen_msa_vec(env, ctx);
25193 break;
25194 case OPC_LD_B:
25195 case OPC_LD_H:
25196 case OPC_LD_W:
25197 case OPC_LD_D:
25198 case OPC_ST_B:
25199 case OPC_ST_H:
25200 case OPC_ST_W:
25201 case OPC_ST_D:
25203 int32_t s10 = sextract32(ctx->opcode, 16, 10);
25204 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
25205 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25206 uint8_t df = (ctx->opcode >> 0) & 0x3;
25208 TCGv_i32 twd = tcg_const_i32(wd);
25209 TCGv taddr = tcg_temp_new();
25210 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
25212 switch (MASK_MSA_MINOR(opcode)) {
25213 case OPC_LD_B:
25214 gen_helper_msa_ld_b(cpu_env, twd, taddr);
25215 break;
25216 case OPC_LD_H:
25217 gen_helper_msa_ld_h(cpu_env, twd, taddr);
25218 break;
25219 case OPC_LD_W:
25220 gen_helper_msa_ld_w(cpu_env, twd, taddr);
25221 break;
25222 case OPC_LD_D:
25223 gen_helper_msa_ld_d(cpu_env, twd, taddr);
25224 break;
25225 case OPC_ST_B:
25226 gen_helper_msa_st_b(cpu_env, twd, taddr);
25227 break;
25228 case OPC_ST_H:
25229 gen_helper_msa_st_h(cpu_env, twd, taddr);
25230 break;
25231 case OPC_ST_W:
25232 gen_helper_msa_st_w(cpu_env, twd, taddr);
25233 break;
25234 case OPC_ST_D:
25235 gen_helper_msa_st_d(cpu_env, twd, taddr);
25236 break;
25239 tcg_temp_free_i32(twd);
25240 tcg_temp_free(taddr);
25242 break;
25243 default:
25244 MIPS_INVAL("MSA instruction");
25245 generate_exception_end(ctx, EXCP_RI);
25246 break;
25251 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25253 int32_t offset;
25254 int rs, rt, rd, sa;
25255 uint32_t op, op1;
25256 int16_t imm;
25258 /* make sure instructions are on a word boundary */
25259 if (ctx->base.pc_next & 0x3) {
25260 env->CP0_BadVAddr = ctx->base.pc_next;
25261 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25262 return;
25265 /* Handle blikely not taken case */
25266 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25267 TCGLabel *l1 = gen_new_label();
25269 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25270 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25271 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25272 gen_set_label(l1);
25275 op = MASK_OP_MAJOR(ctx->opcode);
25276 rs = (ctx->opcode >> 21) & 0x1f;
25277 rt = (ctx->opcode >> 16) & 0x1f;
25278 rd = (ctx->opcode >> 11) & 0x1f;
25279 sa = (ctx->opcode >> 6) & 0x1f;
25280 imm = (int16_t)ctx->opcode;
25281 switch (op) {
25282 case OPC_SPECIAL:
25283 decode_opc_special(env, ctx);
25284 break;
25285 case OPC_SPECIAL2:
25286 decode_opc_special2_legacy(env, ctx);
25287 break;
25288 case OPC_SPECIAL3:
25289 decode_opc_special3(env, ctx);
25290 break;
25291 case OPC_REGIMM:
25292 op1 = MASK_REGIMM(ctx->opcode);
25293 switch (op1) {
25294 case OPC_BLTZL: /* REGIMM branches */
25295 case OPC_BGEZL:
25296 case OPC_BLTZALL:
25297 case OPC_BGEZALL:
25298 check_insn(ctx, ISA_MIPS2);
25299 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25300 /* Fallthrough */
25301 case OPC_BLTZ:
25302 case OPC_BGEZ:
25303 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25304 break;
25305 case OPC_BLTZAL:
25306 case OPC_BGEZAL:
25307 if (ctx->insn_flags & ISA_MIPS32R6) {
25308 if (rs == 0) {
25309 /* OPC_NAL, OPC_BAL */
25310 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
25311 } else {
25312 generate_exception_end(ctx, EXCP_RI);
25314 } else {
25315 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25317 break;
25318 case OPC_TGEI: /* REGIMM traps */
25319 case OPC_TGEIU:
25320 case OPC_TLTI:
25321 case OPC_TLTIU:
25322 case OPC_TEQI:
25324 case OPC_TNEI:
25325 check_insn(ctx, ISA_MIPS2);
25326 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25327 gen_trap(ctx, op1, rs, -1, imm);
25328 break;
25329 case OPC_SIGRIE:
25330 check_insn(ctx, ISA_MIPS32R6);
25331 generate_exception_end(ctx, EXCP_RI);
25332 break;
25333 case OPC_SYNCI:
25334 check_insn(ctx, ISA_MIPS32R2);
25335 /* Break the TB to be able to sync copied instructions
25336 immediately */
25337 ctx->base.is_jmp = DISAS_STOP;
25338 break;
25339 case OPC_BPOSGE32: /* MIPS DSP branch */
25340 #if defined(TARGET_MIPS64)
25341 case OPC_BPOSGE64:
25342 #endif
25343 check_dsp(ctx);
25344 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
25345 break;
25346 #if defined(TARGET_MIPS64)
25347 case OPC_DAHI:
25348 check_insn(ctx, ISA_MIPS32R6);
25349 check_mips_64(ctx);
25350 if (rs != 0) {
25351 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
25353 break;
25354 case OPC_DATI:
25355 check_insn(ctx, ISA_MIPS32R6);
25356 check_mips_64(ctx);
25357 if (rs != 0) {
25358 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
25360 break;
25361 #endif
25362 default: /* Invalid */
25363 MIPS_INVAL("regimm");
25364 generate_exception_end(ctx, EXCP_RI);
25365 break;
25367 break;
25368 case OPC_CP0:
25369 check_cp0_enabled(ctx);
25370 op1 = MASK_CP0(ctx->opcode);
25371 switch (op1) {
25372 case OPC_MFC0:
25373 case OPC_MTC0:
25374 case OPC_MFTR:
25375 case OPC_MTTR:
25376 case OPC_MFHC0:
25377 case OPC_MTHC0:
25378 #if defined(TARGET_MIPS64)
25379 case OPC_DMFC0:
25380 case OPC_DMTC0:
25381 #endif
25382 #ifndef CONFIG_USER_ONLY
25383 gen_cp0(env, ctx, op1, rt, rd);
25384 #endif /* !CONFIG_USER_ONLY */
25385 break;
25386 case OPC_C0:
25387 case OPC_C0_1:
25388 case OPC_C0_2:
25389 case OPC_C0_3:
25390 case OPC_C0_4:
25391 case OPC_C0_5:
25392 case OPC_C0_6:
25393 case OPC_C0_7:
25394 case OPC_C0_8:
25395 case OPC_C0_9:
25396 case OPC_C0_A:
25397 case OPC_C0_B:
25398 case OPC_C0_C:
25399 case OPC_C0_D:
25400 case OPC_C0_E:
25401 case OPC_C0_F:
25402 #ifndef CONFIG_USER_ONLY
25403 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
25404 #endif /* !CONFIG_USER_ONLY */
25405 break;
25406 case OPC_MFMC0:
25407 #ifndef CONFIG_USER_ONLY
25409 uint32_t op2;
25410 TCGv t0 = tcg_temp_new();
25412 op2 = MASK_MFMC0(ctx->opcode);
25413 switch (op2) {
25414 case OPC_DMT:
25415 check_cp0_mt(ctx);
25416 gen_helper_dmt(t0);
25417 gen_store_gpr(t0, rt);
25418 break;
25419 case OPC_EMT:
25420 check_cp0_mt(ctx);
25421 gen_helper_emt(t0);
25422 gen_store_gpr(t0, rt);
25423 break;
25424 case OPC_DVPE:
25425 check_cp0_mt(ctx);
25426 gen_helper_dvpe(t0, cpu_env);
25427 gen_store_gpr(t0, rt);
25428 break;
25429 case OPC_EVPE:
25430 check_cp0_mt(ctx);
25431 gen_helper_evpe(t0, cpu_env);
25432 gen_store_gpr(t0, rt);
25433 break;
25434 case OPC_DVP:
25435 check_insn(ctx, ISA_MIPS32R6);
25436 if (ctx->vp) {
25437 gen_helper_dvp(t0, cpu_env);
25438 gen_store_gpr(t0, rt);
25440 break;
25441 case OPC_EVP:
25442 check_insn(ctx, ISA_MIPS32R6);
25443 if (ctx->vp) {
25444 gen_helper_evp(t0, cpu_env);
25445 gen_store_gpr(t0, rt);
25447 break;
25448 case OPC_DI:
25449 check_insn(ctx, ISA_MIPS32R2);
25450 save_cpu_state(ctx, 1);
25451 gen_helper_di(t0, cpu_env);
25452 gen_store_gpr(t0, rt);
25453 /* Stop translation as we may have switched
25454 the execution mode. */
25455 ctx->base.is_jmp = DISAS_STOP;
25456 break;
25457 case OPC_EI:
25458 check_insn(ctx, ISA_MIPS32R2);
25459 save_cpu_state(ctx, 1);
25460 gen_helper_ei(t0, cpu_env);
25461 gen_store_gpr(t0, rt);
25462 /* DISAS_STOP isn't sufficient, we need to ensure we break
25463 out of translated code to check for pending interrupts */
25464 gen_save_pc(ctx->base.pc_next + 4);
25465 ctx->base.is_jmp = DISAS_EXIT;
25466 break;
25467 default: /* Invalid */
25468 MIPS_INVAL("mfmc0");
25469 generate_exception_end(ctx, EXCP_RI);
25470 break;
25472 tcg_temp_free(t0);
25474 #endif /* !CONFIG_USER_ONLY */
25475 break;
25476 case OPC_RDPGPR:
25477 check_insn(ctx, ISA_MIPS32R2);
25478 gen_load_srsgpr(rt, rd);
25479 break;
25480 case OPC_WRPGPR:
25481 check_insn(ctx, ISA_MIPS32R2);
25482 gen_store_srsgpr(rt, rd);
25483 break;
25484 default:
25485 MIPS_INVAL("cp0");
25486 generate_exception_end(ctx, EXCP_RI);
25487 break;
25489 break;
25490 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
25491 if (ctx->insn_flags & ISA_MIPS32R6) {
25492 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
25493 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25494 } else {
25495 /* OPC_ADDI */
25496 /* Arithmetic with immediate opcode */
25497 gen_arith_imm(ctx, op, rt, rs, imm);
25499 break;
25500 case OPC_ADDIU:
25501 gen_arith_imm(ctx, op, rt, rs, imm);
25502 break;
25503 case OPC_SLTI: /* Set on less than with immediate opcode */
25504 case OPC_SLTIU:
25505 gen_slt_imm(ctx, op, rt, rs, imm);
25506 break;
25507 case OPC_ANDI: /* Arithmetic with immediate opcode */
25508 case OPC_LUI: /* OPC_AUI */
25509 case OPC_ORI:
25510 case OPC_XORI:
25511 gen_logic_imm(ctx, op, rt, rs, imm);
25512 break;
25513 case OPC_J: /* Jump */
25514 case OPC_JAL:
25515 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25516 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25517 break;
25518 /* Branch */
25519 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
25520 if (ctx->insn_flags & ISA_MIPS32R6) {
25521 if (rt == 0) {
25522 generate_exception_end(ctx, EXCP_RI);
25523 break;
25525 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
25526 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25527 } else {
25528 /* OPC_BLEZL */
25529 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25531 break;
25532 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
25533 if (ctx->insn_flags & ISA_MIPS32R6) {
25534 if (rt == 0) {
25535 generate_exception_end(ctx, EXCP_RI);
25536 break;
25538 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
25539 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25540 } else {
25541 /* OPC_BGTZL */
25542 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25544 break;
25545 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
25546 if (rt == 0) {
25547 /* OPC_BLEZ */
25548 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25549 } else {
25550 check_insn(ctx, ISA_MIPS32R6);
25551 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
25552 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25554 break;
25555 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
25556 if (rt == 0) {
25557 /* OPC_BGTZ */
25558 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25559 } else {
25560 check_insn(ctx, ISA_MIPS32R6);
25561 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
25562 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25564 break;
25565 case OPC_BEQL:
25566 case OPC_BNEL:
25567 check_insn(ctx, ISA_MIPS2);
25568 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25569 /* Fallthrough */
25570 case OPC_BEQ:
25571 case OPC_BNE:
25572 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25573 break;
25574 case OPC_LL: /* Load and stores */
25575 check_insn(ctx, ISA_MIPS2);
25576 /* Fallthrough */
25577 case OPC_LWL:
25578 case OPC_LWR:
25579 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25580 /* Fallthrough */
25581 case OPC_LB:
25582 case OPC_LH:
25583 case OPC_LW:
25584 case OPC_LWPC:
25585 case OPC_LBU:
25586 case OPC_LHU:
25587 gen_ld(ctx, op, rt, rs, imm);
25588 break;
25589 case OPC_SWL:
25590 case OPC_SWR:
25591 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25592 /* fall through */
25593 case OPC_SB:
25594 case OPC_SH:
25595 case OPC_SW:
25596 gen_st(ctx, op, rt, rs, imm);
25597 break;
25598 case OPC_SC:
25599 check_insn(ctx, ISA_MIPS2);
25600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25601 gen_st_cond(ctx, op, rt, rs, imm);
25602 break;
25603 case OPC_CACHE:
25604 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25605 check_cp0_enabled(ctx);
25606 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
25607 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25608 gen_cache_operation(ctx, rt, rs, imm);
25610 /* Treat as NOP. */
25611 break;
25612 case OPC_PREF:
25613 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25614 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
25615 /* Treat as NOP. */
25616 break;
25618 /* Floating point (COP1). */
25619 case OPC_LWC1:
25620 case OPC_LDC1:
25621 case OPC_SWC1:
25622 case OPC_SDC1:
25623 gen_cop1_ldst(ctx, op, rt, rs, imm);
25624 break;
25626 case OPC_CP1:
25627 op1 = MASK_CP1(ctx->opcode);
25629 switch (op1) {
25630 case OPC_MFHC1:
25631 case OPC_MTHC1:
25632 check_cp1_enabled(ctx);
25633 check_insn(ctx, ISA_MIPS32R2);
25634 /* fall through */
25635 case OPC_MFC1:
25636 case OPC_CFC1:
25637 case OPC_MTC1:
25638 case OPC_CTC1:
25639 check_cp1_enabled(ctx);
25640 gen_cp1(ctx, op1, rt, rd);
25641 break;
25642 #if defined(TARGET_MIPS64)
25643 case OPC_DMFC1:
25644 case OPC_DMTC1:
25645 check_cp1_enabled(ctx);
25646 check_insn(ctx, ISA_MIPS3);
25647 check_mips_64(ctx);
25648 gen_cp1(ctx, op1, rt, rd);
25649 break;
25650 #endif
25651 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25652 check_cp1_enabled(ctx);
25653 if (ctx->insn_flags & ISA_MIPS32R6) {
25654 /* OPC_BC1EQZ */
25655 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25656 rt, imm << 2, 4);
25657 } else {
25658 /* OPC_BC1ANY2 */
25659 check_cop1x(ctx);
25660 check_insn(ctx, ASE_MIPS3D);
25661 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25662 (rt >> 2) & 0x7, imm << 2);
25664 break;
25665 case OPC_BC1NEZ:
25666 check_cp1_enabled(ctx);
25667 check_insn(ctx, ISA_MIPS32R6);
25668 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25669 rt, imm << 2, 4);
25670 break;
25671 case OPC_BC1ANY4:
25672 check_cp1_enabled(ctx);
25673 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25674 check_cop1x(ctx);
25675 check_insn(ctx, ASE_MIPS3D);
25676 /* fall through */
25677 case OPC_BC1:
25678 check_cp1_enabled(ctx);
25679 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25680 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25681 (rt >> 2) & 0x7, imm << 2);
25682 break;
25683 case OPC_PS_FMT:
25684 check_ps(ctx);
25685 /* fall through */
25686 case OPC_S_FMT:
25687 case OPC_D_FMT:
25688 check_cp1_enabled(ctx);
25689 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25690 (imm >> 8) & 0x7);
25691 break;
25692 case OPC_W_FMT:
25693 case OPC_L_FMT:
25695 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25696 check_cp1_enabled(ctx);
25697 if (ctx->insn_flags & ISA_MIPS32R6) {
25698 switch (r6_op) {
25699 case R6_OPC_CMP_AF_S:
25700 case R6_OPC_CMP_UN_S:
25701 case R6_OPC_CMP_EQ_S:
25702 case R6_OPC_CMP_UEQ_S:
25703 case R6_OPC_CMP_LT_S:
25704 case R6_OPC_CMP_ULT_S:
25705 case R6_OPC_CMP_LE_S:
25706 case R6_OPC_CMP_ULE_S:
25707 case R6_OPC_CMP_SAF_S:
25708 case R6_OPC_CMP_SUN_S:
25709 case R6_OPC_CMP_SEQ_S:
25710 case R6_OPC_CMP_SEUQ_S:
25711 case R6_OPC_CMP_SLT_S:
25712 case R6_OPC_CMP_SULT_S:
25713 case R6_OPC_CMP_SLE_S:
25714 case R6_OPC_CMP_SULE_S:
25715 case R6_OPC_CMP_OR_S:
25716 case R6_OPC_CMP_UNE_S:
25717 case R6_OPC_CMP_NE_S:
25718 case R6_OPC_CMP_SOR_S:
25719 case R6_OPC_CMP_SUNE_S:
25720 case R6_OPC_CMP_SNE_S:
25721 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25722 break;
25723 case R6_OPC_CMP_AF_D:
25724 case R6_OPC_CMP_UN_D:
25725 case R6_OPC_CMP_EQ_D:
25726 case R6_OPC_CMP_UEQ_D:
25727 case R6_OPC_CMP_LT_D:
25728 case R6_OPC_CMP_ULT_D:
25729 case R6_OPC_CMP_LE_D:
25730 case R6_OPC_CMP_ULE_D:
25731 case R6_OPC_CMP_SAF_D:
25732 case R6_OPC_CMP_SUN_D:
25733 case R6_OPC_CMP_SEQ_D:
25734 case R6_OPC_CMP_SEUQ_D:
25735 case R6_OPC_CMP_SLT_D:
25736 case R6_OPC_CMP_SULT_D:
25737 case R6_OPC_CMP_SLE_D:
25738 case R6_OPC_CMP_SULE_D:
25739 case R6_OPC_CMP_OR_D:
25740 case R6_OPC_CMP_UNE_D:
25741 case R6_OPC_CMP_NE_D:
25742 case R6_OPC_CMP_SOR_D:
25743 case R6_OPC_CMP_SUNE_D:
25744 case R6_OPC_CMP_SNE_D:
25745 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25746 break;
25747 default:
25748 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25749 rt, rd, sa, (imm >> 8) & 0x7);
25751 break;
25753 } else {
25754 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25755 (imm >> 8) & 0x7);
25757 break;
25759 case OPC_BZ_V:
25760 case OPC_BNZ_V:
25761 case OPC_BZ_B:
25762 case OPC_BZ_H:
25763 case OPC_BZ_W:
25764 case OPC_BZ_D:
25765 case OPC_BNZ_B:
25766 case OPC_BNZ_H:
25767 case OPC_BNZ_W:
25768 case OPC_BNZ_D:
25769 check_insn(ctx, ASE_MSA);
25770 gen_msa_branch(env, ctx, op1);
25771 break;
25772 default:
25773 MIPS_INVAL("cp1");
25774 generate_exception_end(ctx, EXCP_RI);
25775 break;
25777 break;
25779 /* Compact branches [R6] and COP2 [non-R6] */
25780 case OPC_BC: /* OPC_LWC2 */
25781 case OPC_BALC: /* OPC_SWC2 */
25782 if (ctx->insn_flags & ISA_MIPS32R6) {
25783 /* OPC_BC, OPC_BALC */
25784 gen_compute_compact_branch(ctx, op, 0, 0,
25785 sextract32(ctx->opcode << 2, 0, 28));
25786 } else {
25787 /* OPC_LWC2, OPC_SWC2 */
25788 /* COP2: Not implemented. */
25789 generate_exception_err(ctx, EXCP_CpU, 2);
25791 break;
25792 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25793 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25794 if (ctx->insn_flags & ISA_MIPS32R6) {
25795 if (rs != 0) {
25796 /* OPC_BEQZC, OPC_BNEZC */
25797 gen_compute_compact_branch(ctx, op, rs, 0,
25798 sextract32(ctx->opcode << 2, 0, 23));
25799 } else {
25800 /* OPC_JIC, OPC_JIALC */
25801 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25803 } else {
25804 /* OPC_LWC2, OPC_SWC2 */
25805 /* COP2: Not implemented. */
25806 generate_exception_err(ctx, EXCP_CpU, 2);
25808 break;
25809 case OPC_CP2:
25810 check_insn(ctx, INSN_LOONGSON2F);
25811 /* Note that these instructions use different fields. */
25812 gen_loongson_multimedia(ctx, sa, rd, rt);
25813 break;
25815 case OPC_CP3:
25816 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25817 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
25818 check_cp1_enabled(ctx);
25819 op1 = MASK_CP3(ctx->opcode);
25820 switch (op1) {
25821 case OPC_LUXC1:
25822 case OPC_SUXC1:
25823 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
25824 /* Fallthrough */
25825 case OPC_LWXC1:
25826 case OPC_LDXC1:
25827 case OPC_SWXC1:
25828 case OPC_SDXC1:
25829 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25830 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
25831 break;
25832 case OPC_PREFX:
25833 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25834 /* Treat as NOP. */
25835 break;
25836 case OPC_ALNV_PS:
25837 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
25838 /* Fallthrough */
25839 case OPC_MADD_S:
25840 case OPC_MADD_D:
25841 case OPC_MADD_PS:
25842 case OPC_MSUB_S:
25843 case OPC_MSUB_D:
25844 case OPC_MSUB_PS:
25845 case OPC_NMADD_S:
25846 case OPC_NMADD_D:
25847 case OPC_NMADD_PS:
25848 case OPC_NMSUB_S:
25849 case OPC_NMSUB_D:
25850 case OPC_NMSUB_PS:
25851 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
25852 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25853 break;
25854 default:
25855 MIPS_INVAL("cp3");
25856 generate_exception_end(ctx, EXCP_RI);
25857 break;
25859 } else {
25860 generate_exception_err(ctx, EXCP_CpU, 1);
25862 break;
25864 #if defined(TARGET_MIPS64)
25865 /* MIPS64 opcodes */
25866 case OPC_LDL:
25867 case OPC_LDR:
25868 case OPC_LLD:
25869 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25870 /* fall through */
25871 case OPC_LWU:
25872 case OPC_LD:
25873 check_insn(ctx, ISA_MIPS3);
25874 check_mips_64(ctx);
25875 gen_ld(ctx, op, rt, rs, imm);
25876 break;
25877 case OPC_SDL:
25878 case OPC_SDR:
25879 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25880 /* fall through */
25881 case OPC_SD:
25882 check_insn(ctx, ISA_MIPS3);
25883 check_mips_64(ctx);
25884 gen_st(ctx, op, rt, rs, imm);
25885 break;
25886 case OPC_SCD:
25887 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25888 check_insn(ctx, ISA_MIPS3);
25889 check_mips_64(ctx);
25890 gen_st_cond(ctx, op, rt, rs, imm);
25891 break;
25892 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25893 if (ctx->insn_flags & ISA_MIPS32R6) {
25894 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25895 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25896 } else {
25897 /* OPC_DADDI */
25898 check_insn(ctx, ISA_MIPS3);
25899 check_mips_64(ctx);
25900 gen_arith_imm(ctx, op, rt, rs, imm);
25902 break;
25903 case OPC_DADDIU:
25904 check_insn(ctx, ISA_MIPS3);
25905 check_mips_64(ctx);
25906 gen_arith_imm(ctx, op, rt, rs, imm);
25907 break;
25908 #else
25909 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25910 if (ctx->insn_flags & ISA_MIPS32R6) {
25911 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25912 } else {
25913 MIPS_INVAL("major opcode");
25914 generate_exception_end(ctx, EXCP_RI);
25916 break;
25917 #endif
25918 case OPC_DAUI: /* OPC_JALX */
25919 if (ctx->insn_flags & ISA_MIPS32R6) {
25920 #if defined(TARGET_MIPS64)
25921 /* OPC_DAUI */
25922 check_mips_64(ctx);
25923 if (rs == 0) {
25924 generate_exception(ctx, EXCP_RI);
25925 } else if (rt != 0) {
25926 TCGv t0 = tcg_temp_new();
25927 gen_load_gpr(t0, rs);
25928 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25929 tcg_temp_free(t0);
25931 #else
25932 generate_exception_end(ctx, EXCP_RI);
25933 MIPS_INVAL("major opcode");
25934 #endif
25935 } else {
25936 /* OPC_JALX */
25937 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25938 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25939 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25941 break;
25942 case OPC_MSA: /* OPC_MDMX */
25943 /* MDMX: Not implemented. */
25944 gen_msa(env, ctx);
25945 break;
25946 case OPC_PCREL:
25947 check_insn(ctx, ISA_MIPS32R6);
25948 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
25949 break;
25950 default: /* Invalid */
25951 MIPS_INVAL("major opcode");
25952 generate_exception_end(ctx, EXCP_RI);
25953 break;
25957 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
25959 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25960 CPUMIPSState *env = cs->env_ptr;
25962 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
25963 ctx->saved_pc = -1;
25964 ctx->insn_flags = env->insn_flags;
25965 ctx->CP0_Config1 = env->CP0_Config1;
25966 ctx->CP0_Config2 = env->CP0_Config2;
25967 ctx->CP0_Config3 = env->CP0_Config3;
25968 ctx->CP0_Config5 = env->CP0_Config5;
25969 ctx->btarget = 0;
25970 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25971 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25972 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25973 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25974 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25975 ctx->PAMask = env->PAMask;
25976 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25977 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25978 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25979 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25980 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
25981 /* Restore delay slot state from the tb context. */
25982 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25983 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25984 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
25985 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
25986 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25987 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25988 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25989 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25990 restore_cpu_state(env, ctx);
25991 #ifdef CONFIG_USER_ONLY
25992 ctx->mem_idx = MIPS_HFLAG_UM;
25993 #else
25994 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
25995 #endif
25996 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
25997 MO_UNALN : MO_ALIGN;
25999 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26000 ctx->hflags);
26003 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26007 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26009 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26011 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26012 ctx->btarget);
26015 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26016 const CPUBreakpoint *bp)
26018 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26020 save_cpu_state(ctx, 1);
26021 ctx->base.is_jmp = DISAS_NORETURN;
26022 gen_helper_raise_exception_debug(cpu_env);
26023 /* The address covered by the breakpoint must be included in
26024 [tb->pc, tb->pc + tb->size) in order to for it to be
26025 properly cleared -- thus we increment the PC here so that
26026 the logic setting tb->size below does the right thing. */
26027 ctx->base.pc_next += 4;
26028 return true;
26031 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
26033 CPUMIPSState *env = cs->env_ptr;
26034 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26035 int insn_bytes;
26036 int is_slot;
26038 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
26039 if (ctx->insn_flags & ISA_NANOMIPS32) {
26040 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26041 insn_bytes = decode_nanomips_opc(env, ctx);
26042 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
26043 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
26044 insn_bytes = 4;
26045 decode_opc(env, ctx);
26046 } else if (ctx->insn_flags & ASE_MICROMIPS) {
26047 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26048 insn_bytes = decode_micromips_opc(env, ctx);
26049 } else if (ctx->insn_flags & ASE_MIPS16) {
26050 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26051 insn_bytes = decode_mips16_opc(env, ctx);
26052 } else {
26053 generate_exception_end(ctx, EXCP_RI);
26054 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
26055 return;
26058 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26059 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
26060 MIPS_HFLAG_FBNSLOT))) {
26061 /* force to generate branch as there is neither delay nor
26062 forbidden slot */
26063 is_slot = 1;
26065 if ((ctx->hflags & MIPS_HFLAG_M16) &&
26066 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
26067 /* Force to generate branch as microMIPS R6 doesn't restrict
26068 branches in the forbidden slot. */
26069 is_slot = 1;
26072 if (is_slot) {
26073 gen_branch(ctx, insn_bytes);
26075 ctx->base.pc_next += insn_bytes;
26077 if (ctx->base.is_jmp != DISAS_NEXT) {
26078 return;
26080 /* Execute a branch and its delay slot as a single instruction.
26081 This is what GDB expects and is consistent with what the
26082 hardware does (e.g. if a delay slot instruction faults, the
26083 reported PC is the PC of the branch). */
26084 if (ctx->base.singlestep_enabled &&
26085 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
26086 ctx->base.is_jmp = DISAS_TOO_MANY;
26088 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
26089 ctx->base.is_jmp = DISAS_TOO_MANY;
26093 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
26095 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26097 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
26098 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
26099 gen_helper_raise_exception_debug(cpu_env);
26100 } else {
26101 switch (ctx->base.is_jmp) {
26102 case DISAS_STOP:
26103 gen_save_pc(ctx->base.pc_next);
26104 tcg_gen_lookup_and_goto_ptr();
26105 break;
26106 case DISAS_NEXT:
26107 case DISAS_TOO_MANY:
26108 save_cpu_state(ctx, 0);
26109 gen_goto_tb(ctx, 0, ctx->base.pc_next);
26110 break;
26111 case DISAS_EXIT:
26112 tcg_gen_exit_tb(NULL, 0);
26113 break;
26114 case DISAS_NORETURN:
26115 break;
26116 default:
26117 g_assert_not_reached();
26122 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
26124 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
26125 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
26128 static const TranslatorOps mips_tr_ops = {
26129 .init_disas_context = mips_tr_init_disas_context,
26130 .tb_start = mips_tr_tb_start,
26131 .insn_start = mips_tr_insn_start,
26132 .breakpoint_check = mips_tr_breakpoint_check,
26133 .translate_insn = mips_tr_translate_insn,
26134 .tb_stop = mips_tr_tb_stop,
26135 .disas_log = mips_tr_disas_log,
26138 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
26140 DisasContext ctx;
26142 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
26145 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
26146 int flags)
26148 int i;
26149 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
26151 #define printfpr(fp) \
26152 do { \
26153 if (is_fpu64) \
26154 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26155 " fd:%13g fs:%13g psu: %13g\n", \
26156 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
26157 (double)(fp)->fd, \
26158 (double)(fp)->fs[FP_ENDIAN_IDX], \
26159 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
26160 else { \
26161 fpr_t tmp; \
26162 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
26163 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
26164 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26165 " fd:%13g fs:%13g psu:%13g\n", \
26166 tmp.w[FP_ENDIAN_IDX], tmp.d, \
26167 (double)tmp.fd, \
26168 (double)tmp.fs[FP_ENDIAN_IDX], \
26169 (double)tmp.fs[!FP_ENDIAN_IDX]); \
26171 } while(0)
26174 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
26175 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
26176 get_float_exception_flags(&env->active_fpu.fp_status));
26177 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
26178 fpu_fprintf(f, "%3s: ", fregnames[i]);
26179 printfpr(&env->active_fpu.fpr[i]);
26182 #undef printfpr
26185 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
26186 int flags)
26188 MIPSCPU *cpu = MIPS_CPU(cs);
26189 CPUMIPSState *env = &cpu->env;
26190 int i;
26192 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
26193 " LO=0x" TARGET_FMT_lx " ds %04x "
26194 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
26195 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
26196 env->hflags, env->btarget, env->bcond);
26197 for (i = 0; i < 32; i++) {
26198 if ((i & 3) == 0)
26199 cpu_fprintf(f, "GPR%02d:", i);
26200 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
26201 if ((i & 3) == 3)
26202 cpu_fprintf(f, "\n");
26205 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
26206 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
26207 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
26208 PRIx64 "\n",
26209 env->CP0_Config0, env->CP0_Config1, env->lladdr);
26210 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
26211 env->CP0_Config2, env->CP0_Config3);
26212 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
26213 env->CP0_Config4, env->CP0_Config5);
26214 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
26215 fpu_dump_state(env, f, cpu_fprintf, flags);
26219 void mips_tcg_init(void)
26221 int i;
26223 cpu_gpr[0] = NULL;
26224 for (i = 1; i < 32; i++)
26225 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
26226 offsetof(CPUMIPSState, active_tc.gpr[i]),
26227 regnames[i]);
26229 for (i = 0; i < 32; i++) {
26230 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
26231 msa_wr_d[i * 2] =
26232 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
26233 /* The scalar floating-point unit (FPU) registers are mapped on
26234 * the MSA vector registers. */
26235 fpu_f64[i] = msa_wr_d[i * 2];
26236 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
26237 msa_wr_d[i * 2 + 1] =
26238 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
26241 cpu_PC = tcg_global_mem_new(cpu_env,
26242 offsetof(CPUMIPSState, active_tc.PC), "PC");
26243 for (i = 0; i < MIPS_DSP_ACC; i++) {
26244 cpu_HI[i] = tcg_global_mem_new(cpu_env,
26245 offsetof(CPUMIPSState, active_tc.HI[i]),
26246 regnames_HI[i]);
26247 cpu_LO[i] = tcg_global_mem_new(cpu_env,
26248 offsetof(CPUMIPSState, active_tc.LO[i]),
26249 regnames_LO[i]);
26251 cpu_dspctrl = tcg_global_mem_new(cpu_env,
26252 offsetof(CPUMIPSState, active_tc.DSPControl),
26253 "DSPControl");
26254 bcond = tcg_global_mem_new(cpu_env,
26255 offsetof(CPUMIPSState, bcond), "bcond");
26256 btarget = tcg_global_mem_new(cpu_env,
26257 offsetof(CPUMIPSState, btarget), "btarget");
26258 hflags = tcg_global_mem_new_i32(cpu_env,
26259 offsetof(CPUMIPSState, hflags), "hflags");
26261 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
26262 offsetof(CPUMIPSState, active_fpu.fcr0),
26263 "fcr0");
26264 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
26265 offsetof(CPUMIPSState, active_fpu.fcr31),
26266 "fcr31");
26269 #include "translate_init.inc.c"
26271 void cpu_mips_realize_env(CPUMIPSState *env)
26273 env->exception_base = (int32_t)0xBFC00000;
26275 #ifndef CONFIG_USER_ONLY
26276 mmu_init(env, env->cpu_model);
26277 #endif
26278 fpu_init(env, env->cpu_model);
26279 mvp_init(env, env->cpu_model);
26282 bool cpu_supports_cps_smp(const char *cpu_type)
26284 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
26285 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
26288 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
26290 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
26291 return (mcc->cpu_def->insn_flags & isa) != 0;
26294 void cpu_set_exception_base(int vp_index, target_ulong address)
26296 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
26297 vp->env.exception_base = address;
26300 void cpu_state_reset(CPUMIPSState *env)
26302 MIPSCPU *cpu = mips_env_get_cpu(env);
26303 CPUState *cs = CPU(cpu);
26305 /* Reset registers to their default values */
26306 env->CP0_PRid = env->cpu_model->CP0_PRid;
26307 env->CP0_Config0 = env->cpu_model->CP0_Config0;
26308 #ifdef TARGET_WORDS_BIGENDIAN
26309 env->CP0_Config0 |= (1 << CP0C0_BE);
26310 #endif
26311 env->CP0_Config1 = env->cpu_model->CP0_Config1;
26312 env->CP0_Config2 = env->cpu_model->CP0_Config2;
26313 env->CP0_Config3 = env->cpu_model->CP0_Config3;
26314 env->CP0_Config4 = env->cpu_model->CP0_Config4;
26315 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
26316 env->CP0_Config5 = env->cpu_model->CP0_Config5;
26317 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
26318 env->CP0_Config6 = env->cpu_model->CP0_Config6;
26319 env->CP0_Config7 = env->cpu_model->CP0_Config7;
26320 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
26321 << env->cpu_model->CP0_LLAddr_shift;
26322 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
26323 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
26324 env->CCRes = env->cpu_model->CCRes;
26325 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
26326 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
26327 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
26328 env->current_tc = 0;
26329 env->SEGBITS = env->cpu_model->SEGBITS;
26330 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
26331 #if defined(TARGET_MIPS64)
26332 if (env->cpu_model->insn_flags & ISA_MIPS3) {
26333 env->SEGMask |= 3ULL << 62;
26335 #endif
26336 env->PABITS = env->cpu_model->PABITS;
26337 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
26338 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
26339 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
26340 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
26341 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
26342 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
26343 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
26344 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
26345 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
26346 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
26347 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
26348 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
26349 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
26350 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
26351 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
26352 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
26353 env->msair = env->cpu_model->MSAIR;
26354 env->insn_flags = env->cpu_model->insn_flags;
26356 #if defined(CONFIG_USER_ONLY)
26357 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
26358 # ifdef TARGET_MIPS64
26359 /* Enable 64-bit register mode. */
26360 env->CP0_Status |= (1 << CP0St_PX);
26361 # endif
26362 # ifdef TARGET_ABI_MIPSN64
26363 /* Enable 64-bit address mode. */
26364 env->CP0_Status |= (1 << CP0St_UX);
26365 # endif
26366 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
26367 hardware registers. */
26368 env->CP0_HWREna |= 0x0000000F;
26369 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
26370 env->CP0_Status |= (1 << CP0St_CU1);
26372 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
26373 env->CP0_Status |= (1 << CP0St_MX);
26375 # if defined(TARGET_MIPS64)
26376 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
26377 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
26378 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
26379 env->CP0_Status |= (1 << CP0St_FR);
26381 # endif
26382 #else
26383 if (env->hflags & MIPS_HFLAG_BMASK) {
26384 /* If the exception was raised from a delay slot,
26385 come back to the jump. */
26386 env->CP0_ErrorEPC = (env->active_tc.PC
26387 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
26388 } else {
26389 env->CP0_ErrorEPC = env->active_tc.PC;
26391 env->active_tc.PC = env->exception_base;
26392 env->CP0_Random = env->tlb->nb_tlb - 1;
26393 env->tlb->tlb_in_use = env->tlb->nb_tlb;
26394 env->CP0_Wired = 0;
26395 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
26396 env->CP0_EBase = (cs->cpu_index & 0x3FF);
26397 if (mips_um_ksegs_enabled()) {
26398 env->CP0_EBase |= 0x40000000;
26399 } else {
26400 env->CP0_EBase |= (int32_t)0x80000000;
26402 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
26403 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
26405 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
26406 0x3ff : 0xff;
26407 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
26408 /* vectored interrupts not implemented, timer on int 7,
26409 no performance counters. */
26410 env->CP0_IntCtl = 0xe0000000;
26412 int i;
26414 for (i = 0; i < 7; i++) {
26415 env->CP0_WatchLo[i] = 0;
26416 env->CP0_WatchHi[i] = 0x80000000;
26418 env->CP0_WatchLo[7] = 0;
26419 env->CP0_WatchHi[7] = 0;
26421 /* Count register increments in debug mode, EJTAG version 1 */
26422 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
26424 cpu_mips_store_count(env, 1);
26426 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
26427 int i;
26429 /* Only TC0 on VPE 0 starts as active. */
26430 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
26431 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
26432 env->tcs[i].CP0_TCHalt = 1;
26434 env->active_tc.CP0_TCHalt = 1;
26435 cs->halted = 1;
26437 if (cs->cpu_index == 0) {
26438 /* VPE0 starts up enabled. */
26439 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
26440 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
26442 /* TC0 starts up unhalted. */
26443 cs->halted = 0;
26444 env->active_tc.CP0_TCHalt = 0;
26445 env->tcs[0].CP0_TCHalt = 0;
26446 /* With thread 0 active. */
26447 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
26448 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
26453 * Configure default legacy segmentation control. We use this regardless of
26454 * whether segmentation control is presented to the guest.
26456 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
26457 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
26458 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
26459 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
26460 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
26461 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26462 (2 << CP0SC_C);
26463 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
26464 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26465 (3 << CP0SC_C)) << 16;
26466 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
26467 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26468 (1 << CP0SC_EU) | (2 << CP0SC_C);
26469 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
26470 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26471 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
26472 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
26473 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
26474 #endif
26475 if ((env->insn_flags & ISA_MIPS32R6) &&
26476 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
26477 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
26478 env->CP0_Status |= (1 << CP0St_FR);
26481 if (env->insn_flags & ISA_MIPS32R6) {
26482 /* PTW = 1 */
26483 env->CP0_PWSize = 0x40;
26484 /* GDI = 12 */
26485 /* UDI = 12 */
26486 /* MDI = 12 */
26487 /* PRI = 12 */
26488 /* PTEI = 2 */
26489 env->CP0_PWField = 0x0C30C302;
26490 } else {
26491 /* GDI = 0 */
26492 /* UDI = 0 */
26493 /* MDI = 0 */
26494 /* PRI = 0 */
26495 /* PTEI = 2 */
26496 env->CP0_PWField = 0x02;
26499 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
26500 /* microMIPS on reset when Config3.ISA is 3 */
26501 env->hflags |= MIPS_HFLAG_M16;
26504 /* MSA */
26505 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
26506 msa_reset(env);
26509 compute_hflags(env);
26510 restore_fp_status(env);
26511 restore_pamask(env);
26512 cs->exception_index = EXCP_NONE;
26514 if (semihosting_get_argc()) {
26515 /* UHI interface can be used to obtain argc and argv */
26516 env->active_tc.gpr[4] = -1;
26520 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
26521 target_ulong *data)
26523 env->active_tc.PC = data[0];
26524 env->hflags &= ~MIPS_HFLAG_BMASK;
26525 env->hflags |= data[1];
26526 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
26527 case MIPS_HFLAG_BR:
26528 break;
26529 case MIPS_HFLAG_BC:
26530 case MIPS_HFLAG_BL:
26531 case MIPS_HFLAG_B:
26532 env->btarget = data[2];
26533 break;