target/mips: Add emulation of MXU instruction D16MAC
[qemu/ar7.git] / target / mips / translate.c
blob4777228ad2690d72821648642d5e41d7082b65e4
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
467 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
468 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
469 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
470 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
473 /* DBSHFL opcodes */
474 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
476 enum {
477 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
478 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
479 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
480 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
481 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
482 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
483 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
484 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
485 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
486 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
487 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
490 /* MIPS DSP REGIMM opcodes */
491 enum {
492 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
493 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
496 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
497 /* MIPS DSP Load */
498 enum {
499 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
500 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
501 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
502 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
505 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
506 enum {
507 /* MIPS DSP Arithmetic Sub-class */
508 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
509 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
511 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
515 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
522 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
523 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
524 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
525 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
526 /* MIPS DSP Multiply Sub-class insns */
527 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
529 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
530 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
535 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
536 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
537 enum {
538 /* MIPS DSP Arithmetic Sub-class */
539 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
551 /* MIPS DSP Multiply Sub-class insns */
552 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
553 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
554 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
555 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
558 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
559 enum {
560 /* MIPS DSP Arithmetic Sub-class */
561 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
574 /* DSP Bit/Manipulation Sub-class */
575 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
578 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
582 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583 enum {
584 /* MIPS DSP Arithmetic Sub-class */
585 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
592 /* DSP Compare-Pick Sub-class */
593 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
610 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
611 enum {
612 /* MIPS DSP GPR-Based Shift Sub-class */
613 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
637 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
638 enum {
639 /* MIPS DSP Multiply Sub-class insns */
640 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
654 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
664 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
665 enum {
666 /* DSP Bit/Manipulation Sub-class */
667 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
670 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Append Sub-class */
673 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
674 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
675 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
678 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
679 enum {
680 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
681 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
693 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
694 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
695 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
696 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
697 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
700 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701 enum {
702 /* MIPS DSP Arithmetic Sub-class */
703 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
720 /* DSP Bit/Manipulation Sub-class */
721 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
724 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
729 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
730 enum {
731 /* MIPS DSP Multiply Sub-class insns */
732 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
733 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
734 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
735 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
737 /* MIPS DSP Arithmetic Sub-class */
738 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
761 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
762 enum {
763 /* DSP Compare-Pick Sub-class */
764 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
783 /* MIPS DSP Arithmetic Sub-class */
784 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
787 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
794 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
795 enum {
796 /* DSP Append Sub-class */
797 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
798 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
799 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
800 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
803 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804 enum {
805 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
806 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
807 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
829 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
830 enum {
831 /* DSP Bit/Manipulation Sub-class */
832 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
835 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
836 enum {
837 /* MIPS DSP Multiply Sub-class insns */
838 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
866 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
867 enum {
868 /* MIPS DSP GPR-Based Shift Sub-class */
869 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
897 /* Coprocessor 0 (rs field) */
898 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
900 enum {
901 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
902 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
903 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
904 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
905 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
906 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
907 OPC_MFTR = (0x08 << 21) | OPC_CP0,
908 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
909 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
910 OPC_MTTR = (0x0C << 21) | OPC_CP0,
911 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
912 OPC_C0 = (0x10 << 21) | OPC_CP0,
913 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
914 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
915 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
916 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
917 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
918 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
919 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
920 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
921 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
922 OPC_C0_A = (0x1A << 21) | OPC_CP0,
923 OPC_C0_B = (0x1B << 21) | OPC_CP0,
924 OPC_C0_C = (0x1C << 21) | OPC_CP0,
925 OPC_C0_D = (0x1D << 21) | OPC_CP0,
926 OPC_C0_E = (0x1E << 21) | OPC_CP0,
927 OPC_C0_F = (0x1F << 21) | OPC_CP0,
930 /* MFMC0 opcodes */
931 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
933 enum {
934 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
935 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
936 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
937 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
938 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
939 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
940 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
941 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
944 /* Coprocessor 0 (with rs == C0) */
945 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
947 enum {
948 OPC_TLBR = 0x01 | OPC_C0,
949 OPC_TLBWI = 0x02 | OPC_C0,
950 OPC_TLBINV = 0x03 | OPC_C0,
951 OPC_TLBINVF = 0x04 | OPC_C0,
952 OPC_TLBWR = 0x06 | OPC_C0,
953 OPC_TLBP = 0x08 | OPC_C0,
954 OPC_RFE = 0x10 | OPC_C0,
955 OPC_ERET = 0x18 | OPC_C0,
956 OPC_DERET = 0x1F | OPC_C0,
957 OPC_WAIT = 0x20 | OPC_C0,
960 /* Coprocessor 1 (rs field) */
961 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
963 /* Values for the fmt field in FP instructions */
964 enum {
965 /* 0 - 15 are reserved */
966 FMT_S = 16, /* single fp */
967 FMT_D = 17, /* double fp */
968 FMT_E = 18, /* extended fp */
969 FMT_Q = 19, /* quad fp */
970 FMT_W = 20, /* 32-bit fixed */
971 FMT_L = 21, /* 64-bit fixed */
972 FMT_PS = 22, /* paired single fp */
973 /* 23 - 31 are reserved */
976 enum {
977 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
978 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
979 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
980 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
981 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
982 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
983 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
984 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
985 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
986 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
987 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
988 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
989 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
990 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
991 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
992 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
993 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
994 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
995 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
996 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
997 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
998 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
999 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1000 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1001 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1002 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1003 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1004 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1005 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1006 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1009 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1010 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1012 enum {
1013 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1014 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1015 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1016 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1019 enum {
1020 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1021 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1024 enum {
1025 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1026 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1029 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1031 enum {
1032 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1033 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1034 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1035 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1036 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1037 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1038 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1039 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1040 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1041 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1042 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1045 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1047 enum {
1048 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1049 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1050 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1051 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1057 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1059 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1060 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1067 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1068 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1069 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1070 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1071 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1072 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1073 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1075 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1076 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1077 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1078 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1079 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1080 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1081 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1084 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1085 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1086 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1087 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1088 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1091 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1092 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1093 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1094 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1098 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1099 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1100 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1101 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1106 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1107 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1108 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1112 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1113 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1114 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1115 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1116 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1117 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1120 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1121 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1122 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1123 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1127 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1128 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1129 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1130 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1131 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1134 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1135 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1136 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1137 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1138 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1142 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1144 enum {
1145 OPC_LWXC1 = 0x00 | OPC_CP3,
1146 OPC_LDXC1 = 0x01 | OPC_CP3,
1147 OPC_LUXC1 = 0x05 | OPC_CP3,
1148 OPC_SWXC1 = 0x08 | OPC_CP3,
1149 OPC_SDXC1 = 0x09 | OPC_CP3,
1150 OPC_SUXC1 = 0x0D | OPC_CP3,
1151 OPC_PREFX = 0x0F | OPC_CP3,
1152 OPC_ALNV_PS = 0x1E | OPC_CP3,
1153 OPC_MADD_S = 0x20 | OPC_CP3,
1154 OPC_MADD_D = 0x21 | OPC_CP3,
1155 OPC_MADD_PS = 0x26 | OPC_CP3,
1156 OPC_MSUB_S = 0x28 | OPC_CP3,
1157 OPC_MSUB_D = 0x29 | OPC_CP3,
1158 OPC_MSUB_PS = 0x2E | OPC_CP3,
1159 OPC_NMADD_S = 0x30 | OPC_CP3,
1160 OPC_NMADD_D = 0x31 | OPC_CP3,
1161 OPC_NMADD_PS= 0x36 | OPC_CP3,
1162 OPC_NMSUB_S = 0x38 | OPC_CP3,
1163 OPC_NMSUB_D = 0x39 | OPC_CP3,
1164 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1167 /* MSA Opcodes */
1168 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1169 enum {
1170 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1171 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1172 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1173 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1174 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1175 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1176 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1177 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1178 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1179 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1180 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1181 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1182 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1183 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1184 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1185 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1186 OPC_MSA_ELM = 0x19 | OPC_MSA,
1187 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1188 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1189 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1190 OPC_MSA_VEC = 0x1E | OPC_MSA,
1192 /* MI10 instruction */
1193 OPC_LD_B = (0x20) | OPC_MSA,
1194 OPC_LD_H = (0x21) | OPC_MSA,
1195 OPC_LD_W = (0x22) | OPC_MSA,
1196 OPC_LD_D = (0x23) | OPC_MSA,
1197 OPC_ST_B = (0x24) | OPC_MSA,
1198 OPC_ST_H = (0x25) | OPC_MSA,
1199 OPC_ST_W = (0x26) | OPC_MSA,
1200 OPC_ST_D = (0x27) | OPC_MSA,
1203 enum {
1204 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1205 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1206 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1207 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1208 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1209 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1210 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1211 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1212 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1213 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1214 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1215 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1216 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1218 /* I8 instruction */
1219 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1220 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1221 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1222 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1223 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1225 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1226 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1228 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1230 /* VEC/2R/2RF instruction */
1231 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1232 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1233 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1234 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1235 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1236 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1237 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1239 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1240 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1242 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1243 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1244 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1245 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1246 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1248 /* 2RF instruction df(bit 16) = _w, _d */
1249 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1250 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1251 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1252 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1253 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1254 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1255 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1256 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1257 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1258 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1259 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1260 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1261 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1262 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1263 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1264 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1266 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1267 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1268 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1269 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1270 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1272 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1274 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1275 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1276 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1277 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1278 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1279 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1280 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1281 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1282 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1283 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1284 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1285 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1286 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1287 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1288 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1289 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1290 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1292 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1293 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1294 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1295 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1296 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1297 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1298 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1299 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1300 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1301 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1302 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1303 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1304 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1305 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1306 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1307 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1308 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1309 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1310 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1311 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1312 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1313 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1314 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1315 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1316 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1317 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1318 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1319 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1320 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1321 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1322 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1323 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1324 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1325 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1326 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1327 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1328 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1329 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1331 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1332 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1333 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1334 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1335 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1336 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 /* 3RF instruction _df(bit 21) = _w, _d */
1343 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1346 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1347 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1348 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1356 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1361 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1362 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1363 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1364 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1365 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1366 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1369 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1372 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1373 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1374 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1375 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1378 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1381 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1385 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1386 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1387 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1388 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1389 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1390 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1391 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1392 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1393 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1394 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1395 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1396 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1397 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1402 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1403 * ============================================
1405 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1406 * instructions set. It is designed to fit the needs of signal, graphical and
1407 * video processing applications. MXU instruction set is used in Xburst family
1408 * of microprocessors by Ingenic.
1410 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1411 * the control register.
1413 * The notation used in MXU assembler mnemonics:
1415 * XRa, XRb, XRc, XRd - MXU registers
1416 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1417 * s12 - a subfield of an instruction code
1418 * strd2 - a subfield of an instruction code
1419 * eptn2 - a subfield of an instruction code
1420 * eptn3 - a subfield of an instruction code
1421 * optn2 - a subfield of an instruction code
1422 * optn3 - a subfield of an instruction code
1423 * sft4 - a subfield of an instruction code
1425 * Load/Store instructions Multiplication instructions
1426 * ----------------------- ---------------------------
1428 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1429 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1430 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1431 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1432 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1433 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1434 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1435 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1436 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1437 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1438 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1439 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1440 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1441 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1442 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1443 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1444 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1445 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1446 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1447 * S16SDI XRa, Rb, s10, eptn2
1448 * S8LDD XRa, Rb, s8, eptn3
1449 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1450 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1451 * S8SDI XRa, Rb, s8, eptn3
1452 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1453 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1454 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1455 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1456 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1457 * S32CPS XRa, XRb, XRc
1458 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1459 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1460 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1461 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1462 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1463 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1464 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1465 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1466 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1467 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1468 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1469 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1470 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1471 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1472 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1473 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1474 * Q8SLT XRa, XRb, XRc
1475 * Q8SLTU XRa, XRb, XRc
1476 * Q8MOVZ XRa, XRb, XRc Shift instructions
1477 * Q8MOVN XRa, XRb, XRc ------------------
1479 * D32SLL XRa, XRb, XRc, XRd, sft4
1480 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1481 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1482 * D32SARL XRa, XRb, XRc, sft4
1483 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1484 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1485 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1486 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1487 * Q16SLL XRa, XRb, XRc, XRd, sft4
1488 * Q16SLR XRa, XRb, XRc, XRd, sft4
1489 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1490 * ------------------------- Q16SLLV XRa, XRb, Rb
1491 * Q16SLRV XRa, XRb, Rb
1492 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1493 * S32ALN XRa, XRb, XRc, Rb
1494 * S32ALNI XRa, XRb, XRc, s3
1495 * S32LUI XRa, s8, optn3 Move instructions
1496 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1497 * S32EXTRV XRa, XRb, Rs, Rt
1498 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1499 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1502 * bits
1503 * 05..00
1505 * ┌─ 000000 ─ OPC_MXU_S32MADD
1506 * ├─ 000001 ─ OPC_MXU_S32MADDU
1507 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1508 * │
1509 * │ 20..18
1510 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1511 * │ ├─ 001 ─ OPC_MXU_S32MIN
1512 * │ ├─ 010 ─ OPC_MXU_D16MAX
1513 * │ ├─ 011 ─ OPC_MXU_D16MIN
1514 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1515 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1516 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1517 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1518 * ├─ 000100 ─ OPC_MXU_S32MSUB
1519 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1520 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1521 * │ ├─ 001 ─ OPC_MXU_D16SLT
1522 * │ ├─ 010 ─ OPC_MXU_D16AVG
1523 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1524 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1525 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1526 * │ └─ 111 ─ OPC_MXU_Q8ADD
1527 * │
1528 * │ 20..18
1529 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1530 * │ ├─ 010 ─ OPC_MXU_D16CPS
1531 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1532 * │ └─ 110 ─ OPC_MXU_Q16SAT
1533 * ├─ 001000 ─ OPC_MXU_D16MUL
1534 * │ 25..24
1535 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1536 * │ └─ 01 ─ OPC_MXU_D16MULE
1537 * ├─ 001010 ─ OPC_MXU_D16MAC
1538 * ├─ 001011 ─ OPC_MXU_D16MACF
1539 * ├─ 001100 ─ OPC_MXU_D16MADL
1540 * ├─ 001101 ─ OPC_MXU_S16MAD
1541 * ├─ 001110 ─ OPC_MXU_Q16ADD
1542 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1543 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1544 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1545 * │
1546 * │ 23
1547 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1548 * │ └─ 1 ─ OPC_MXU_S32STDR
1549 * │
1550 * │ 13..10
1551 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1552 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1553 * │
1554 * │ 13..10
1555 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1556 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1557 * │
1558 * │ 23
1559 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1560 * │ └─ 1 ─ OPC_MXU_S32LDIR
1561 * │
1562 * │ 23
1563 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1564 * │ └─ 1 ─ OPC_MXU_S32SDIR
1565 * │
1566 * │ 13..10
1567 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1568 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1569 * │
1570 * │ 13..10
1571 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1572 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1573 * ├─ 011000 ─ OPC_MXU_D32ADD
1574 * │ 23..22
1575 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1576 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1577 * │ └─ 10 ─ OPC_MXU_D32ASUM
1578 * ├─ 011010 ─ <not assigned>
1579 * │ 23..22
1580 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1581 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1582 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1583 * │
1584 * │ 23..22
1585 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1586 * │ ├─ 01 ─ OPC_MXU_D8SUM
1587 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1588 * ├─ 011110 ─ <not assigned>
1589 * ├─ 011111 ─ <not assigned>
1590 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1591 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1592 * ├─ 100010 ─ OPC_MXU_S8LDD
1593 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1594 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1595 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1596 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1597 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1598 * │
1599 * │ 20..18
1600 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1601 * │ ├─ 001 ─ OPC_MXU_S32ALN
1602 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1603 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1604 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1605 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1606 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1607 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1608 * ├─ 101110 ─ OPC_MXU_S32M2I
1609 * ├─ 101111 ─ OPC_MXU_S32I2M
1610 * ├─ 110000 ─ OPC_MXU_D32SLL
1611 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1612 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1613 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1614 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1615 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1616 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1617 * ├─ 110110 ─ OPC_MXU__POOL17 ─┴─ 101 ─ OPC_MXU_Q16SARV
1618 * │
1619 * ├─ 110111 ─ OPC_MXU_Q16SAR
1620 * │ 23..22
1621 * ├─ 111000 ─ OPC_MXU__POOL18 ─┬─ 00 ─ OPC_MXU_Q8MUL
1622 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1623 * │
1624 * │ 20..18
1625 * ├─ 111001 ─ OPC_MXU__POOL19 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1626 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1627 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1628 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1629 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1630 * │ └─ 101 ─ OPC_MXU_S32MOV
1631 * │
1632 * │ 23..22
1633 * ├─ 111010 ─ OPC_MXU__POOL20 ─┬─ 00 ─ OPC_MXU_Q8MAC
1634 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1635 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1636 * ├─ 111100 ─ OPC_MXU_Q8MADL
1637 * ├─ 111101 ─ OPC_MXU_S32SFL
1638 * ├─ 111110 ─ OPC_MXU_Q8SAD
1639 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1642 * Compiled after:
1644 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1645 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1648 enum {
1649 OPC_MXU_S32MADD = 0x00,
1650 OPC_MXU_S32MADDU = 0x01,
1651 OPC__MXU_MUL = 0x02,
1652 OPC_MXU__POOL00 = 0x03,
1653 OPC_MXU_S32MSUB = 0x04,
1654 OPC_MXU_S32MSUBU = 0x05,
1655 OPC_MXU__POOL01 = 0x06,
1656 OPC_MXU__POOL02 = 0x07,
1657 OPC_MXU_D16MUL = 0x08,
1658 OPC_MXU__POOL03 = 0x09,
1659 OPC_MXU_D16MAC = 0x0A,
1660 OPC_MXU_D16MACF = 0x0B,
1661 OPC_MXU_D16MADL = 0x0C,
1662 OPC_MXU_S16MAD = 0x0D,
1663 OPC_MXU_Q16ADD = 0x0E,
1664 OPC_MXU_D16MACE = 0x0F,
1665 OPC_MXU__POOL04 = 0x10,
1666 OPC_MXU__POOL05 = 0x11,
1667 OPC_MXU__POOL06 = 0x12,
1668 OPC_MXU__POOL07 = 0x13,
1669 OPC_MXU__POOL08 = 0x14,
1670 OPC_MXU__POOL09 = 0x15,
1671 OPC_MXU__POOL10 = 0x16,
1672 OPC_MXU__POOL11 = 0x17,
1673 OPC_MXU_D32ADD = 0x18,
1674 OPC_MXU__POOL12 = 0x19,
1675 /* not assigned 0x1A */
1676 OPC_MXU__POOL13 = 0x1B,
1677 OPC_MXU__POOL14 = 0x1C,
1678 OPC_MXU_Q8ACCE = 0x1D,
1679 /* not assigned 0x1E */
1680 /* not assigned 0x1F */
1681 /* not assigned 0x20 */
1682 /* not assigned 0x21 */
1683 OPC_MXU_S8LDD = 0x22,
1684 OPC_MXU_S8STD = 0x23,
1685 OPC_MXU_S8LDI = 0x24,
1686 OPC_MXU_S8SDI = 0x25,
1687 OPC_MXU__POOL15 = 0x26,
1688 OPC_MXU__POOL16 = 0x27,
1689 OPC_MXU_LXB = 0x28,
1690 /* not assigned 0x29 */
1691 OPC_MXU_S16LDD = 0x2A,
1692 OPC_MXU_S16STD = 0x2B,
1693 OPC_MXU_S16LDI = 0x2C,
1694 OPC_MXU_S16SDI = 0x2D,
1695 OPC_MXU_S32M2I = 0x2E,
1696 OPC_MXU_S32I2M = 0x2F,
1697 OPC_MXU_D32SLL = 0x30,
1698 OPC_MXU_D32SLR = 0x31,
1699 OPC_MXU_D32SARL = 0x32,
1700 OPC_MXU_D32SAR = 0x33,
1701 OPC_MXU_Q16SLL = 0x34,
1702 OPC_MXU_Q16SLR = 0x35,
1703 OPC_MXU__POOL17 = 0x36,
1704 OPC_MXU_Q16SAR = 0x37,
1705 OPC_MXU__POOL18 = 0x38,
1706 OPC_MXU__POOL19 = 0x39,
1707 OPC_MXU__POOL20 = 0x3A,
1708 OPC_MXU_Q16SCOP = 0x3B,
1709 OPC_MXU_Q8MADL = 0x3C,
1710 OPC_MXU_S32SFL = 0x3D,
1711 OPC_MXU_Q8SAD = 0x3E,
1712 /* not assigned 0x3F */
1717 * MXU pool 00
1719 enum {
1720 OPC_MXU_S32MAX = 0x00,
1721 OPC_MXU_S32MIN = 0x01,
1722 OPC_MXU_D16MAX = 0x02,
1723 OPC_MXU_D16MIN = 0x03,
1724 OPC_MXU_Q8MAX = 0x04,
1725 OPC_MXU_Q8MIN = 0x05,
1726 OPC_MXU_Q8SLT = 0x06,
1727 OPC_MXU_Q8SLTU = 0x07,
1731 * MXU pool 01
1733 enum {
1734 OPC_MXU_S32SLT = 0x00,
1735 OPC_MXU_D16SLT = 0x01,
1736 OPC_MXU_D16AVG = 0x02,
1737 OPC_MXU_D16AVGR = 0x03,
1738 OPC_MXU_Q8AVG = 0x04,
1739 OPC_MXU_Q8AVGR = 0x05,
1740 OPC_MXU_Q8ADD = 0x07,
1744 * MXU pool 02
1746 enum {
1747 OPC_MXU_S32CPS = 0x00,
1748 OPC_MXU_D16CPS = 0x02,
1749 OPC_MXU_Q8ABD = 0x04,
1750 OPC_MXU_Q16SAT = 0x06,
1754 * MXU pool 03
1756 enum {
1757 OPC_MXU_D16MULF = 0x00,
1758 OPC_MXU_D16MULE = 0x01,
1762 * MXU pool 04
1764 enum {
1765 OPC_MXU_S32LDD = 0x00,
1766 OPC_MXU_S32LDDR = 0x01,
1770 * MXU pool 05
1772 enum {
1773 OPC_MXU_S32STD = 0x00,
1774 OPC_MXU_S32STDR = 0x01,
1778 * MXU pool 06
1780 enum {
1781 OPC_MXU_S32LDDV = 0x00,
1782 OPC_MXU_S32LDDVR = 0x01,
1786 * MXU pool 07
1788 enum {
1789 OPC_MXU_S32STDV = 0x00,
1790 OPC_MXU_S32STDVR = 0x01,
1794 * MXU pool 08
1796 enum {
1797 OPC_MXU_S32LDI = 0x00,
1798 OPC_MXU_S32LDIR = 0x01,
1802 * MXU pool 09
1804 enum {
1805 OPC_MXU_S32SDI = 0x00,
1806 OPC_MXU_S32SDIR = 0x01,
1810 * MXU pool 10
1812 enum {
1813 OPC_MXU_S32LDIV = 0x00,
1814 OPC_MXU_S32LDIVR = 0x01,
1818 * MXU pool 11
1820 enum {
1821 OPC_MXU_S32SDIV = 0x00,
1822 OPC_MXU_S32SDIVR = 0x01,
1826 * MXU pool 12
1828 enum {
1829 OPC_MXU_D32ACC = 0x00,
1830 OPC_MXU_D32ACCM = 0x01,
1831 OPC_MXU_D32ASUM = 0x02,
1835 * MXU pool 13
1837 enum {
1838 OPC_MXU_Q16ACC = 0x00,
1839 OPC_MXU_Q16ACCM = 0x01,
1840 OPC_MXU_Q16ASUM = 0x02,
1844 * MXU pool 14
1846 enum {
1847 OPC_MXU_Q8ADDE = 0x00,
1848 OPC_MXU_D8SUM = 0x01,
1849 OPC_MXU_D8SUMC = 0x02,
1853 * MXU pool 15
1855 enum {
1856 OPC_MXU_S32MUL = 0x00,
1857 OPC_MXU_S32MULU = 0x01,
1858 OPC_MXU_S32EXTR = 0x02,
1859 OPC_MXU_S32EXTRV = 0x03,
1863 * MXU pool 16
1865 enum {
1866 OPC_MXU_D32SARW = 0x00,
1867 OPC_MXU_S32ALN = 0x01,
1868 OPC_MXU_S32ALNI = 0x02,
1869 OPC_MXU_S32NOR = 0x03,
1870 OPC_MXU_S32AND = 0x04,
1871 OPC_MXU_S32OR = 0x05,
1872 OPC_MXU_S32XOR = 0x06,
1873 OPC_MXU_S32LUI = 0x07,
1877 * MXU pool 17
1879 enum {
1880 OPC_MXU_D32SLLV = 0x00,
1881 OPC_MXU_D32SLRV = 0x01,
1882 OPC_MXU_D32SARV = 0x03,
1883 OPC_MXU_Q16SLLV = 0x04,
1884 OPC_MXU_Q16SLRV = 0x05,
1885 OPC_MXU_Q16SARV = 0x07,
1889 * MXU pool 18
1891 enum {
1892 OPC_MXU_Q8MUL = 0x00,
1893 OPC_MXU_Q8MULSU = 0x01,
1897 * MXU pool 19
1899 enum {
1900 OPC_MXU_Q8MOVZ = 0x00,
1901 OPC_MXU_Q8MOVN = 0x01,
1902 OPC_MXU_D16MOVZ = 0x02,
1903 OPC_MXU_D16MOVN = 0x03,
1904 OPC_MXU_S32MOVZ = 0x04,
1905 OPC_MXU_S32MOVN = 0x05,
1909 * MXU pool 20
1911 enum {
1912 OPC_MXU_Q8MAC = 0x00,
1913 OPC_MXU_Q8MACSU = 0x01,
1917 * Overview of the TX79-specific instruction set
1918 * =============================================
1920 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1921 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1922 * instructions and certain multimedia instructions (MMIs). These MMIs
1923 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1924 * or sixteen 8-bit paths.
1926 * Reference:
1928 * The Toshiba TX System RISC TX79 Core Architecture manual,
1929 * https://wiki.qemu.org/File:C790.pdf
1931 * Three-Operand Multiply and Multiply-Add (4 instructions)
1932 * --------------------------------------------------------
1933 * MADD [rd,] rs, rt Multiply/Add
1934 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1935 * MULT [rd,] rs, rt Multiply (3-operand)
1936 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1938 * Multiply Instructions for Pipeline 1 (10 instructions)
1939 * ------------------------------------------------------
1940 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1941 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1942 * DIV1 rs, rt Divide Pipeline 1
1943 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1944 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1945 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1946 * MFHI1 rd Move From HI1 Register
1947 * MFLO1 rd Move From LO1 Register
1948 * MTHI1 rs Move To HI1 Register
1949 * MTLO1 rs Move To LO1 Register
1951 * Arithmetic (19 instructions)
1952 * ----------------------------
1953 * PADDB rd, rs, rt Parallel Add Byte
1954 * PSUBB rd, rs, rt Parallel Subtract Byte
1955 * PADDH rd, rs, rt Parallel Add Halfword
1956 * PSUBH rd, rs, rt Parallel Subtract Halfword
1957 * PADDW rd, rs, rt Parallel Add Word
1958 * PSUBW rd, rs, rt Parallel Subtract Word
1959 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1960 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1961 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1962 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1963 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1964 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1965 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1966 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1967 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1968 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1969 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1970 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1971 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1973 * Min/Max (4 instructions)
1974 * ------------------------
1975 * PMAXH rd, rs, rt Parallel Maximum Halfword
1976 * PMINH rd, rs, rt Parallel Minimum Halfword
1977 * PMAXW rd, rs, rt Parallel Maximum Word
1978 * PMINW rd, rs, rt Parallel Minimum Word
1980 * Absolute (2 instructions)
1981 * -------------------------
1982 * PABSH rd, rt Parallel Absolute Halfword
1983 * PABSW rd, rt Parallel Absolute Word
1985 * Logical (4 instructions)
1986 * ------------------------
1987 * PAND rd, rs, rt Parallel AND
1988 * POR rd, rs, rt Parallel OR
1989 * PXOR rd, rs, rt Parallel XOR
1990 * PNOR rd, rs, rt Parallel NOR
1992 * Shift (9 instructions)
1993 * ----------------------
1994 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
1995 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
1996 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
1997 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
1998 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
1999 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2000 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2001 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2002 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2004 * Compare (6 instructions)
2005 * ------------------------
2006 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2007 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2008 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2009 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2010 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2011 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2013 * LZC (1 instruction)
2014 * -------------------
2015 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2017 * Quadword Load and Store (2 instructions)
2018 * ----------------------------------------
2019 * LQ rt, offset(base) Load Quadword
2020 * SQ rt, offset(base) Store Quadword
2022 * Multiply and Divide (19 instructions)
2023 * -------------------------------------
2024 * PMULTW rd, rs, rt Parallel Multiply Word
2025 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2026 * PDIVW rs, rt Parallel Divide Word
2027 * PDIVUW rs, rt Parallel Divide Unsigned Word
2028 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2029 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2030 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2031 * PMULTH rd, rs, rt Parallel Multiply Halfword
2032 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2033 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2034 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2035 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2036 * PDIVBW rs, rt Parallel Divide Broadcast Word
2037 * PMFHI rd Parallel Move From HI Register
2038 * PMFLO rd Parallel Move From LO Register
2039 * PMTHI rs Parallel Move To HI Register
2040 * PMTLO rs Parallel Move To LO Register
2041 * PMFHL rd Parallel Move From HI/LO Register
2042 * PMTHL rs Parallel Move To HI/LO Register
2044 * Pack/Extend (11 instructions)
2045 * -----------------------------
2046 * PPAC5 rd, rt Parallel Pack to 5 bits
2047 * PPACB rd, rs, rt Parallel Pack to Byte
2048 * PPACH rd, rs, rt Parallel Pack to Halfword
2049 * PPACW rd, rs, rt Parallel Pack to Word
2050 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2051 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2052 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2053 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2054 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2055 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2056 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2058 * Others (16 instructions)
2059 * ------------------------
2060 * PCPYH rd, rt Parallel Copy Halfword
2061 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2062 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2063 * PREVH rd, rt Parallel Reverse Halfword
2064 * PINTH rd, rs, rt Parallel Interleave Halfword
2065 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2066 * PEXEH rd, rt Parallel Exchange Even Halfword
2067 * PEXCH rd, rt Parallel Exchange Center Halfword
2068 * PEXEW rd, rt Parallel Exchange Even Word
2069 * PEXCW rd, rt Parallel Exchange Center Word
2070 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2071 * MFSA rd Move from Shift Amount Register
2072 * MTSA rs Move to Shift Amount Register
2073 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2074 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2075 * PROT3W rd, rt Parallel Rotate 3 Words
2077 * The TX79-specific Multimedia Instruction encodings
2078 * ==================================================
2080 * TX79 Multimedia Instruction encoding table keys:
2082 * * This code is reserved for future use. An attempt to execute it
2083 * causes a Reserved Instruction exception.
2084 * % This code indicates an instruction class. The instruction word
2085 * must be further decoded by examining additional tables that show
2086 * the values for other instruction fields.
2087 * # This code is reserved for the unsupported instructions DMULT,
2088 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2089 * to execute it causes a Reserved Instruction exception.
2091 * TX79 Multimedia Instructions encoded by opcode field (MMI, LQ, SQ):
2093 * 31 26 0
2094 * +--------+----------------------------------------+
2095 * | opcode | |
2096 * +--------+----------------------------------------+
2098 * opcode bits 28..26
2099 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2100 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2101 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2102 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2103 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2104 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2105 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2106 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2107 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2108 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2109 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2112 enum {
2113 TX79_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2114 TX79_LQ = 0x1E << 26, /* Same as OPC_MSA */
2115 TX79_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2119 * TX79 Multimedia Instructions with opcode field = MMI:
2121 * 31 26 5 0
2122 * +--------+-------------------------------+--------+
2123 * | MMI | |function|
2124 * +--------+-------------------------------+--------+
2126 * function bits 2..0
2127 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2128 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2129 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2130 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2131 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2132 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2133 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2134 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2135 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2136 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2137 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2140 #define MASK_TX79_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2141 enum {
2142 TX79_MMI_MADD = 0x00 | TX79_CLASS_MMI, /* Same as OPC_MADD */
2143 TX79_MMI_MADDU = 0x01 | TX79_CLASS_MMI, /* Same as OPC_MADDU */
2144 TX79_MMI_PLZCW = 0x04 | TX79_CLASS_MMI,
2145 TX79_MMI_CLASS_MMI0 = 0x08 | TX79_CLASS_MMI,
2146 TX79_MMI_CLASS_MMI2 = 0x09 | TX79_CLASS_MMI,
2147 TX79_MMI_MFHI1 = 0x10 | TX79_CLASS_MMI, /* Same minor as OPC_MFHI */
2148 TX79_MMI_MTHI1 = 0x11 | TX79_CLASS_MMI, /* Same minor as OPC_MTHI */
2149 TX79_MMI_MFLO1 = 0x12 | TX79_CLASS_MMI, /* Same minor as OPC_MFLO */
2150 TX79_MMI_MTLO1 = 0x13 | TX79_CLASS_MMI, /* Same minor as OPC_MTLO */
2151 TX79_MMI_MULT1 = 0x18 | TX79_CLASS_MMI, /* Same minor as OPC_MULT */
2152 TX79_MMI_MULTU1 = 0x19 | TX79_CLASS_MMI, /* Same minor as OPC_MULTU */
2153 TX79_MMI_DIV1 = 0x1A | TX79_CLASS_MMI, /* Same minor as OPC_DIV */
2154 TX79_MMI_DIVU1 = 0x1B | TX79_CLASS_MMI, /* Same minor as OPC_DIVU */
2155 TX79_MMI_MADD1 = 0x20 | TX79_CLASS_MMI,
2156 TX79_MMI_MADDU1 = 0x21 | TX79_CLASS_MMI,
2157 TX79_MMI_CLASS_MMI1 = 0x28 | TX79_CLASS_MMI,
2158 TX79_MMI_CLASS_MMI3 = 0x29 | TX79_CLASS_MMI,
2159 TX79_MMI_PMFHL = 0x30 | TX79_CLASS_MMI,
2160 TX79_MMI_PMTHL = 0x31 | TX79_CLASS_MMI,
2161 TX79_MMI_PSLLH = 0x34 | TX79_CLASS_MMI,
2162 TX79_MMI_PSRLH = 0x36 | TX79_CLASS_MMI,
2163 TX79_MMI_PSRAH = 0x37 | TX79_CLASS_MMI,
2164 TX79_MMI_PSLLW = 0x3C | TX79_CLASS_MMI,
2165 TX79_MMI_PSRLW = 0x3E | TX79_CLASS_MMI,
2166 TX79_MMI_PSRAW = 0x3F | TX79_CLASS_MMI,
2170 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI0:
2172 * 31 26 10 6 5 0
2173 * +--------+----------------------+--------+--------+
2174 * | MMI | |function| MMI0 |
2175 * +--------+----------------------+--------+--------+
2177 * function bits 7..6
2178 * bits | 0 | 1 | 2 | 3
2179 * 10..8 | 00 | 01 | 10 | 11
2180 * -------+-------+-------+-------+-------
2181 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2182 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2183 * 2 010 | PADDB | PSUBB | PCGTB | *
2184 * 3 011 | * | * | * | *
2185 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2186 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2187 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2188 * 7 111 | * | * | PEXT5 | PPAC5
2191 #define MASK_TX79_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2192 enum {
2193 TX79_MMI0_PADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI0,
2194 TX79_MMI0_PSUBW = (0x01 << 6) | TX79_MMI_CLASS_MMI0,
2195 TX79_MMI0_PCGTW = (0x02 << 6) | TX79_MMI_CLASS_MMI0,
2196 TX79_MMI0_PMAXW = (0x03 << 6) | TX79_MMI_CLASS_MMI0,
2197 TX79_MMI0_PADDH = (0x04 << 6) | TX79_MMI_CLASS_MMI0,
2198 TX79_MMI0_PSUBH = (0x05 << 6) | TX79_MMI_CLASS_MMI0,
2199 TX79_MMI0_PCGTH = (0x06 << 6) | TX79_MMI_CLASS_MMI0,
2200 TX79_MMI0_PMAXH = (0x07 << 6) | TX79_MMI_CLASS_MMI0,
2201 TX79_MMI0_PADDB = (0x08 << 6) | TX79_MMI_CLASS_MMI0,
2202 TX79_MMI0_PSUBB = (0x09 << 6) | TX79_MMI_CLASS_MMI0,
2203 TX79_MMI0_PCGTB = (0x0A << 6) | TX79_MMI_CLASS_MMI0,
2204 TX79_MMI0_PADDSW = (0x10 << 6) | TX79_MMI_CLASS_MMI0,
2205 TX79_MMI0_PSUBSW = (0x11 << 6) | TX79_MMI_CLASS_MMI0,
2206 TX79_MMI0_PEXTLW = (0x12 << 6) | TX79_MMI_CLASS_MMI0,
2207 TX79_MMI0_PPACW = (0x13 << 6) | TX79_MMI_CLASS_MMI0,
2208 TX79_MMI0_PADDSH = (0x14 << 6) | TX79_MMI_CLASS_MMI0,
2209 TX79_MMI0_PSUBSH = (0x15 << 6) | TX79_MMI_CLASS_MMI0,
2210 TX79_MMI0_PEXTLH = (0x16 << 6) | TX79_MMI_CLASS_MMI0,
2211 TX79_MMI0_PPACH = (0x17 << 6) | TX79_MMI_CLASS_MMI0,
2212 TX79_MMI0_PADDSB = (0x18 << 6) | TX79_MMI_CLASS_MMI0,
2213 TX79_MMI0_PSUBSB = (0x19 << 6) | TX79_MMI_CLASS_MMI0,
2214 TX79_MMI0_PEXTLB = (0x1A << 6) | TX79_MMI_CLASS_MMI0,
2215 TX79_MMI0_PPACB = (0x1B << 6) | TX79_MMI_CLASS_MMI0,
2216 TX79_MMI0_PEXT5 = (0x1E << 6) | TX79_MMI_CLASS_MMI0,
2217 TX79_MMI0_PPAC5 = (0x1F << 6) | TX79_MMI_CLASS_MMI0,
2221 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI1:
2223 * 31 26 10 6 5 0
2224 * +--------+----------------------+--------+--------+
2225 * | MMI | |function| MMI1 |
2226 * +--------+----------------------+--------+--------+
2228 * function bits 7..6
2229 * bits | 0 | 1 | 2 | 3
2230 * 10..8 | 00 | 01 | 10 | 11
2231 * -------+-------+-------+-------+-------
2232 * 0 000 | * | PABSW | PCEQW | PMINW
2233 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2234 * 2 010 | * | * | PCEQB | *
2235 * 3 011 | * | * | * | *
2236 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2237 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2238 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2239 * 7 111 | * | * | * | *
2242 #define MASK_TX79_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2243 enum {
2244 TX79_MMI1_PABSW = (0x01 << 6) | TX79_MMI_CLASS_MMI1,
2245 TX79_MMI1_PCEQW = (0x02 << 6) | TX79_MMI_CLASS_MMI1,
2246 TX79_MMI1_PMINW = (0x03 << 6) | TX79_MMI_CLASS_MMI1,
2247 TX79_MMI1_PADSBH = (0x04 << 6) | TX79_MMI_CLASS_MMI1,
2248 TX79_MMI1_PABSH = (0x05 << 6) | TX79_MMI_CLASS_MMI1,
2249 TX79_MMI1_PCEQH = (0x06 << 6) | TX79_MMI_CLASS_MMI1,
2250 TX79_MMI1_PMINH = (0x07 << 6) | TX79_MMI_CLASS_MMI1,
2251 TX79_MMI1_PCEQB = (0x0A << 6) | TX79_MMI_CLASS_MMI1,
2252 TX79_MMI1_PADDUW = (0x10 << 6) | TX79_MMI_CLASS_MMI1,
2253 TX79_MMI1_PSUBUW = (0x11 << 6) | TX79_MMI_CLASS_MMI1,
2254 TX79_MMI1_PEXTUW = (0x12 << 6) | TX79_MMI_CLASS_MMI1,
2255 TX79_MMI1_PADDUH = (0x14 << 6) | TX79_MMI_CLASS_MMI1,
2256 TX79_MMI1_PSUBUH = (0x15 << 6) | TX79_MMI_CLASS_MMI1,
2257 TX79_MMI1_PEXTUH = (0x16 << 6) | TX79_MMI_CLASS_MMI1,
2258 TX79_MMI1_PADDUB = (0x18 << 6) | TX79_MMI_CLASS_MMI1,
2259 TX79_MMI1_PSUBUB = (0x19 << 6) | TX79_MMI_CLASS_MMI1,
2260 TX79_MMI1_PEXTUB = (0x1A << 6) | TX79_MMI_CLASS_MMI1,
2261 TX79_MMI1_QFSRV = (0x1B << 6) | TX79_MMI_CLASS_MMI1,
2265 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI2:
2267 * 31 26 10 6 5 0
2268 * +--------+----------------------+--------+--------+
2269 * | MMI | |function| MMI2 |
2270 * +--------+----------------------+--------+--------+
2272 * function bits 7..6
2273 * bits | 0 | 1 | 2 | 3
2274 * 10..8 | 00 | 01 | 10 | 11
2275 * -------+-------+-------+-------+-------
2276 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2277 * 1 001 | PMSUBW| * | * | *
2278 * 2 010 | PMFHI | PMFLO | PINTH | *
2279 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2280 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2281 * 5 101 | PMSUBH| PHMSBH| * | *
2282 * 6 110 | * | * | PEXEH | PREVH
2283 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2286 #define MASK_TX79_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2287 enum {
2288 TX79_MMI2_PMADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI2,
2289 TX79_MMI2_PSLLVW = (0x02 << 6) | TX79_MMI_CLASS_MMI2,
2290 TX79_MMI2_PSRLVW = (0x03 << 6) | TX79_MMI_CLASS_MMI2,
2291 TX79_MMI2_PMSUBW = (0x04 << 6) | TX79_MMI_CLASS_MMI2,
2292 TX79_MMI2_PMFHI = (0x08 << 6) | TX79_MMI_CLASS_MMI2,
2293 TX79_MMI2_PMFLO = (0x09 << 6) | TX79_MMI_CLASS_MMI2,
2294 TX79_MMI2_PINTH = (0x0A << 6) | TX79_MMI_CLASS_MMI2,
2295 TX79_MMI2_PMULTW = (0x0C << 6) | TX79_MMI_CLASS_MMI2,
2296 TX79_MMI2_PDIVW = (0x0D << 6) | TX79_MMI_CLASS_MMI2,
2297 TX79_MMI2_PCPYLD = (0x0E << 6) | TX79_MMI_CLASS_MMI2,
2298 TX79_MMI2_PMADDH = (0x10 << 6) | TX79_MMI_CLASS_MMI2,
2299 TX79_MMI2_PHMADH = (0x11 << 6) | TX79_MMI_CLASS_MMI2,
2300 TX79_MMI2_PAND = (0x12 << 6) | TX79_MMI_CLASS_MMI2,
2301 TX79_MMI2_PXOR = (0x13 << 6) | TX79_MMI_CLASS_MMI2,
2302 TX79_MMI2_PMSUBH = (0x14 << 6) | TX79_MMI_CLASS_MMI2,
2303 TX79_MMI2_PHMSBH = (0x15 << 6) | TX79_MMI_CLASS_MMI2,
2304 TX79_MMI2_PEXEH = (0x1A << 6) | TX79_MMI_CLASS_MMI2,
2305 TX79_MMI2_PREVH = (0x1B << 6) | TX79_MMI_CLASS_MMI2,
2306 TX79_MMI2_PMULTH = (0x1C << 6) | TX79_MMI_CLASS_MMI2,
2307 TX79_MMI2_PDIVBW = (0x1D << 6) | TX79_MMI_CLASS_MMI2,
2308 TX79_MMI2_PEXEW = (0x1E << 6) | TX79_MMI_CLASS_MMI2,
2309 TX79_MMI2_PROT3W = (0x1F << 6) | TX79_MMI_CLASS_MMI2,
2313 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI3:
2315 * 31 26 10 6 5 0
2316 * +--------+----------------------+--------+--------+
2317 * | MMI | |function| MMI3 |
2318 * +--------+----------------------+--------+--------+
2320 * function bits 7..6
2321 * bits | 0 | 1 | 2 | 3
2322 * 10..8 | 00 | 01 | 10 | 11
2323 * -------+-------+-------+-------+-------
2324 * 0 000 |PMADDUW| * | * | PSRAVW
2325 * 1 001 | * | * | * | *
2326 * 2 010 | PMTHI | PMTLO | PINTEH| *
2327 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2328 * 4 100 | * | * | POR | PNOR
2329 * 5 101 | * | * | * | *
2330 * 6 110 | * | * | PEXCH | PCPYH
2331 * 7 111 | * | * | PEXCW | *
2334 #define MASK_TX79_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2335 enum {
2336 TX79_MMI3_PMADDUW = (0x00 << 6) | TX79_MMI_CLASS_MMI3,
2337 TX79_MMI3_PSRAVW = (0x03 << 6) | TX79_MMI_CLASS_MMI3,
2338 TX79_MMI3_PMTHI = (0x08 << 6) | TX79_MMI_CLASS_MMI3,
2339 TX79_MMI3_PMTLO = (0x09 << 6) | TX79_MMI_CLASS_MMI3,
2340 TX79_MMI3_PINTEH = (0x0A << 6) | TX79_MMI_CLASS_MMI3,
2341 TX79_MMI3_PMULTUW = (0x0C << 6) | TX79_MMI_CLASS_MMI3,
2342 TX79_MMI3_PDIVUW = (0x0D << 6) | TX79_MMI_CLASS_MMI3,
2343 TX79_MMI3_PCPYUD = (0x0E << 6) | TX79_MMI_CLASS_MMI3,
2344 TX79_MMI3_POR = (0x12 << 6) | TX79_MMI_CLASS_MMI3,
2345 TX79_MMI3_PNOR = (0x13 << 6) | TX79_MMI_CLASS_MMI3,
2346 TX79_MMI3_PEXCH = (0x1A << 6) | TX79_MMI_CLASS_MMI3,
2347 TX79_MMI3_PCPYH = (0x1B << 6) | TX79_MMI_CLASS_MMI3,
2348 TX79_MMI3_PEXCW = (0x1E << 6) | TX79_MMI_CLASS_MMI3,
2351 /* global register indices */
2352 static TCGv cpu_gpr[32], cpu_PC;
2353 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2354 static TCGv cpu_dspctrl, btarget, bcond;
2355 static TCGv_i32 hflags;
2356 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2357 static TCGv_i64 fpu_f64[32];
2358 static TCGv_i64 msa_wr_d[64];
2360 /* MXU registers */
2361 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2362 static TCGv mxu_CR;
2364 #include "exec/gen-icount.h"
2366 #define gen_helper_0e0i(name, arg) do { \
2367 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2368 gen_helper_##name(cpu_env, helper_tmp); \
2369 tcg_temp_free_i32(helper_tmp); \
2370 } while(0)
2372 #define gen_helper_0e1i(name, arg1, arg2) do { \
2373 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2374 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2375 tcg_temp_free_i32(helper_tmp); \
2376 } while(0)
2378 #define gen_helper_1e0i(name, ret, arg1) do { \
2379 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2380 gen_helper_##name(ret, cpu_env, helper_tmp); \
2381 tcg_temp_free_i32(helper_tmp); \
2382 } while(0)
2384 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2385 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2386 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2387 tcg_temp_free_i32(helper_tmp); \
2388 } while(0)
2390 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2391 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2392 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2393 tcg_temp_free_i32(helper_tmp); \
2394 } while(0)
2396 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2397 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2398 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2399 tcg_temp_free_i32(helper_tmp); \
2400 } while(0)
2402 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2403 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2404 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2405 tcg_temp_free_i32(helper_tmp); \
2406 } while(0)
2408 typedef struct DisasContext {
2409 DisasContextBase base;
2410 target_ulong saved_pc;
2411 target_ulong page_start;
2412 uint32_t opcode;
2413 uint64_t insn_flags;
2414 int32_t CP0_Config1;
2415 int32_t CP0_Config2;
2416 int32_t CP0_Config3;
2417 int32_t CP0_Config5;
2418 /* Routine used to access memory */
2419 int mem_idx;
2420 TCGMemOp default_tcg_memop_mask;
2421 uint32_t hflags, saved_hflags;
2422 target_ulong btarget;
2423 bool ulri;
2424 int kscrexist;
2425 bool rxi;
2426 int ie;
2427 bool bi;
2428 bool bp;
2429 uint64_t PAMask;
2430 bool mvh;
2431 bool eva;
2432 bool sc;
2433 int CP0_LLAddr_shift;
2434 bool ps;
2435 bool vp;
2436 bool cmgcr;
2437 bool mrp;
2438 bool nan2008;
2439 bool abs2008;
2440 } DisasContext;
2442 #define DISAS_STOP DISAS_TARGET_0
2443 #define DISAS_EXIT DISAS_TARGET_1
2445 static const char * const regnames[] = {
2446 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2447 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2448 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2449 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2452 static const char * const regnames_HI[] = {
2453 "HI0", "HI1", "HI2", "HI3",
2456 static const char * const regnames_LO[] = {
2457 "LO0", "LO1", "LO2", "LO3",
2460 static const char * const fregnames[] = {
2461 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2462 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2463 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2464 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2467 static const char * const msaregnames[] = {
2468 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2469 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2470 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2471 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2472 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2473 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2474 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2475 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2476 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2477 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2478 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2479 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2480 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2481 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2482 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2483 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2486 static const char * const mxuregnames[] = {
2487 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2488 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2491 #define LOG_DISAS(...) \
2492 do { \
2493 if (MIPS_DEBUG_DISAS) { \
2494 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2496 } while (0)
2498 #define MIPS_INVAL(op) \
2499 do { \
2500 if (MIPS_DEBUG_DISAS) { \
2501 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2502 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2503 ctx->base.pc_next, ctx->opcode, op, \
2504 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2505 ((ctx->opcode >> 16) & 0x1F)); \
2507 } while (0)
2509 /* General purpose registers moves. */
2510 static inline void gen_load_gpr (TCGv t, int reg)
2512 if (reg == 0)
2513 tcg_gen_movi_tl(t, 0);
2514 else
2515 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2518 static inline void gen_store_gpr (TCGv t, int reg)
2520 if (reg != 0)
2521 tcg_gen_mov_tl(cpu_gpr[reg], t);
2524 /* Moves to/from shadow registers. */
2525 static inline void gen_load_srsgpr (int from, int to)
2527 TCGv t0 = tcg_temp_new();
2529 if (from == 0)
2530 tcg_gen_movi_tl(t0, 0);
2531 else {
2532 TCGv_i32 t2 = tcg_temp_new_i32();
2533 TCGv_ptr addr = tcg_temp_new_ptr();
2535 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2536 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2537 tcg_gen_andi_i32(t2, t2, 0xf);
2538 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2539 tcg_gen_ext_i32_ptr(addr, t2);
2540 tcg_gen_add_ptr(addr, cpu_env, addr);
2542 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2543 tcg_temp_free_ptr(addr);
2544 tcg_temp_free_i32(t2);
2546 gen_store_gpr(t0, to);
2547 tcg_temp_free(t0);
2550 static inline void gen_store_srsgpr (int from, int to)
2552 if (to != 0) {
2553 TCGv t0 = tcg_temp_new();
2554 TCGv_i32 t2 = tcg_temp_new_i32();
2555 TCGv_ptr addr = tcg_temp_new_ptr();
2557 gen_load_gpr(t0, from);
2558 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2559 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2560 tcg_gen_andi_i32(t2, t2, 0xf);
2561 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2562 tcg_gen_ext_i32_ptr(addr, t2);
2563 tcg_gen_add_ptr(addr, cpu_env, addr);
2565 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2566 tcg_temp_free_ptr(addr);
2567 tcg_temp_free_i32(t2);
2568 tcg_temp_free(t0);
2572 /* MXU General purpose registers moves. */
2573 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2575 if (reg == 0) {
2576 tcg_gen_movi_tl(t, 0);
2577 } else if (reg <= 15) {
2578 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2582 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2584 if (reg > 0 && reg <= 15) {
2585 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2589 /* MXU control register moves. */
2590 static inline void gen_load_mxu_cr(TCGv t)
2592 tcg_gen_mov_tl(t, mxu_CR);
2595 static inline void gen_store_mxu_cr(TCGv t)
2597 /* TODO: Add handling of RW rules for MXU_CR. */
2598 tcg_gen_mov_tl(mxu_CR, t);
2602 /* Tests */
2603 static inline void gen_save_pc(target_ulong pc)
2605 tcg_gen_movi_tl(cpu_PC, pc);
2608 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2610 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2611 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2612 gen_save_pc(ctx->base.pc_next);
2613 ctx->saved_pc = ctx->base.pc_next;
2615 if (ctx->hflags != ctx->saved_hflags) {
2616 tcg_gen_movi_i32(hflags, ctx->hflags);
2617 ctx->saved_hflags = ctx->hflags;
2618 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2619 case MIPS_HFLAG_BR:
2620 break;
2621 case MIPS_HFLAG_BC:
2622 case MIPS_HFLAG_BL:
2623 case MIPS_HFLAG_B:
2624 tcg_gen_movi_tl(btarget, ctx->btarget);
2625 break;
2630 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2632 ctx->saved_hflags = ctx->hflags;
2633 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2634 case MIPS_HFLAG_BR:
2635 break;
2636 case MIPS_HFLAG_BC:
2637 case MIPS_HFLAG_BL:
2638 case MIPS_HFLAG_B:
2639 ctx->btarget = env->btarget;
2640 break;
2644 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2646 TCGv_i32 texcp = tcg_const_i32(excp);
2647 TCGv_i32 terr = tcg_const_i32(err);
2648 save_cpu_state(ctx, 1);
2649 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2650 tcg_temp_free_i32(terr);
2651 tcg_temp_free_i32(texcp);
2652 ctx->base.is_jmp = DISAS_NORETURN;
2655 static inline void generate_exception(DisasContext *ctx, int excp)
2657 gen_helper_0e0i(raise_exception, excp);
2660 static inline void generate_exception_end(DisasContext *ctx, int excp)
2662 generate_exception_err(ctx, excp, 0);
2665 /* Floating point register moves. */
2666 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2668 if (ctx->hflags & MIPS_HFLAG_FRE) {
2669 generate_exception(ctx, EXCP_RI);
2671 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2674 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2676 TCGv_i64 t64;
2677 if (ctx->hflags & MIPS_HFLAG_FRE) {
2678 generate_exception(ctx, EXCP_RI);
2680 t64 = tcg_temp_new_i64();
2681 tcg_gen_extu_i32_i64(t64, t);
2682 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2683 tcg_temp_free_i64(t64);
2686 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2688 if (ctx->hflags & MIPS_HFLAG_F64) {
2689 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2690 } else {
2691 gen_load_fpr32(ctx, t, reg | 1);
2695 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2697 if (ctx->hflags & MIPS_HFLAG_F64) {
2698 TCGv_i64 t64 = tcg_temp_new_i64();
2699 tcg_gen_extu_i32_i64(t64, t);
2700 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2701 tcg_temp_free_i64(t64);
2702 } else {
2703 gen_store_fpr32(ctx, t, reg | 1);
2707 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2709 if (ctx->hflags & MIPS_HFLAG_F64) {
2710 tcg_gen_mov_i64(t, fpu_f64[reg]);
2711 } else {
2712 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2716 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2718 if (ctx->hflags & MIPS_HFLAG_F64) {
2719 tcg_gen_mov_i64(fpu_f64[reg], t);
2720 } else {
2721 TCGv_i64 t0;
2722 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2723 t0 = tcg_temp_new_i64();
2724 tcg_gen_shri_i64(t0, t, 32);
2725 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2726 tcg_temp_free_i64(t0);
2730 static inline int get_fp_bit (int cc)
2732 if (cc)
2733 return 24 + cc;
2734 else
2735 return 23;
2738 /* Addresses computation */
2739 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2741 tcg_gen_add_tl(ret, arg0, arg1);
2743 #if defined(TARGET_MIPS64)
2744 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2745 tcg_gen_ext32s_i64(ret, ret);
2747 #endif
2750 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2751 target_long ofs)
2753 tcg_gen_addi_tl(ret, base, ofs);
2755 #if defined(TARGET_MIPS64)
2756 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2757 tcg_gen_ext32s_i64(ret, ret);
2759 #endif
2762 /* Addresses computation (translation time) */
2763 static target_long addr_add(DisasContext *ctx, target_long base,
2764 target_long offset)
2766 target_long sum = base + offset;
2768 #if defined(TARGET_MIPS64)
2769 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2770 sum = (int32_t)sum;
2772 #endif
2773 return sum;
2776 /* Sign-extract the low 32-bits to a target_long. */
2777 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2779 #if defined(TARGET_MIPS64)
2780 tcg_gen_ext32s_i64(ret, arg);
2781 #else
2782 tcg_gen_extrl_i64_i32(ret, arg);
2783 #endif
2786 /* Sign-extract the high 32-bits to a target_long. */
2787 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2789 #if defined(TARGET_MIPS64)
2790 tcg_gen_sari_i64(ret, arg, 32);
2791 #else
2792 tcg_gen_extrh_i64_i32(ret, arg);
2793 #endif
2796 static inline void check_cp0_enabled(DisasContext *ctx)
2798 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2799 generate_exception_err(ctx, EXCP_CpU, 0);
2802 static inline void check_cp1_enabled(DisasContext *ctx)
2804 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2805 generate_exception_err(ctx, EXCP_CpU, 1);
2808 /* Verify that the processor is running with COP1X instructions enabled.
2809 This is associated with the nabla symbol in the MIPS32 and MIPS64
2810 opcode tables. */
2812 static inline void check_cop1x(DisasContext *ctx)
2814 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2815 generate_exception_end(ctx, EXCP_RI);
2818 /* Verify that the processor is running with 64-bit floating-point
2819 operations enabled. */
2821 static inline void check_cp1_64bitmode(DisasContext *ctx)
2823 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2824 generate_exception_end(ctx, EXCP_RI);
2828 * Verify if floating point register is valid; an operation is not defined
2829 * if bit 0 of any register specification is set and the FR bit in the
2830 * Status register equals zero, since the register numbers specify an
2831 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2832 * in the Status register equals one, both even and odd register numbers
2833 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2835 * Multiple 64 bit wide registers can be checked by calling
2836 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2838 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2840 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2841 generate_exception_end(ctx, EXCP_RI);
2844 /* Verify that the processor is running with DSP instructions enabled.
2845 This is enabled by CP0 Status register MX(24) bit.
2848 static inline void check_dsp(DisasContext *ctx)
2850 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2851 if (ctx->insn_flags & ASE_DSP) {
2852 generate_exception_end(ctx, EXCP_DSPDIS);
2853 } else {
2854 generate_exception_end(ctx, EXCP_RI);
2859 static inline void check_dsp_r2(DisasContext *ctx)
2861 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2862 if (ctx->insn_flags & ASE_DSP) {
2863 generate_exception_end(ctx, EXCP_DSPDIS);
2864 } else {
2865 generate_exception_end(ctx, EXCP_RI);
2870 static inline void check_dsp_r3(DisasContext *ctx)
2872 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2873 if (ctx->insn_flags & ASE_DSP) {
2874 generate_exception_end(ctx, EXCP_DSPDIS);
2875 } else {
2876 generate_exception_end(ctx, EXCP_RI);
2881 /* This code generates a "reserved instruction" exception if the
2882 CPU does not support the instruction set corresponding to flags. */
2883 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2885 if (unlikely(!(ctx->insn_flags & flags))) {
2886 generate_exception_end(ctx, EXCP_RI);
2890 /* This code generates a "reserved instruction" exception if the
2891 CPU has corresponding flag set which indicates that the instruction
2892 has been removed. */
2893 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2895 if (unlikely(ctx->insn_flags & flags)) {
2896 generate_exception_end(ctx, EXCP_RI);
2901 * The Linux kernel traps certain reserved instruction exceptions to
2902 * emulate the corresponding instructions. QEMU is the kernel in user
2903 * mode, so those traps are emulated by accepting the instructions.
2905 * A reserved instruction exception is generated for flagged CPUs if
2906 * QEMU runs in system mode.
2908 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2910 #ifndef CONFIG_USER_ONLY
2911 check_insn_opc_removed(ctx, flags);
2912 #endif
2915 /* This code generates a "reserved instruction" exception if the
2916 CPU does not support 64-bit paired-single (PS) floating point data type */
2917 static inline void check_ps(DisasContext *ctx)
2919 if (unlikely(!ctx->ps)) {
2920 generate_exception(ctx, EXCP_RI);
2922 check_cp1_64bitmode(ctx);
2925 #ifdef TARGET_MIPS64
2926 /* This code generates a "reserved instruction" exception if 64-bit
2927 instructions are not enabled. */
2928 static inline void check_mips_64(DisasContext *ctx)
2930 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2931 generate_exception_end(ctx, EXCP_RI);
2933 #endif
2935 #ifndef CONFIG_USER_ONLY
2936 static inline void check_mvh(DisasContext *ctx)
2938 if (unlikely(!ctx->mvh)) {
2939 generate_exception(ctx, EXCP_RI);
2942 #endif
2945 * This code generates a "reserved instruction" exception if the
2946 * Config5 XNP bit is set.
2948 static inline void check_xnp(DisasContext *ctx)
2950 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2951 generate_exception_end(ctx, EXCP_RI);
2955 #ifndef CONFIG_USER_ONLY
2957 * This code generates a "reserved instruction" exception if the
2958 * Config3 PW bit is NOT set.
2960 static inline void check_pw(DisasContext *ctx)
2962 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2963 generate_exception_end(ctx, EXCP_RI);
2966 #endif
2969 * This code generates a "reserved instruction" exception if the
2970 * Config3 MT bit is NOT set.
2972 static inline void check_mt(DisasContext *ctx)
2974 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2975 generate_exception_end(ctx, EXCP_RI);
2979 #ifndef CONFIG_USER_ONLY
2981 * This code generates a "coprocessor unusable" exception if CP0 is not
2982 * available, and, if that is not the case, generates a "reserved instruction"
2983 * exception if the Config5 MT bit is NOT set. This is needed for availability
2984 * control of some of MT ASE instructions.
2986 static inline void check_cp0_mt(DisasContext *ctx)
2988 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2989 generate_exception_err(ctx, EXCP_CpU, 0);
2990 } else {
2991 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2992 generate_exception_err(ctx, EXCP_RI, 0);
2996 #endif
2999 * This code generates a "reserved instruction" exception if the
3000 * Config5 NMS bit is set.
3002 static inline void check_nms(DisasContext *ctx)
3004 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3005 generate_exception_end(ctx, EXCP_RI);
3010 * This code generates a "reserved instruction" exception if the
3011 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3012 * Config2 TL, and Config5 L2C are unset.
3014 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3016 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3017 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3018 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3019 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3020 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3021 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
3023 generate_exception_end(ctx, EXCP_RI);
3028 * This code generates a "reserved instruction" exception if the
3029 * Config5 EVA bit is NOT set.
3031 static inline void check_eva(DisasContext *ctx)
3033 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3034 generate_exception_end(ctx, EXCP_RI);
3039 /* Define small wrappers for gen_load_fpr* so that we have a uniform
3040 calling interface for 32 and 64-bit FPRs. No sense in changing
3041 all callers for gen_load_fpr32 when we need the CTX parameter for
3042 this one use. */
3043 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3044 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3045 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3046 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3047 int ft, int fs, int cc) \
3049 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3050 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3051 switch (ifmt) { \
3052 case FMT_PS: \
3053 check_ps(ctx); \
3054 break; \
3055 case FMT_D: \
3056 if (abs) { \
3057 check_cop1x(ctx); \
3059 check_cp1_registers(ctx, fs | ft); \
3060 break; \
3061 case FMT_S: \
3062 if (abs) { \
3063 check_cop1x(ctx); \
3065 break; \
3067 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3068 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3069 switch (n) { \
3070 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3071 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3072 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3073 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3074 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3075 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3076 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3077 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3078 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3079 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3080 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3081 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3082 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3083 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3084 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3085 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3086 default: abort(); \
3088 tcg_temp_free_i##bits (fp0); \
3089 tcg_temp_free_i##bits (fp1); \
3092 FOP_CONDS(, 0, d, FMT_D, 64)
3093 FOP_CONDS(abs, 1, d, FMT_D, 64)
3094 FOP_CONDS(, 0, s, FMT_S, 32)
3095 FOP_CONDS(abs, 1, s, FMT_S, 32)
3096 FOP_CONDS(, 0, ps, FMT_PS, 64)
3097 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3098 #undef FOP_CONDS
3100 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3101 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3102 int ft, int fs, int fd) \
3104 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3105 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3106 if (ifmt == FMT_D) { \
3107 check_cp1_registers(ctx, fs | ft | fd); \
3109 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3110 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3111 switch (n) { \
3112 case 0: \
3113 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3114 break; \
3115 case 1: \
3116 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3117 break; \
3118 case 2: \
3119 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3120 break; \
3121 case 3: \
3122 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3123 break; \
3124 case 4: \
3125 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3126 break; \
3127 case 5: \
3128 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3129 break; \
3130 case 6: \
3131 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3132 break; \
3133 case 7: \
3134 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3135 break; \
3136 case 8: \
3137 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3138 break; \
3139 case 9: \
3140 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3141 break; \
3142 case 10: \
3143 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3144 break; \
3145 case 11: \
3146 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3147 break; \
3148 case 12: \
3149 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3150 break; \
3151 case 13: \
3152 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3153 break; \
3154 case 14: \
3155 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3156 break; \
3157 case 15: \
3158 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3159 break; \
3160 case 17: \
3161 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3162 break; \
3163 case 18: \
3164 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3165 break; \
3166 case 19: \
3167 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3168 break; \
3169 case 25: \
3170 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3171 break; \
3172 case 26: \
3173 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3174 break; \
3175 case 27: \
3176 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3177 break; \
3178 default: \
3179 abort(); \
3181 STORE; \
3182 tcg_temp_free_i ## bits (fp0); \
3183 tcg_temp_free_i ## bits (fp1); \
3186 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3187 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3188 #undef FOP_CONDNS
3189 #undef gen_ldcmp_fpr32
3190 #undef gen_ldcmp_fpr64
3192 /* load/store instructions. */
3193 #ifdef CONFIG_USER_ONLY
3194 #define OP_LD_ATOMIC(insn,fname) \
3195 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3196 DisasContext *ctx) \
3198 TCGv t0 = tcg_temp_new(); \
3199 tcg_gen_mov_tl(t0, arg1); \
3200 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3201 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3202 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3203 tcg_temp_free(t0); \
3205 #else
3206 #define OP_LD_ATOMIC(insn,fname) \
3207 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3208 DisasContext *ctx) \
3210 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3212 #endif
3213 OP_LD_ATOMIC(ll,ld32s);
3214 #if defined(TARGET_MIPS64)
3215 OP_LD_ATOMIC(lld,ld64);
3216 #endif
3217 #undef OP_LD_ATOMIC
3219 #ifdef CONFIG_USER_ONLY
3220 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3221 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3222 DisasContext *ctx) \
3224 TCGv t0 = tcg_temp_new(); \
3225 TCGLabel *l1 = gen_new_label(); \
3226 TCGLabel *l2 = gen_new_label(); \
3228 tcg_gen_andi_tl(t0, arg2, almask); \
3229 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
3230 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
3231 generate_exception(ctx, EXCP_AdES); \
3232 gen_set_label(l1); \
3233 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3234 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3235 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
3236 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3237 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
3238 generate_exception_end(ctx, EXCP_SC); \
3239 gen_set_label(l2); \
3240 tcg_gen_movi_tl(t0, 0); \
3241 gen_store_gpr(t0, rt); \
3242 tcg_temp_free(t0); \
3244 #else
3245 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3246 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3247 DisasContext *ctx) \
3249 TCGv t0 = tcg_temp_new(); \
3250 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
3251 gen_store_gpr(t0, rt); \
3252 tcg_temp_free(t0); \
3254 #endif
3255 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
3256 #if defined(TARGET_MIPS64)
3257 OP_ST_ATOMIC(scd,st64,ld64,0x7);
3258 #endif
3259 #undef OP_ST_ATOMIC
3261 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3262 int base, int offset)
3264 if (base == 0) {
3265 tcg_gen_movi_tl(addr, offset);
3266 } else if (offset == 0) {
3267 gen_load_gpr(addr, base);
3268 } else {
3269 tcg_gen_movi_tl(addr, offset);
3270 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3274 static target_ulong pc_relative_pc (DisasContext *ctx)
3276 target_ulong pc = ctx->base.pc_next;
3278 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3279 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3281 pc -= branch_bytes;
3284 pc &= ~(target_ulong)3;
3285 return pc;
3288 /* Load */
3289 static void gen_ld(DisasContext *ctx, uint32_t opc,
3290 int rt, int base, int offset)
3292 TCGv t0, t1, t2;
3293 int mem_idx = ctx->mem_idx;
3295 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3296 /* Loongson CPU uses a load to zero register for prefetch.
3297 We emulate it as a NOP. On other CPU we must perform the
3298 actual memory access. */
3299 return;
3302 t0 = tcg_temp_new();
3303 gen_base_offset_addr(ctx, t0, base, offset);
3305 switch (opc) {
3306 #if defined(TARGET_MIPS64)
3307 case OPC_LWU:
3308 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3309 ctx->default_tcg_memop_mask);
3310 gen_store_gpr(t0, rt);
3311 break;
3312 case OPC_LD:
3313 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3314 ctx->default_tcg_memop_mask);
3315 gen_store_gpr(t0, rt);
3316 break;
3317 case OPC_LLD:
3318 case R6_OPC_LLD:
3319 op_ld_lld(t0, t0, mem_idx, ctx);
3320 gen_store_gpr(t0, rt);
3321 break;
3322 case OPC_LDL:
3323 t1 = tcg_temp_new();
3324 /* Do a byte access to possibly trigger a page
3325 fault with the unaligned address. */
3326 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3327 tcg_gen_andi_tl(t1, t0, 7);
3328 #ifndef TARGET_WORDS_BIGENDIAN
3329 tcg_gen_xori_tl(t1, t1, 7);
3330 #endif
3331 tcg_gen_shli_tl(t1, t1, 3);
3332 tcg_gen_andi_tl(t0, t0, ~7);
3333 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3334 tcg_gen_shl_tl(t0, t0, t1);
3335 t2 = tcg_const_tl(-1);
3336 tcg_gen_shl_tl(t2, t2, t1);
3337 gen_load_gpr(t1, rt);
3338 tcg_gen_andc_tl(t1, t1, t2);
3339 tcg_temp_free(t2);
3340 tcg_gen_or_tl(t0, t0, t1);
3341 tcg_temp_free(t1);
3342 gen_store_gpr(t0, rt);
3343 break;
3344 case OPC_LDR:
3345 t1 = tcg_temp_new();
3346 /* Do a byte access to possibly trigger a page
3347 fault with the unaligned address. */
3348 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3349 tcg_gen_andi_tl(t1, t0, 7);
3350 #ifdef TARGET_WORDS_BIGENDIAN
3351 tcg_gen_xori_tl(t1, t1, 7);
3352 #endif
3353 tcg_gen_shli_tl(t1, t1, 3);
3354 tcg_gen_andi_tl(t0, t0, ~7);
3355 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3356 tcg_gen_shr_tl(t0, t0, t1);
3357 tcg_gen_xori_tl(t1, t1, 63);
3358 t2 = tcg_const_tl(0xfffffffffffffffeull);
3359 tcg_gen_shl_tl(t2, t2, t1);
3360 gen_load_gpr(t1, rt);
3361 tcg_gen_and_tl(t1, t1, t2);
3362 tcg_temp_free(t2);
3363 tcg_gen_or_tl(t0, t0, t1);
3364 tcg_temp_free(t1);
3365 gen_store_gpr(t0, rt);
3366 break;
3367 case OPC_LDPC:
3368 t1 = tcg_const_tl(pc_relative_pc(ctx));
3369 gen_op_addr_add(ctx, t0, t0, t1);
3370 tcg_temp_free(t1);
3371 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3372 gen_store_gpr(t0, rt);
3373 break;
3374 #endif
3375 case OPC_LWPC:
3376 t1 = tcg_const_tl(pc_relative_pc(ctx));
3377 gen_op_addr_add(ctx, t0, t0, t1);
3378 tcg_temp_free(t1);
3379 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3380 gen_store_gpr(t0, rt);
3381 break;
3382 case OPC_LWE:
3383 mem_idx = MIPS_HFLAG_UM;
3384 /* fall through */
3385 case OPC_LW:
3386 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3387 ctx->default_tcg_memop_mask);
3388 gen_store_gpr(t0, rt);
3389 break;
3390 case OPC_LHE:
3391 mem_idx = MIPS_HFLAG_UM;
3392 /* fall through */
3393 case OPC_LH:
3394 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3395 ctx->default_tcg_memop_mask);
3396 gen_store_gpr(t0, rt);
3397 break;
3398 case OPC_LHUE:
3399 mem_idx = MIPS_HFLAG_UM;
3400 /* fall through */
3401 case OPC_LHU:
3402 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3403 ctx->default_tcg_memop_mask);
3404 gen_store_gpr(t0, rt);
3405 break;
3406 case OPC_LBE:
3407 mem_idx = MIPS_HFLAG_UM;
3408 /* fall through */
3409 case OPC_LB:
3410 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3411 gen_store_gpr(t0, rt);
3412 break;
3413 case OPC_LBUE:
3414 mem_idx = MIPS_HFLAG_UM;
3415 /* fall through */
3416 case OPC_LBU:
3417 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3418 gen_store_gpr(t0, rt);
3419 break;
3420 case OPC_LWLE:
3421 mem_idx = MIPS_HFLAG_UM;
3422 /* fall through */
3423 case OPC_LWL:
3424 t1 = tcg_temp_new();
3425 /* Do a byte access to possibly trigger a page
3426 fault with the unaligned address. */
3427 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3428 tcg_gen_andi_tl(t1, t0, 3);
3429 #ifndef TARGET_WORDS_BIGENDIAN
3430 tcg_gen_xori_tl(t1, t1, 3);
3431 #endif
3432 tcg_gen_shli_tl(t1, t1, 3);
3433 tcg_gen_andi_tl(t0, t0, ~3);
3434 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3435 tcg_gen_shl_tl(t0, t0, t1);
3436 t2 = tcg_const_tl(-1);
3437 tcg_gen_shl_tl(t2, t2, t1);
3438 gen_load_gpr(t1, rt);
3439 tcg_gen_andc_tl(t1, t1, t2);
3440 tcg_temp_free(t2);
3441 tcg_gen_or_tl(t0, t0, t1);
3442 tcg_temp_free(t1);
3443 tcg_gen_ext32s_tl(t0, t0);
3444 gen_store_gpr(t0, rt);
3445 break;
3446 case OPC_LWRE:
3447 mem_idx = MIPS_HFLAG_UM;
3448 /* fall through */
3449 case OPC_LWR:
3450 t1 = tcg_temp_new();
3451 /* Do a byte access to possibly trigger a page
3452 fault with the unaligned address. */
3453 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3454 tcg_gen_andi_tl(t1, t0, 3);
3455 #ifdef TARGET_WORDS_BIGENDIAN
3456 tcg_gen_xori_tl(t1, t1, 3);
3457 #endif
3458 tcg_gen_shli_tl(t1, t1, 3);
3459 tcg_gen_andi_tl(t0, t0, ~3);
3460 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3461 tcg_gen_shr_tl(t0, t0, t1);
3462 tcg_gen_xori_tl(t1, t1, 31);
3463 t2 = tcg_const_tl(0xfffffffeull);
3464 tcg_gen_shl_tl(t2, t2, t1);
3465 gen_load_gpr(t1, rt);
3466 tcg_gen_and_tl(t1, t1, t2);
3467 tcg_temp_free(t2);
3468 tcg_gen_or_tl(t0, t0, t1);
3469 tcg_temp_free(t1);
3470 tcg_gen_ext32s_tl(t0, t0);
3471 gen_store_gpr(t0, rt);
3472 break;
3473 case OPC_LLE:
3474 mem_idx = MIPS_HFLAG_UM;
3475 /* fall through */
3476 case OPC_LL:
3477 case R6_OPC_LL:
3478 op_ld_ll(t0, t0, mem_idx, ctx);
3479 gen_store_gpr(t0, rt);
3480 break;
3482 tcg_temp_free(t0);
3485 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3486 uint32_t reg1, uint32_t reg2)
3488 TCGv taddr = tcg_temp_new();
3489 TCGv_i64 tval = tcg_temp_new_i64();
3490 TCGv tmp1 = tcg_temp_new();
3491 TCGv tmp2 = tcg_temp_new();
3493 gen_base_offset_addr(ctx, taddr, base, offset);
3494 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3495 #ifdef TARGET_WORDS_BIGENDIAN
3496 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3497 #else
3498 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3499 #endif
3500 gen_store_gpr(tmp1, reg1);
3501 tcg_temp_free(tmp1);
3502 gen_store_gpr(tmp2, reg2);
3503 tcg_temp_free(tmp2);
3504 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3505 tcg_temp_free_i64(tval);
3506 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3507 tcg_temp_free(taddr);
3510 /* Store */
3511 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3512 int base, int offset)
3514 TCGv t0 = tcg_temp_new();
3515 TCGv t1 = tcg_temp_new();
3516 int mem_idx = ctx->mem_idx;
3518 gen_base_offset_addr(ctx, t0, base, offset);
3519 gen_load_gpr(t1, rt);
3520 switch (opc) {
3521 #if defined(TARGET_MIPS64)
3522 case OPC_SD:
3523 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3524 ctx->default_tcg_memop_mask);
3525 break;
3526 case OPC_SDL:
3527 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3528 break;
3529 case OPC_SDR:
3530 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3531 break;
3532 #endif
3533 case OPC_SWE:
3534 mem_idx = MIPS_HFLAG_UM;
3535 /* fall through */
3536 case OPC_SW:
3537 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3538 ctx->default_tcg_memop_mask);
3539 break;
3540 case OPC_SHE:
3541 mem_idx = MIPS_HFLAG_UM;
3542 /* fall through */
3543 case OPC_SH:
3544 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3545 ctx->default_tcg_memop_mask);
3546 break;
3547 case OPC_SBE:
3548 mem_idx = MIPS_HFLAG_UM;
3549 /* fall through */
3550 case OPC_SB:
3551 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3552 break;
3553 case OPC_SWLE:
3554 mem_idx = MIPS_HFLAG_UM;
3555 /* fall through */
3556 case OPC_SWL:
3557 gen_helper_0e2i(swl, t1, t0, mem_idx);
3558 break;
3559 case OPC_SWRE:
3560 mem_idx = MIPS_HFLAG_UM;
3561 /* fall through */
3562 case OPC_SWR:
3563 gen_helper_0e2i(swr, t1, t0, mem_idx);
3564 break;
3566 tcg_temp_free(t0);
3567 tcg_temp_free(t1);
3571 /* Store conditional */
3572 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3573 int base, int16_t offset)
3575 TCGv t0, t1;
3576 int mem_idx = ctx->mem_idx;
3578 #ifdef CONFIG_USER_ONLY
3579 t0 = tcg_temp_local_new();
3580 t1 = tcg_temp_local_new();
3581 #else
3582 t0 = tcg_temp_new();
3583 t1 = tcg_temp_new();
3584 #endif
3585 gen_base_offset_addr(ctx, t0, base, offset);
3586 gen_load_gpr(t1, rt);
3587 switch (opc) {
3588 #if defined(TARGET_MIPS64)
3589 case OPC_SCD:
3590 case R6_OPC_SCD:
3591 op_st_scd(t1, t0, rt, mem_idx, ctx);
3592 break;
3593 #endif
3594 case OPC_SCE:
3595 mem_idx = MIPS_HFLAG_UM;
3596 /* fall through */
3597 case OPC_SC:
3598 case R6_OPC_SC:
3599 op_st_sc(t1, t0, rt, mem_idx, ctx);
3600 break;
3602 tcg_temp_free(t1);
3603 tcg_temp_free(t0);
3606 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3607 uint32_t reg1, uint32_t reg2)
3609 TCGv taddr = tcg_temp_local_new();
3610 TCGv lladdr = tcg_temp_local_new();
3611 TCGv_i64 tval = tcg_temp_new_i64();
3612 TCGv_i64 llval = tcg_temp_new_i64();
3613 TCGv_i64 val = tcg_temp_new_i64();
3614 TCGv tmp1 = tcg_temp_new();
3615 TCGv tmp2 = tcg_temp_new();
3616 TCGLabel *lab_fail = gen_new_label();
3617 TCGLabel *lab_done = gen_new_label();
3619 gen_base_offset_addr(ctx, taddr, base, offset);
3621 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3622 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3624 gen_load_gpr(tmp1, reg1);
3625 gen_load_gpr(tmp2, reg2);
3627 #ifdef TARGET_WORDS_BIGENDIAN
3628 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3629 #else
3630 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3631 #endif
3633 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3634 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3635 ctx->mem_idx, MO_64);
3636 if (reg1 != 0) {
3637 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3639 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3641 gen_set_label(lab_fail);
3643 if (reg1 != 0) {
3644 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3646 gen_set_label(lab_done);
3647 tcg_gen_movi_tl(lladdr, -1);
3648 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3651 /* Load and store */
3652 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3653 TCGv t0)
3655 /* Don't do NOP if destination is zero: we must perform the actual
3656 memory access. */
3657 switch (opc) {
3658 case OPC_LWC1:
3660 TCGv_i32 fp0 = tcg_temp_new_i32();
3661 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3662 ctx->default_tcg_memop_mask);
3663 gen_store_fpr32(ctx, fp0, ft);
3664 tcg_temp_free_i32(fp0);
3666 break;
3667 case OPC_SWC1:
3669 TCGv_i32 fp0 = tcg_temp_new_i32();
3670 gen_load_fpr32(ctx, fp0, ft);
3671 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3672 ctx->default_tcg_memop_mask);
3673 tcg_temp_free_i32(fp0);
3675 break;
3676 case OPC_LDC1:
3678 TCGv_i64 fp0 = tcg_temp_new_i64();
3679 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3680 ctx->default_tcg_memop_mask);
3681 gen_store_fpr64(ctx, fp0, ft);
3682 tcg_temp_free_i64(fp0);
3684 break;
3685 case OPC_SDC1:
3687 TCGv_i64 fp0 = tcg_temp_new_i64();
3688 gen_load_fpr64(ctx, fp0, ft);
3689 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3690 ctx->default_tcg_memop_mask);
3691 tcg_temp_free_i64(fp0);
3693 break;
3694 default:
3695 MIPS_INVAL("flt_ldst");
3696 generate_exception_end(ctx, EXCP_RI);
3697 break;
3701 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3702 int rs, int16_t imm)
3704 TCGv t0 = tcg_temp_new();
3706 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3707 check_cp1_enabled(ctx);
3708 switch (op) {
3709 case OPC_LDC1:
3710 case OPC_SDC1:
3711 check_insn(ctx, ISA_MIPS2);
3712 /* Fallthrough */
3713 default:
3714 gen_base_offset_addr(ctx, t0, rs, imm);
3715 gen_flt_ldst(ctx, op, rt, t0);
3717 } else {
3718 generate_exception_err(ctx, EXCP_CpU, 1);
3720 tcg_temp_free(t0);
3723 /* Arithmetic with immediate operand */
3724 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3725 int rt, int rs, int imm)
3727 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3729 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3730 /* If no destination, treat it as a NOP.
3731 For addi, we must generate the overflow exception when needed. */
3732 return;
3734 switch (opc) {
3735 case OPC_ADDI:
3737 TCGv t0 = tcg_temp_local_new();
3738 TCGv t1 = tcg_temp_new();
3739 TCGv t2 = tcg_temp_new();
3740 TCGLabel *l1 = gen_new_label();
3742 gen_load_gpr(t1, rs);
3743 tcg_gen_addi_tl(t0, t1, uimm);
3744 tcg_gen_ext32s_tl(t0, t0);
3746 tcg_gen_xori_tl(t1, t1, ~uimm);
3747 tcg_gen_xori_tl(t2, t0, uimm);
3748 tcg_gen_and_tl(t1, t1, t2);
3749 tcg_temp_free(t2);
3750 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3751 tcg_temp_free(t1);
3752 /* operands of same sign, result different sign */
3753 generate_exception(ctx, EXCP_OVERFLOW);
3754 gen_set_label(l1);
3755 tcg_gen_ext32s_tl(t0, t0);
3756 gen_store_gpr(t0, rt);
3757 tcg_temp_free(t0);
3759 break;
3760 case OPC_ADDIU:
3761 if (rs != 0) {
3762 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3763 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3764 } else {
3765 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3767 break;
3768 #if defined(TARGET_MIPS64)
3769 case OPC_DADDI:
3771 TCGv t0 = tcg_temp_local_new();
3772 TCGv t1 = tcg_temp_new();
3773 TCGv t2 = tcg_temp_new();
3774 TCGLabel *l1 = gen_new_label();
3776 gen_load_gpr(t1, rs);
3777 tcg_gen_addi_tl(t0, t1, uimm);
3779 tcg_gen_xori_tl(t1, t1, ~uimm);
3780 tcg_gen_xori_tl(t2, t0, uimm);
3781 tcg_gen_and_tl(t1, t1, t2);
3782 tcg_temp_free(t2);
3783 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3784 tcg_temp_free(t1);
3785 /* operands of same sign, result different sign */
3786 generate_exception(ctx, EXCP_OVERFLOW);
3787 gen_set_label(l1);
3788 gen_store_gpr(t0, rt);
3789 tcg_temp_free(t0);
3791 break;
3792 case OPC_DADDIU:
3793 if (rs != 0) {
3794 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3795 } else {
3796 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3798 break;
3799 #endif
3803 /* Logic with immediate operand */
3804 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3805 int rt, int rs, int16_t imm)
3807 target_ulong uimm;
3809 if (rt == 0) {
3810 /* If no destination, treat it as a NOP. */
3811 return;
3813 uimm = (uint16_t)imm;
3814 switch (opc) {
3815 case OPC_ANDI:
3816 if (likely(rs != 0))
3817 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3818 else
3819 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3820 break;
3821 case OPC_ORI:
3822 if (rs != 0)
3823 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3824 else
3825 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3826 break;
3827 case OPC_XORI:
3828 if (likely(rs != 0))
3829 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3830 else
3831 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3832 break;
3833 case OPC_LUI:
3834 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3835 /* OPC_AUI */
3836 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3837 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3838 } else {
3839 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3841 break;
3843 default:
3844 break;
3848 /* Set on less than with immediate operand */
3849 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3850 int rt, int rs, int16_t imm)
3852 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3853 TCGv t0;
3855 if (rt == 0) {
3856 /* If no destination, treat it as a NOP. */
3857 return;
3859 t0 = tcg_temp_new();
3860 gen_load_gpr(t0, rs);
3861 switch (opc) {
3862 case OPC_SLTI:
3863 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3864 break;
3865 case OPC_SLTIU:
3866 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3867 break;
3869 tcg_temp_free(t0);
3872 /* Shifts with immediate operand */
3873 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3874 int rt, int rs, int16_t imm)
3876 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3877 TCGv t0;
3879 if (rt == 0) {
3880 /* If no destination, treat it as a NOP. */
3881 return;
3884 t0 = tcg_temp_new();
3885 gen_load_gpr(t0, rs);
3886 switch (opc) {
3887 case OPC_SLL:
3888 tcg_gen_shli_tl(t0, t0, uimm);
3889 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3890 break;
3891 case OPC_SRA:
3892 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3893 break;
3894 case OPC_SRL:
3895 if (uimm != 0) {
3896 tcg_gen_ext32u_tl(t0, t0);
3897 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3898 } else {
3899 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3901 break;
3902 case OPC_ROTR:
3903 if (uimm != 0) {
3904 TCGv_i32 t1 = tcg_temp_new_i32();
3906 tcg_gen_trunc_tl_i32(t1, t0);
3907 tcg_gen_rotri_i32(t1, t1, uimm);
3908 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3909 tcg_temp_free_i32(t1);
3910 } else {
3911 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3913 break;
3914 #if defined(TARGET_MIPS64)
3915 case OPC_DSLL:
3916 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3917 break;
3918 case OPC_DSRA:
3919 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3920 break;
3921 case OPC_DSRL:
3922 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3923 break;
3924 case OPC_DROTR:
3925 if (uimm != 0) {
3926 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3927 } else {
3928 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3930 break;
3931 case OPC_DSLL32:
3932 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3933 break;
3934 case OPC_DSRA32:
3935 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3936 break;
3937 case OPC_DSRL32:
3938 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3939 break;
3940 case OPC_DROTR32:
3941 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3942 break;
3943 #endif
3945 tcg_temp_free(t0);
3948 /* Arithmetic */
3949 static void gen_arith(DisasContext *ctx, uint32_t opc,
3950 int rd, int rs, int rt)
3952 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3953 && opc != OPC_DADD && opc != OPC_DSUB) {
3954 /* If no destination, treat it as a NOP.
3955 For add & sub, we must generate the overflow exception when needed. */
3956 return;
3959 switch (opc) {
3960 case OPC_ADD:
3962 TCGv t0 = tcg_temp_local_new();
3963 TCGv t1 = tcg_temp_new();
3964 TCGv t2 = tcg_temp_new();
3965 TCGLabel *l1 = gen_new_label();
3967 gen_load_gpr(t1, rs);
3968 gen_load_gpr(t2, rt);
3969 tcg_gen_add_tl(t0, t1, t2);
3970 tcg_gen_ext32s_tl(t0, t0);
3971 tcg_gen_xor_tl(t1, t1, t2);
3972 tcg_gen_xor_tl(t2, t0, t2);
3973 tcg_gen_andc_tl(t1, t2, t1);
3974 tcg_temp_free(t2);
3975 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3976 tcg_temp_free(t1);
3977 /* operands of same sign, result different sign */
3978 generate_exception(ctx, EXCP_OVERFLOW);
3979 gen_set_label(l1);
3980 gen_store_gpr(t0, rd);
3981 tcg_temp_free(t0);
3983 break;
3984 case OPC_ADDU:
3985 if (rs != 0 && rt != 0) {
3986 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3987 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3988 } else if (rs == 0 && rt != 0) {
3989 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3990 } else if (rs != 0 && rt == 0) {
3991 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3992 } else {
3993 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3995 break;
3996 case OPC_SUB:
3998 TCGv t0 = tcg_temp_local_new();
3999 TCGv t1 = tcg_temp_new();
4000 TCGv t2 = tcg_temp_new();
4001 TCGLabel *l1 = gen_new_label();
4003 gen_load_gpr(t1, rs);
4004 gen_load_gpr(t2, rt);
4005 tcg_gen_sub_tl(t0, t1, t2);
4006 tcg_gen_ext32s_tl(t0, t0);
4007 tcg_gen_xor_tl(t2, t1, t2);
4008 tcg_gen_xor_tl(t1, t0, t1);
4009 tcg_gen_and_tl(t1, t1, t2);
4010 tcg_temp_free(t2);
4011 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4012 tcg_temp_free(t1);
4013 /* operands of different sign, first operand and result different sign */
4014 generate_exception(ctx, EXCP_OVERFLOW);
4015 gen_set_label(l1);
4016 gen_store_gpr(t0, rd);
4017 tcg_temp_free(t0);
4019 break;
4020 case OPC_SUBU:
4021 if (rs != 0 && rt != 0) {
4022 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4023 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4024 } else if (rs == 0 && rt != 0) {
4025 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4026 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4027 } else if (rs != 0 && rt == 0) {
4028 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4029 } else {
4030 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4032 break;
4033 #if defined(TARGET_MIPS64)
4034 case OPC_DADD:
4036 TCGv t0 = tcg_temp_local_new();
4037 TCGv t1 = tcg_temp_new();
4038 TCGv t2 = tcg_temp_new();
4039 TCGLabel *l1 = gen_new_label();
4041 gen_load_gpr(t1, rs);
4042 gen_load_gpr(t2, rt);
4043 tcg_gen_add_tl(t0, t1, t2);
4044 tcg_gen_xor_tl(t1, t1, t2);
4045 tcg_gen_xor_tl(t2, t0, t2);
4046 tcg_gen_andc_tl(t1, t2, t1);
4047 tcg_temp_free(t2);
4048 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4049 tcg_temp_free(t1);
4050 /* operands of same sign, result different sign */
4051 generate_exception(ctx, EXCP_OVERFLOW);
4052 gen_set_label(l1);
4053 gen_store_gpr(t0, rd);
4054 tcg_temp_free(t0);
4056 break;
4057 case OPC_DADDU:
4058 if (rs != 0 && rt != 0) {
4059 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4060 } else if (rs == 0 && rt != 0) {
4061 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4062 } else if (rs != 0 && rt == 0) {
4063 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4064 } else {
4065 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4067 break;
4068 case OPC_DSUB:
4070 TCGv t0 = tcg_temp_local_new();
4071 TCGv t1 = tcg_temp_new();
4072 TCGv t2 = tcg_temp_new();
4073 TCGLabel *l1 = gen_new_label();
4075 gen_load_gpr(t1, rs);
4076 gen_load_gpr(t2, rt);
4077 tcg_gen_sub_tl(t0, t1, t2);
4078 tcg_gen_xor_tl(t2, t1, t2);
4079 tcg_gen_xor_tl(t1, t0, t1);
4080 tcg_gen_and_tl(t1, t1, t2);
4081 tcg_temp_free(t2);
4082 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4083 tcg_temp_free(t1);
4084 /* operands of different sign, first operand and result different sign */
4085 generate_exception(ctx, EXCP_OVERFLOW);
4086 gen_set_label(l1);
4087 gen_store_gpr(t0, rd);
4088 tcg_temp_free(t0);
4090 break;
4091 case OPC_DSUBU:
4092 if (rs != 0 && rt != 0) {
4093 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4094 } else if (rs == 0 && rt != 0) {
4095 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4096 } else if (rs != 0 && rt == 0) {
4097 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4098 } else {
4099 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4101 break;
4102 #endif
4103 case OPC_MUL:
4104 if (likely(rs != 0 && rt != 0)) {
4105 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4106 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4107 } else {
4108 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4110 break;
4114 /* Conditional move */
4115 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4116 int rd, int rs, int rt)
4118 TCGv t0, t1, t2;
4120 if (rd == 0) {
4121 /* If no destination, treat it as a NOP. */
4122 return;
4125 t0 = tcg_temp_new();
4126 gen_load_gpr(t0, rt);
4127 t1 = tcg_const_tl(0);
4128 t2 = tcg_temp_new();
4129 gen_load_gpr(t2, rs);
4130 switch (opc) {
4131 case OPC_MOVN:
4132 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4133 break;
4134 case OPC_MOVZ:
4135 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4136 break;
4137 case OPC_SELNEZ:
4138 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4139 break;
4140 case OPC_SELEQZ:
4141 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4142 break;
4144 tcg_temp_free(t2);
4145 tcg_temp_free(t1);
4146 tcg_temp_free(t0);
4149 /* Logic */
4150 static void gen_logic(DisasContext *ctx, uint32_t opc,
4151 int rd, int rs, int rt)
4153 if (rd == 0) {
4154 /* If no destination, treat it as a NOP. */
4155 return;
4158 switch (opc) {
4159 case OPC_AND:
4160 if (likely(rs != 0 && rt != 0)) {
4161 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4162 } else {
4163 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4165 break;
4166 case OPC_NOR:
4167 if (rs != 0 && rt != 0) {
4168 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4169 } else if (rs == 0 && rt != 0) {
4170 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4171 } else if (rs != 0 && rt == 0) {
4172 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4173 } else {
4174 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4176 break;
4177 case OPC_OR:
4178 if (likely(rs != 0 && rt != 0)) {
4179 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4180 } else if (rs == 0 && rt != 0) {
4181 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4182 } else if (rs != 0 && rt == 0) {
4183 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4184 } else {
4185 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4187 break;
4188 case OPC_XOR:
4189 if (likely(rs != 0 && rt != 0)) {
4190 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4191 } else if (rs == 0 && rt != 0) {
4192 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4193 } else if (rs != 0 && rt == 0) {
4194 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4195 } else {
4196 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4198 break;
4202 /* Set on lower than */
4203 static void gen_slt(DisasContext *ctx, uint32_t opc,
4204 int rd, int rs, int rt)
4206 TCGv t0, t1;
4208 if (rd == 0) {
4209 /* If no destination, treat it as a NOP. */
4210 return;
4213 t0 = tcg_temp_new();
4214 t1 = tcg_temp_new();
4215 gen_load_gpr(t0, rs);
4216 gen_load_gpr(t1, rt);
4217 switch (opc) {
4218 case OPC_SLT:
4219 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4220 break;
4221 case OPC_SLTU:
4222 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4223 break;
4225 tcg_temp_free(t0);
4226 tcg_temp_free(t1);
4229 /* Shifts */
4230 static void gen_shift(DisasContext *ctx, uint32_t opc,
4231 int rd, int rs, int rt)
4233 TCGv t0, t1;
4235 if (rd == 0) {
4236 /* If no destination, treat it as a NOP.
4237 For add & sub, we must generate the overflow exception when needed. */
4238 return;
4241 t0 = tcg_temp_new();
4242 t1 = tcg_temp_new();
4243 gen_load_gpr(t0, rs);
4244 gen_load_gpr(t1, rt);
4245 switch (opc) {
4246 case OPC_SLLV:
4247 tcg_gen_andi_tl(t0, t0, 0x1f);
4248 tcg_gen_shl_tl(t0, t1, t0);
4249 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4250 break;
4251 case OPC_SRAV:
4252 tcg_gen_andi_tl(t0, t0, 0x1f);
4253 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4254 break;
4255 case OPC_SRLV:
4256 tcg_gen_ext32u_tl(t1, t1);
4257 tcg_gen_andi_tl(t0, t0, 0x1f);
4258 tcg_gen_shr_tl(t0, t1, t0);
4259 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4260 break;
4261 case OPC_ROTRV:
4263 TCGv_i32 t2 = tcg_temp_new_i32();
4264 TCGv_i32 t3 = tcg_temp_new_i32();
4266 tcg_gen_trunc_tl_i32(t2, t0);
4267 tcg_gen_trunc_tl_i32(t3, t1);
4268 tcg_gen_andi_i32(t2, t2, 0x1f);
4269 tcg_gen_rotr_i32(t2, t3, t2);
4270 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4271 tcg_temp_free_i32(t2);
4272 tcg_temp_free_i32(t3);
4274 break;
4275 #if defined(TARGET_MIPS64)
4276 case OPC_DSLLV:
4277 tcg_gen_andi_tl(t0, t0, 0x3f);
4278 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4279 break;
4280 case OPC_DSRAV:
4281 tcg_gen_andi_tl(t0, t0, 0x3f);
4282 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4283 break;
4284 case OPC_DSRLV:
4285 tcg_gen_andi_tl(t0, t0, 0x3f);
4286 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4287 break;
4288 case OPC_DROTRV:
4289 tcg_gen_andi_tl(t0, t0, 0x3f);
4290 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4291 break;
4292 #endif
4294 tcg_temp_free(t0);
4295 tcg_temp_free(t1);
4298 /* Arithmetic on HI/LO registers */
4299 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4301 if (reg == 0 && (opc == OPC_MFHI || opc == TX79_MMI_MFHI1 ||
4302 opc == OPC_MFLO || opc == TX79_MMI_MFLO1)) {
4303 /* Treat as NOP. */
4304 return;
4307 if (acc != 0) {
4308 if (!(ctx->insn_flags & INSN_R5900)) {
4309 check_dsp(ctx);
4313 switch (opc) {
4314 case OPC_MFHI:
4315 case TX79_MMI_MFHI1:
4316 #if defined(TARGET_MIPS64)
4317 if (acc != 0) {
4318 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4319 } else
4320 #endif
4322 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4324 break;
4325 case OPC_MFLO:
4326 case TX79_MMI_MFLO1:
4327 #if defined(TARGET_MIPS64)
4328 if (acc != 0) {
4329 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4330 } else
4331 #endif
4333 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4335 break;
4336 case OPC_MTHI:
4337 case TX79_MMI_MTHI1:
4338 if (reg != 0) {
4339 #if defined(TARGET_MIPS64)
4340 if (acc != 0) {
4341 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4342 } else
4343 #endif
4345 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4347 } else {
4348 tcg_gen_movi_tl(cpu_HI[acc], 0);
4350 break;
4351 case OPC_MTLO:
4352 case TX79_MMI_MTLO1:
4353 if (reg != 0) {
4354 #if defined(TARGET_MIPS64)
4355 if (acc != 0) {
4356 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4357 } else
4358 #endif
4360 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4362 } else {
4363 tcg_gen_movi_tl(cpu_LO[acc], 0);
4365 break;
4369 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4370 TCGMemOp memop)
4372 TCGv t0 = tcg_const_tl(addr);
4373 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4374 gen_store_gpr(t0, reg);
4375 tcg_temp_free(t0);
4378 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4379 int rs)
4381 target_long offset;
4382 target_long addr;
4384 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4385 case OPC_ADDIUPC:
4386 if (rs != 0) {
4387 offset = sextract32(ctx->opcode << 2, 0, 21);
4388 addr = addr_add(ctx, pc, offset);
4389 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4391 break;
4392 case R6_OPC_LWPC:
4393 offset = sextract32(ctx->opcode << 2, 0, 21);
4394 addr = addr_add(ctx, pc, offset);
4395 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4396 break;
4397 #if defined(TARGET_MIPS64)
4398 case OPC_LWUPC:
4399 check_mips_64(ctx);
4400 offset = sextract32(ctx->opcode << 2, 0, 21);
4401 addr = addr_add(ctx, pc, offset);
4402 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4403 break;
4404 #endif
4405 default:
4406 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4407 case OPC_AUIPC:
4408 if (rs != 0) {
4409 offset = sextract32(ctx->opcode, 0, 16) << 16;
4410 addr = addr_add(ctx, pc, offset);
4411 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4413 break;
4414 case OPC_ALUIPC:
4415 if (rs != 0) {
4416 offset = sextract32(ctx->opcode, 0, 16) << 16;
4417 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4418 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4420 break;
4421 #if defined(TARGET_MIPS64)
4422 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4423 case R6_OPC_LDPC + (1 << 16):
4424 case R6_OPC_LDPC + (2 << 16):
4425 case R6_OPC_LDPC + (3 << 16):
4426 check_mips_64(ctx);
4427 offset = sextract32(ctx->opcode << 3, 0, 21);
4428 addr = addr_add(ctx, (pc & ~0x7), offset);
4429 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4430 break;
4431 #endif
4432 default:
4433 MIPS_INVAL("OPC_PCREL");
4434 generate_exception_end(ctx, EXCP_RI);
4435 break;
4437 break;
4441 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4443 TCGv t0, t1;
4445 if (rd == 0) {
4446 /* Treat as NOP. */
4447 return;
4450 t0 = tcg_temp_new();
4451 t1 = tcg_temp_new();
4453 gen_load_gpr(t0, rs);
4454 gen_load_gpr(t1, rt);
4456 switch (opc) {
4457 case R6_OPC_DIV:
4459 TCGv t2 = tcg_temp_new();
4460 TCGv t3 = tcg_temp_new();
4461 tcg_gen_ext32s_tl(t0, t0);
4462 tcg_gen_ext32s_tl(t1, t1);
4463 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4464 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4465 tcg_gen_and_tl(t2, t2, t3);
4466 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4467 tcg_gen_or_tl(t2, t2, t3);
4468 tcg_gen_movi_tl(t3, 0);
4469 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4470 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4471 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4472 tcg_temp_free(t3);
4473 tcg_temp_free(t2);
4475 break;
4476 case R6_OPC_MOD:
4478 TCGv t2 = tcg_temp_new();
4479 TCGv t3 = tcg_temp_new();
4480 tcg_gen_ext32s_tl(t0, t0);
4481 tcg_gen_ext32s_tl(t1, t1);
4482 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4483 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4484 tcg_gen_and_tl(t2, t2, t3);
4485 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4486 tcg_gen_or_tl(t2, t2, t3);
4487 tcg_gen_movi_tl(t3, 0);
4488 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4489 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4490 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4491 tcg_temp_free(t3);
4492 tcg_temp_free(t2);
4494 break;
4495 case R6_OPC_DIVU:
4497 TCGv t2 = tcg_const_tl(0);
4498 TCGv t3 = tcg_const_tl(1);
4499 tcg_gen_ext32u_tl(t0, t0);
4500 tcg_gen_ext32u_tl(t1, t1);
4501 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4502 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4503 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4504 tcg_temp_free(t3);
4505 tcg_temp_free(t2);
4507 break;
4508 case R6_OPC_MODU:
4510 TCGv t2 = tcg_const_tl(0);
4511 TCGv t3 = tcg_const_tl(1);
4512 tcg_gen_ext32u_tl(t0, t0);
4513 tcg_gen_ext32u_tl(t1, t1);
4514 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4515 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4516 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4517 tcg_temp_free(t3);
4518 tcg_temp_free(t2);
4520 break;
4521 case R6_OPC_MUL:
4523 TCGv_i32 t2 = tcg_temp_new_i32();
4524 TCGv_i32 t3 = tcg_temp_new_i32();
4525 tcg_gen_trunc_tl_i32(t2, t0);
4526 tcg_gen_trunc_tl_i32(t3, t1);
4527 tcg_gen_mul_i32(t2, t2, t3);
4528 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4529 tcg_temp_free_i32(t2);
4530 tcg_temp_free_i32(t3);
4532 break;
4533 case R6_OPC_MUH:
4535 TCGv_i32 t2 = tcg_temp_new_i32();
4536 TCGv_i32 t3 = tcg_temp_new_i32();
4537 tcg_gen_trunc_tl_i32(t2, t0);
4538 tcg_gen_trunc_tl_i32(t3, t1);
4539 tcg_gen_muls2_i32(t2, t3, t2, t3);
4540 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4541 tcg_temp_free_i32(t2);
4542 tcg_temp_free_i32(t3);
4544 break;
4545 case R6_OPC_MULU:
4547 TCGv_i32 t2 = tcg_temp_new_i32();
4548 TCGv_i32 t3 = tcg_temp_new_i32();
4549 tcg_gen_trunc_tl_i32(t2, t0);
4550 tcg_gen_trunc_tl_i32(t3, t1);
4551 tcg_gen_mul_i32(t2, t2, t3);
4552 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4553 tcg_temp_free_i32(t2);
4554 tcg_temp_free_i32(t3);
4556 break;
4557 case R6_OPC_MUHU:
4559 TCGv_i32 t2 = tcg_temp_new_i32();
4560 TCGv_i32 t3 = tcg_temp_new_i32();
4561 tcg_gen_trunc_tl_i32(t2, t0);
4562 tcg_gen_trunc_tl_i32(t3, t1);
4563 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4564 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4565 tcg_temp_free_i32(t2);
4566 tcg_temp_free_i32(t3);
4568 break;
4569 #if defined(TARGET_MIPS64)
4570 case R6_OPC_DDIV:
4572 TCGv t2 = tcg_temp_new();
4573 TCGv t3 = tcg_temp_new();
4574 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4575 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4576 tcg_gen_and_tl(t2, t2, t3);
4577 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4578 tcg_gen_or_tl(t2, t2, t3);
4579 tcg_gen_movi_tl(t3, 0);
4580 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4581 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4582 tcg_temp_free(t3);
4583 tcg_temp_free(t2);
4585 break;
4586 case R6_OPC_DMOD:
4588 TCGv t2 = tcg_temp_new();
4589 TCGv t3 = tcg_temp_new();
4590 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4591 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4592 tcg_gen_and_tl(t2, t2, t3);
4593 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4594 tcg_gen_or_tl(t2, t2, t3);
4595 tcg_gen_movi_tl(t3, 0);
4596 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4597 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4598 tcg_temp_free(t3);
4599 tcg_temp_free(t2);
4601 break;
4602 case R6_OPC_DDIVU:
4604 TCGv t2 = tcg_const_tl(0);
4605 TCGv t3 = tcg_const_tl(1);
4606 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4607 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4608 tcg_temp_free(t3);
4609 tcg_temp_free(t2);
4611 break;
4612 case R6_OPC_DMODU:
4614 TCGv t2 = tcg_const_tl(0);
4615 TCGv t3 = tcg_const_tl(1);
4616 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4617 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4618 tcg_temp_free(t3);
4619 tcg_temp_free(t2);
4621 break;
4622 case R6_OPC_DMUL:
4623 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4624 break;
4625 case R6_OPC_DMUH:
4627 TCGv t2 = tcg_temp_new();
4628 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4629 tcg_temp_free(t2);
4631 break;
4632 case R6_OPC_DMULU:
4633 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4634 break;
4635 case R6_OPC_DMUHU:
4637 TCGv t2 = tcg_temp_new();
4638 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4639 tcg_temp_free(t2);
4641 break;
4642 #endif
4643 default:
4644 MIPS_INVAL("r6 mul/div");
4645 generate_exception_end(ctx, EXCP_RI);
4646 goto out;
4648 out:
4649 tcg_temp_free(t0);
4650 tcg_temp_free(t1);
4653 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4654 int acc, int rs, int rt)
4656 TCGv t0, t1;
4658 t0 = tcg_temp_new();
4659 t1 = tcg_temp_new();
4661 gen_load_gpr(t0, rs);
4662 gen_load_gpr(t1, rt);
4664 if (acc != 0) {
4665 if (!(ctx->insn_flags & INSN_R5900)) {
4666 check_dsp(ctx);
4670 switch (opc) {
4671 case OPC_DIV:
4672 case TX79_MMI_DIV1:
4674 TCGv t2 = tcg_temp_new();
4675 TCGv t3 = tcg_temp_new();
4676 tcg_gen_ext32s_tl(t0, t0);
4677 tcg_gen_ext32s_tl(t1, t1);
4678 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4679 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4680 tcg_gen_and_tl(t2, t2, t3);
4681 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4682 tcg_gen_or_tl(t2, t2, t3);
4683 tcg_gen_movi_tl(t3, 0);
4684 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4685 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4686 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4687 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4688 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4689 tcg_temp_free(t3);
4690 tcg_temp_free(t2);
4692 break;
4693 case OPC_DIVU:
4694 case TX79_MMI_DIVU1:
4696 TCGv t2 = tcg_const_tl(0);
4697 TCGv t3 = tcg_const_tl(1);
4698 tcg_gen_ext32u_tl(t0, t0);
4699 tcg_gen_ext32u_tl(t1, t1);
4700 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4701 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4702 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4703 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4704 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4705 tcg_temp_free(t3);
4706 tcg_temp_free(t2);
4708 break;
4709 case OPC_MULT:
4711 TCGv_i32 t2 = tcg_temp_new_i32();
4712 TCGv_i32 t3 = tcg_temp_new_i32();
4713 tcg_gen_trunc_tl_i32(t2, t0);
4714 tcg_gen_trunc_tl_i32(t3, t1);
4715 tcg_gen_muls2_i32(t2, t3, t2, t3);
4716 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4717 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4718 tcg_temp_free_i32(t2);
4719 tcg_temp_free_i32(t3);
4721 break;
4722 case OPC_MULTU:
4724 TCGv_i32 t2 = tcg_temp_new_i32();
4725 TCGv_i32 t3 = tcg_temp_new_i32();
4726 tcg_gen_trunc_tl_i32(t2, t0);
4727 tcg_gen_trunc_tl_i32(t3, t1);
4728 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4729 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4730 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4731 tcg_temp_free_i32(t2);
4732 tcg_temp_free_i32(t3);
4734 break;
4735 #if defined(TARGET_MIPS64)
4736 case OPC_DDIV:
4738 TCGv t2 = tcg_temp_new();
4739 TCGv t3 = tcg_temp_new();
4740 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4741 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4742 tcg_gen_and_tl(t2, t2, t3);
4743 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4744 tcg_gen_or_tl(t2, t2, t3);
4745 tcg_gen_movi_tl(t3, 0);
4746 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4747 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4748 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4749 tcg_temp_free(t3);
4750 tcg_temp_free(t2);
4752 break;
4753 case OPC_DDIVU:
4755 TCGv t2 = tcg_const_tl(0);
4756 TCGv t3 = tcg_const_tl(1);
4757 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4758 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4759 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4760 tcg_temp_free(t3);
4761 tcg_temp_free(t2);
4763 break;
4764 case OPC_DMULT:
4765 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4766 break;
4767 case OPC_DMULTU:
4768 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4769 break;
4770 #endif
4771 case OPC_MADD:
4773 TCGv_i64 t2 = tcg_temp_new_i64();
4774 TCGv_i64 t3 = tcg_temp_new_i64();
4776 tcg_gen_ext_tl_i64(t2, t0);
4777 tcg_gen_ext_tl_i64(t3, t1);
4778 tcg_gen_mul_i64(t2, t2, t3);
4779 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4780 tcg_gen_add_i64(t2, t2, t3);
4781 tcg_temp_free_i64(t3);
4782 gen_move_low32(cpu_LO[acc], t2);
4783 gen_move_high32(cpu_HI[acc], t2);
4784 tcg_temp_free_i64(t2);
4786 break;
4787 case OPC_MADDU:
4789 TCGv_i64 t2 = tcg_temp_new_i64();
4790 TCGv_i64 t3 = tcg_temp_new_i64();
4792 tcg_gen_ext32u_tl(t0, t0);
4793 tcg_gen_ext32u_tl(t1, t1);
4794 tcg_gen_extu_tl_i64(t2, t0);
4795 tcg_gen_extu_tl_i64(t3, t1);
4796 tcg_gen_mul_i64(t2, t2, t3);
4797 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4798 tcg_gen_add_i64(t2, t2, t3);
4799 tcg_temp_free_i64(t3);
4800 gen_move_low32(cpu_LO[acc], t2);
4801 gen_move_high32(cpu_HI[acc], t2);
4802 tcg_temp_free_i64(t2);
4804 break;
4805 case OPC_MSUB:
4807 TCGv_i64 t2 = tcg_temp_new_i64();
4808 TCGv_i64 t3 = tcg_temp_new_i64();
4810 tcg_gen_ext_tl_i64(t2, t0);
4811 tcg_gen_ext_tl_i64(t3, t1);
4812 tcg_gen_mul_i64(t2, t2, t3);
4813 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4814 tcg_gen_sub_i64(t2, t3, t2);
4815 tcg_temp_free_i64(t3);
4816 gen_move_low32(cpu_LO[acc], t2);
4817 gen_move_high32(cpu_HI[acc], t2);
4818 tcg_temp_free_i64(t2);
4820 break;
4821 case OPC_MSUBU:
4823 TCGv_i64 t2 = tcg_temp_new_i64();
4824 TCGv_i64 t3 = tcg_temp_new_i64();
4826 tcg_gen_ext32u_tl(t0, t0);
4827 tcg_gen_ext32u_tl(t1, t1);
4828 tcg_gen_extu_tl_i64(t2, t0);
4829 tcg_gen_extu_tl_i64(t3, t1);
4830 tcg_gen_mul_i64(t2, t2, t3);
4831 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4832 tcg_gen_sub_i64(t2, t3, t2);
4833 tcg_temp_free_i64(t3);
4834 gen_move_low32(cpu_LO[acc], t2);
4835 gen_move_high32(cpu_HI[acc], t2);
4836 tcg_temp_free_i64(t2);
4838 break;
4839 default:
4840 MIPS_INVAL("mul/div");
4841 generate_exception_end(ctx, EXCP_RI);
4842 goto out;
4844 out:
4845 tcg_temp_free(t0);
4846 tcg_temp_free(t1);
4850 * These MULT and MULTU instructions implemented in for example the
4851 * Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4852 * architectures are special three-operand variants with the syntax
4854 * MULT[U][1] rd, rs, rt
4856 * such that
4858 * (rd, LO, HI) <- rs * rt
4860 * where the low-order 32-bits of the result is placed into both the
4861 * GPR rd and the special register LO. The high-order 32-bits of the
4862 * result is placed into the special register HI.
4864 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4865 * which is the zero register that always reads as 0.
4867 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4868 int rd, int rs, int rt)
4870 TCGv t0 = tcg_temp_new();
4871 TCGv t1 = tcg_temp_new();
4872 int acc = 0;
4874 gen_load_gpr(t0, rs);
4875 gen_load_gpr(t1, rt);
4877 switch (opc) {
4878 case TX79_MMI_MULT1:
4879 acc = 1;
4880 /* Fall through */
4881 case OPC_MULT:
4883 TCGv_i32 t2 = tcg_temp_new_i32();
4884 TCGv_i32 t3 = tcg_temp_new_i32();
4885 tcg_gen_trunc_tl_i32(t2, t0);
4886 tcg_gen_trunc_tl_i32(t3, t1);
4887 tcg_gen_muls2_i32(t2, t3, t2, t3);
4888 if (rd) {
4889 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4891 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4892 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4893 tcg_temp_free_i32(t2);
4894 tcg_temp_free_i32(t3);
4896 break;
4897 case TX79_MMI_MULTU1:
4898 acc = 1;
4899 /* Fall through */
4900 case OPC_MULTU:
4902 TCGv_i32 t2 = tcg_temp_new_i32();
4903 TCGv_i32 t3 = tcg_temp_new_i32();
4904 tcg_gen_trunc_tl_i32(t2, t0);
4905 tcg_gen_trunc_tl_i32(t3, t1);
4906 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4907 if (rd) {
4908 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4910 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4911 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4912 tcg_temp_free_i32(t2);
4913 tcg_temp_free_i32(t3);
4915 break;
4916 default:
4917 MIPS_INVAL("mul TXx9");
4918 generate_exception_end(ctx, EXCP_RI);
4919 goto out;
4922 out:
4923 tcg_temp_free(t0);
4924 tcg_temp_free(t1);
4927 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4928 int rd, int rs, int rt)
4930 TCGv t0 = tcg_temp_new();
4931 TCGv t1 = tcg_temp_new();
4933 gen_load_gpr(t0, rs);
4934 gen_load_gpr(t1, rt);
4936 switch (opc) {
4937 case OPC_VR54XX_MULS:
4938 gen_helper_muls(t0, cpu_env, t0, t1);
4939 break;
4940 case OPC_VR54XX_MULSU:
4941 gen_helper_mulsu(t0, cpu_env, t0, t1);
4942 break;
4943 case OPC_VR54XX_MACC:
4944 gen_helper_macc(t0, cpu_env, t0, t1);
4945 break;
4946 case OPC_VR54XX_MACCU:
4947 gen_helper_maccu(t0, cpu_env, t0, t1);
4948 break;
4949 case OPC_VR54XX_MSAC:
4950 gen_helper_msac(t0, cpu_env, t0, t1);
4951 break;
4952 case OPC_VR54XX_MSACU:
4953 gen_helper_msacu(t0, cpu_env, t0, t1);
4954 break;
4955 case OPC_VR54XX_MULHI:
4956 gen_helper_mulhi(t0, cpu_env, t0, t1);
4957 break;
4958 case OPC_VR54XX_MULHIU:
4959 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4960 break;
4961 case OPC_VR54XX_MULSHI:
4962 gen_helper_mulshi(t0, cpu_env, t0, t1);
4963 break;
4964 case OPC_VR54XX_MULSHIU:
4965 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4966 break;
4967 case OPC_VR54XX_MACCHI:
4968 gen_helper_macchi(t0, cpu_env, t0, t1);
4969 break;
4970 case OPC_VR54XX_MACCHIU:
4971 gen_helper_macchiu(t0, cpu_env, t0, t1);
4972 break;
4973 case OPC_VR54XX_MSACHI:
4974 gen_helper_msachi(t0, cpu_env, t0, t1);
4975 break;
4976 case OPC_VR54XX_MSACHIU:
4977 gen_helper_msachiu(t0, cpu_env, t0, t1);
4978 break;
4979 default:
4980 MIPS_INVAL("mul vr54xx");
4981 generate_exception_end(ctx, EXCP_RI);
4982 goto out;
4984 gen_store_gpr(t0, rd);
4986 out:
4987 tcg_temp_free(t0);
4988 tcg_temp_free(t1);
4991 static void gen_cl (DisasContext *ctx, uint32_t opc,
4992 int rd, int rs)
4994 TCGv t0;
4996 if (rd == 0) {
4997 /* Treat as NOP. */
4998 return;
5000 t0 = cpu_gpr[rd];
5001 gen_load_gpr(t0, rs);
5003 switch (opc) {
5004 case OPC_CLO:
5005 case R6_OPC_CLO:
5006 #if defined(TARGET_MIPS64)
5007 case OPC_DCLO:
5008 case R6_OPC_DCLO:
5009 #endif
5010 tcg_gen_not_tl(t0, t0);
5011 break;
5014 switch (opc) {
5015 case OPC_CLO:
5016 case R6_OPC_CLO:
5017 case OPC_CLZ:
5018 case R6_OPC_CLZ:
5019 tcg_gen_ext32u_tl(t0, t0);
5020 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5021 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5022 break;
5023 #if defined(TARGET_MIPS64)
5024 case OPC_DCLO:
5025 case R6_OPC_DCLO:
5026 case OPC_DCLZ:
5027 case R6_OPC_DCLZ:
5028 tcg_gen_clzi_i64(t0, t0, 64);
5029 break;
5030 #endif
5034 /* Godson integer instructions */
5035 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5036 int rd, int rs, int rt)
5038 TCGv t0, t1;
5040 if (rd == 0) {
5041 /* Treat as NOP. */
5042 return;
5045 switch (opc) {
5046 case OPC_MULT_G_2E:
5047 case OPC_MULT_G_2F:
5048 case OPC_MULTU_G_2E:
5049 case OPC_MULTU_G_2F:
5050 #if defined(TARGET_MIPS64)
5051 case OPC_DMULT_G_2E:
5052 case OPC_DMULT_G_2F:
5053 case OPC_DMULTU_G_2E:
5054 case OPC_DMULTU_G_2F:
5055 #endif
5056 t0 = tcg_temp_new();
5057 t1 = tcg_temp_new();
5058 break;
5059 default:
5060 t0 = tcg_temp_local_new();
5061 t1 = tcg_temp_local_new();
5062 break;
5065 gen_load_gpr(t0, rs);
5066 gen_load_gpr(t1, rt);
5068 switch (opc) {
5069 case OPC_MULT_G_2E:
5070 case OPC_MULT_G_2F:
5071 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5072 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5073 break;
5074 case OPC_MULTU_G_2E:
5075 case OPC_MULTU_G_2F:
5076 tcg_gen_ext32u_tl(t0, t0);
5077 tcg_gen_ext32u_tl(t1, t1);
5078 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5079 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5080 break;
5081 case OPC_DIV_G_2E:
5082 case OPC_DIV_G_2F:
5084 TCGLabel *l1 = gen_new_label();
5085 TCGLabel *l2 = gen_new_label();
5086 TCGLabel *l3 = gen_new_label();
5087 tcg_gen_ext32s_tl(t0, t0);
5088 tcg_gen_ext32s_tl(t1, t1);
5089 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5090 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5091 tcg_gen_br(l3);
5092 gen_set_label(l1);
5093 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5094 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5095 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5096 tcg_gen_br(l3);
5097 gen_set_label(l2);
5098 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5099 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5100 gen_set_label(l3);
5102 break;
5103 case OPC_DIVU_G_2E:
5104 case OPC_DIVU_G_2F:
5106 TCGLabel *l1 = gen_new_label();
5107 TCGLabel *l2 = gen_new_label();
5108 tcg_gen_ext32u_tl(t0, t0);
5109 tcg_gen_ext32u_tl(t1, t1);
5110 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5111 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5112 tcg_gen_br(l2);
5113 gen_set_label(l1);
5114 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5115 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5116 gen_set_label(l2);
5118 break;
5119 case OPC_MOD_G_2E:
5120 case OPC_MOD_G_2F:
5122 TCGLabel *l1 = gen_new_label();
5123 TCGLabel *l2 = gen_new_label();
5124 TCGLabel *l3 = gen_new_label();
5125 tcg_gen_ext32u_tl(t0, t0);
5126 tcg_gen_ext32u_tl(t1, t1);
5127 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5128 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5129 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5130 gen_set_label(l1);
5131 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5132 tcg_gen_br(l3);
5133 gen_set_label(l2);
5134 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5135 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5136 gen_set_label(l3);
5138 break;
5139 case OPC_MODU_G_2E:
5140 case OPC_MODU_G_2F:
5142 TCGLabel *l1 = gen_new_label();
5143 TCGLabel *l2 = gen_new_label();
5144 tcg_gen_ext32u_tl(t0, t0);
5145 tcg_gen_ext32u_tl(t1, t1);
5146 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5147 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5148 tcg_gen_br(l2);
5149 gen_set_label(l1);
5150 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5151 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5152 gen_set_label(l2);
5154 break;
5155 #if defined(TARGET_MIPS64)
5156 case OPC_DMULT_G_2E:
5157 case OPC_DMULT_G_2F:
5158 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5159 break;
5160 case OPC_DMULTU_G_2E:
5161 case OPC_DMULTU_G_2F:
5162 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5163 break;
5164 case OPC_DDIV_G_2E:
5165 case OPC_DDIV_G_2F:
5167 TCGLabel *l1 = gen_new_label();
5168 TCGLabel *l2 = gen_new_label();
5169 TCGLabel *l3 = gen_new_label();
5170 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5171 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5172 tcg_gen_br(l3);
5173 gen_set_label(l1);
5174 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5175 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5176 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5177 tcg_gen_br(l3);
5178 gen_set_label(l2);
5179 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5180 gen_set_label(l3);
5182 break;
5183 case OPC_DDIVU_G_2E:
5184 case OPC_DDIVU_G_2F:
5186 TCGLabel *l1 = gen_new_label();
5187 TCGLabel *l2 = gen_new_label();
5188 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5189 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5190 tcg_gen_br(l2);
5191 gen_set_label(l1);
5192 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5193 gen_set_label(l2);
5195 break;
5196 case OPC_DMOD_G_2E:
5197 case OPC_DMOD_G_2F:
5199 TCGLabel *l1 = gen_new_label();
5200 TCGLabel *l2 = gen_new_label();
5201 TCGLabel *l3 = gen_new_label();
5202 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5203 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5204 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5205 gen_set_label(l1);
5206 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5207 tcg_gen_br(l3);
5208 gen_set_label(l2);
5209 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5210 gen_set_label(l3);
5212 break;
5213 case OPC_DMODU_G_2E:
5214 case OPC_DMODU_G_2F:
5216 TCGLabel *l1 = gen_new_label();
5217 TCGLabel *l2 = gen_new_label();
5218 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5219 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5220 tcg_gen_br(l2);
5221 gen_set_label(l1);
5222 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5223 gen_set_label(l2);
5225 break;
5226 #endif
5229 tcg_temp_free(t0);
5230 tcg_temp_free(t1);
5233 /* Loongson multimedia instructions */
5234 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5236 uint32_t opc, shift_max;
5237 TCGv_i64 t0, t1;
5239 opc = MASK_LMI(ctx->opcode);
5240 switch (opc) {
5241 case OPC_ADD_CP2:
5242 case OPC_SUB_CP2:
5243 case OPC_DADD_CP2:
5244 case OPC_DSUB_CP2:
5245 t0 = tcg_temp_local_new_i64();
5246 t1 = tcg_temp_local_new_i64();
5247 break;
5248 default:
5249 t0 = tcg_temp_new_i64();
5250 t1 = tcg_temp_new_i64();
5251 break;
5254 check_cp1_enabled(ctx);
5255 gen_load_fpr64(ctx, t0, rs);
5256 gen_load_fpr64(ctx, t1, rt);
5258 #define LMI_HELPER(UP, LO) \
5259 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5260 #define LMI_HELPER_1(UP, LO) \
5261 case OPC_##UP: gen_helper_##LO(t0, t0); break
5262 #define LMI_DIRECT(UP, LO, OP) \
5263 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5265 switch (opc) {
5266 LMI_HELPER(PADDSH, paddsh);
5267 LMI_HELPER(PADDUSH, paddush);
5268 LMI_HELPER(PADDH, paddh);
5269 LMI_HELPER(PADDW, paddw);
5270 LMI_HELPER(PADDSB, paddsb);
5271 LMI_HELPER(PADDUSB, paddusb);
5272 LMI_HELPER(PADDB, paddb);
5274 LMI_HELPER(PSUBSH, psubsh);
5275 LMI_HELPER(PSUBUSH, psubush);
5276 LMI_HELPER(PSUBH, psubh);
5277 LMI_HELPER(PSUBW, psubw);
5278 LMI_HELPER(PSUBSB, psubsb);
5279 LMI_HELPER(PSUBUSB, psubusb);
5280 LMI_HELPER(PSUBB, psubb);
5282 LMI_HELPER(PSHUFH, pshufh);
5283 LMI_HELPER(PACKSSWH, packsswh);
5284 LMI_HELPER(PACKSSHB, packsshb);
5285 LMI_HELPER(PACKUSHB, packushb);
5287 LMI_HELPER(PUNPCKLHW, punpcklhw);
5288 LMI_HELPER(PUNPCKHHW, punpckhhw);
5289 LMI_HELPER(PUNPCKLBH, punpcklbh);
5290 LMI_HELPER(PUNPCKHBH, punpckhbh);
5291 LMI_HELPER(PUNPCKLWD, punpcklwd);
5292 LMI_HELPER(PUNPCKHWD, punpckhwd);
5294 LMI_HELPER(PAVGH, pavgh);
5295 LMI_HELPER(PAVGB, pavgb);
5296 LMI_HELPER(PMAXSH, pmaxsh);
5297 LMI_HELPER(PMINSH, pminsh);
5298 LMI_HELPER(PMAXUB, pmaxub);
5299 LMI_HELPER(PMINUB, pminub);
5301 LMI_HELPER(PCMPEQW, pcmpeqw);
5302 LMI_HELPER(PCMPGTW, pcmpgtw);
5303 LMI_HELPER(PCMPEQH, pcmpeqh);
5304 LMI_HELPER(PCMPGTH, pcmpgth);
5305 LMI_HELPER(PCMPEQB, pcmpeqb);
5306 LMI_HELPER(PCMPGTB, pcmpgtb);
5308 LMI_HELPER(PSLLW, psllw);
5309 LMI_HELPER(PSLLH, psllh);
5310 LMI_HELPER(PSRLW, psrlw);
5311 LMI_HELPER(PSRLH, psrlh);
5312 LMI_HELPER(PSRAW, psraw);
5313 LMI_HELPER(PSRAH, psrah);
5315 LMI_HELPER(PMULLH, pmullh);
5316 LMI_HELPER(PMULHH, pmulhh);
5317 LMI_HELPER(PMULHUH, pmulhuh);
5318 LMI_HELPER(PMADDHW, pmaddhw);
5320 LMI_HELPER(PASUBUB, pasubub);
5321 LMI_HELPER_1(BIADD, biadd);
5322 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5324 LMI_DIRECT(PADDD, paddd, add);
5325 LMI_DIRECT(PSUBD, psubd, sub);
5326 LMI_DIRECT(XOR_CP2, xor, xor);
5327 LMI_DIRECT(NOR_CP2, nor, nor);
5328 LMI_DIRECT(AND_CP2, and, and);
5329 LMI_DIRECT(OR_CP2, or, or);
5331 case OPC_PANDN:
5332 tcg_gen_andc_i64(t0, t1, t0);
5333 break;
5335 case OPC_PINSRH_0:
5336 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5337 break;
5338 case OPC_PINSRH_1:
5339 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5340 break;
5341 case OPC_PINSRH_2:
5342 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5343 break;
5344 case OPC_PINSRH_3:
5345 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5346 break;
5348 case OPC_PEXTRH:
5349 tcg_gen_andi_i64(t1, t1, 3);
5350 tcg_gen_shli_i64(t1, t1, 4);
5351 tcg_gen_shr_i64(t0, t0, t1);
5352 tcg_gen_ext16u_i64(t0, t0);
5353 break;
5355 case OPC_ADDU_CP2:
5356 tcg_gen_add_i64(t0, t0, t1);
5357 tcg_gen_ext32s_i64(t0, t0);
5358 break;
5359 case OPC_SUBU_CP2:
5360 tcg_gen_sub_i64(t0, t0, t1);
5361 tcg_gen_ext32s_i64(t0, t0);
5362 break;
5364 case OPC_SLL_CP2:
5365 shift_max = 32;
5366 goto do_shift;
5367 case OPC_SRL_CP2:
5368 shift_max = 32;
5369 goto do_shift;
5370 case OPC_SRA_CP2:
5371 shift_max = 32;
5372 goto do_shift;
5373 case OPC_DSLL_CP2:
5374 shift_max = 64;
5375 goto do_shift;
5376 case OPC_DSRL_CP2:
5377 shift_max = 64;
5378 goto do_shift;
5379 case OPC_DSRA_CP2:
5380 shift_max = 64;
5381 goto do_shift;
5382 do_shift:
5383 /* Make sure shift count isn't TCG undefined behaviour. */
5384 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5386 switch (opc) {
5387 case OPC_SLL_CP2:
5388 case OPC_DSLL_CP2:
5389 tcg_gen_shl_i64(t0, t0, t1);
5390 break;
5391 case OPC_SRA_CP2:
5392 case OPC_DSRA_CP2:
5393 /* Since SRA is UndefinedResult without sign-extended inputs,
5394 we can treat SRA and DSRA the same. */
5395 tcg_gen_sar_i64(t0, t0, t1);
5396 break;
5397 case OPC_SRL_CP2:
5398 /* We want to shift in zeros for SRL; zero-extend first. */
5399 tcg_gen_ext32u_i64(t0, t0);
5400 /* FALLTHRU */
5401 case OPC_DSRL_CP2:
5402 tcg_gen_shr_i64(t0, t0, t1);
5403 break;
5406 if (shift_max == 32) {
5407 tcg_gen_ext32s_i64(t0, t0);
5410 /* Shifts larger than MAX produce zero. */
5411 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5412 tcg_gen_neg_i64(t1, t1);
5413 tcg_gen_and_i64(t0, t0, t1);
5414 break;
5416 case OPC_ADD_CP2:
5417 case OPC_DADD_CP2:
5419 TCGv_i64 t2 = tcg_temp_new_i64();
5420 TCGLabel *lab = gen_new_label();
5422 tcg_gen_mov_i64(t2, t0);
5423 tcg_gen_add_i64(t0, t1, t2);
5424 if (opc == OPC_ADD_CP2) {
5425 tcg_gen_ext32s_i64(t0, t0);
5427 tcg_gen_xor_i64(t1, t1, t2);
5428 tcg_gen_xor_i64(t2, t2, t0);
5429 tcg_gen_andc_i64(t1, t2, t1);
5430 tcg_temp_free_i64(t2);
5431 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5432 generate_exception(ctx, EXCP_OVERFLOW);
5433 gen_set_label(lab);
5434 break;
5437 case OPC_SUB_CP2:
5438 case OPC_DSUB_CP2:
5440 TCGv_i64 t2 = tcg_temp_new_i64();
5441 TCGLabel *lab = gen_new_label();
5443 tcg_gen_mov_i64(t2, t0);
5444 tcg_gen_sub_i64(t0, t1, t2);
5445 if (opc == OPC_SUB_CP2) {
5446 tcg_gen_ext32s_i64(t0, t0);
5448 tcg_gen_xor_i64(t1, t1, t2);
5449 tcg_gen_xor_i64(t2, t2, t0);
5450 tcg_gen_and_i64(t1, t1, t2);
5451 tcg_temp_free_i64(t2);
5452 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5453 generate_exception(ctx, EXCP_OVERFLOW);
5454 gen_set_label(lab);
5455 break;
5458 case OPC_PMULUW:
5459 tcg_gen_ext32u_i64(t0, t0);
5460 tcg_gen_ext32u_i64(t1, t1);
5461 tcg_gen_mul_i64(t0, t0, t1);
5462 break;
5464 case OPC_SEQU_CP2:
5465 case OPC_SEQ_CP2:
5466 case OPC_SLTU_CP2:
5467 case OPC_SLT_CP2:
5468 case OPC_SLEU_CP2:
5469 case OPC_SLE_CP2:
5470 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5471 FD field is the CC field? */
5472 default:
5473 MIPS_INVAL("loongson_cp2");
5474 generate_exception_end(ctx, EXCP_RI);
5475 return;
5478 #undef LMI_HELPER
5479 #undef LMI_DIRECT
5481 gen_store_fpr64(ctx, t0, rd);
5483 tcg_temp_free_i64(t0);
5484 tcg_temp_free_i64(t1);
5487 /* Traps */
5488 static void gen_trap (DisasContext *ctx, uint32_t opc,
5489 int rs, int rt, int16_t imm)
5491 int cond;
5492 TCGv t0 = tcg_temp_new();
5493 TCGv t1 = tcg_temp_new();
5495 cond = 0;
5496 /* Load needed operands */
5497 switch (opc) {
5498 case OPC_TEQ:
5499 case OPC_TGE:
5500 case OPC_TGEU:
5501 case OPC_TLT:
5502 case OPC_TLTU:
5503 case OPC_TNE:
5504 /* Compare two registers */
5505 if (rs != rt) {
5506 gen_load_gpr(t0, rs);
5507 gen_load_gpr(t1, rt);
5508 cond = 1;
5510 break;
5511 case OPC_TEQI:
5512 case OPC_TGEI:
5513 case OPC_TGEIU:
5514 case OPC_TLTI:
5515 case OPC_TLTIU:
5516 case OPC_TNEI:
5517 /* Compare register to immediate */
5518 if (rs != 0 || imm != 0) {
5519 gen_load_gpr(t0, rs);
5520 tcg_gen_movi_tl(t1, (int32_t)imm);
5521 cond = 1;
5523 break;
5525 if (cond == 0) {
5526 switch (opc) {
5527 case OPC_TEQ: /* rs == rs */
5528 case OPC_TEQI: /* r0 == 0 */
5529 case OPC_TGE: /* rs >= rs */
5530 case OPC_TGEI: /* r0 >= 0 */
5531 case OPC_TGEU: /* rs >= rs unsigned */
5532 case OPC_TGEIU: /* r0 >= 0 unsigned */
5533 /* Always trap */
5534 generate_exception_end(ctx, EXCP_TRAP);
5535 break;
5536 case OPC_TLT: /* rs < rs */
5537 case OPC_TLTI: /* r0 < 0 */
5538 case OPC_TLTU: /* rs < rs unsigned */
5539 case OPC_TLTIU: /* r0 < 0 unsigned */
5540 case OPC_TNE: /* rs != rs */
5541 case OPC_TNEI: /* r0 != 0 */
5542 /* Never trap: treat as NOP. */
5543 break;
5545 } else {
5546 TCGLabel *l1 = gen_new_label();
5548 switch (opc) {
5549 case OPC_TEQ:
5550 case OPC_TEQI:
5551 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5552 break;
5553 case OPC_TGE:
5554 case OPC_TGEI:
5555 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5556 break;
5557 case OPC_TGEU:
5558 case OPC_TGEIU:
5559 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5560 break;
5561 case OPC_TLT:
5562 case OPC_TLTI:
5563 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5564 break;
5565 case OPC_TLTU:
5566 case OPC_TLTIU:
5567 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5568 break;
5569 case OPC_TNE:
5570 case OPC_TNEI:
5571 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5572 break;
5574 generate_exception(ctx, EXCP_TRAP);
5575 gen_set_label(l1);
5577 tcg_temp_free(t0);
5578 tcg_temp_free(t1);
5581 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5583 if (unlikely(ctx->base.singlestep_enabled)) {
5584 return false;
5587 #ifndef CONFIG_USER_ONLY
5588 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5589 #else
5590 return true;
5591 #endif
5594 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5596 if (use_goto_tb(ctx, dest)) {
5597 tcg_gen_goto_tb(n);
5598 gen_save_pc(dest);
5599 tcg_gen_exit_tb(ctx->base.tb, n);
5600 } else {
5601 gen_save_pc(dest);
5602 if (ctx->base.singlestep_enabled) {
5603 save_cpu_state(ctx, 0);
5604 gen_helper_raise_exception_debug(cpu_env);
5606 tcg_gen_lookup_and_goto_ptr();
5610 /* Branches (before delay slot) */
5611 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5612 int insn_bytes,
5613 int rs, int rt, int32_t offset,
5614 int delayslot_size)
5616 target_ulong btgt = -1;
5617 int blink = 0;
5618 int bcond_compute = 0;
5619 TCGv t0 = tcg_temp_new();
5620 TCGv t1 = tcg_temp_new();
5622 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5623 #ifdef MIPS_DEBUG_DISAS
5624 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5625 TARGET_FMT_lx "\n", ctx->base.pc_next);
5626 #endif
5627 generate_exception_end(ctx, EXCP_RI);
5628 goto out;
5631 /* Load needed operands */
5632 switch (opc) {
5633 case OPC_BEQ:
5634 case OPC_BEQL:
5635 case OPC_BNE:
5636 case OPC_BNEL:
5637 /* Compare two registers */
5638 if (rs != rt) {
5639 gen_load_gpr(t0, rs);
5640 gen_load_gpr(t1, rt);
5641 bcond_compute = 1;
5643 btgt = ctx->base.pc_next + insn_bytes + offset;
5644 break;
5645 case OPC_BGEZ:
5646 case OPC_BGEZAL:
5647 case OPC_BGEZALL:
5648 case OPC_BGEZL:
5649 case OPC_BGTZ:
5650 case OPC_BGTZL:
5651 case OPC_BLEZ:
5652 case OPC_BLEZL:
5653 case OPC_BLTZ:
5654 case OPC_BLTZAL:
5655 case OPC_BLTZALL:
5656 case OPC_BLTZL:
5657 /* Compare to zero */
5658 if (rs != 0) {
5659 gen_load_gpr(t0, rs);
5660 bcond_compute = 1;
5662 btgt = ctx->base.pc_next + insn_bytes + offset;
5663 break;
5664 case OPC_BPOSGE32:
5665 #if defined(TARGET_MIPS64)
5666 case OPC_BPOSGE64:
5667 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5668 #else
5669 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5670 #endif
5671 bcond_compute = 1;
5672 btgt = ctx->base.pc_next + insn_bytes + offset;
5673 break;
5674 case OPC_J:
5675 case OPC_JAL:
5676 case OPC_JALX:
5677 /* Jump to immediate */
5678 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5679 (uint32_t)offset;
5680 break;
5681 case OPC_JR:
5682 case OPC_JALR:
5683 /* Jump to register */
5684 if (offset != 0 && offset != 16) {
5685 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5686 others are reserved. */
5687 MIPS_INVAL("jump hint");
5688 generate_exception_end(ctx, EXCP_RI);
5689 goto out;
5691 gen_load_gpr(btarget, rs);
5692 break;
5693 default:
5694 MIPS_INVAL("branch/jump");
5695 generate_exception_end(ctx, EXCP_RI);
5696 goto out;
5698 if (bcond_compute == 0) {
5699 /* No condition to be computed */
5700 switch (opc) {
5701 case OPC_BEQ: /* rx == rx */
5702 case OPC_BEQL: /* rx == rx likely */
5703 case OPC_BGEZ: /* 0 >= 0 */
5704 case OPC_BGEZL: /* 0 >= 0 likely */
5705 case OPC_BLEZ: /* 0 <= 0 */
5706 case OPC_BLEZL: /* 0 <= 0 likely */
5707 /* Always take */
5708 ctx->hflags |= MIPS_HFLAG_B;
5709 break;
5710 case OPC_BGEZAL: /* 0 >= 0 */
5711 case OPC_BGEZALL: /* 0 >= 0 likely */
5712 /* Always take and link */
5713 blink = 31;
5714 ctx->hflags |= MIPS_HFLAG_B;
5715 break;
5716 case OPC_BNE: /* rx != rx */
5717 case OPC_BGTZ: /* 0 > 0 */
5718 case OPC_BLTZ: /* 0 < 0 */
5719 /* Treat as NOP. */
5720 goto out;
5721 case OPC_BLTZAL: /* 0 < 0 */
5722 /* Handle as an unconditional branch to get correct delay
5723 slot checking. */
5724 blink = 31;
5725 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5726 ctx->hflags |= MIPS_HFLAG_B;
5727 break;
5728 case OPC_BLTZALL: /* 0 < 0 likely */
5729 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5730 /* Skip the instruction in the delay slot */
5731 ctx->base.pc_next += 4;
5732 goto out;
5733 case OPC_BNEL: /* rx != rx likely */
5734 case OPC_BGTZL: /* 0 > 0 likely */
5735 case OPC_BLTZL: /* 0 < 0 likely */
5736 /* Skip the instruction in the delay slot */
5737 ctx->base.pc_next += 4;
5738 goto out;
5739 case OPC_J:
5740 ctx->hflags |= MIPS_HFLAG_B;
5741 break;
5742 case OPC_JALX:
5743 ctx->hflags |= MIPS_HFLAG_BX;
5744 /* Fallthrough */
5745 case OPC_JAL:
5746 blink = 31;
5747 ctx->hflags |= MIPS_HFLAG_B;
5748 break;
5749 case OPC_JR:
5750 ctx->hflags |= MIPS_HFLAG_BR;
5751 break;
5752 case OPC_JALR:
5753 blink = rt;
5754 ctx->hflags |= MIPS_HFLAG_BR;
5755 break;
5756 default:
5757 MIPS_INVAL("branch/jump");
5758 generate_exception_end(ctx, EXCP_RI);
5759 goto out;
5761 } else {
5762 switch (opc) {
5763 case OPC_BEQ:
5764 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5765 goto not_likely;
5766 case OPC_BEQL:
5767 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5768 goto likely;
5769 case OPC_BNE:
5770 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5771 goto not_likely;
5772 case OPC_BNEL:
5773 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5774 goto likely;
5775 case OPC_BGEZ:
5776 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5777 goto not_likely;
5778 case OPC_BGEZL:
5779 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5780 goto likely;
5781 case OPC_BGEZAL:
5782 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5783 blink = 31;
5784 goto not_likely;
5785 case OPC_BGEZALL:
5786 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5787 blink = 31;
5788 goto likely;
5789 case OPC_BGTZ:
5790 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5791 goto not_likely;
5792 case OPC_BGTZL:
5793 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5794 goto likely;
5795 case OPC_BLEZ:
5796 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5797 goto not_likely;
5798 case OPC_BLEZL:
5799 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5800 goto likely;
5801 case OPC_BLTZ:
5802 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5803 goto not_likely;
5804 case OPC_BLTZL:
5805 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5806 goto likely;
5807 case OPC_BPOSGE32:
5808 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5809 goto not_likely;
5810 #if defined(TARGET_MIPS64)
5811 case OPC_BPOSGE64:
5812 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5813 goto not_likely;
5814 #endif
5815 case OPC_BLTZAL:
5816 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5817 blink = 31;
5818 not_likely:
5819 ctx->hflags |= MIPS_HFLAG_BC;
5820 break;
5821 case OPC_BLTZALL:
5822 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5823 blink = 31;
5824 likely:
5825 ctx->hflags |= MIPS_HFLAG_BL;
5826 break;
5827 default:
5828 MIPS_INVAL("conditional branch/jump");
5829 generate_exception_end(ctx, EXCP_RI);
5830 goto out;
5834 ctx->btarget = btgt;
5836 switch (delayslot_size) {
5837 case 2:
5838 ctx->hflags |= MIPS_HFLAG_BDS16;
5839 break;
5840 case 4:
5841 ctx->hflags |= MIPS_HFLAG_BDS32;
5842 break;
5845 if (blink > 0) {
5846 int post_delay = insn_bytes + delayslot_size;
5847 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5849 tcg_gen_movi_tl(cpu_gpr[blink],
5850 ctx->base.pc_next + post_delay + lowbit);
5853 out:
5854 if (insn_bytes == 2)
5855 ctx->hflags |= MIPS_HFLAG_B16;
5856 tcg_temp_free(t0);
5857 tcg_temp_free(t1);
5861 /* nanoMIPS Branches */
5862 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5863 int insn_bytes,
5864 int rs, int rt, int32_t offset)
5866 target_ulong btgt = -1;
5867 int bcond_compute = 0;
5868 TCGv t0 = tcg_temp_new();
5869 TCGv t1 = tcg_temp_new();
5871 /* Load needed operands */
5872 switch (opc) {
5873 case OPC_BEQ:
5874 case OPC_BNE:
5875 /* Compare two registers */
5876 if (rs != rt) {
5877 gen_load_gpr(t0, rs);
5878 gen_load_gpr(t1, rt);
5879 bcond_compute = 1;
5881 btgt = ctx->base.pc_next + insn_bytes + offset;
5882 break;
5883 case OPC_BGEZAL:
5884 /* Compare to zero */
5885 if (rs != 0) {
5886 gen_load_gpr(t0, rs);
5887 bcond_compute = 1;
5889 btgt = ctx->base.pc_next + insn_bytes + offset;
5890 break;
5891 case OPC_BPOSGE32:
5892 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5893 bcond_compute = 1;
5894 btgt = ctx->base.pc_next + insn_bytes + offset;
5895 break;
5896 case OPC_JR:
5897 case OPC_JALR:
5898 /* Jump to register */
5899 if (offset != 0 && offset != 16) {
5900 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5901 others are reserved. */
5902 MIPS_INVAL("jump hint");
5903 generate_exception_end(ctx, EXCP_RI);
5904 goto out;
5906 gen_load_gpr(btarget, rs);
5907 break;
5908 default:
5909 MIPS_INVAL("branch/jump");
5910 generate_exception_end(ctx, EXCP_RI);
5911 goto out;
5913 if (bcond_compute == 0) {
5914 /* No condition to be computed */
5915 switch (opc) {
5916 case OPC_BEQ: /* rx == rx */
5917 /* Always take */
5918 ctx->hflags |= MIPS_HFLAG_B;
5919 break;
5920 case OPC_BGEZAL: /* 0 >= 0 */
5921 /* Always take and link */
5922 tcg_gen_movi_tl(cpu_gpr[31],
5923 ctx->base.pc_next + insn_bytes);
5924 ctx->hflags |= MIPS_HFLAG_B;
5925 break;
5926 case OPC_BNE: /* rx != rx */
5927 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5928 /* Skip the instruction in the delay slot */
5929 ctx->base.pc_next += 4;
5930 goto out;
5931 case OPC_JR:
5932 ctx->hflags |= MIPS_HFLAG_BR;
5933 break;
5934 case OPC_JALR:
5935 if (rt > 0) {
5936 tcg_gen_movi_tl(cpu_gpr[rt],
5937 ctx->base.pc_next + insn_bytes);
5939 ctx->hflags |= MIPS_HFLAG_BR;
5940 break;
5941 default:
5942 MIPS_INVAL("branch/jump");
5943 generate_exception_end(ctx, EXCP_RI);
5944 goto out;
5946 } else {
5947 switch (opc) {
5948 case OPC_BEQ:
5949 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5950 goto not_likely;
5951 case OPC_BNE:
5952 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5953 goto not_likely;
5954 case OPC_BGEZAL:
5955 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5956 tcg_gen_movi_tl(cpu_gpr[31],
5957 ctx->base.pc_next + insn_bytes);
5958 goto not_likely;
5959 case OPC_BPOSGE32:
5960 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5961 not_likely:
5962 ctx->hflags |= MIPS_HFLAG_BC;
5963 break;
5964 default:
5965 MIPS_INVAL("conditional branch/jump");
5966 generate_exception_end(ctx, EXCP_RI);
5967 goto out;
5971 ctx->btarget = btgt;
5973 out:
5974 if (insn_bytes == 2) {
5975 ctx->hflags |= MIPS_HFLAG_B16;
5977 tcg_temp_free(t0);
5978 tcg_temp_free(t1);
5982 /* special3 bitfield operations */
5983 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5984 int rs, int lsb, int msb)
5986 TCGv t0 = tcg_temp_new();
5987 TCGv t1 = tcg_temp_new();
5989 gen_load_gpr(t1, rs);
5990 switch (opc) {
5991 case OPC_EXT:
5992 if (lsb + msb > 31) {
5993 goto fail;
5995 if (msb != 31) {
5996 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5997 } else {
5998 /* The two checks together imply that lsb == 0,
5999 so this is a simple sign-extension. */
6000 tcg_gen_ext32s_tl(t0, t1);
6002 break;
6003 #if defined(TARGET_MIPS64)
6004 case OPC_DEXTU:
6005 lsb += 32;
6006 goto do_dext;
6007 case OPC_DEXTM:
6008 msb += 32;
6009 goto do_dext;
6010 case OPC_DEXT:
6011 do_dext:
6012 if (lsb + msb > 63) {
6013 goto fail;
6015 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6016 break;
6017 #endif
6018 case OPC_INS:
6019 if (lsb > msb) {
6020 goto fail;
6022 gen_load_gpr(t0, rt);
6023 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6024 tcg_gen_ext32s_tl(t0, t0);
6025 break;
6026 #if defined(TARGET_MIPS64)
6027 case OPC_DINSU:
6028 lsb += 32;
6029 /* FALLTHRU */
6030 case OPC_DINSM:
6031 msb += 32;
6032 /* FALLTHRU */
6033 case OPC_DINS:
6034 if (lsb > msb) {
6035 goto fail;
6037 gen_load_gpr(t0, rt);
6038 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6039 break;
6040 #endif
6041 default:
6042 fail:
6043 MIPS_INVAL("bitops");
6044 generate_exception_end(ctx, EXCP_RI);
6045 tcg_temp_free(t0);
6046 tcg_temp_free(t1);
6047 return;
6049 gen_store_gpr(t0, rt);
6050 tcg_temp_free(t0);
6051 tcg_temp_free(t1);
6054 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6056 TCGv t0;
6058 if (rd == 0) {
6059 /* If no destination, treat it as a NOP. */
6060 return;
6063 t0 = tcg_temp_new();
6064 gen_load_gpr(t0, rt);
6065 switch (op2) {
6066 case OPC_WSBH:
6068 TCGv t1 = tcg_temp_new();
6069 TCGv t2 = tcg_const_tl(0x00FF00FF);
6071 tcg_gen_shri_tl(t1, t0, 8);
6072 tcg_gen_and_tl(t1, t1, t2);
6073 tcg_gen_and_tl(t0, t0, t2);
6074 tcg_gen_shli_tl(t0, t0, 8);
6075 tcg_gen_or_tl(t0, t0, t1);
6076 tcg_temp_free(t2);
6077 tcg_temp_free(t1);
6078 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6080 break;
6081 case OPC_SEB:
6082 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6083 break;
6084 case OPC_SEH:
6085 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6086 break;
6087 #if defined(TARGET_MIPS64)
6088 case OPC_DSBH:
6090 TCGv t1 = tcg_temp_new();
6091 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6093 tcg_gen_shri_tl(t1, t0, 8);
6094 tcg_gen_and_tl(t1, t1, t2);
6095 tcg_gen_and_tl(t0, t0, t2);
6096 tcg_gen_shli_tl(t0, t0, 8);
6097 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6098 tcg_temp_free(t2);
6099 tcg_temp_free(t1);
6101 break;
6102 case OPC_DSHD:
6104 TCGv t1 = tcg_temp_new();
6105 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6107 tcg_gen_shri_tl(t1, t0, 16);
6108 tcg_gen_and_tl(t1, t1, t2);
6109 tcg_gen_and_tl(t0, t0, t2);
6110 tcg_gen_shli_tl(t0, t0, 16);
6111 tcg_gen_or_tl(t0, t0, t1);
6112 tcg_gen_shri_tl(t1, t0, 32);
6113 tcg_gen_shli_tl(t0, t0, 32);
6114 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6115 tcg_temp_free(t2);
6116 tcg_temp_free(t1);
6118 break;
6119 #endif
6120 default:
6121 MIPS_INVAL("bsfhl");
6122 generate_exception_end(ctx, EXCP_RI);
6123 tcg_temp_free(t0);
6124 return;
6126 tcg_temp_free(t0);
6129 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6130 int imm2)
6132 TCGv t0;
6133 TCGv t1;
6134 if (rd == 0) {
6135 /* Treat as NOP. */
6136 return;
6138 t0 = tcg_temp_new();
6139 t1 = tcg_temp_new();
6140 gen_load_gpr(t0, rs);
6141 gen_load_gpr(t1, rt);
6142 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6143 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6144 if (opc == OPC_LSA) {
6145 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6148 tcg_temp_free(t1);
6149 tcg_temp_free(t0);
6151 return;
6154 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6155 int rt, int bits)
6157 TCGv t0;
6158 if (rd == 0) {
6159 /* Treat as NOP. */
6160 return;
6162 t0 = tcg_temp_new();
6163 if (bits == 0 || bits == wordsz) {
6164 if (bits == 0) {
6165 gen_load_gpr(t0, rt);
6166 } else {
6167 gen_load_gpr(t0, rs);
6169 switch (wordsz) {
6170 case 32:
6171 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6172 break;
6173 #if defined(TARGET_MIPS64)
6174 case 64:
6175 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6176 break;
6177 #endif
6179 } else {
6180 TCGv t1 = tcg_temp_new();
6181 gen_load_gpr(t0, rt);
6182 gen_load_gpr(t1, rs);
6183 switch (wordsz) {
6184 case 32:
6186 TCGv_i64 t2 = tcg_temp_new_i64();
6187 tcg_gen_concat_tl_i64(t2, t1, t0);
6188 tcg_gen_shri_i64(t2, t2, 32 - bits);
6189 gen_move_low32(cpu_gpr[rd], t2);
6190 tcg_temp_free_i64(t2);
6192 break;
6193 #if defined(TARGET_MIPS64)
6194 case 64:
6195 tcg_gen_shli_tl(t0, t0, bits);
6196 tcg_gen_shri_tl(t1, t1, 64 - bits);
6197 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6198 break;
6199 #endif
6201 tcg_temp_free(t1);
6204 tcg_temp_free(t0);
6207 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6208 int bp)
6210 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6213 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6214 int shift)
6216 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6219 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6221 TCGv t0;
6222 if (rd == 0) {
6223 /* Treat as NOP. */
6224 return;
6226 t0 = tcg_temp_new();
6227 gen_load_gpr(t0, rt);
6228 switch (opc) {
6229 case OPC_BITSWAP:
6230 gen_helper_bitswap(cpu_gpr[rd], t0);
6231 break;
6232 #if defined(TARGET_MIPS64)
6233 case OPC_DBITSWAP:
6234 gen_helper_dbitswap(cpu_gpr[rd], t0);
6235 break;
6236 #endif
6238 tcg_temp_free(t0);
6241 #ifndef CONFIG_USER_ONLY
6242 /* CP0 (MMU and control) */
6243 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6245 TCGv_i64 t0 = tcg_temp_new_i64();
6246 TCGv_i64 t1 = tcg_temp_new_i64();
6248 tcg_gen_ext_tl_i64(t0, arg);
6249 tcg_gen_ld_i64(t1, cpu_env, off);
6250 #if defined(TARGET_MIPS64)
6251 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6252 #else
6253 tcg_gen_concat32_i64(t1, t1, t0);
6254 #endif
6255 tcg_gen_st_i64(t1, cpu_env, off);
6256 tcg_temp_free_i64(t1);
6257 tcg_temp_free_i64(t0);
6260 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6262 TCGv_i64 t0 = tcg_temp_new_i64();
6263 TCGv_i64 t1 = tcg_temp_new_i64();
6265 tcg_gen_ext_tl_i64(t0, arg);
6266 tcg_gen_ld_i64(t1, cpu_env, off);
6267 tcg_gen_concat32_i64(t1, t1, t0);
6268 tcg_gen_st_i64(t1, cpu_env, off);
6269 tcg_temp_free_i64(t1);
6270 tcg_temp_free_i64(t0);
6273 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6275 TCGv_i64 t0 = tcg_temp_new_i64();
6277 tcg_gen_ld_i64(t0, cpu_env, off);
6278 #if defined(TARGET_MIPS64)
6279 tcg_gen_shri_i64(t0, t0, 30);
6280 #else
6281 tcg_gen_shri_i64(t0, t0, 32);
6282 #endif
6283 gen_move_low32(arg, t0);
6284 tcg_temp_free_i64(t0);
6287 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6289 TCGv_i64 t0 = tcg_temp_new_i64();
6291 tcg_gen_ld_i64(t0, cpu_env, off);
6292 tcg_gen_shri_i64(t0, t0, 32 + shift);
6293 gen_move_low32(arg, t0);
6294 tcg_temp_free_i64(t0);
6297 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6299 TCGv_i32 t0 = tcg_temp_new_i32();
6301 tcg_gen_ld_i32(t0, cpu_env, off);
6302 tcg_gen_ext_i32_tl(arg, t0);
6303 tcg_temp_free_i32(t0);
6306 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6308 tcg_gen_ld_tl(arg, cpu_env, off);
6309 tcg_gen_ext32s_tl(arg, arg);
6312 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6314 TCGv_i32 t0 = tcg_temp_new_i32();
6316 tcg_gen_trunc_tl_i32(t0, arg);
6317 tcg_gen_st_i32(t0, cpu_env, off);
6318 tcg_temp_free_i32(t0);
6321 #define CP0_CHECK(c) \
6322 do { \
6323 if (!(c)) { \
6324 goto cp0_unimplemented; \
6326 } while (0)
6328 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6330 const char *rn = "invalid";
6332 switch (reg) {
6333 case 2:
6334 switch (sel) {
6335 case 0:
6336 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6337 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6338 rn = "EntryLo0";
6339 break;
6340 default:
6341 goto cp0_unimplemented;
6343 break;
6344 case 3:
6345 switch (sel) {
6346 case 0:
6347 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6348 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6349 rn = "EntryLo1";
6350 break;
6351 default:
6352 goto cp0_unimplemented;
6354 break;
6355 case 17:
6356 switch (sel) {
6357 case 0:
6358 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6359 ctx->CP0_LLAddr_shift);
6360 rn = "LLAddr";
6361 break;
6362 case 1:
6363 CP0_CHECK(ctx->mrp);
6364 gen_helper_mfhc0_maar(arg, cpu_env);
6365 rn = "MAAR";
6366 break;
6367 default:
6368 goto cp0_unimplemented;
6370 break;
6371 case 28:
6372 switch (sel) {
6373 case 0:
6374 case 2:
6375 case 4:
6376 case 6:
6377 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6378 rn = "TagLo";
6379 break;
6380 default:
6381 goto cp0_unimplemented;
6383 break;
6384 default:
6385 goto cp0_unimplemented;
6387 trace_mips_translate_c0("mfhc0", rn, reg, sel);
6388 return;
6390 cp0_unimplemented:
6391 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6392 tcg_gen_movi_tl(arg, 0);
6395 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6397 const char *rn = "invalid";
6398 uint64_t mask = ctx->PAMask >> 36;
6400 switch (reg) {
6401 case 2:
6402 switch (sel) {
6403 case 0:
6404 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6405 tcg_gen_andi_tl(arg, arg, mask);
6406 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6407 rn = "EntryLo0";
6408 break;
6409 default:
6410 goto cp0_unimplemented;
6412 break;
6413 case 3:
6414 switch (sel) {
6415 case 0:
6416 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6417 tcg_gen_andi_tl(arg, arg, mask);
6418 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6419 rn = "EntryLo1";
6420 break;
6421 default:
6422 goto cp0_unimplemented;
6424 break;
6425 case 17:
6426 switch (sel) {
6427 case 0:
6428 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6429 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6430 relevant for modern MIPS cores supporting MTHC0, therefore
6431 treating MTHC0 to LLAddr as NOP. */
6432 rn = "LLAddr";
6433 break;
6434 case 1:
6435 CP0_CHECK(ctx->mrp);
6436 gen_helper_mthc0_maar(cpu_env, arg);
6437 rn = "MAAR";
6438 break;
6439 default:
6440 goto cp0_unimplemented;
6442 break;
6443 case 28:
6444 switch (sel) {
6445 case 0:
6446 case 2:
6447 case 4:
6448 case 6:
6449 tcg_gen_andi_tl(arg, arg, mask);
6450 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6451 rn = "TagLo";
6452 break;
6453 default:
6454 goto cp0_unimplemented;
6456 break;
6457 default:
6458 goto cp0_unimplemented;
6460 trace_mips_translate_c0("mthc0", rn, reg, sel);
6462 cp0_unimplemented:
6463 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6466 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6468 if (ctx->insn_flags & ISA_MIPS32R6) {
6469 tcg_gen_movi_tl(arg, 0);
6470 } else {
6471 tcg_gen_movi_tl(arg, ~0);
6475 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6477 const char *rn = "invalid";
6479 if (sel != 0)
6480 check_insn(ctx, ISA_MIPS32);
6482 switch (reg) {
6483 case 0:
6484 switch (sel) {
6485 case 0:
6486 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6487 rn = "Index";
6488 break;
6489 case 1:
6490 CP0_CHECK(ctx->insn_flags & ASE_MT);
6491 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6492 rn = "MVPControl";
6493 break;
6494 case 2:
6495 CP0_CHECK(ctx->insn_flags & ASE_MT);
6496 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6497 rn = "MVPConf0";
6498 break;
6499 case 3:
6500 CP0_CHECK(ctx->insn_flags & ASE_MT);
6501 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6502 rn = "MVPConf1";
6503 break;
6504 case 4:
6505 CP0_CHECK(ctx->vp);
6506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6507 rn = "VPControl";
6508 break;
6509 default:
6510 goto cp0_unimplemented;
6512 break;
6513 case 1:
6514 switch (sel) {
6515 case 0:
6516 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6517 gen_helper_mfc0_random(arg, cpu_env);
6518 rn = "Random";
6519 break;
6520 case 1:
6521 CP0_CHECK(ctx->insn_flags & ASE_MT);
6522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6523 rn = "VPEControl";
6524 break;
6525 case 2:
6526 CP0_CHECK(ctx->insn_flags & ASE_MT);
6527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6528 rn = "VPEConf0";
6529 break;
6530 case 3:
6531 CP0_CHECK(ctx->insn_flags & ASE_MT);
6532 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6533 rn = "VPEConf1";
6534 break;
6535 case 4:
6536 CP0_CHECK(ctx->insn_flags & ASE_MT);
6537 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6538 rn = "YQMask";
6539 break;
6540 case 5:
6541 CP0_CHECK(ctx->insn_flags & ASE_MT);
6542 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6543 rn = "VPESchedule";
6544 break;
6545 case 6:
6546 CP0_CHECK(ctx->insn_flags & ASE_MT);
6547 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6548 rn = "VPEScheFBack";
6549 break;
6550 case 7:
6551 CP0_CHECK(ctx->insn_flags & ASE_MT);
6552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6553 rn = "VPEOpt";
6554 break;
6555 default:
6556 goto cp0_unimplemented;
6558 break;
6559 case 2:
6560 switch (sel) {
6561 case 0:
6563 TCGv_i64 tmp = tcg_temp_new_i64();
6564 tcg_gen_ld_i64(tmp, cpu_env,
6565 offsetof(CPUMIPSState, CP0_EntryLo0));
6566 #if defined(TARGET_MIPS64)
6567 if (ctx->rxi) {
6568 /* Move RI/XI fields to bits 31:30 */
6569 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6570 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6572 #endif
6573 gen_move_low32(arg, tmp);
6574 tcg_temp_free_i64(tmp);
6576 rn = "EntryLo0";
6577 break;
6578 case 1:
6579 CP0_CHECK(ctx->insn_flags & ASE_MT);
6580 gen_helper_mfc0_tcstatus(arg, cpu_env);
6581 rn = "TCStatus";
6582 break;
6583 case 2:
6584 CP0_CHECK(ctx->insn_flags & ASE_MT);
6585 gen_helper_mfc0_tcbind(arg, cpu_env);
6586 rn = "TCBind";
6587 break;
6588 case 3:
6589 CP0_CHECK(ctx->insn_flags & ASE_MT);
6590 gen_helper_mfc0_tcrestart(arg, cpu_env);
6591 rn = "TCRestart";
6592 break;
6593 case 4:
6594 CP0_CHECK(ctx->insn_flags & ASE_MT);
6595 gen_helper_mfc0_tchalt(arg, cpu_env);
6596 rn = "TCHalt";
6597 break;
6598 case 5:
6599 CP0_CHECK(ctx->insn_flags & ASE_MT);
6600 gen_helper_mfc0_tccontext(arg, cpu_env);
6601 rn = "TCContext";
6602 break;
6603 case 6:
6604 CP0_CHECK(ctx->insn_flags & ASE_MT);
6605 gen_helper_mfc0_tcschedule(arg, cpu_env);
6606 rn = "TCSchedule";
6607 break;
6608 case 7:
6609 CP0_CHECK(ctx->insn_flags & ASE_MT);
6610 gen_helper_mfc0_tcschefback(arg, cpu_env);
6611 rn = "TCScheFBack";
6612 break;
6613 default:
6614 goto cp0_unimplemented;
6616 break;
6617 case 3:
6618 switch (sel) {
6619 case 0:
6621 TCGv_i64 tmp = tcg_temp_new_i64();
6622 tcg_gen_ld_i64(tmp, cpu_env,
6623 offsetof(CPUMIPSState, CP0_EntryLo1));
6624 #if defined(TARGET_MIPS64)
6625 if (ctx->rxi) {
6626 /* Move RI/XI fields to bits 31:30 */
6627 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6628 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6630 #endif
6631 gen_move_low32(arg, tmp);
6632 tcg_temp_free_i64(tmp);
6634 rn = "EntryLo1";
6635 break;
6636 case 1:
6637 CP0_CHECK(ctx->vp);
6638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6639 rn = "GlobalNumber";
6640 break;
6641 default:
6642 goto cp0_unimplemented;
6644 break;
6645 case 4:
6646 switch (sel) {
6647 case 0:
6648 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6649 tcg_gen_ext32s_tl(arg, arg);
6650 rn = "Context";
6651 break;
6652 case 1:
6653 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6654 rn = "ContextConfig";
6655 goto cp0_unimplemented;
6656 case 2:
6657 CP0_CHECK(ctx->ulri);
6658 tcg_gen_ld_tl(arg, cpu_env,
6659 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6660 tcg_gen_ext32s_tl(arg, arg);
6661 rn = "UserLocal";
6662 break;
6663 default:
6664 goto cp0_unimplemented;
6666 break;
6667 case 5:
6668 switch (sel) {
6669 case 0:
6670 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6671 rn = "PageMask";
6672 break;
6673 case 1:
6674 check_insn(ctx, ISA_MIPS32R2);
6675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6676 rn = "PageGrain";
6677 break;
6678 case 2:
6679 CP0_CHECK(ctx->sc);
6680 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6681 tcg_gen_ext32s_tl(arg, arg);
6682 rn = "SegCtl0";
6683 break;
6684 case 3:
6685 CP0_CHECK(ctx->sc);
6686 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6687 tcg_gen_ext32s_tl(arg, arg);
6688 rn = "SegCtl1";
6689 break;
6690 case 4:
6691 CP0_CHECK(ctx->sc);
6692 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6693 tcg_gen_ext32s_tl(arg, arg);
6694 rn = "SegCtl2";
6695 break;
6696 case 5:
6697 check_pw(ctx);
6698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6699 rn = "PWBase";
6700 break;
6701 case 6:
6702 check_pw(ctx);
6703 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6704 rn = "PWField";
6705 break;
6706 case 7:
6707 check_pw(ctx);
6708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6709 rn = "PWSize";
6710 break;
6711 default:
6712 goto cp0_unimplemented;
6714 break;
6715 case 6:
6716 switch (sel) {
6717 case 0:
6718 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6719 rn = "Wired";
6720 break;
6721 case 1:
6722 check_insn(ctx, ISA_MIPS32R2);
6723 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6724 rn = "SRSConf0";
6725 break;
6726 case 2:
6727 check_insn(ctx, ISA_MIPS32R2);
6728 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6729 rn = "SRSConf1";
6730 break;
6731 case 3:
6732 check_insn(ctx, ISA_MIPS32R2);
6733 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6734 rn = "SRSConf2";
6735 break;
6736 case 4:
6737 check_insn(ctx, ISA_MIPS32R2);
6738 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6739 rn = "SRSConf3";
6740 break;
6741 case 5:
6742 check_insn(ctx, ISA_MIPS32R2);
6743 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6744 rn = "SRSConf4";
6745 break;
6746 case 6:
6747 check_pw(ctx);
6748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6749 rn = "PWCtl";
6750 break;
6751 default:
6752 goto cp0_unimplemented;
6754 break;
6755 case 7:
6756 switch (sel) {
6757 case 0:
6758 check_insn(ctx, ISA_MIPS32R2);
6759 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6760 rn = "HWREna";
6761 break;
6762 default:
6763 goto cp0_unimplemented;
6765 break;
6766 case 8:
6767 switch (sel) {
6768 case 0:
6769 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6770 tcg_gen_ext32s_tl(arg, arg);
6771 rn = "BadVAddr";
6772 break;
6773 case 1:
6774 CP0_CHECK(ctx->bi);
6775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6776 rn = "BadInstr";
6777 break;
6778 case 2:
6779 CP0_CHECK(ctx->bp);
6780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6781 rn = "BadInstrP";
6782 break;
6783 case 3:
6784 CP0_CHECK(ctx->bi);
6785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6786 tcg_gen_andi_tl(arg, arg, ~0xffff);
6787 rn = "BadInstrX";
6788 break;
6789 default:
6790 goto cp0_unimplemented;
6792 break;
6793 case 9:
6794 switch (sel) {
6795 case 0:
6796 /* Mark as an IO operation because we read the time. */
6797 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6798 gen_io_start();
6800 gen_helper_mfc0_count(arg, cpu_env);
6801 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6802 gen_io_end();
6804 /* Break the TB to be able to take timer interrupts immediately
6805 after reading count. DISAS_STOP isn't sufficient, we need to
6806 ensure we break completely out of translated code. */
6807 gen_save_pc(ctx->base.pc_next + 4);
6808 ctx->base.is_jmp = DISAS_EXIT;
6809 rn = "Count";
6810 break;
6811 /* 6,7 are implementation dependent */
6812 default:
6813 goto cp0_unimplemented;
6815 break;
6816 case 10:
6817 switch (sel) {
6818 case 0:
6819 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6820 tcg_gen_ext32s_tl(arg, arg);
6821 rn = "EntryHi";
6822 break;
6823 default:
6824 goto cp0_unimplemented;
6826 break;
6827 case 11:
6828 switch (sel) {
6829 case 0:
6830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6831 rn = "Compare";
6832 break;
6833 /* 6,7 are implementation dependent */
6834 default:
6835 goto cp0_unimplemented;
6837 break;
6838 case 12:
6839 switch (sel) {
6840 case 0:
6841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6842 rn = "Status";
6843 break;
6844 case 1:
6845 check_insn(ctx, ISA_MIPS32R2);
6846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6847 rn = "IntCtl";
6848 break;
6849 case 2:
6850 check_insn(ctx, ISA_MIPS32R2);
6851 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6852 rn = "SRSCtl";
6853 break;
6854 case 3:
6855 check_insn(ctx, ISA_MIPS32R2);
6856 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6857 rn = "SRSMap";
6858 break;
6859 default:
6860 goto cp0_unimplemented;
6862 break;
6863 case 13:
6864 switch (sel) {
6865 case 0:
6866 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6867 rn = "Cause";
6868 break;
6869 default:
6870 goto cp0_unimplemented;
6872 break;
6873 case 14:
6874 switch (sel) {
6875 case 0:
6876 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6877 tcg_gen_ext32s_tl(arg, arg);
6878 rn = "EPC";
6879 break;
6880 default:
6881 goto cp0_unimplemented;
6883 break;
6884 case 15:
6885 switch (sel) {
6886 case 0:
6887 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6888 rn = "PRid";
6889 break;
6890 case 1:
6891 check_insn(ctx, ISA_MIPS32R2);
6892 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6893 tcg_gen_ext32s_tl(arg, arg);
6894 rn = "EBase";
6895 break;
6896 case 3:
6897 check_insn(ctx, ISA_MIPS32R2);
6898 CP0_CHECK(ctx->cmgcr);
6899 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6900 tcg_gen_ext32s_tl(arg, arg);
6901 rn = "CMGCRBase";
6902 break;
6903 default:
6904 goto cp0_unimplemented;
6906 break;
6907 case 16:
6908 switch (sel) {
6909 case 0:
6910 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6911 rn = "Config";
6912 break;
6913 case 1:
6914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6915 rn = "Config1";
6916 break;
6917 case 2:
6918 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6919 rn = "Config2";
6920 break;
6921 case 3:
6922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6923 rn = "Config3";
6924 break;
6925 case 4:
6926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6927 rn = "Config4";
6928 break;
6929 case 5:
6930 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6931 rn = "Config5";
6932 break;
6933 /* 6,7 are implementation dependent */
6934 case 6:
6935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6936 rn = "Config6";
6937 break;
6938 case 7:
6939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6940 rn = "Config7";
6941 break;
6942 default:
6943 goto cp0_unimplemented;
6945 break;
6946 case 17:
6947 switch (sel) {
6948 case 0:
6949 gen_helper_mfc0_lladdr(arg, cpu_env);
6950 rn = "LLAddr";
6951 break;
6952 case 1:
6953 CP0_CHECK(ctx->mrp);
6954 gen_helper_mfc0_maar(arg, cpu_env);
6955 rn = "MAAR";
6956 break;
6957 case 2:
6958 CP0_CHECK(ctx->mrp);
6959 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6960 rn = "MAARI";
6961 break;
6962 default:
6963 goto cp0_unimplemented;
6965 break;
6966 case 18:
6967 switch (sel) {
6968 case 0:
6969 case 1:
6970 case 2:
6971 case 3:
6972 case 4:
6973 case 5:
6974 case 6:
6975 case 7:
6976 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6977 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6978 rn = "WatchLo";
6979 break;
6980 default:
6981 goto cp0_unimplemented;
6983 break;
6984 case 19:
6985 switch (sel) {
6986 case 0:
6987 case 1:
6988 case 2:
6989 case 3:
6990 case 4:
6991 case 5:
6992 case 6:
6993 case 7:
6994 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6995 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6996 rn = "WatchHi";
6997 break;
6998 default:
6999 goto cp0_unimplemented;
7001 break;
7002 case 20:
7003 switch (sel) {
7004 case 0:
7005 #if defined(TARGET_MIPS64)
7006 check_insn(ctx, ISA_MIPS3);
7007 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7008 tcg_gen_ext32s_tl(arg, arg);
7009 rn = "XContext";
7010 break;
7011 #endif
7012 default:
7013 goto cp0_unimplemented;
7015 break;
7016 case 21:
7017 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7018 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7019 switch (sel) {
7020 case 0:
7021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7022 rn = "Framemask";
7023 break;
7024 default:
7025 goto cp0_unimplemented;
7027 break;
7028 case 22:
7029 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7030 rn = "'Diagnostic"; /* implementation dependent */
7031 break;
7032 case 23:
7033 switch (sel) {
7034 case 0:
7035 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7036 rn = "Debug";
7037 break;
7038 case 1:
7039 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7040 rn = "TraceControl";
7041 goto cp0_unimplemented;
7042 case 2:
7043 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7044 rn = "TraceControl2";
7045 goto cp0_unimplemented;
7046 case 3:
7047 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7048 rn = "UserTraceData";
7049 goto cp0_unimplemented;
7050 case 4:
7051 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7052 rn = "TraceBPC";
7053 goto cp0_unimplemented;
7054 default:
7055 goto cp0_unimplemented;
7057 break;
7058 case 24:
7059 switch (sel) {
7060 case 0:
7061 /* EJTAG support */
7062 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7063 tcg_gen_ext32s_tl(arg, arg);
7064 rn = "DEPC";
7065 break;
7066 default:
7067 goto cp0_unimplemented;
7069 break;
7070 case 25:
7071 switch (sel) {
7072 case 0:
7073 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7074 rn = "Performance0";
7075 break;
7076 case 1:
7077 // gen_helper_mfc0_performance1(arg);
7078 rn = "Performance1";
7079 goto cp0_unimplemented;
7080 case 2:
7081 // gen_helper_mfc0_performance2(arg);
7082 rn = "Performance2";
7083 goto cp0_unimplemented;
7084 case 3:
7085 // gen_helper_mfc0_performance3(arg);
7086 rn = "Performance3";
7087 goto cp0_unimplemented;
7088 case 4:
7089 // gen_helper_mfc0_performance4(arg);
7090 rn = "Performance4";
7091 goto cp0_unimplemented;
7092 case 5:
7093 // gen_helper_mfc0_performance5(arg);
7094 rn = "Performance5";
7095 goto cp0_unimplemented;
7096 case 6:
7097 // gen_helper_mfc0_performance6(arg);
7098 rn = "Performance6";
7099 goto cp0_unimplemented;
7100 case 7:
7101 // gen_helper_mfc0_performance7(arg);
7102 rn = "Performance7";
7103 goto cp0_unimplemented;
7104 default:
7105 goto cp0_unimplemented;
7107 break;
7108 case 26:
7109 switch (sel) {
7110 case 0:
7111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7112 rn = "ErrCtl";
7113 break;
7114 default:
7115 goto cp0_unimplemented;
7117 break;
7118 case 27:
7119 switch (sel) {
7120 case 0:
7121 case 1:
7122 case 2:
7123 case 3:
7124 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7125 rn = "CacheErr";
7126 break;
7127 default:
7128 goto cp0_unimplemented;
7130 break;
7131 case 28:
7132 switch (sel) {
7133 case 0:
7134 case 2:
7135 case 4:
7136 case 6:
7138 TCGv_i64 tmp = tcg_temp_new_i64();
7139 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7140 gen_move_low32(arg, tmp);
7141 tcg_temp_free_i64(tmp);
7143 rn = "TagLo";
7144 break;
7145 case 1:
7146 case 3:
7147 case 5:
7148 case 7:
7149 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7150 rn = "DataLo";
7151 break;
7152 default:
7153 goto cp0_unimplemented;
7155 break;
7156 case 29:
7157 switch (sel) {
7158 case 0:
7159 case 2:
7160 case 4:
7161 case 6:
7162 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7163 rn = "TagHi";
7164 break;
7165 case 1:
7166 case 3:
7167 case 5:
7168 case 7:
7169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7170 rn = "DataHi";
7171 break;
7172 default:
7173 goto cp0_unimplemented;
7175 break;
7176 case 30:
7177 switch (sel) {
7178 case 0:
7179 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7180 tcg_gen_ext32s_tl(arg, arg);
7181 rn = "ErrorEPC";
7182 break;
7183 default:
7184 goto cp0_unimplemented;
7186 break;
7187 case 31:
7188 switch (sel) {
7189 case 0:
7190 /* EJTAG support */
7191 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7192 rn = "DESAVE";
7193 break;
7194 case 2:
7195 case 3:
7196 case 4:
7197 case 5:
7198 case 6:
7199 case 7:
7200 CP0_CHECK(ctx->kscrexist & (1 << sel));
7201 tcg_gen_ld_tl(arg, cpu_env,
7202 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7203 tcg_gen_ext32s_tl(arg, arg);
7204 rn = "KScratch";
7205 break;
7206 default:
7207 goto cp0_unimplemented;
7209 break;
7210 default:
7211 goto cp0_unimplemented;
7213 trace_mips_translate_c0("mfc0", rn, reg, sel);
7214 return;
7216 cp0_unimplemented:
7217 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7218 gen_mfc0_unimplemented(ctx, arg);
7221 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7223 const char *rn = "invalid";
7225 if (sel != 0)
7226 check_insn(ctx, ISA_MIPS32);
7228 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7229 gen_io_start();
7232 switch (reg) {
7233 case 0:
7234 switch (sel) {
7235 case 0:
7236 gen_helper_mtc0_index(cpu_env, arg);
7237 rn = "Index";
7238 break;
7239 case 1:
7240 CP0_CHECK(ctx->insn_flags & ASE_MT);
7241 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7242 rn = "MVPControl";
7243 break;
7244 case 2:
7245 CP0_CHECK(ctx->insn_flags & ASE_MT);
7246 /* ignored */
7247 rn = "MVPConf0";
7248 break;
7249 case 3:
7250 CP0_CHECK(ctx->insn_flags & ASE_MT);
7251 /* ignored */
7252 rn = "MVPConf1";
7253 break;
7254 case 4:
7255 CP0_CHECK(ctx->vp);
7256 /* ignored */
7257 rn = "VPControl";
7258 break;
7259 default:
7260 goto cp0_unimplemented;
7262 break;
7263 case 1:
7264 switch (sel) {
7265 case 0:
7266 /* ignored */
7267 rn = "Random";
7268 break;
7269 case 1:
7270 CP0_CHECK(ctx->insn_flags & ASE_MT);
7271 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7272 rn = "VPEControl";
7273 break;
7274 case 2:
7275 CP0_CHECK(ctx->insn_flags & ASE_MT);
7276 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7277 rn = "VPEConf0";
7278 break;
7279 case 3:
7280 CP0_CHECK(ctx->insn_flags & ASE_MT);
7281 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7282 rn = "VPEConf1";
7283 break;
7284 case 4:
7285 CP0_CHECK(ctx->insn_flags & ASE_MT);
7286 gen_helper_mtc0_yqmask(cpu_env, arg);
7287 rn = "YQMask";
7288 break;
7289 case 5:
7290 CP0_CHECK(ctx->insn_flags & ASE_MT);
7291 tcg_gen_st_tl(arg, cpu_env,
7292 offsetof(CPUMIPSState, CP0_VPESchedule));
7293 rn = "VPESchedule";
7294 break;
7295 case 6:
7296 CP0_CHECK(ctx->insn_flags & ASE_MT);
7297 tcg_gen_st_tl(arg, cpu_env,
7298 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7299 rn = "VPEScheFBack";
7300 break;
7301 case 7:
7302 CP0_CHECK(ctx->insn_flags & ASE_MT);
7303 gen_helper_mtc0_vpeopt(cpu_env, arg);
7304 rn = "VPEOpt";
7305 break;
7306 default:
7307 goto cp0_unimplemented;
7309 break;
7310 case 2:
7311 switch (sel) {
7312 case 0:
7313 gen_helper_mtc0_entrylo0(cpu_env, arg);
7314 rn = "EntryLo0";
7315 break;
7316 case 1:
7317 CP0_CHECK(ctx->insn_flags & ASE_MT);
7318 gen_helper_mtc0_tcstatus(cpu_env, arg);
7319 rn = "TCStatus";
7320 break;
7321 case 2:
7322 CP0_CHECK(ctx->insn_flags & ASE_MT);
7323 gen_helper_mtc0_tcbind(cpu_env, arg);
7324 rn = "TCBind";
7325 break;
7326 case 3:
7327 CP0_CHECK(ctx->insn_flags & ASE_MT);
7328 gen_helper_mtc0_tcrestart(cpu_env, arg);
7329 rn = "TCRestart";
7330 break;
7331 case 4:
7332 CP0_CHECK(ctx->insn_flags & ASE_MT);
7333 gen_helper_mtc0_tchalt(cpu_env, arg);
7334 rn = "TCHalt";
7335 break;
7336 case 5:
7337 CP0_CHECK(ctx->insn_flags & ASE_MT);
7338 gen_helper_mtc0_tccontext(cpu_env, arg);
7339 rn = "TCContext";
7340 break;
7341 case 6:
7342 CP0_CHECK(ctx->insn_flags & ASE_MT);
7343 gen_helper_mtc0_tcschedule(cpu_env, arg);
7344 rn = "TCSchedule";
7345 break;
7346 case 7:
7347 CP0_CHECK(ctx->insn_flags & ASE_MT);
7348 gen_helper_mtc0_tcschefback(cpu_env, arg);
7349 rn = "TCScheFBack";
7350 break;
7351 default:
7352 goto cp0_unimplemented;
7354 break;
7355 case 3:
7356 switch (sel) {
7357 case 0:
7358 gen_helper_mtc0_entrylo1(cpu_env, arg);
7359 rn = "EntryLo1";
7360 break;
7361 case 1:
7362 CP0_CHECK(ctx->vp);
7363 /* ignored */
7364 rn = "GlobalNumber";
7365 break;
7366 default:
7367 goto cp0_unimplemented;
7369 break;
7370 case 4:
7371 switch (sel) {
7372 case 0:
7373 gen_helper_mtc0_context(cpu_env, arg);
7374 rn = "Context";
7375 break;
7376 case 1:
7377 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7378 rn = "ContextConfig";
7379 goto cp0_unimplemented;
7380 case 2:
7381 CP0_CHECK(ctx->ulri);
7382 tcg_gen_st_tl(arg, cpu_env,
7383 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7384 rn = "UserLocal";
7385 break;
7386 default:
7387 goto cp0_unimplemented;
7389 break;
7390 case 5:
7391 switch (sel) {
7392 case 0:
7393 gen_helper_mtc0_pagemask(cpu_env, arg);
7394 rn = "PageMask";
7395 break;
7396 case 1:
7397 check_insn(ctx, ISA_MIPS32R2);
7398 gen_helper_mtc0_pagegrain(cpu_env, arg);
7399 rn = "PageGrain";
7400 ctx->base.is_jmp = DISAS_STOP;
7401 break;
7402 case 2:
7403 CP0_CHECK(ctx->sc);
7404 gen_helper_mtc0_segctl0(cpu_env, arg);
7405 rn = "SegCtl0";
7406 break;
7407 case 3:
7408 CP0_CHECK(ctx->sc);
7409 gen_helper_mtc0_segctl1(cpu_env, arg);
7410 rn = "SegCtl1";
7411 break;
7412 case 4:
7413 CP0_CHECK(ctx->sc);
7414 gen_helper_mtc0_segctl2(cpu_env, arg);
7415 rn = "SegCtl2";
7416 break;
7417 case 5:
7418 check_pw(ctx);
7419 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7420 rn = "PWBase";
7421 break;
7422 case 6:
7423 check_pw(ctx);
7424 gen_helper_mtc0_pwfield(cpu_env, arg);
7425 rn = "PWField";
7426 break;
7427 case 7:
7428 check_pw(ctx);
7429 gen_helper_mtc0_pwsize(cpu_env, arg);
7430 rn = "PWSize";
7431 break;
7432 default:
7433 goto cp0_unimplemented;
7435 break;
7436 case 6:
7437 switch (sel) {
7438 case 0:
7439 gen_helper_mtc0_wired(cpu_env, arg);
7440 rn = "Wired";
7441 break;
7442 case 1:
7443 check_insn(ctx, ISA_MIPS32R2);
7444 gen_helper_mtc0_srsconf0(cpu_env, arg);
7445 rn = "SRSConf0";
7446 break;
7447 case 2:
7448 check_insn(ctx, ISA_MIPS32R2);
7449 gen_helper_mtc0_srsconf1(cpu_env, arg);
7450 rn = "SRSConf1";
7451 break;
7452 case 3:
7453 check_insn(ctx, ISA_MIPS32R2);
7454 gen_helper_mtc0_srsconf2(cpu_env, arg);
7455 rn = "SRSConf2";
7456 break;
7457 case 4:
7458 check_insn(ctx, ISA_MIPS32R2);
7459 gen_helper_mtc0_srsconf3(cpu_env, arg);
7460 rn = "SRSConf3";
7461 break;
7462 case 5:
7463 check_insn(ctx, ISA_MIPS32R2);
7464 gen_helper_mtc0_srsconf4(cpu_env, arg);
7465 rn = "SRSConf4";
7466 break;
7467 case 6:
7468 check_pw(ctx);
7469 gen_helper_mtc0_pwctl(cpu_env, arg);
7470 rn = "PWCtl";
7471 break;
7472 default:
7473 goto cp0_unimplemented;
7475 break;
7476 case 7:
7477 switch (sel) {
7478 case 0:
7479 check_insn(ctx, ISA_MIPS32R2);
7480 gen_helper_mtc0_hwrena(cpu_env, arg);
7481 ctx->base.is_jmp = DISAS_STOP;
7482 rn = "HWREna";
7483 break;
7484 default:
7485 goto cp0_unimplemented;
7487 break;
7488 case 8:
7489 switch (sel) {
7490 case 0:
7491 /* ignored */
7492 rn = "BadVAddr";
7493 break;
7494 case 1:
7495 /* ignored */
7496 rn = "BadInstr";
7497 break;
7498 case 2:
7499 /* ignored */
7500 rn = "BadInstrP";
7501 break;
7502 case 3:
7503 /* ignored */
7504 rn = "BadInstrX";
7505 break;
7506 default:
7507 goto cp0_unimplemented;
7509 break;
7510 case 9:
7511 switch (sel) {
7512 case 0:
7513 gen_helper_mtc0_count(cpu_env, arg);
7514 rn = "Count";
7515 break;
7516 /* 6,7 are implementation dependent */
7517 default:
7518 goto cp0_unimplemented;
7520 break;
7521 case 10:
7522 switch (sel) {
7523 case 0:
7524 gen_helper_mtc0_entryhi(cpu_env, arg);
7525 rn = "EntryHi";
7526 break;
7527 default:
7528 goto cp0_unimplemented;
7530 break;
7531 case 11:
7532 switch (sel) {
7533 case 0:
7534 gen_helper_mtc0_compare(cpu_env, arg);
7535 rn = "Compare";
7536 break;
7537 /* 6,7 are implementation dependent */
7538 default:
7539 goto cp0_unimplemented;
7541 break;
7542 case 12:
7543 switch (sel) {
7544 case 0:
7545 save_cpu_state(ctx, 1);
7546 gen_helper_mtc0_status(cpu_env, arg);
7547 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7548 gen_save_pc(ctx->base.pc_next + 4);
7549 ctx->base.is_jmp = DISAS_EXIT;
7550 rn = "Status";
7551 break;
7552 case 1:
7553 check_insn(ctx, ISA_MIPS32R2);
7554 gen_helper_mtc0_intctl(cpu_env, arg);
7555 /* Stop translation as we may have switched the execution mode */
7556 ctx->base.is_jmp = DISAS_STOP;
7557 rn = "IntCtl";
7558 break;
7559 case 2:
7560 check_insn(ctx, ISA_MIPS32R2);
7561 gen_helper_mtc0_srsctl(cpu_env, arg);
7562 /* Stop translation as we may have switched the execution mode */
7563 ctx->base.is_jmp = DISAS_STOP;
7564 rn = "SRSCtl";
7565 break;
7566 case 3:
7567 check_insn(ctx, ISA_MIPS32R2);
7568 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7569 /* Stop translation as we may have switched the execution mode */
7570 ctx->base.is_jmp = DISAS_STOP;
7571 rn = "SRSMap";
7572 break;
7573 default:
7574 goto cp0_unimplemented;
7576 break;
7577 case 13:
7578 switch (sel) {
7579 case 0:
7580 save_cpu_state(ctx, 1);
7581 gen_helper_mtc0_cause(cpu_env, arg);
7582 /* Stop translation as we may have triggered an interrupt.
7583 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7584 * translated code to check for pending interrupts. */
7585 gen_save_pc(ctx->base.pc_next + 4);
7586 ctx->base.is_jmp = DISAS_EXIT;
7587 rn = "Cause";
7588 break;
7589 default:
7590 goto cp0_unimplemented;
7592 break;
7593 case 14:
7594 switch (sel) {
7595 case 0:
7596 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7597 rn = "EPC";
7598 break;
7599 default:
7600 goto cp0_unimplemented;
7602 break;
7603 case 15:
7604 switch (sel) {
7605 case 0:
7606 /* ignored */
7607 rn = "PRid";
7608 break;
7609 case 1:
7610 check_insn(ctx, ISA_MIPS32R2);
7611 gen_helper_mtc0_ebase(cpu_env, arg);
7612 rn = "EBase";
7613 break;
7614 default:
7615 goto cp0_unimplemented;
7617 break;
7618 case 16:
7619 switch (sel) {
7620 case 0:
7621 gen_helper_mtc0_config0(cpu_env, arg);
7622 rn = "Config";
7623 /* Stop translation as we may have switched the execution mode */
7624 ctx->base.is_jmp = DISAS_STOP;
7625 break;
7626 case 1:
7627 /* ignored, read only */
7628 rn = "Config1";
7629 break;
7630 case 2:
7631 gen_helper_mtc0_config2(cpu_env, arg);
7632 rn = "Config2";
7633 /* Stop translation as we may have switched the execution mode */
7634 ctx->base.is_jmp = DISAS_STOP;
7635 break;
7636 case 3:
7637 gen_helper_mtc0_config3(cpu_env, arg);
7638 rn = "Config3";
7639 /* Stop translation as we may have switched the execution mode */
7640 ctx->base.is_jmp = DISAS_STOP;
7641 break;
7642 case 4:
7643 gen_helper_mtc0_config4(cpu_env, arg);
7644 rn = "Config4";
7645 ctx->base.is_jmp = DISAS_STOP;
7646 break;
7647 case 5:
7648 gen_helper_mtc0_config5(cpu_env, arg);
7649 rn = "Config5";
7650 /* Stop translation as we may have switched the execution mode */
7651 ctx->base.is_jmp = DISAS_STOP;
7652 break;
7653 /* 6,7 are implementation dependent */
7654 case 6:
7655 /* ignored */
7656 rn = "Config6";
7657 break;
7658 case 7:
7659 /* ignored */
7660 rn = "Config7";
7661 break;
7662 default:
7663 rn = "Invalid config selector";
7664 goto cp0_unimplemented;
7666 break;
7667 case 17:
7668 switch (sel) {
7669 case 0:
7670 gen_helper_mtc0_lladdr(cpu_env, arg);
7671 rn = "LLAddr";
7672 break;
7673 case 1:
7674 CP0_CHECK(ctx->mrp);
7675 gen_helper_mtc0_maar(cpu_env, arg);
7676 rn = "MAAR";
7677 break;
7678 case 2:
7679 CP0_CHECK(ctx->mrp);
7680 gen_helper_mtc0_maari(cpu_env, arg);
7681 rn = "MAARI";
7682 break;
7683 default:
7684 goto cp0_unimplemented;
7686 break;
7687 case 18:
7688 switch (sel) {
7689 case 0:
7690 case 1:
7691 case 2:
7692 case 3:
7693 case 4:
7694 case 5:
7695 case 6:
7696 case 7:
7697 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7698 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7699 rn = "WatchLo";
7700 break;
7701 default:
7702 goto cp0_unimplemented;
7704 break;
7705 case 19:
7706 switch (sel) {
7707 case 0:
7708 case 1:
7709 case 2:
7710 case 3:
7711 case 4:
7712 case 5:
7713 case 6:
7714 case 7:
7715 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7716 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7717 rn = "WatchHi";
7718 break;
7719 default:
7720 goto cp0_unimplemented;
7722 break;
7723 case 20:
7724 switch (sel) {
7725 case 0:
7726 #if defined(TARGET_MIPS64)
7727 check_insn(ctx, ISA_MIPS3);
7728 gen_helper_mtc0_xcontext(cpu_env, arg);
7729 rn = "XContext";
7730 break;
7731 #endif
7732 default:
7733 goto cp0_unimplemented;
7735 break;
7736 case 21:
7737 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7738 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7739 switch (sel) {
7740 case 0:
7741 gen_helper_mtc0_framemask(cpu_env, arg);
7742 rn = "Framemask";
7743 break;
7744 default:
7745 goto cp0_unimplemented;
7747 break;
7748 case 22:
7749 /* ignored */
7750 rn = "Diagnostic"; /* implementation dependent */
7751 break;
7752 case 23:
7753 switch (sel) {
7754 case 0:
7755 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7756 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7757 gen_save_pc(ctx->base.pc_next + 4);
7758 ctx->base.is_jmp = DISAS_EXIT;
7759 rn = "Debug";
7760 break;
7761 case 1:
7762 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7763 rn = "TraceControl";
7764 /* Stop translation as we may have switched the execution mode */
7765 ctx->base.is_jmp = DISAS_STOP;
7766 goto cp0_unimplemented;
7767 case 2:
7768 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7769 rn = "TraceControl2";
7770 /* Stop translation as we may have switched the execution mode */
7771 ctx->base.is_jmp = DISAS_STOP;
7772 goto cp0_unimplemented;
7773 case 3:
7774 /* Stop translation as we may have switched the execution mode */
7775 ctx->base.is_jmp = DISAS_STOP;
7776 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7777 rn = "UserTraceData";
7778 /* Stop translation as we may have switched the execution mode */
7779 ctx->base.is_jmp = DISAS_STOP;
7780 goto cp0_unimplemented;
7781 case 4:
7782 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7783 /* Stop translation as we may have switched the execution mode */
7784 ctx->base.is_jmp = DISAS_STOP;
7785 rn = "TraceBPC";
7786 goto cp0_unimplemented;
7787 default:
7788 goto cp0_unimplemented;
7790 break;
7791 case 24:
7792 switch (sel) {
7793 case 0:
7794 /* EJTAG support */
7795 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7796 rn = "DEPC";
7797 break;
7798 default:
7799 goto cp0_unimplemented;
7801 break;
7802 case 25:
7803 switch (sel) {
7804 case 0:
7805 gen_helper_mtc0_performance0(cpu_env, arg);
7806 rn = "Performance0";
7807 break;
7808 case 1:
7809 // gen_helper_mtc0_performance1(arg);
7810 rn = "Performance1";
7811 goto cp0_unimplemented;
7812 case 2:
7813 // gen_helper_mtc0_performance2(arg);
7814 rn = "Performance2";
7815 goto cp0_unimplemented;
7816 case 3:
7817 // gen_helper_mtc0_performance3(arg);
7818 rn = "Performance3";
7819 goto cp0_unimplemented;
7820 case 4:
7821 // gen_helper_mtc0_performance4(arg);
7822 rn = "Performance4";
7823 goto cp0_unimplemented;
7824 case 5:
7825 // gen_helper_mtc0_performance5(arg);
7826 rn = "Performance5";
7827 goto cp0_unimplemented;
7828 case 6:
7829 // gen_helper_mtc0_performance6(arg);
7830 rn = "Performance6";
7831 goto cp0_unimplemented;
7832 case 7:
7833 // gen_helper_mtc0_performance7(arg);
7834 rn = "Performance7";
7835 goto cp0_unimplemented;
7836 default:
7837 goto cp0_unimplemented;
7839 break;
7840 case 26:
7841 switch (sel) {
7842 case 0:
7843 gen_helper_mtc0_errctl(cpu_env, arg);
7844 ctx->base.is_jmp = DISAS_STOP;
7845 rn = "ErrCtl";
7846 break;
7847 default:
7848 goto cp0_unimplemented;
7850 break;
7851 case 27:
7852 switch (sel) {
7853 case 0:
7854 case 1:
7855 case 2:
7856 case 3:
7857 /* ignored */
7858 rn = "CacheErr";
7859 break;
7860 default:
7861 goto cp0_unimplemented;
7863 break;
7864 case 28:
7865 switch (sel) {
7866 case 0:
7867 case 2:
7868 case 4:
7869 case 6:
7870 gen_helper_mtc0_taglo(cpu_env, arg);
7871 rn = "TagLo";
7872 break;
7873 case 1:
7874 case 3:
7875 case 5:
7876 case 7:
7877 gen_helper_mtc0_datalo(cpu_env, arg);
7878 rn = "DataLo";
7879 break;
7880 default:
7881 goto cp0_unimplemented;
7883 break;
7884 case 29:
7885 switch (sel) {
7886 case 0:
7887 case 2:
7888 case 4:
7889 case 6:
7890 gen_helper_mtc0_taghi(cpu_env, arg);
7891 rn = "TagHi";
7892 break;
7893 case 1:
7894 case 3:
7895 case 5:
7896 case 7:
7897 gen_helper_mtc0_datahi(cpu_env, arg);
7898 rn = "DataHi";
7899 break;
7900 default:
7901 rn = "invalid sel";
7902 goto cp0_unimplemented;
7904 break;
7905 case 30:
7906 switch (sel) {
7907 case 0:
7908 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7909 rn = "ErrorEPC";
7910 break;
7911 default:
7912 goto cp0_unimplemented;
7914 break;
7915 case 31:
7916 switch (sel) {
7917 case 0:
7918 /* EJTAG support */
7919 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7920 rn = "DESAVE";
7921 break;
7922 case 2:
7923 case 3:
7924 case 4:
7925 case 5:
7926 case 6:
7927 case 7:
7928 CP0_CHECK(ctx->kscrexist & (1 << sel));
7929 tcg_gen_st_tl(arg, cpu_env,
7930 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7931 rn = "KScratch";
7932 break;
7933 default:
7934 goto cp0_unimplemented;
7936 break;
7937 default:
7938 goto cp0_unimplemented;
7940 trace_mips_translate_c0("mtc0", rn, reg, sel);
7942 /* For simplicity assume that all writes can cause interrupts. */
7943 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7944 gen_io_end();
7945 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7946 * translated code to check for pending interrupts. */
7947 gen_save_pc(ctx->base.pc_next + 4);
7948 ctx->base.is_jmp = DISAS_EXIT;
7950 return;
7952 cp0_unimplemented:
7953 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7956 #if defined(TARGET_MIPS64)
7957 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7959 const char *rn = "invalid";
7961 if (sel != 0)
7962 check_insn(ctx, ISA_MIPS64);
7964 switch (reg) {
7965 case 0:
7966 switch (sel) {
7967 case 0:
7968 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7969 rn = "Index";
7970 break;
7971 case 1:
7972 CP0_CHECK(ctx->insn_flags & ASE_MT);
7973 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7974 rn = "MVPControl";
7975 break;
7976 case 2:
7977 CP0_CHECK(ctx->insn_flags & ASE_MT);
7978 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7979 rn = "MVPConf0";
7980 break;
7981 case 3:
7982 CP0_CHECK(ctx->insn_flags & ASE_MT);
7983 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7984 rn = "MVPConf1";
7985 break;
7986 case 4:
7987 CP0_CHECK(ctx->vp);
7988 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7989 rn = "VPControl";
7990 break;
7991 default:
7992 goto cp0_unimplemented;
7994 break;
7995 case 1:
7996 switch (sel) {
7997 case 0:
7998 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7999 gen_helper_mfc0_random(arg, cpu_env);
8000 rn = "Random";
8001 break;
8002 case 1:
8003 CP0_CHECK(ctx->insn_flags & ASE_MT);
8004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8005 rn = "VPEControl";
8006 break;
8007 case 2:
8008 CP0_CHECK(ctx->insn_flags & ASE_MT);
8009 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8010 rn = "VPEConf0";
8011 break;
8012 case 3:
8013 CP0_CHECK(ctx->insn_flags & ASE_MT);
8014 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8015 rn = "VPEConf1";
8016 break;
8017 case 4:
8018 CP0_CHECK(ctx->insn_flags & ASE_MT);
8019 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8020 rn = "YQMask";
8021 break;
8022 case 5:
8023 CP0_CHECK(ctx->insn_flags & ASE_MT);
8024 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8025 rn = "VPESchedule";
8026 break;
8027 case 6:
8028 CP0_CHECK(ctx->insn_flags & ASE_MT);
8029 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8030 rn = "VPEScheFBack";
8031 break;
8032 case 7:
8033 CP0_CHECK(ctx->insn_flags & ASE_MT);
8034 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8035 rn = "VPEOpt";
8036 break;
8037 default:
8038 goto cp0_unimplemented;
8040 break;
8041 case 2:
8042 switch (sel) {
8043 case 0:
8044 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8045 rn = "EntryLo0";
8046 break;
8047 case 1:
8048 CP0_CHECK(ctx->insn_flags & ASE_MT);
8049 gen_helper_mfc0_tcstatus(arg, cpu_env);
8050 rn = "TCStatus";
8051 break;
8052 case 2:
8053 CP0_CHECK(ctx->insn_flags & ASE_MT);
8054 gen_helper_mfc0_tcbind(arg, cpu_env);
8055 rn = "TCBind";
8056 break;
8057 case 3:
8058 CP0_CHECK(ctx->insn_flags & ASE_MT);
8059 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8060 rn = "TCRestart";
8061 break;
8062 case 4:
8063 CP0_CHECK(ctx->insn_flags & ASE_MT);
8064 gen_helper_dmfc0_tchalt(arg, cpu_env);
8065 rn = "TCHalt";
8066 break;
8067 case 5:
8068 CP0_CHECK(ctx->insn_flags & ASE_MT);
8069 gen_helper_dmfc0_tccontext(arg, cpu_env);
8070 rn = "TCContext";
8071 break;
8072 case 6:
8073 CP0_CHECK(ctx->insn_flags & ASE_MT);
8074 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8075 rn = "TCSchedule";
8076 break;
8077 case 7:
8078 CP0_CHECK(ctx->insn_flags & ASE_MT);
8079 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8080 rn = "TCScheFBack";
8081 break;
8082 default:
8083 goto cp0_unimplemented;
8085 break;
8086 case 3:
8087 switch (sel) {
8088 case 0:
8089 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8090 rn = "EntryLo1";
8091 break;
8092 case 1:
8093 CP0_CHECK(ctx->vp);
8094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8095 rn = "GlobalNumber";
8096 break;
8097 default:
8098 goto cp0_unimplemented;
8100 break;
8101 case 4:
8102 switch (sel) {
8103 case 0:
8104 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8105 rn = "Context";
8106 break;
8107 case 1:
8108 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8109 rn = "ContextConfig";
8110 goto cp0_unimplemented;
8111 case 2:
8112 CP0_CHECK(ctx->ulri);
8113 tcg_gen_ld_tl(arg, cpu_env,
8114 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8115 rn = "UserLocal";
8116 break;
8117 default:
8118 goto cp0_unimplemented;
8120 break;
8121 case 5:
8122 switch (sel) {
8123 case 0:
8124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8125 rn = "PageMask";
8126 break;
8127 case 1:
8128 check_insn(ctx, ISA_MIPS32R2);
8129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8130 rn = "PageGrain";
8131 break;
8132 case 2:
8133 CP0_CHECK(ctx->sc);
8134 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8135 rn = "SegCtl0";
8136 break;
8137 case 3:
8138 CP0_CHECK(ctx->sc);
8139 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8140 rn = "SegCtl1";
8141 break;
8142 case 4:
8143 CP0_CHECK(ctx->sc);
8144 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8145 rn = "SegCtl2";
8146 break;
8147 case 5:
8148 check_pw(ctx);
8149 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8150 rn = "PWBase";
8151 break;
8152 case 6:
8153 check_pw(ctx);
8154 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8155 rn = "PWField";
8156 break;
8157 case 7:
8158 check_pw(ctx);
8159 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8160 rn = "PWSize";
8161 break;
8162 default:
8163 goto cp0_unimplemented;
8165 break;
8166 case 6:
8167 switch (sel) {
8168 case 0:
8169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8170 rn = "Wired";
8171 break;
8172 case 1:
8173 check_insn(ctx, ISA_MIPS32R2);
8174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8175 rn = "SRSConf0";
8176 break;
8177 case 2:
8178 check_insn(ctx, ISA_MIPS32R2);
8179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8180 rn = "SRSConf1";
8181 break;
8182 case 3:
8183 check_insn(ctx, ISA_MIPS32R2);
8184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8185 rn = "SRSConf2";
8186 break;
8187 case 4:
8188 check_insn(ctx, ISA_MIPS32R2);
8189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8190 rn = "SRSConf3";
8191 break;
8192 case 5:
8193 check_insn(ctx, ISA_MIPS32R2);
8194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8195 rn = "SRSConf4";
8196 break;
8197 case 6:
8198 check_pw(ctx);
8199 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8200 rn = "PWCtl";
8201 break;
8202 default:
8203 goto cp0_unimplemented;
8205 break;
8206 case 7:
8207 switch (sel) {
8208 case 0:
8209 check_insn(ctx, ISA_MIPS32R2);
8210 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8211 rn = "HWREna";
8212 break;
8213 default:
8214 goto cp0_unimplemented;
8216 break;
8217 case 8:
8218 switch (sel) {
8219 case 0:
8220 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8221 rn = "BadVAddr";
8222 break;
8223 case 1:
8224 CP0_CHECK(ctx->bi);
8225 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8226 rn = "BadInstr";
8227 break;
8228 case 2:
8229 CP0_CHECK(ctx->bp);
8230 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8231 rn = "BadInstrP";
8232 break;
8233 case 3:
8234 CP0_CHECK(ctx->bi);
8235 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8236 tcg_gen_andi_tl(arg, arg, ~0xffff);
8237 rn = "BadInstrX";
8238 break;
8239 default:
8240 goto cp0_unimplemented;
8242 break;
8243 case 9:
8244 switch (sel) {
8245 case 0:
8246 /* Mark as an IO operation because we read the time. */
8247 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8248 gen_io_start();
8250 gen_helper_mfc0_count(arg, cpu_env);
8251 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8252 gen_io_end();
8254 /* Break the TB to be able to take timer interrupts immediately
8255 after reading count. DISAS_STOP isn't sufficient, we need to
8256 ensure we break completely out of translated code. */
8257 gen_save_pc(ctx->base.pc_next + 4);
8258 ctx->base.is_jmp = DISAS_EXIT;
8259 rn = "Count";
8260 break;
8261 /* 6,7 are implementation dependent */
8262 default:
8263 goto cp0_unimplemented;
8265 break;
8266 case 10:
8267 switch (sel) {
8268 case 0:
8269 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8270 rn = "EntryHi";
8271 break;
8272 default:
8273 goto cp0_unimplemented;
8275 break;
8276 case 11:
8277 switch (sel) {
8278 case 0:
8279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8280 rn = "Compare";
8281 break;
8282 /* 6,7 are implementation dependent */
8283 default:
8284 goto cp0_unimplemented;
8286 break;
8287 case 12:
8288 switch (sel) {
8289 case 0:
8290 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8291 rn = "Status";
8292 break;
8293 case 1:
8294 check_insn(ctx, ISA_MIPS32R2);
8295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8296 rn = "IntCtl";
8297 break;
8298 case 2:
8299 check_insn(ctx, ISA_MIPS32R2);
8300 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8301 rn = "SRSCtl";
8302 break;
8303 case 3:
8304 check_insn(ctx, ISA_MIPS32R2);
8305 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8306 rn = "SRSMap";
8307 break;
8308 default:
8309 goto cp0_unimplemented;
8311 break;
8312 case 13:
8313 switch (sel) {
8314 case 0:
8315 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8316 rn = "Cause";
8317 break;
8318 default:
8319 goto cp0_unimplemented;
8321 break;
8322 case 14:
8323 switch (sel) {
8324 case 0:
8325 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8326 rn = "EPC";
8327 break;
8328 default:
8329 goto cp0_unimplemented;
8331 break;
8332 case 15:
8333 switch (sel) {
8334 case 0:
8335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8336 rn = "PRid";
8337 break;
8338 case 1:
8339 check_insn(ctx, ISA_MIPS32R2);
8340 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8341 rn = "EBase";
8342 break;
8343 case 3:
8344 check_insn(ctx, ISA_MIPS32R2);
8345 CP0_CHECK(ctx->cmgcr);
8346 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8347 rn = "CMGCRBase";
8348 break;
8349 default:
8350 goto cp0_unimplemented;
8352 break;
8353 case 16:
8354 switch (sel) {
8355 case 0:
8356 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8357 rn = "Config";
8358 break;
8359 case 1:
8360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8361 rn = "Config1";
8362 break;
8363 case 2:
8364 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8365 rn = "Config2";
8366 break;
8367 case 3:
8368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8369 rn = "Config3";
8370 break;
8371 case 4:
8372 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8373 rn = "Config4";
8374 break;
8375 case 5:
8376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8377 rn = "Config5";
8378 break;
8379 /* 6,7 are implementation dependent */
8380 case 6:
8381 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8382 rn = "Config6";
8383 break;
8384 case 7:
8385 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8386 rn = "Config7";
8387 break;
8388 default:
8389 goto cp0_unimplemented;
8391 break;
8392 case 17:
8393 switch (sel) {
8394 case 0:
8395 gen_helper_dmfc0_lladdr(arg, cpu_env);
8396 rn = "LLAddr";
8397 break;
8398 case 1:
8399 CP0_CHECK(ctx->mrp);
8400 gen_helper_dmfc0_maar(arg, cpu_env);
8401 rn = "MAAR";
8402 break;
8403 case 2:
8404 CP0_CHECK(ctx->mrp);
8405 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8406 rn = "MAARI";
8407 break;
8408 default:
8409 goto cp0_unimplemented;
8411 break;
8412 case 18:
8413 switch (sel) {
8414 case 0:
8415 case 1:
8416 case 2:
8417 case 3:
8418 case 4:
8419 case 5:
8420 case 6:
8421 case 7:
8422 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8423 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8424 rn = "WatchLo";
8425 break;
8426 default:
8427 goto cp0_unimplemented;
8429 break;
8430 case 19:
8431 switch (sel) {
8432 case 0:
8433 case 1:
8434 case 2:
8435 case 3:
8436 case 4:
8437 case 5:
8438 case 6:
8439 case 7:
8440 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8441 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8442 rn = "WatchHi";
8443 break;
8444 default:
8445 goto cp0_unimplemented;
8447 break;
8448 case 20:
8449 switch (sel) {
8450 case 0:
8451 check_insn(ctx, ISA_MIPS3);
8452 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8453 rn = "XContext";
8454 break;
8455 default:
8456 goto cp0_unimplemented;
8458 break;
8459 case 21:
8460 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8461 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8462 switch (sel) {
8463 case 0:
8464 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8465 rn = "Framemask";
8466 break;
8467 default:
8468 goto cp0_unimplemented;
8470 break;
8471 case 22:
8472 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8473 rn = "'Diagnostic"; /* implementation dependent */
8474 break;
8475 case 23:
8476 switch (sel) {
8477 case 0:
8478 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8479 rn = "Debug";
8480 break;
8481 case 1:
8482 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8483 rn = "TraceControl";
8484 goto cp0_unimplemented;
8485 case 2:
8486 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8487 rn = "TraceControl2";
8488 goto cp0_unimplemented;
8489 case 3:
8490 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8491 rn = "UserTraceData";
8492 goto cp0_unimplemented;
8493 case 4:
8494 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8495 rn = "TraceBPC";
8496 goto cp0_unimplemented;
8497 default:
8498 goto cp0_unimplemented;
8500 break;
8501 case 24:
8502 switch (sel) {
8503 case 0:
8504 /* EJTAG support */
8505 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8506 rn = "DEPC";
8507 break;
8508 default:
8509 goto cp0_unimplemented;
8511 break;
8512 case 25:
8513 switch (sel) {
8514 case 0:
8515 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8516 rn = "Performance0";
8517 break;
8518 case 1:
8519 // gen_helper_dmfc0_performance1(arg);
8520 rn = "Performance1";
8521 goto cp0_unimplemented;
8522 case 2:
8523 // gen_helper_dmfc0_performance2(arg);
8524 rn = "Performance2";
8525 goto cp0_unimplemented;
8526 case 3:
8527 // gen_helper_dmfc0_performance3(arg);
8528 rn = "Performance3";
8529 goto cp0_unimplemented;
8530 case 4:
8531 // gen_helper_dmfc0_performance4(arg);
8532 rn = "Performance4";
8533 goto cp0_unimplemented;
8534 case 5:
8535 // gen_helper_dmfc0_performance5(arg);
8536 rn = "Performance5";
8537 goto cp0_unimplemented;
8538 case 6:
8539 // gen_helper_dmfc0_performance6(arg);
8540 rn = "Performance6";
8541 goto cp0_unimplemented;
8542 case 7:
8543 // gen_helper_dmfc0_performance7(arg);
8544 rn = "Performance7";
8545 goto cp0_unimplemented;
8546 default:
8547 goto cp0_unimplemented;
8549 break;
8550 case 26:
8551 switch (sel) {
8552 case 0:
8553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8554 rn = "ErrCtl";
8555 break;
8556 default:
8557 goto cp0_unimplemented;
8559 break;
8560 case 27:
8561 switch (sel) {
8562 /* ignored */
8563 case 0:
8564 case 1:
8565 case 2:
8566 case 3:
8567 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8568 rn = "CacheErr";
8569 break;
8570 default:
8571 goto cp0_unimplemented;
8573 break;
8574 case 28:
8575 switch (sel) {
8576 case 0:
8577 case 2:
8578 case 4:
8579 case 6:
8580 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8581 rn = "TagLo";
8582 break;
8583 case 1:
8584 case 3:
8585 case 5:
8586 case 7:
8587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8588 rn = "DataLo";
8589 break;
8590 default:
8591 goto cp0_unimplemented;
8593 break;
8594 case 29:
8595 switch (sel) {
8596 case 0:
8597 case 2:
8598 case 4:
8599 case 6:
8600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8601 rn = "TagHi";
8602 break;
8603 case 1:
8604 case 3:
8605 case 5:
8606 case 7:
8607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8608 rn = "DataHi";
8609 break;
8610 default:
8611 goto cp0_unimplemented;
8613 break;
8614 case 30:
8615 switch (sel) {
8616 case 0:
8617 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8618 rn = "ErrorEPC";
8619 break;
8620 default:
8621 goto cp0_unimplemented;
8623 break;
8624 case 31:
8625 switch (sel) {
8626 case 0:
8627 /* EJTAG support */
8628 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8629 rn = "DESAVE";
8630 break;
8631 case 2:
8632 case 3:
8633 case 4:
8634 case 5:
8635 case 6:
8636 case 7:
8637 CP0_CHECK(ctx->kscrexist & (1 << sel));
8638 tcg_gen_ld_tl(arg, cpu_env,
8639 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8640 rn = "KScratch";
8641 break;
8642 default:
8643 goto cp0_unimplemented;
8645 break;
8646 default:
8647 goto cp0_unimplemented;
8649 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8650 return;
8652 cp0_unimplemented:
8653 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8654 gen_mfc0_unimplemented(ctx, arg);
8657 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8659 const char *rn = "invalid";
8661 if (sel != 0)
8662 check_insn(ctx, ISA_MIPS64);
8664 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8665 gen_io_start();
8668 switch (reg) {
8669 case 0:
8670 switch (sel) {
8671 case 0:
8672 gen_helper_mtc0_index(cpu_env, arg);
8673 rn = "Index";
8674 break;
8675 case 1:
8676 CP0_CHECK(ctx->insn_flags & ASE_MT);
8677 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8678 rn = "MVPControl";
8679 break;
8680 case 2:
8681 CP0_CHECK(ctx->insn_flags & ASE_MT);
8682 /* ignored */
8683 rn = "MVPConf0";
8684 break;
8685 case 3:
8686 CP0_CHECK(ctx->insn_flags & ASE_MT);
8687 /* ignored */
8688 rn = "MVPConf1";
8689 break;
8690 case 4:
8691 CP0_CHECK(ctx->vp);
8692 /* ignored */
8693 rn = "VPControl";
8694 break;
8695 default:
8696 goto cp0_unimplemented;
8698 break;
8699 case 1:
8700 switch (sel) {
8701 case 0:
8702 /* ignored */
8703 rn = "Random";
8704 break;
8705 case 1:
8706 CP0_CHECK(ctx->insn_flags & ASE_MT);
8707 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8708 rn = "VPEControl";
8709 break;
8710 case 2:
8711 CP0_CHECK(ctx->insn_flags & ASE_MT);
8712 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8713 rn = "VPEConf0";
8714 break;
8715 case 3:
8716 CP0_CHECK(ctx->insn_flags & ASE_MT);
8717 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8718 rn = "VPEConf1";
8719 break;
8720 case 4:
8721 CP0_CHECK(ctx->insn_flags & ASE_MT);
8722 gen_helper_mtc0_yqmask(cpu_env, arg);
8723 rn = "YQMask";
8724 break;
8725 case 5:
8726 CP0_CHECK(ctx->insn_flags & ASE_MT);
8727 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8728 rn = "VPESchedule";
8729 break;
8730 case 6:
8731 CP0_CHECK(ctx->insn_flags & ASE_MT);
8732 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8733 rn = "VPEScheFBack";
8734 break;
8735 case 7:
8736 CP0_CHECK(ctx->insn_flags & ASE_MT);
8737 gen_helper_mtc0_vpeopt(cpu_env, arg);
8738 rn = "VPEOpt";
8739 break;
8740 default:
8741 goto cp0_unimplemented;
8743 break;
8744 case 2:
8745 switch (sel) {
8746 case 0:
8747 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8748 rn = "EntryLo0";
8749 break;
8750 case 1:
8751 CP0_CHECK(ctx->insn_flags & ASE_MT);
8752 gen_helper_mtc0_tcstatus(cpu_env, arg);
8753 rn = "TCStatus";
8754 break;
8755 case 2:
8756 CP0_CHECK(ctx->insn_flags & ASE_MT);
8757 gen_helper_mtc0_tcbind(cpu_env, arg);
8758 rn = "TCBind";
8759 break;
8760 case 3:
8761 CP0_CHECK(ctx->insn_flags & ASE_MT);
8762 gen_helper_mtc0_tcrestart(cpu_env, arg);
8763 rn = "TCRestart";
8764 break;
8765 case 4:
8766 CP0_CHECK(ctx->insn_flags & ASE_MT);
8767 gen_helper_mtc0_tchalt(cpu_env, arg);
8768 rn = "TCHalt";
8769 break;
8770 case 5:
8771 CP0_CHECK(ctx->insn_flags & ASE_MT);
8772 gen_helper_mtc0_tccontext(cpu_env, arg);
8773 rn = "TCContext";
8774 break;
8775 case 6:
8776 CP0_CHECK(ctx->insn_flags & ASE_MT);
8777 gen_helper_mtc0_tcschedule(cpu_env, arg);
8778 rn = "TCSchedule";
8779 break;
8780 case 7:
8781 CP0_CHECK(ctx->insn_flags & ASE_MT);
8782 gen_helper_mtc0_tcschefback(cpu_env, arg);
8783 rn = "TCScheFBack";
8784 break;
8785 default:
8786 goto cp0_unimplemented;
8788 break;
8789 case 3:
8790 switch (sel) {
8791 case 0:
8792 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8793 rn = "EntryLo1";
8794 break;
8795 case 1:
8796 CP0_CHECK(ctx->vp);
8797 /* ignored */
8798 rn = "GlobalNumber";
8799 break;
8800 default:
8801 goto cp0_unimplemented;
8803 break;
8804 case 4:
8805 switch (sel) {
8806 case 0:
8807 gen_helper_mtc0_context(cpu_env, arg);
8808 rn = "Context";
8809 break;
8810 case 1:
8811 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8812 rn = "ContextConfig";
8813 goto cp0_unimplemented;
8814 case 2:
8815 CP0_CHECK(ctx->ulri);
8816 tcg_gen_st_tl(arg, cpu_env,
8817 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8818 rn = "UserLocal";
8819 break;
8820 default:
8821 goto cp0_unimplemented;
8823 break;
8824 case 5:
8825 switch (sel) {
8826 case 0:
8827 gen_helper_mtc0_pagemask(cpu_env, arg);
8828 rn = "PageMask";
8829 break;
8830 case 1:
8831 check_insn(ctx, ISA_MIPS32R2);
8832 gen_helper_mtc0_pagegrain(cpu_env, arg);
8833 rn = "PageGrain";
8834 break;
8835 case 2:
8836 CP0_CHECK(ctx->sc);
8837 gen_helper_mtc0_segctl0(cpu_env, arg);
8838 rn = "SegCtl0";
8839 break;
8840 case 3:
8841 CP0_CHECK(ctx->sc);
8842 gen_helper_mtc0_segctl1(cpu_env, arg);
8843 rn = "SegCtl1";
8844 break;
8845 case 4:
8846 CP0_CHECK(ctx->sc);
8847 gen_helper_mtc0_segctl2(cpu_env, arg);
8848 rn = "SegCtl2";
8849 break;
8850 case 5:
8851 check_pw(ctx);
8852 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8853 rn = "PWBase";
8854 break;
8855 case 6:
8856 check_pw(ctx);
8857 gen_helper_mtc0_pwfield(cpu_env, arg);
8858 rn = "PWField";
8859 break;
8860 case 7:
8861 check_pw(ctx);
8862 gen_helper_mtc0_pwsize(cpu_env, arg);
8863 rn = "PWSize";
8864 break;
8865 default:
8866 goto cp0_unimplemented;
8868 break;
8869 case 6:
8870 switch (sel) {
8871 case 0:
8872 gen_helper_mtc0_wired(cpu_env, arg);
8873 rn = "Wired";
8874 break;
8875 case 1:
8876 check_insn(ctx, ISA_MIPS32R2);
8877 gen_helper_mtc0_srsconf0(cpu_env, arg);
8878 rn = "SRSConf0";
8879 break;
8880 case 2:
8881 check_insn(ctx, ISA_MIPS32R2);
8882 gen_helper_mtc0_srsconf1(cpu_env, arg);
8883 rn = "SRSConf1";
8884 break;
8885 case 3:
8886 check_insn(ctx, ISA_MIPS32R2);
8887 gen_helper_mtc0_srsconf2(cpu_env, arg);
8888 rn = "SRSConf2";
8889 break;
8890 case 4:
8891 check_insn(ctx, ISA_MIPS32R2);
8892 gen_helper_mtc0_srsconf3(cpu_env, arg);
8893 rn = "SRSConf3";
8894 break;
8895 case 5:
8896 check_insn(ctx, ISA_MIPS32R2);
8897 gen_helper_mtc0_srsconf4(cpu_env, arg);
8898 rn = "SRSConf4";
8899 break;
8900 case 6:
8901 check_pw(ctx);
8902 gen_helper_mtc0_pwctl(cpu_env, arg);
8903 rn = "PWCtl";
8904 break;
8905 default:
8906 goto cp0_unimplemented;
8908 break;
8909 case 7:
8910 switch (sel) {
8911 case 0:
8912 check_insn(ctx, ISA_MIPS32R2);
8913 gen_helper_mtc0_hwrena(cpu_env, arg);
8914 ctx->base.is_jmp = DISAS_STOP;
8915 rn = "HWREna";
8916 break;
8917 default:
8918 goto cp0_unimplemented;
8920 break;
8921 case 8:
8922 switch (sel) {
8923 case 0:
8924 /* ignored */
8925 rn = "BadVAddr";
8926 break;
8927 case 1:
8928 /* ignored */
8929 rn = "BadInstr";
8930 break;
8931 case 2:
8932 /* ignored */
8933 rn = "BadInstrP";
8934 break;
8935 case 3:
8936 /* ignored */
8937 rn = "BadInstrX";
8938 break;
8939 default:
8940 goto cp0_unimplemented;
8942 break;
8943 case 9:
8944 switch (sel) {
8945 case 0:
8946 gen_helper_mtc0_count(cpu_env, arg);
8947 rn = "Count";
8948 break;
8949 /* 6,7 are implementation dependent */
8950 default:
8951 goto cp0_unimplemented;
8953 /* Stop translation as we may have switched the execution mode */
8954 ctx->base.is_jmp = DISAS_STOP;
8955 break;
8956 case 10:
8957 switch (sel) {
8958 case 0:
8959 gen_helper_mtc0_entryhi(cpu_env, arg);
8960 rn = "EntryHi";
8961 break;
8962 default:
8963 goto cp0_unimplemented;
8965 break;
8966 case 11:
8967 switch (sel) {
8968 case 0:
8969 gen_helper_mtc0_compare(cpu_env, arg);
8970 rn = "Compare";
8971 break;
8972 /* 6,7 are implementation dependent */
8973 default:
8974 goto cp0_unimplemented;
8976 /* Stop translation as we may have switched the execution mode */
8977 ctx->base.is_jmp = DISAS_STOP;
8978 break;
8979 case 12:
8980 switch (sel) {
8981 case 0:
8982 save_cpu_state(ctx, 1);
8983 gen_helper_mtc0_status(cpu_env, arg);
8984 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8985 gen_save_pc(ctx->base.pc_next + 4);
8986 ctx->base.is_jmp = DISAS_EXIT;
8987 rn = "Status";
8988 break;
8989 case 1:
8990 check_insn(ctx, ISA_MIPS32R2);
8991 gen_helper_mtc0_intctl(cpu_env, arg);
8992 /* Stop translation as we may have switched the execution mode */
8993 ctx->base.is_jmp = DISAS_STOP;
8994 rn = "IntCtl";
8995 break;
8996 case 2:
8997 check_insn(ctx, ISA_MIPS32R2);
8998 gen_helper_mtc0_srsctl(cpu_env, arg);
8999 /* Stop translation as we may have switched the execution mode */
9000 ctx->base.is_jmp = DISAS_STOP;
9001 rn = "SRSCtl";
9002 break;
9003 case 3:
9004 check_insn(ctx, ISA_MIPS32R2);
9005 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9006 /* Stop translation as we may have switched the execution mode */
9007 ctx->base.is_jmp = DISAS_STOP;
9008 rn = "SRSMap";
9009 break;
9010 default:
9011 goto cp0_unimplemented;
9013 break;
9014 case 13:
9015 switch (sel) {
9016 case 0:
9017 save_cpu_state(ctx, 1);
9018 gen_helper_mtc0_cause(cpu_env, arg);
9019 /* Stop translation as we may have triggered an interrupt.
9020 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9021 * translated code to check for pending interrupts. */
9022 gen_save_pc(ctx->base.pc_next + 4);
9023 ctx->base.is_jmp = DISAS_EXIT;
9024 rn = "Cause";
9025 break;
9026 default:
9027 goto cp0_unimplemented;
9029 break;
9030 case 14:
9031 switch (sel) {
9032 case 0:
9033 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9034 rn = "EPC";
9035 break;
9036 default:
9037 goto cp0_unimplemented;
9039 break;
9040 case 15:
9041 switch (sel) {
9042 case 0:
9043 /* ignored */
9044 rn = "PRid";
9045 break;
9046 case 1:
9047 check_insn(ctx, ISA_MIPS32R2);
9048 gen_helper_mtc0_ebase(cpu_env, arg);
9049 rn = "EBase";
9050 break;
9051 default:
9052 goto cp0_unimplemented;
9054 break;
9055 case 16:
9056 switch (sel) {
9057 case 0:
9058 gen_helper_mtc0_config0(cpu_env, arg);
9059 rn = "Config";
9060 /* Stop translation as we may have switched the execution mode */
9061 ctx->base.is_jmp = DISAS_STOP;
9062 break;
9063 case 1:
9064 /* ignored, read only */
9065 rn = "Config1";
9066 break;
9067 case 2:
9068 gen_helper_mtc0_config2(cpu_env, arg);
9069 rn = "Config2";
9070 /* Stop translation as we may have switched the execution mode */
9071 ctx->base.is_jmp = DISAS_STOP;
9072 break;
9073 case 3:
9074 gen_helper_mtc0_config3(cpu_env, arg);
9075 rn = "Config3";
9076 /* Stop translation as we may have switched the execution mode */
9077 ctx->base.is_jmp = DISAS_STOP;
9078 break;
9079 case 4:
9080 /* currently ignored */
9081 rn = "Config4";
9082 break;
9083 case 5:
9084 gen_helper_mtc0_config5(cpu_env, arg);
9085 rn = "Config5";
9086 /* Stop translation as we may have switched the execution mode */
9087 ctx->base.is_jmp = DISAS_STOP;
9088 break;
9089 /* 6,7 are implementation dependent */
9090 default:
9091 rn = "Invalid config selector";
9092 goto cp0_unimplemented;
9094 break;
9095 case 17:
9096 switch (sel) {
9097 case 0:
9098 gen_helper_mtc0_lladdr(cpu_env, arg);
9099 rn = "LLAddr";
9100 break;
9101 case 1:
9102 CP0_CHECK(ctx->mrp);
9103 gen_helper_mtc0_maar(cpu_env, arg);
9104 rn = "MAAR";
9105 break;
9106 case 2:
9107 CP0_CHECK(ctx->mrp);
9108 gen_helper_mtc0_maari(cpu_env, arg);
9109 rn = "MAARI";
9110 break;
9111 default:
9112 goto cp0_unimplemented;
9114 break;
9115 case 18:
9116 switch (sel) {
9117 case 0:
9118 case 1:
9119 case 2:
9120 case 3:
9121 case 4:
9122 case 5:
9123 case 6:
9124 case 7:
9125 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9126 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9127 rn = "WatchLo";
9128 break;
9129 default:
9130 goto cp0_unimplemented;
9132 break;
9133 case 19:
9134 switch (sel) {
9135 case 0:
9136 case 1:
9137 case 2:
9138 case 3:
9139 case 4:
9140 case 5:
9141 case 6:
9142 case 7:
9143 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9144 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9145 rn = "WatchHi";
9146 break;
9147 default:
9148 goto cp0_unimplemented;
9150 break;
9151 case 20:
9152 switch (sel) {
9153 case 0:
9154 check_insn(ctx, ISA_MIPS3);
9155 gen_helper_mtc0_xcontext(cpu_env, arg);
9156 rn = "XContext";
9157 break;
9158 default:
9159 goto cp0_unimplemented;
9161 break;
9162 case 21:
9163 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9164 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9165 switch (sel) {
9166 case 0:
9167 gen_helper_mtc0_framemask(cpu_env, arg);
9168 rn = "Framemask";
9169 break;
9170 default:
9171 goto cp0_unimplemented;
9173 break;
9174 case 22:
9175 /* ignored */
9176 rn = "Diagnostic"; /* implementation dependent */
9177 break;
9178 case 23:
9179 switch (sel) {
9180 case 0:
9181 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9182 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9183 gen_save_pc(ctx->base.pc_next + 4);
9184 ctx->base.is_jmp = DISAS_EXIT;
9185 rn = "Debug";
9186 break;
9187 case 1:
9188 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9189 /* Stop translation as we may have switched the execution mode */
9190 ctx->base.is_jmp = DISAS_STOP;
9191 rn = "TraceControl";
9192 goto cp0_unimplemented;
9193 case 2:
9194 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9195 /* Stop translation as we may have switched the execution mode */
9196 ctx->base.is_jmp = DISAS_STOP;
9197 rn = "TraceControl2";
9198 goto cp0_unimplemented;
9199 case 3:
9200 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9201 /* Stop translation as we may have switched the execution mode */
9202 ctx->base.is_jmp = DISAS_STOP;
9203 rn = "UserTraceData";
9204 goto cp0_unimplemented;
9205 case 4:
9206 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9207 /* Stop translation as we may have switched the execution mode */
9208 ctx->base.is_jmp = DISAS_STOP;
9209 rn = "TraceBPC";
9210 goto cp0_unimplemented;
9211 default:
9212 goto cp0_unimplemented;
9214 break;
9215 case 24:
9216 switch (sel) {
9217 case 0:
9218 /* EJTAG support */
9219 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9220 rn = "DEPC";
9221 break;
9222 default:
9223 goto cp0_unimplemented;
9225 break;
9226 case 25:
9227 switch (sel) {
9228 case 0:
9229 gen_helper_mtc0_performance0(cpu_env, arg);
9230 rn = "Performance0";
9231 break;
9232 case 1:
9233 // gen_helper_mtc0_performance1(cpu_env, arg);
9234 rn = "Performance1";
9235 goto cp0_unimplemented;
9236 case 2:
9237 // gen_helper_mtc0_performance2(cpu_env, arg);
9238 rn = "Performance2";
9239 goto cp0_unimplemented;
9240 case 3:
9241 // gen_helper_mtc0_performance3(cpu_env, arg);
9242 rn = "Performance3";
9243 goto cp0_unimplemented;
9244 case 4:
9245 // gen_helper_mtc0_performance4(cpu_env, arg);
9246 rn = "Performance4";
9247 goto cp0_unimplemented;
9248 case 5:
9249 // gen_helper_mtc0_performance5(cpu_env, arg);
9250 rn = "Performance5";
9251 goto cp0_unimplemented;
9252 case 6:
9253 // gen_helper_mtc0_performance6(cpu_env, arg);
9254 rn = "Performance6";
9255 goto cp0_unimplemented;
9256 case 7:
9257 // gen_helper_mtc0_performance7(cpu_env, arg);
9258 rn = "Performance7";
9259 goto cp0_unimplemented;
9260 default:
9261 goto cp0_unimplemented;
9263 break;
9264 case 26:
9265 switch (sel) {
9266 case 0:
9267 gen_helper_mtc0_errctl(cpu_env, arg);
9268 ctx->base.is_jmp = DISAS_STOP;
9269 rn = "ErrCtl";
9270 break;
9271 default:
9272 goto cp0_unimplemented;
9274 break;
9275 case 27:
9276 switch (sel) {
9277 case 0:
9278 case 1:
9279 case 2:
9280 case 3:
9281 /* ignored */
9282 rn = "CacheErr";
9283 break;
9284 default:
9285 goto cp0_unimplemented;
9287 break;
9288 case 28:
9289 switch (sel) {
9290 case 0:
9291 case 2:
9292 case 4:
9293 case 6:
9294 gen_helper_mtc0_taglo(cpu_env, arg);
9295 rn = "TagLo";
9296 break;
9297 case 1:
9298 case 3:
9299 case 5:
9300 case 7:
9301 gen_helper_mtc0_datalo(cpu_env, arg);
9302 rn = "DataLo";
9303 break;
9304 default:
9305 goto cp0_unimplemented;
9307 break;
9308 case 29:
9309 switch (sel) {
9310 case 0:
9311 case 2:
9312 case 4:
9313 case 6:
9314 gen_helper_mtc0_taghi(cpu_env, arg);
9315 rn = "TagHi";
9316 break;
9317 case 1:
9318 case 3:
9319 case 5:
9320 case 7:
9321 gen_helper_mtc0_datahi(cpu_env, arg);
9322 rn = "DataHi";
9323 break;
9324 default:
9325 rn = "invalid sel";
9326 goto cp0_unimplemented;
9328 break;
9329 case 30:
9330 switch (sel) {
9331 case 0:
9332 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9333 rn = "ErrorEPC";
9334 break;
9335 default:
9336 goto cp0_unimplemented;
9338 break;
9339 case 31:
9340 switch (sel) {
9341 case 0:
9342 /* EJTAG support */
9343 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9344 rn = "DESAVE";
9345 break;
9346 case 2:
9347 case 3:
9348 case 4:
9349 case 5:
9350 case 6:
9351 case 7:
9352 CP0_CHECK(ctx->kscrexist & (1 << sel));
9353 tcg_gen_st_tl(arg, cpu_env,
9354 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9355 rn = "KScratch";
9356 break;
9357 default:
9358 goto cp0_unimplemented;
9360 break;
9361 default:
9362 goto cp0_unimplemented;
9364 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9366 /* For simplicity assume that all writes can cause interrupts. */
9367 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9368 gen_io_end();
9369 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9370 * translated code to check for pending interrupts. */
9371 gen_save_pc(ctx->base.pc_next + 4);
9372 ctx->base.is_jmp = DISAS_EXIT;
9374 return;
9376 cp0_unimplemented:
9377 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9379 #endif /* TARGET_MIPS64 */
9381 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9382 int u, int sel, int h)
9384 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9385 TCGv t0 = tcg_temp_local_new();
9387 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9388 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9389 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9390 tcg_gen_movi_tl(t0, -1);
9391 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9392 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9393 tcg_gen_movi_tl(t0, -1);
9394 else if (u == 0) {
9395 switch (rt) {
9396 case 1:
9397 switch (sel) {
9398 case 1:
9399 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9400 break;
9401 case 2:
9402 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9403 break;
9404 default:
9405 goto die;
9406 break;
9408 break;
9409 case 2:
9410 switch (sel) {
9411 case 1:
9412 gen_helper_mftc0_tcstatus(t0, cpu_env);
9413 break;
9414 case 2:
9415 gen_helper_mftc0_tcbind(t0, cpu_env);
9416 break;
9417 case 3:
9418 gen_helper_mftc0_tcrestart(t0, cpu_env);
9419 break;
9420 case 4:
9421 gen_helper_mftc0_tchalt(t0, cpu_env);
9422 break;
9423 case 5:
9424 gen_helper_mftc0_tccontext(t0, cpu_env);
9425 break;
9426 case 6:
9427 gen_helper_mftc0_tcschedule(t0, cpu_env);
9428 break;
9429 case 7:
9430 gen_helper_mftc0_tcschefback(t0, cpu_env);
9431 break;
9432 default:
9433 gen_mfc0(ctx, t0, rt, sel);
9434 break;
9436 break;
9437 case 10:
9438 switch (sel) {
9439 case 0:
9440 gen_helper_mftc0_entryhi(t0, cpu_env);
9441 break;
9442 default:
9443 gen_mfc0(ctx, t0, rt, sel);
9444 break;
9446 case 12:
9447 switch (sel) {
9448 case 0:
9449 gen_helper_mftc0_status(t0, cpu_env);
9450 break;
9451 default:
9452 gen_mfc0(ctx, t0, rt, sel);
9453 break;
9455 case 13:
9456 switch (sel) {
9457 case 0:
9458 gen_helper_mftc0_cause(t0, cpu_env);
9459 break;
9460 default:
9461 goto die;
9462 break;
9464 break;
9465 case 14:
9466 switch (sel) {
9467 case 0:
9468 gen_helper_mftc0_epc(t0, cpu_env);
9469 break;
9470 default:
9471 goto die;
9472 break;
9474 break;
9475 case 15:
9476 switch (sel) {
9477 case 1:
9478 gen_helper_mftc0_ebase(t0, cpu_env);
9479 break;
9480 default:
9481 goto die;
9482 break;
9484 break;
9485 case 16:
9486 switch (sel) {
9487 case 0:
9488 case 1:
9489 case 2:
9490 case 3:
9491 case 4:
9492 case 5:
9493 case 6:
9494 case 7:
9495 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9496 break;
9497 default:
9498 goto die;
9499 break;
9501 break;
9502 case 23:
9503 switch (sel) {
9504 case 0:
9505 gen_helper_mftc0_debug(t0, cpu_env);
9506 break;
9507 default:
9508 gen_mfc0(ctx, t0, rt, sel);
9509 break;
9511 break;
9512 default:
9513 gen_mfc0(ctx, t0, rt, sel);
9515 } else switch (sel) {
9516 /* GPR registers. */
9517 case 0:
9518 gen_helper_1e0i(mftgpr, t0, rt);
9519 break;
9520 /* Auxiliary CPU registers */
9521 case 1:
9522 switch (rt) {
9523 case 0:
9524 gen_helper_1e0i(mftlo, t0, 0);
9525 break;
9526 case 1:
9527 gen_helper_1e0i(mfthi, t0, 0);
9528 break;
9529 case 2:
9530 gen_helper_1e0i(mftacx, t0, 0);
9531 break;
9532 case 4:
9533 gen_helper_1e0i(mftlo, t0, 1);
9534 break;
9535 case 5:
9536 gen_helper_1e0i(mfthi, t0, 1);
9537 break;
9538 case 6:
9539 gen_helper_1e0i(mftacx, t0, 1);
9540 break;
9541 case 8:
9542 gen_helper_1e0i(mftlo, t0, 2);
9543 break;
9544 case 9:
9545 gen_helper_1e0i(mfthi, t0, 2);
9546 break;
9547 case 10:
9548 gen_helper_1e0i(mftacx, t0, 2);
9549 break;
9550 case 12:
9551 gen_helper_1e0i(mftlo, t0, 3);
9552 break;
9553 case 13:
9554 gen_helper_1e0i(mfthi, t0, 3);
9555 break;
9556 case 14:
9557 gen_helper_1e0i(mftacx, t0, 3);
9558 break;
9559 case 16:
9560 gen_helper_mftdsp(t0, cpu_env);
9561 break;
9562 default:
9563 goto die;
9565 break;
9566 /* Floating point (COP1). */
9567 case 2:
9568 /* XXX: For now we support only a single FPU context. */
9569 if (h == 0) {
9570 TCGv_i32 fp0 = tcg_temp_new_i32();
9572 gen_load_fpr32(ctx, fp0, rt);
9573 tcg_gen_ext_i32_tl(t0, fp0);
9574 tcg_temp_free_i32(fp0);
9575 } else {
9576 TCGv_i32 fp0 = tcg_temp_new_i32();
9578 gen_load_fpr32h(ctx, fp0, rt);
9579 tcg_gen_ext_i32_tl(t0, fp0);
9580 tcg_temp_free_i32(fp0);
9582 break;
9583 case 3:
9584 /* XXX: For now we support only a single FPU context. */
9585 gen_helper_1e0i(cfc1, t0, rt);
9586 break;
9587 /* COP2: Not implemented. */
9588 case 4:
9589 case 5:
9590 /* fall through */
9591 default:
9592 goto die;
9594 trace_mips_translate_tr("mftr", rt, u, sel, h);
9595 gen_store_gpr(t0, rd);
9596 tcg_temp_free(t0);
9597 return;
9599 die:
9600 tcg_temp_free(t0);
9601 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9602 generate_exception_end(ctx, EXCP_RI);
9605 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9606 int u, int sel, int h)
9608 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9609 TCGv t0 = tcg_temp_local_new();
9611 gen_load_gpr(t0, rt);
9612 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9613 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9614 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9615 /* NOP */ ;
9616 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9617 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9618 /* NOP */ ;
9619 else if (u == 0) {
9620 switch (rd) {
9621 case 1:
9622 switch (sel) {
9623 case 1:
9624 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9625 break;
9626 case 2:
9627 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9628 break;
9629 default:
9630 goto die;
9631 break;
9633 break;
9634 case 2:
9635 switch (sel) {
9636 case 1:
9637 gen_helper_mttc0_tcstatus(cpu_env, t0);
9638 break;
9639 case 2:
9640 gen_helper_mttc0_tcbind(cpu_env, t0);
9641 break;
9642 case 3:
9643 gen_helper_mttc0_tcrestart(cpu_env, t0);
9644 break;
9645 case 4:
9646 gen_helper_mttc0_tchalt(cpu_env, t0);
9647 break;
9648 case 5:
9649 gen_helper_mttc0_tccontext(cpu_env, t0);
9650 break;
9651 case 6:
9652 gen_helper_mttc0_tcschedule(cpu_env, t0);
9653 break;
9654 case 7:
9655 gen_helper_mttc0_tcschefback(cpu_env, t0);
9656 break;
9657 default:
9658 gen_mtc0(ctx, t0, rd, sel);
9659 break;
9661 break;
9662 case 10:
9663 switch (sel) {
9664 case 0:
9665 gen_helper_mttc0_entryhi(cpu_env, t0);
9666 break;
9667 default:
9668 gen_mtc0(ctx, t0, rd, sel);
9669 break;
9671 case 12:
9672 switch (sel) {
9673 case 0:
9674 gen_helper_mttc0_status(cpu_env, t0);
9675 break;
9676 default:
9677 gen_mtc0(ctx, t0, rd, sel);
9678 break;
9680 case 13:
9681 switch (sel) {
9682 case 0:
9683 gen_helper_mttc0_cause(cpu_env, t0);
9684 break;
9685 default:
9686 goto die;
9687 break;
9689 break;
9690 case 15:
9691 switch (sel) {
9692 case 1:
9693 gen_helper_mttc0_ebase(cpu_env, t0);
9694 break;
9695 default:
9696 goto die;
9697 break;
9699 break;
9700 case 23:
9701 switch (sel) {
9702 case 0:
9703 gen_helper_mttc0_debug(cpu_env, t0);
9704 break;
9705 default:
9706 gen_mtc0(ctx, t0, rd, sel);
9707 break;
9709 break;
9710 default:
9711 gen_mtc0(ctx, t0, rd, sel);
9713 } else switch (sel) {
9714 /* GPR registers. */
9715 case 0:
9716 gen_helper_0e1i(mttgpr, t0, rd);
9717 break;
9718 /* Auxiliary CPU registers */
9719 case 1:
9720 switch (rd) {
9721 case 0:
9722 gen_helper_0e1i(mttlo, t0, 0);
9723 break;
9724 case 1:
9725 gen_helper_0e1i(mtthi, t0, 0);
9726 break;
9727 case 2:
9728 gen_helper_0e1i(mttacx, t0, 0);
9729 break;
9730 case 4:
9731 gen_helper_0e1i(mttlo, t0, 1);
9732 break;
9733 case 5:
9734 gen_helper_0e1i(mtthi, t0, 1);
9735 break;
9736 case 6:
9737 gen_helper_0e1i(mttacx, t0, 1);
9738 break;
9739 case 8:
9740 gen_helper_0e1i(mttlo, t0, 2);
9741 break;
9742 case 9:
9743 gen_helper_0e1i(mtthi, t0, 2);
9744 break;
9745 case 10:
9746 gen_helper_0e1i(mttacx, t0, 2);
9747 break;
9748 case 12:
9749 gen_helper_0e1i(mttlo, t0, 3);
9750 break;
9751 case 13:
9752 gen_helper_0e1i(mtthi, t0, 3);
9753 break;
9754 case 14:
9755 gen_helper_0e1i(mttacx, t0, 3);
9756 break;
9757 case 16:
9758 gen_helper_mttdsp(cpu_env, t0);
9759 break;
9760 default:
9761 goto die;
9763 break;
9764 /* Floating point (COP1). */
9765 case 2:
9766 /* XXX: For now we support only a single FPU context. */
9767 if (h == 0) {
9768 TCGv_i32 fp0 = tcg_temp_new_i32();
9770 tcg_gen_trunc_tl_i32(fp0, t0);
9771 gen_store_fpr32(ctx, fp0, rd);
9772 tcg_temp_free_i32(fp0);
9773 } else {
9774 TCGv_i32 fp0 = tcg_temp_new_i32();
9776 tcg_gen_trunc_tl_i32(fp0, t0);
9777 gen_store_fpr32h(ctx, fp0, rd);
9778 tcg_temp_free_i32(fp0);
9780 break;
9781 case 3:
9782 /* XXX: For now we support only a single FPU context. */
9784 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9786 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9787 tcg_temp_free_i32(fs_tmp);
9789 /* Stop translation as we may have changed hflags */
9790 ctx->base.is_jmp = DISAS_STOP;
9791 break;
9792 /* COP2: Not implemented. */
9793 case 4:
9794 case 5:
9795 /* fall through */
9796 default:
9797 goto die;
9799 trace_mips_translate_tr("mttr", rd, u, sel, h);
9800 tcg_temp_free(t0);
9801 return;
9803 die:
9804 tcg_temp_free(t0);
9805 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9806 generate_exception_end(ctx, EXCP_RI);
9809 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9811 const char *opn = "ldst";
9813 check_cp0_enabled(ctx);
9814 switch (opc) {
9815 case OPC_MFC0:
9816 if (rt == 0) {
9817 /* Treat as NOP. */
9818 return;
9820 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9821 opn = "mfc0";
9822 break;
9823 case OPC_MTC0:
9825 TCGv t0 = tcg_temp_new();
9827 gen_load_gpr(t0, rt);
9828 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9829 tcg_temp_free(t0);
9831 opn = "mtc0";
9832 break;
9833 #if defined(TARGET_MIPS64)
9834 case OPC_DMFC0:
9835 check_insn(ctx, ISA_MIPS3);
9836 if (rt == 0) {
9837 /* Treat as NOP. */
9838 return;
9840 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9841 opn = "dmfc0";
9842 break;
9843 case OPC_DMTC0:
9844 check_insn(ctx, ISA_MIPS3);
9846 TCGv t0 = tcg_temp_new();
9848 gen_load_gpr(t0, rt);
9849 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9850 tcg_temp_free(t0);
9852 opn = "dmtc0";
9853 break;
9854 #endif
9855 case OPC_MFHC0:
9856 check_mvh(ctx);
9857 if (rt == 0) {
9858 /* Treat as NOP. */
9859 return;
9861 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9862 opn = "mfhc0";
9863 break;
9864 case OPC_MTHC0:
9865 check_mvh(ctx);
9867 TCGv t0 = tcg_temp_new();
9868 gen_load_gpr(t0, rt);
9869 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9870 tcg_temp_free(t0);
9872 opn = "mthc0";
9873 break;
9874 case OPC_MFTR:
9875 check_cp0_enabled(ctx);
9876 if (rd == 0) {
9877 /* Treat as NOP. */
9878 return;
9880 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9881 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9882 opn = "mftr";
9883 break;
9884 case OPC_MTTR:
9885 check_cp0_enabled(ctx);
9886 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9887 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9888 opn = "mttr";
9889 break;
9890 case OPC_TLBWI:
9891 opn = "tlbwi";
9892 if (!env->tlb->helper_tlbwi)
9893 goto die;
9894 gen_helper_tlbwi(cpu_env);
9895 break;
9896 case OPC_TLBINV:
9897 opn = "tlbinv";
9898 if (ctx->ie >= 2) {
9899 if (!env->tlb->helper_tlbinv) {
9900 goto die;
9902 gen_helper_tlbinv(cpu_env);
9903 } /* treat as nop if TLBINV not supported */
9904 break;
9905 case OPC_TLBINVF:
9906 opn = "tlbinvf";
9907 if (ctx->ie >= 2) {
9908 if (!env->tlb->helper_tlbinvf) {
9909 goto die;
9911 gen_helper_tlbinvf(cpu_env);
9912 } /* treat as nop if TLBINV not supported */
9913 break;
9914 case OPC_TLBWR:
9915 opn = "tlbwr";
9916 if (!env->tlb->helper_tlbwr)
9917 goto die;
9918 gen_helper_tlbwr(cpu_env);
9919 break;
9920 case OPC_TLBP:
9921 opn = "tlbp";
9922 if (!env->tlb->helper_tlbp)
9923 goto die;
9924 gen_helper_tlbp(cpu_env);
9925 break;
9926 case OPC_TLBR:
9927 opn = "tlbr";
9928 if (!env->tlb->helper_tlbr)
9929 goto die;
9930 gen_helper_tlbr(cpu_env);
9931 break;
9932 case OPC_ERET: /* OPC_ERETNC */
9933 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9934 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9935 goto die;
9936 } else {
9937 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9938 if (ctx->opcode & (1 << bit_shift)) {
9939 /* OPC_ERETNC */
9940 opn = "eretnc";
9941 check_insn(ctx, ISA_MIPS32R5);
9942 gen_helper_eretnc(cpu_env);
9943 } else {
9944 /* OPC_ERET */
9945 opn = "eret";
9946 check_insn(ctx, ISA_MIPS2);
9947 gen_helper_eret(cpu_env);
9949 ctx->base.is_jmp = DISAS_EXIT;
9951 break;
9952 case OPC_DERET:
9953 opn = "deret";
9954 check_insn(ctx, ISA_MIPS32);
9955 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9956 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9957 goto die;
9959 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9960 MIPS_INVAL(opn);
9961 generate_exception_end(ctx, EXCP_RI);
9962 } else {
9963 gen_helper_deret(cpu_env);
9964 ctx->base.is_jmp = DISAS_EXIT;
9966 break;
9967 case OPC_WAIT:
9968 opn = "wait";
9969 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9970 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9971 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9972 goto die;
9974 /* If we get an exception, we want to restart at next instruction */
9975 ctx->base.pc_next += 4;
9976 save_cpu_state(ctx, 1);
9977 ctx->base.pc_next -= 4;
9978 gen_helper_wait(cpu_env);
9979 ctx->base.is_jmp = DISAS_NORETURN;
9980 break;
9981 default:
9982 die:
9983 MIPS_INVAL(opn);
9984 generate_exception_end(ctx, EXCP_RI);
9985 return;
9987 (void)opn; /* avoid a compiler warning */
9989 #endif /* !CONFIG_USER_ONLY */
9991 /* CP1 Branches (before delay slot) */
9992 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9993 int32_t cc, int32_t offset)
9995 target_ulong btarget;
9996 TCGv_i32 t0 = tcg_temp_new_i32();
9998 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9999 generate_exception_end(ctx, EXCP_RI);
10000 goto out;
10003 if (cc != 0)
10004 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10006 btarget = ctx->base.pc_next + 4 + offset;
10008 switch (op) {
10009 case OPC_BC1F:
10010 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10011 tcg_gen_not_i32(t0, t0);
10012 tcg_gen_andi_i32(t0, t0, 1);
10013 tcg_gen_extu_i32_tl(bcond, t0);
10014 goto not_likely;
10015 case OPC_BC1FL:
10016 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10017 tcg_gen_not_i32(t0, t0);
10018 tcg_gen_andi_i32(t0, t0, 1);
10019 tcg_gen_extu_i32_tl(bcond, t0);
10020 goto likely;
10021 case OPC_BC1T:
10022 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10023 tcg_gen_andi_i32(t0, t0, 1);
10024 tcg_gen_extu_i32_tl(bcond, t0);
10025 goto not_likely;
10026 case OPC_BC1TL:
10027 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10028 tcg_gen_andi_i32(t0, t0, 1);
10029 tcg_gen_extu_i32_tl(bcond, t0);
10030 likely:
10031 ctx->hflags |= MIPS_HFLAG_BL;
10032 break;
10033 case OPC_BC1FANY2:
10035 TCGv_i32 t1 = tcg_temp_new_i32();
10036 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10037 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10038 tcg_gen_nand_i32(t0, t0, t1);
10039 tcg_temp_free_i32(t1);
10040 tcg_gen_andi_i32(t0, t0, 1);
10041 tcg_gen_extu_i32_tl(bcond, t0);
10043 goto not_likely;
10044 case OPC_BC1TANY2:
10046 TCGv_i32 t1 = tcg_temp_new_i32();
10047 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10048 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10049 tcg_gen_or_i32(t0, t0, t1);
10050 tcg_temp_free_i32(t1);
10051 tcg_gen_andi_i32(t0, t0, 1);
10052 tcg_gen_extu_i32_tl(bcond, t0);
10054 goto not_likely;
10055 case OPC_BC1FANY4:
10057 TCGv_i32 t1 = tcg_temp_new_i32();
10058 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10059 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10060 tcg_gen_and_i32(t0, t0, t1);
10061 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10062 tcg_gen_and_i32(t0, t0, t1);
10063 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10064 tcg_gen_nand_i32(t0, t0, t1);
10065 tcg_temp_free_i32(t1);
10066 tcg_gen_andi_i32(t0, t0, 1);
10067 tcg_gen_extu_i32_tl(bcond, t0);
10069 goto not_likely;
10070 case OPC_BC1TANY4:
10072 TCGv_i32 t1 = tcg_temp_new_i32();
10073 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10074 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10075 tcg_gen_or_i32(t0, t0, t1);
10076 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10077 tcg_gen_or_i32(t0, t0, t1);
10078 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10079 tcg_gen_or_i32(t0, t0, t1);
10080 tcg_temp_free_i32(t1);
10081 tcg_gen_andi_i32(t0, t0, 1);
10082 tcg_gen_extu_i32_tl(bcond, t0);
10084 not_likely:
10085 ctx->hflags |= MIPS_HFLAG_BC;
10086 break;
10087 default:
10088 MIPS_INVAL("cp1 cond branch");
10089 generate_exception_end(ctx, EXCP_RI);
10090 goto out;
10092 ctx->btarget = btarget;
10093 ctx->hflags |= MIPS_HFLAG_BDS32;
10094 out:
10095 tcg_temp_free_i32(t0);
10098 /* R6 CP1 Branches */
10099 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10100 int32_t ft, int32_t offset,
10101 int delayslot_size)
10103 target_ulong btarget;
10104 TCGv_i64 t0 = tcg_temp_new_i64();
10106 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10107 #ifdef MIPS_DEBUG_DISAS
10108 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10109 "\n", ctx->base.pc_next);
10110 #endif
10111 generate_exception_end(ctx, EXCP_RI);
10112 goto out;
10115 gen_load_fpr64(ctx, t0, ft);
10116 tcg_gen_andi_i64(t0, t0, 1);
10118 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10120 switch (op) {
10121 case OPC_BC1EQZ:
10122 tcg_gen_xori_i64(t0, t0, 1);
10123 ctx->hflags |= MIPS_HFLAG_BC;
10124 break;
10125 case OPC_BC1NEZ:
10126 /* t0 already set */
10127 ctx->hflags |= MIPS_HFLAG_BC;
10128 break;
10129 default:
10130 MIPS_INVAL("cp1 cond branch");
10131 generate_exception_end(ctx, EXCP_RI);
10132 goto out;
10135 tcg_gen_trunc_i64_tl(bcond, t0);
10137 ctx->btarget = btarget;
10139 switch (delayslot_size) {
10140 case 2:
10141 ctx->hflags |= MIPS_HFLAG_BDS16;
10142 break;
10143 case 4:
10144 ctx->hflags |= MIPS_HFLAG_BDS32;
10145 break;
10148 out:
10149 tcg_temp_free_i64(t0);
10152 /* Coprocessor 1 (FPU) */
10154 #define FOP(func, fmt) (((fmt) << 21) | (func))
10156 enum fopcode {
10157 OPC_ADD_S = FOP(0, FMT_S),
10158 OPC_SUB_S = FOP(1, FMT_S),
10159 OPC_MUL_S = FOP(2, FMT_S),
10160 OPC_DIV_S = FOP(3, FMT_S),
10161 OPC_SQRT_S = FOP(4, FMT_S),
10162 OPC_ABS_S = FOP(5, FMT_S),
10163 OPC_MOV_S = FOP(6, FMT_S),
10164 OPC_NEG_S = FOP(7, FMT_S),
10165 OPC_ROUND_L_S = FOP(8, FMT_S),
10166 OPC_TRUNC_L_S = FOP(9, FMT_S),
10167 OPC_CEIL_L_S = FOP(10, FMT_S),
10168 OPC_FLOOR_L_S = FOP(11, FMT_S),
10169 OPC_ROUND_W_S = FOP(12, FMT_S),
10170 OPC_TRUNC_W_S = FOP(13, FMT_S),
10171 OPC_CEIL_W_S = FOP(14, FMT_S),
10172 OPC_FLOOR_W_S = FOP(15, FMT_S),
10173 OPC_SEL_S = FOP(16, FMT_S),
10174 OPC_MOVCF_S = FOP(17, FMT_S),
10175 OPC_MOVZ_S = FOP(18, FMT_S),
10176 OPC_MOVN_S = FOP(19, FMT_S),
10177 OPC_SELEQZ_S = FOP(20, FMT_S),
10178 OPC_RECIP_S = FOP(21, FMT_S),
10179 OPC_RSQRT_S = FOP(22, FMT_S),
10180 OPC_SELNEZ_S = FOP(23, FMT_S),
10181 OPC_MADDF_S = FOP(24, FMT_S),
10182 OPC_MSUBF_S = FOP(25, FMT_S),
10183 OPC_RINT_S = FOP(26, FMT_S),
10184 OPC_CLASS_S = FOP(27, FMT_S),
10185 OPC_MIN_S = FOP(28, FMT_S),
10186 OPC_RECIP2_S = FOP(28, FMT_S),
10187 OPC_MINA_S = FOP(29, FMT_S),
10188 OPC_RECIP1_S = FOP(29, FMT_S),
10189 OPC_MAX_S = FOP(30, FMT_S),
10190 OPC_RSQRT1_S = FOP(30, FMT_S),
10191 OPC_MAXA_S = FOP(31, FMT_S),
10192 OPC_RSQRT2_S = FOP(31, FMT_S),
10193 OPC_CVT_D_S = FOP(33, FMT_S),
10194 OPC_CVT_W_S = FOP(36, FMT_S),
10195 OPC_CVT_L_S = FOP(37, FMT_S),
10196 OPC_CVT_PS_S = FOP(38, FMT_S),
10197 OPC_CMP_F_S = FOP (48, FMT_S),
10198 OPC_CMP_UN_S = FOP (49, FMT_S),
10199 OPC_CMP_EQ_S = FOP (50, FMT_S),
10200 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10201 OPC_CMP_OLT_S = FOP (52, FMT_S),
10202 OPC_CMP_ULT_S = FOP (53, FMT_S),
10203 OPC_CMP_OLE_S = FOP (54, FMT_S),
10204 OPC_CMP_ULE_S = FOP (55, FMT_S),
10205 OPC_CMP_SF_S = FOP (56, FMT_S),
10206 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10207 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10208 OPC_CMP_NGL_S = FOP (59, FMT_S),
10209 OPC_CMP_LT_S = FOP (60, FMT_S),
10210 OPC_CMP_NGE_S = FOP (61, FMT_S),
10211 OPC_CMP_LE_S = FOP (62, FMT_S),
10212 OPC_CMP_NGT_S = FOP (63, FMT_S),
10214 OPC_ADD_D = FOP(0, FMT_D),
10215 OPC_SUB_D = FOP(1, FMT_D),
10216 OPC_MUL_D = FOP(2, FMT_D),
10217 OPC_DIV_D = FOP(3, FMT_D),
10218 OPC_SQRT_D = FOP(4, FMT_D),
10219 OPC_ABS_D = FOP(5, FMT_D),
10220 OPC_MOV_D = FOP(6, FMT_D),
10221 OPC_NEG_D = FOP(7, FMT_D),
10222 OPC_ROUND_L_D = FOP(8, FMT_D),
10223 OPC_TRUNC_L_D = FOP(9, FMT_D),
10224 OPC_CEIL_L_D = FOP(10, FMT_D),
10225 OPC_FLOOR_L_D = FOP(11, FMT_D),
10226 OPC_ROUND_W_D = FOP(12, FMT_D),
10227 OPC_TRUNC_W_D = FOP(13, FMT_D),
10228 OPC_CEIL_W_D = FOP(14, FMT_D),
10229 OPC_FLOOR_W_D = FOP(15, FMT_D),
10230 OPC_SEL_D = FOP(16, FMT_D),
10231 OPC_MOVCF_D = FOP(17, FMT_D),
10232 OPC_MOVZ_D = FOP(18, FMT_D),
10233 OPC_MOVN_D = FOP(19, FMT_D),
10234 OPC_SELEQZ_D = FOP(20, FMT_D),
10235 OPC_RECIP_D = FOP(21, FMT_D),
10236 OPC_RSQRT_D = FOP(22, FMT_D),
10237 OPC_SELNEZ_D = FOP(23, FMT_D),
10238 OPC_MADDF_D = FOP(24, FMT_D),
10239 OPC_MSUBF_D = FOP(25, FMT_D),
10240 OPC_RINT_D = FOP(26, FMT_D),
10241 OPC_CLASS_D = FOP(27, FMT_D),
10242 OPC_MIN_D = FOP(28, FMT_D),
10243 OPC_RECIP2_D = FOP(28, FMT_D),
10244 OPC_MINA_D = FOP(29, FMT_D),
10245 OPC_RECIP1_D = FOP(29, FMT_D),
10246 OPC_MAX_D = FOP(30, FMT_D),
10247 OPC_RSQRT1_D = FOP(30, FMT_D),
10248 OPC_MAXA_D = FOP(31, FMT_D),
10249 OPC_RSQRT2_D = FOP(31, FMT_D),
10250 OPC_CVT_S_D = FOP(32, FMT_D),
10251 OPC_CVT_W_D = FOP(36, FMT_D),
10252 OPC_CVT_L_D = FOP(37, FMT_D),
10253 OPC_CMP_F_D = FOP (48, FMT_D),
10254 OPC_CMP_UN_D = FOP (49, FMT_D),
10255 OPC_CMP_EQ_D = FOP (50, FMT_D),
10256 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10257 OPC_CMP_OLT_D = FOP (52, FMT_D),
10258 OPC_CMP_ULT_D = FOP (53, FMT_D),
10259 OPC_CMP_OLE_D = FOP (54, FMT_D),
10260 OPC_CMP_ULE_D = FOP (55, FMT_D),
10261 OPC_CMP_SF_D = FOP (56, FMT_D),
10262 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10263 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10264 OPC_CMP_NGL_D = FOP (59, FMT_D),
10265 OPC_CMP_LT_D = FOP (60, FMT_D),
10266 OPC_CMP_NGE_D = FOP (61, FMT_D),
10267 OPC_CMP_LE_D = FOP (62, FMT_D),
10268 OPC_CMP_NGT_D = FOP (63, FMT_D),
10270 OPC_CVT_S_W = FOP(32, FMT_W),
10271 OPC_CVT_D_W = FOP(33, FMT_W),
10272 OPC_CVT_S_L = FOP(32, FMT_L),
10273 OPC_CVT_D_L = FOP(33, FMT_L),
10274 OPC_CVT_PS_PW = FOP(38, FMT_W),
10276 OPC_ADD_PS = FOP(0, FMT_PS),
10277 OPC_SUB_PS = FOP(1, FMT_PS),
10278 OPC_MUL_PS = FOP(2, FMT_PS),
10279 OPC_DIV_PS = FOP(3, FMT_PS),
10280 OPC_ABS_PS = FOP(5, FMT_PS),
10281 OPC_MOV_PS = FOP(6, FMT_PS),
10282 OPC_NEG_PS = FOP(7, FMT_PS),
10283 OPC_MOVCF_PS = FOP(17, FMT_PS),
10284 OPC_MOVZ_PS = FOP(18, FMT_PS),
10285 OPC_MOVN_PS = FOP(19, FMT_PS),
10286 OPC_ADDR_PS = FOP(24, FMT_PS),
10287 OPC_MULR_PS = FOP(26, FMT_PS),
10288 OPC_RECIP2_PS = FOP(28, FMT_PS),
10289 OPC_RECIP1_PS = FOP(29, FMT_PS),
10290 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10291 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10293 OPC_CVT_S_PU = FOP(32, FMT_PS),
10294 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10295 OPC_CVT_S_PL = FOP(40, FMT_PS),
10296 OPC_PLL_PS = FOP(44, FMT_PS),
10297 OPC_PLU_PS = FOP(45, FMT_PS),
10298 OPC_PUL_PS = FOP(46, FMT_PS),
10299 OPC_PUU_PS = FOP(47, FMT_PS),
10300 OPC_CMP_F_PS = FOP (48, FMT_PS),
10301 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10302 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10303 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10304 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10305 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10306 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10307 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10308 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10309 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10310 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10311 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10312 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10313 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10314 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10315 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10318 enum r6_f_cmp_op {
10319 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10320 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10321 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10322 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10323 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10324 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10325 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10326 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10327 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10328 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10329 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10330 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10331 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10332 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10333 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10334 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10335 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10336 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10337 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10338 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10339 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10340 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10342 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10343 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10344 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10345 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10346 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10347 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10348 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10349 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10350 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10351 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10352 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10353 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10354 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10355 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10356 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10357 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10358 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10359 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10360 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10361 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10362 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10363 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10365 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10367 TCGv t0 = tcg_temp_new();
10369 switch (opc) {
10370 case OPC_MFC1:
10372 TCGv_i32 fp0 = tcg_temp_new_i32();
10374 gen_load_fpr32(ctx, fp0, fs);
10375 tcg_gen_ext_i32_tl(t0, fp0);
10376 tcg_temp_free_i32(fp0);
10378 gen_store_gpr(t0, rt);
10379 break;
10380 case OPC_MTC1:
10381 gen_load_gpr(t0, rt);
10383 TCGv_i32 fp0 = tcg_temp_new_i32();
10385 tcg_gen_trunc_tl_i32(fp0, t0);
10386 gen_store_fpr32(ctx, fp0, fs);
10387 tcg_temp_free_i32(fp0);
10389 break;
10390 case OPC_CFC1:
10391 gen_helper_1e0i(cfc1, t0, fs);
10392 gen_store_gpr(t0, rt);
10393 break;
10394 case OPC_CTC1:
10395 gen_load_gpr(t0, rt);
10396 save_cpu_state(ctx, 0);
10398 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10400 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10401 tcg_temp_free_i32(fs_tmp);
10403 /* Stop translation as we may have changed hflags */
10404 ctx->base.is_jmp = DISAS_STOP;
10405 break;
10406 #if defined(TARGET_MIPS64)
10407 case OPC_DMFC1:
10408 gen_load_fpr64(ctx, t0, fs);
10409 gen_store_gpr(t0, rt);
10410 break;
10411 case OPC_DMTC1:
10412 gen_load_gpr(t0, rt);
10413 gen_store_fpr64(ctx, t0, fs);
10414 break;
10415 #endif
10416 case OPC_MFHC1:
10418 TCGv_i32 fp0 = tcg_temp_new_i32();
10420 gen_load_fpr32h(ctx, fp0, fs);
10421 tcg_gen_ext_i32_tl(t0, fp0);
10422 tcg_temp_free_i32(fp0);
10424 gen_store_gpr(t0, rt);
10425 break;
10426 case OPC_MTHC1:
10427 gen_load_gpr(t0, rt);
10429 TCGv_i32 fp0 = tcg_temp_new_i32();
10431 tcg_gen_trunc_tl_i32(fp0, t0);
10432 gen_store_fpr32h(ctx, fp0, fs);
10433 tcg_temp_free_i32(fp0);
10435 break;
10436 default:
10437 MIPS_INVAL("cp1 move");
10438 generate_exception_end(ctx, EXCP_RI);
10439 goto out;
10442 out:
10443 tcg_temp_free(t0);
10446 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10448 TCGLabel *l1;
10449 TCGCond cond;
10450 TCGv_i32 t0;
10452 if (rd == 0) {
10453 /* Treat as NOP. */
10454 return;
10457 if (tf)
10458 cond = TCG_COND_EQ;
10459 else
10460 cond = TCG_COND_NE;
10462 l1 = gen_new_label();
10463 t0 = tcg_temp_new_i32();
10464 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10465 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10466 tcg_temp_free_i32(t0);
10467 if (rs == 0) {
10468 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10469 } else {
10470 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10472 gen_set_label(l1);
10475 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10476 int tf)
10478 int cond;
10479 TCGv_i32 t0 = tcg_temp_new_i32();
10480 TCGLabel *l1 = gen_new_label();
10482 if (tf)
10483 cond = TCG_COND_EQ;
10484 else
10485 cond = TCG_COND_NE;
10487 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10488 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10489 gen_load_fpr32(ctx, t0, fs);
10490 gen_store_fpr32(ctx, t0, fd);
10491 gen_set_label(l1);
10492 tcg_temp_free_i32(t0);
10495 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10497 int cond;
10498 TCGv_i32 t0 = tcg_temp_new_i32();
10499 TCGv_i64 fp0;
10500 TCGLabel *l1 = gen_new_label();
10502 if (tf)
10503 cond = TCG_COND_EQ;
10504 else
10505 cond = TCG_COND_NE;
10507 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10508 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10509 tcg_temp_free_i32(t0);
10510 fp0 = tcg_temp_new_i64();
10511 gen_load_fpr64(ctx, fp0, fs);
10512 gen_store_fpr64(ctx, fp0, fd);
10513 tcg_temp_free_i64(fp0);
10514 gen_set_label(l1);
10517 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10518 int cc, int tf)
10520 int cond;
10521 TCGv_i32 t0 = tcg_temp_new_i32();
10522 TCGLabel *l1 = gen_new_label();
10523 TCGLabel *l2 = gen_new_label();
10525 if (tf)
10526 cond = TCG_COND_EQ;
10527 else
10528 cond = TCG_COND_NE;
10530 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10531 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10532 gen_load_fpr32(ctx, t0, fs);
10533 gen_store_fpr32(ctx, t0, fd);
10534 gen_set_label(l1);
10536 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10537 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10538 gen_load_fpr32h(ctx, t0, fs);
10539 gen_store_fpr32h(ctx, t0, fd);
10540 tcg_temp_free_i32(t0);
10541 gen_set_label(l2);
10544 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10545 int fs)
10547 TCGv_i32 t1 = tcg_const_i32(0);
10548 TCGv_i32 fp0 = tcg_temp_new_i32();
10549 TCGv_i32 fp1 = tcg_temp_new_i32();
10550 TCGv_i32 fp2 = tcg_temp_new_i32();
10551 gen_load_fpr32(ctx, fp0, fd);
10552 gen_load_fpr32(ctx, fp1, ft);
10553 gen_load_fpr32(ctx, fp2, fs);
10555 switch (op1) {
10556 case OPC_SEL_S:
10557 tcg_gen_andi_i32(fp0, fp0, 1);
10558 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10559 break;
10560 case OPC_SELEQZ_S:
10561 tcg_gen_andi_i32(fp1, fp1, 1);
10562 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10563 break;
10564 case OPC_SELNEZ_S:
10565 tcg_gen_andi_i32(fp1, fp1, 1);
10566 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10567 break;
10568 default:
10569 MIPS_INVAL("gen_sel_s");
10570 generate_exception_end(ctx, EXCP_RI);
10571 break;
10574 gen_store_fpr32(ctx, fp0, fd);
10575 tcg_temp_free_i32(fp2);
10576 tcg_temp_free_i32(fp1);
10577 tcg_temp_free_i32(fp0);
10578 tcg_temp_free_i32(t1);
10581 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10582 int fs)
10584 TCGv_i64 t1 = tcg_const_i64(0);
10585 TCGv_i64 fp0 = tcg_temp_new_i64();
10586 TCGv_i64 fp1 = tcg_temp_new_i64();
10587 TCGv_i64 fp2 = tcg_temp_new_i64();
10588 gen_load_fpr64(ctx, fp0, fd);
10589 gen_load_fpr64(ctx, fp1, ft);
10590 gen_load_fpr64(ctx, fp2, fs);
10592 switch (op1) {
10593 case OPC_SEL_D:
10594 tcg_gen_andi_i64(fp0, fp0, 1);
10595 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10596 break;
10597 case OPC_SELEQZ_D:
10598 tcg_gen_andi_i64(fp1, fp1, 1);
10599 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10600 break;
10601 case OPC_SELNEZ_D:
10602 tcg_gen_andi_i64(fp1, fp1, 1);
10603 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10604 break;
10605 default:
10606 MIPS_INVAL("gen_sel_d");
10607 generate_exception_end(ctx, EXCP_RI);
10608 break;
10611 gen_store_fpr64(ctx, fp0, fd);
10612 tcg_temp_free_i64(fp2);
10613 tcg_temp_free_i64(fp1);
10614 tcg_temp_free_i64(fp0);
10615 tcg_temp_free_i64(t1);
10618 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10619 int ft, int fs, int fd, int cc)
10621 uint32_t func = ctx->opcode & 0x3f;
10622 switch (op1) {
10623 case OPC_ADD_S:
10625 TCGv_i32 fp0 = tcg_temp_new_i32();
10626 TCGv_i32 fp1 = tcg_temp_new_i32();
10628 gen_load_fpr32(ctx, fp0, fs);
10629 gen_load_fpr32(ctx, fp1, ft);
10630 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10631 tcg_temp_free_i32(fp1);
10632 gen_store_fpr32(ctx, fp0, fd);
10633 tcg_temp_free_i32(fp0);
10635 break;
10636 case OPC_SUB_S:
10638 TCGv_i32 fp0 = tcg_temp_new_i32();
10639 TCGv_i32 fp1 = tcg_temp_new_i32();
10641 gen_load_fpr32(ctx, fp0, fs);
10642 gen_load_fpr32(ctx, fp1, ft);
10643 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10644 tcg_temp_free_i32(fp1);
10645 gen_store_fpr32(ctx, fp0, fd);
10646 tcg_temp_free_i32(fp0);
10648 break;
10649 case OPC_MUL_S:
10651 TCGv_i32 fp0 = tcg_temp_new_i32();
10652 TCGv_i32 fp1 = tcg_temp_new_i32();
10654 gen_load_fpr32(ctx, fp0, fs);
10655 gen_load_fpr32(ctx, fp1, ft);
10656 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10657 tcg_temp_free_i32(fp1);
10658 gen_store_fpr32(ctx, fp0, fd);
10659 tcg_temp_free_i32(fp0);
10661 break;
10662 case OPC_DIV_S:
10664 TCGv_i32 fp0 = tcg_temp_new_i32();
10665 TCGv_i32 fp1 = tcg_temp_new_i32();
10667 gen_load_fpr32(ctx, fp0, fs);
10668 gen_load_fpr32(ctx, fp1, ft);
10669 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10670 tcg_temp_free_i32(fp1);
10671 gen_store_fpr32(ctx, fp0, fd);
10672 tcg_temp_free_i32(fp0);
10674 break;
10675 case OPC_SQRT_S:
10677 TCGv_i32 fp0 = tcg_temp_new_i32();
10679 gen_load_fpr32(ctx, fp0, fs);
10680 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10681 gen_store_fpr32(ctx, fp0, fd);
10682 tcg_temp_free_i32(fp0);
10684 break;
10685 case OPC_ABS_S:
10687 TCGv_i32 fp0 = tcg_temp_new_i32();
10689 gen_load_fpr32(ctx, fp0, fs);
10690 if (ctx->abs2008) {
10691 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10692 } else {
10693 gen_helper_float_abs_s(fp0, fp0);
10695 gen_store_fpr32(ctx, fp0, fd);
10696 tcg_temp_free_i32(fp0);
10698 break;
10699 case OPC_MOV_S:
10701 TCGv_i32 fp0 = tcg_temp_new_i32();
10703 gen_load_fpr32(ctx, fp0, fs);
10704 gen_store_fpr32(ctx, fp0, fd);
10705 tcg_temp_free_i32(fp0);
10707 break;
10708 case OPC_NEG_S:
10710 TCGv_i32 fp0 = tcg_temp_new_i32();
10712 gen_load_fpr32(ctx, fp0, fs);
10713 if (ctx->abs2008) {
10714 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10715 } else {
10716 gen_helper_float_chs_s(fp0, fp0);
10718 gen_store_fpr32(ctx, fp0, fd);
10719 tcg_temp_free_i32(fp0);
10721 break;
10722 case OPC_ROUND_L_S:
10723 check_cp1_64bitmode(ctx);
10725 TCGv_i32 fp32 = tcg_temp_new_i32();
10726 TCGv_i64 fp64 = tcg_temp_new_i64();
10728 gen_load_fpr32(ctx, fp32, fs);
10729 if (ctx->nan2008) {
10730 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10731 } else {
10732 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10734 tcg_temp_free_i32(fp32);
10735 gen_store_fpr64(ctx, fp64, fd);
10736 tcg_temp_free_i64(fp64);
10738 break;
10739 case OPC_TRUNC_L_S:
10740 check_cp1_64bitmode(ctx);
10742 TCGv_i32 fp32 = tcg_temp_new_i32();
10743 TCGv_i64 fp64 = tcg_temp_new_i64();
10745 gen_load_fpr32(ctx, fp32, fs);
10746 if (ctx->nan2008) {
10747 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10748 } else {
10749 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10751 tcg_temp_free_i32(fp32);
10752 gen_store_fpr64(ctx, fp64, fd);
10753 tcg_temp_free_i64(fp64);
10755 break;
10756 case OPC_CEIL_L_S:
10757 check_cp1_64bitmode(ctx);
10759 TCGv_i32 fp32 = tcg_temp_new_i32();
10760 TCGv_i64 fp64 = tcg_temp_new_i64();
10762 gen_load_fpr32(ctx, fp32, fs);
10763 if (ctx->nan2008) {
10764 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10765 } else {
10766 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10768 tcg_temp_free_i32(fp32);
10769 gen_store_fpr64(ctx, fp64, fd);
10770 tcg_temp_free_i64(fp64);
10772 break;
10773 case OPC_FLOOR_L_S:
10774 check_cp1_64bitmode(ctx);
10776 TCGv_i32 fp32 = tcg_temp_new_i32();
10777 TCGv_i64 fp64 = tcg_temp_new_i64();
10779 gen_load_fpr32(ctx, fp32, fs);
10780 if (ctx->nan2008) {
10781 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10782 } else {
10783 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10785 tcg_temp_free_i32(fp32);
10786 gen_store_fpr64(ctx, fp64, fd);
10787 tcg_temp_free_i64(fp64);
10789 break;
10790 case OPC_ROUND_W_S:
10792 TCGv_i32 fp0 = tcg_temp_new_i32();
10794 gen_load_fpr32(ctx, fp0, fs);
10795 if (ctx->nan2008) {
10796 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10797 } else {
10798 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10800 gen_store_fpr32(ctx, fp0, fd);
10801 tcg_temp_free_i32(fp0);
10803 break;
10804 case OPC_TRUNC_W_S:
10806 TCGv_i32 fp0 = tcg_temp_new_i32();
10808 gen_load_fpr32(ctx, fp0, fs);
10809 if (ctx->nan2008) {
10810 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10811 } else {
10812 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10814 gen_store_fpr32(ctx, fp0, fd);
10815 tcg_temp_free_i32(fp0);
10817 break;
10818 case OPC_CEIL_W_S:
10820 TCGv_i32 fp0 = tcg_temp_new_i32();
10822 gen_load_fpr32(ctx, fp0, fs);
10823 if (ctx->nan2008) {
10824 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10825 } else {
10826 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10828 gen_store_fpr32(ctx, fp0, fd);
10829 tcg_temp_free_i32(fp0);
10831 break;
10832 case OPC_FLOOR_W_S:
10834 TCGv_i32 fp0 = tcg_temp_new_i32();
10836 gen_load_fpr32(ctx, fp0, fs);
10837 if (ctx->nan2008) {
10838 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10839 } else {
10840 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10842 gen_store_fpr32(ctx, fp0, fd);
10843 tcg_temp_free_i32(fp0);
10845 break;
10846 case OPC_SEL_S:
10847 check_insn(ctx, ISA_MIPS32R6);
10848 gen_sel_s(ctx, op1, fd, ft, fs);
10849 break;
10850 case OPC_SELEQZ_S:
10851 check_insn(ctx, ISA_MIPS32R6);
10852 gen_sel_s(ctx, op1, fd, ft, fs);
10853 break;
10854 case OPC_SELNEZ_S:
10855 check_insn(ctx, ISA_MIPS32R6);
10856 gen_sel_s(ctx, op1, fd, ft, fs);
10857 break;
10858 case OPC_MOVCF_S:
10859 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10860 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10861 break;
10862 case OPC_MOVZ_S:
10863 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10865 TCGLabel *l1 = gen_new_label();
10866 TCGv_i32 fp0;
10868 if (ft != 0) {
10869 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10871 fp0 = tcg_temp_new_i32();
10872 gen_load_fpr32(ctx, fp0, fs);
10873 gen_store_fpr32(ctx, fp0, fd);
10874 tcg_temp_free_i32(fp0);
10875 gen_set_label(l1);
10877 break;
10878 case OPC_MOVN_S:
10879 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10881 TCGLabel *l1 = gen_new_label();
10882 TCGv_i32 fp0;
10884 if (ft != 0) {
10885 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10886 fp0 = tcg_temp_new_i32();
10887 gen_load_fpr32(ctx, fp0, fs);
10888 gen_store_fpr32(ctx, fp0, fd);
10889 tcg_temp_free_i32(fp0);
10890 gen_set_label(l1);
10893 break;
10894 case OPC_RECIP_S:
10896 TCGv_i32 fp0 = tcg_temp_new_i32();
10898 gen_load_fpr32(ctx, fp0, fs);
10899 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10900 gen_store_fpr32(ctx, fp0, fd);
10901 tcg_temp_free_i32(fp0);
10903 break;
10904 case OPC_RSQRT_S:
10906 TCGv_i32 fp0 = tcg_temp_new_i32();
10908 gen_load_fpr32(ctx, fp0, fs);
10909 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10910 gen_store_fpr32(ctx, fp0, fd);
10911 tcg_temp_free_i32(fp0);
10913 break;
10914 case OPC_MADDF_S:
10915 check_insn(ctx, ISA_MIPS32R6);
10917 TCGv_i32 fp0 = tcg_temp_new_i32();
10918 TCGv_i32 fp1 = tcg_temp_new_i32();
10919 TCGv_i32 fp2 = tcg_temp_new_i32();
10920 gen_load_fpr32(ctx, fp0, fs);
10921 gen_load_fpr32(ctx, fp1, ft);
10922 gen_load_fpr32(ctx, fp2, fd);
10923 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10924 gen_store_fpr32(ctx, fp2, fd);
10925 tcg_temp_free_i32(fp2);
10926 tcg_temp_free_i32(fp1);
10927 tcg_temp_free_i32(fp0);
10929 break;
10930 case OPC_MSUBF_S:
10931 check_insn(ctx, ISA_MIPS32R6);
10933 TCGv_i32 fp0 = tcg_temp_new_i32();
10934 TCGv_i32 fp1 = tcg_temp_new_i32();
10935 TCGv_i32 fp2 = tcg_temp_new_i32();
10936 gen_load_fpr32(ctx, fp0, fs);
10937 gen_load_fpr32(ctx, fp1, ft);
10938 gen_load_fpr32(ctx, fp2, fd);
10939 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10940 gen_store_fpr32(ctx, fp2, fd);
10941 tcg_temp_free_i32(fp2);
10942 tcg_temp_free_i32(fp1);
10943 tcg_temp_free_i32(fp0);
10945 break;
10946 case OPC_RINT_S:
10947 check_insn(ctx, ISA_MIPS32R6);
10949 TCGv_i32 fp0 = tcg_temp_new_i32();
10950 gen_load_fpr32(ctx, fp0, fs);
10951 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10952 gen_store_fpr32(ctx, fp0, fd);
10953 tcg_temp_free_i32(fp0);
10955 break;
10956 case OPC_CLASS_S:
10957 check_insn(ctx, ISA_MIPS32R6);
10959 TCGv_i32 fp0 = tcg_temp_new_i32();
10960 gen_load_fpr32(ctx, fp0, fs);
10961 gen_helper_float_class_s(fp0, cpu_env, fp0);
10962 gen_store_fpr32(ctx, fp0, fd);
10963 tcg_temp_free_i32(fp0);
10965 break;
10966 case OPC_MIN_S: /* OPC_RECIP2_S */
10967 if (ctx->insn_flags & ISA_MIPS32R6) {
10968 /* OPC_MIN_S */
10969 TCGv_i32 fp0 = tcg_temp_new_i32();
10970 TCGv_i32 fp1 = tcg_temp_new_i32();
10971 TCGv_i32 fp2 = tcg_temp_new_i32();
10972 gen_load_fpr32(ctx, fp0, fs);
10973 gen_load_fpr32(ctx, fp1, ft);
10974 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10975 gen_store_fpr32(ctx, fp2, fd);
10976 tcg_temp_free_i32(fp2);
10977 tcg_temp_free_i32(fp1);
10978 tcg_temp_free_i32(fp0);
10979 } else {
10980 /* OPC_RECIP2_S */
10981 check_cp1_64bitmode(ctx);
10983 TCGv_i32 fp0 = tcg_temp_new_i32();
10984 TCGv_i32 fp1 = tcg_temp_new_i32();
10986 gen_load_fpr32(ctx, fp0, fs);
10987 gen_load_fpr32(ctx, fp1, ft);
10988 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10989 tcg_temp_free_i32(fp1);
10990 gen_store_fpr32(ctx, fp0, fd);
10991 tcg_temp_free_i32(fp0);
10994 break;
10995 case OPC_MINA_S: /* OPC_RECIP1_S */
10996 if (ctx->insn_flags & ISA_MIPS32R6) {
10997 /* OPC_MINA_S */
10998 TCGv_i32 fp0 = tcg_temp_new_i32();
10999 TCGv_i32 fp1 = tcg_temp_new_i32();
11000 TCGv_i32 fp2 = tcg_temp_new_i32();
11001 gen_load_fpr32(ctx, fp0, fs);
11002 gen_load_fpr32(ctx, fp1, ft);
11003 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11004 gen_store_fpr32(ctx, fp2, fd);
11005 tcg_temp_free_i32(fp2);
11006 tcg_temp_free_i32(fp1);
11007 tcg_temp_free_i32(fp0);
11008 } else {
11009 /* OPC_RECIP1_S */
11010 check_cp1_64bitmode(ctx);
11012 TCGv_i32 fp0 = tcg_temp_new_i32();
11014 gen_load_fpr32(ctx, fp0, fs);
11015 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11016 gen_store_fpr32(ctx, fp0, fd);
11017 tcg_temp_free_i32(fp0);
11020 break;
11021 case OPC_MAX_S: /* OPC_RSQRT1_S */
11022 if (ctx->insn_flags & ISA_MIPS32R6) {
11023 /* OPC_MAX_S */
11024 TCGv_i32 fp0 = tcg_temp_new_i32();
11025 TCGv_i32 fp1 = tcg_temp_new_i32();
11026 gen_load_fpr32(ctx, fp0, fs);
11027 gen_load_fpr32(ctx, fp1, ft);
11028 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11029 gen_store_fpr32(ctx, fp1, fd);
11030 tcg_temp_free_i32(fp1);
11031 tcg_temp_free_i32(fp0);
11032 } else {
11033 /* OPC_RSQRT1_S */
11034 check_cp1_64bitmode(ctx);
11036 TCGv_i32 fp0 = tcg_temp_new_i32();
11038 gen_load_fpr32(ctx, fp0, fs);
11039 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11040 gen_store_fpr32(ctx, fp0, fd);
11041 tcg_temp_free_i32(fp0);
11044 break;
11045 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11046 if (ctx->insn_flags & ISA_MIPS32R6) {
11047 /* OPC_MAXA_S */
11048 TCGv_i32 fp0 = tcg_temp_new_i32();
11049 TCGv_i32 fp1 = tcg_temp_new_i32();
11050 gen_load_fpr32(ctx, fp0, fs);
11051 gen_load_fpr32(ctx, fp1, ft);
11052 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11053 gen_store_fpr32(ctx, fp1, fd);
11054 tcg_temp_free_i32(fp1);
11055 tcg_temp_free_i32(fp0);
11056 } else {
11057 /* OPC_RSQRT2_S */
11058 check_cp1_64bitmode(ctx);
11060 TCGv_i32 fp0 = tcg_temp_new_i32();
11061 TCGv_i32 fp1 = tcg_temp_new_i32();
11063 gen_load_fpr32(ctx, fp0, fs);
11064 gen_load_fpr32(ctx, fp1, ft);
11065 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11066 tcg_temp_free_i32(fp1);
11067 gen_store_fpr32(ctx, fp0, fd);
11068 tcg_temp_free_i32(fp0);
11071 break;
11072 case OPC_CVT_D_S:
11073 check_cp1_registers(ctx, fd);
11075 TCGv_i32 fp32 = tcg_temp_new_i32();
11076 TCGv_i64 fp64 = tcg_temp_new_i64();
11078 gen_load_fpr32(ctx, fp32, fs);
11079 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11080 tcg_temp_free_i32(fp32);
11081 gen_store_fpr64(ctx, fp64, fd);
11082 tcg_temp_free_i64(fp64);
11084 break;
11085 case OPC_CVT_W_S:
11087 TCGv_i32 fp0 = tcg_temp_new_i32();
11089 gen_load_fpr32(ctx, fp0, fs);
11090 if (ctx->nan2008) {
11091 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11092 } else {
11093 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11095 gen_store_fpr32(ctx, fp0, fd);
11096 tcg_temp_free_i32(fp0);
11098 break;
11099 case OPC_CVT_L_S:
11100 check_cp1_64bitmode(ctx);
11102 TCGv_i32 fp32 = tcg_temp_new_i32();
11103 TCGv_i64 fp64 = tcg_temp_new_i64();
11105 gen_load_fpr32(ctx, fp32, fs);
11106 if (ctx->nan2008) {
11107 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11108 } else {
11109 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11111 tcg_temp_free_i32(fp32);
11112 gen_store_fpr64(ctx, fp64, fd);
11113 tcg_temp_free_i64(fp64);
11115 break;
11116 case OPC_CVT_PS_S:
11117 check_ps(ctx);
11119 TCGv_i64 fp64 = tcg_temp_new_i64();
11120 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11121 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11123 gen_load_fpr32(ctx, fp32_0, fs);
11124 gen_load_fpr32(ctx, fp32_1, ft);
11125 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11126 tcg_temp_free_i32(fp32_1);
11127 tcg_temp_free_i32(fp32_0);
11128 gen_store_fpr64(ctx, fp64, fd);
11129 tcg_temp_free_i64(fp64);
11131 break;
11132 case OPC_CMP_F_S:
11133 case OPC_CMP_UN_S:
11134 case OPC_CMP_EQ_S:
11135 case OPC_CMP_UEQ_S:
11136 case OPC_CMP_OLT_S:
11137 case OPC_CMP_ULT_S:
11138 case OPC_CMP_OLE_S:
11139 case OPC_CMP_ULE_S:
11140 case OPC_CMP_SF_S:
11141 case OPC_CMP_NGLE_S:
11142 case OPC_CMP_SEQ_S:
11143 case OPC_CMP_NGL_S:
11144 case OPC_CMP_LT_S:
11145 case OPC_CMP_NGE_S:
11146 case OPC_CMP_LE_S:
11147 case OPC_CMP_NGT_S:
11148 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11149 if (ctx->opcode & (1 << 6)) {
11150 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11151 } else {
11152 gen_cmp_s(ctx, func-48, ft, fs, cc);
11154 break;
11155 case OPC_ADD_D:
11156 check_cp1_registers(ctx, fs | ft | fd);
11158 TCGv_i64 fp0 = tcg_temp_new_i64();
11159 TCGv_i64 fp1 = tcg_temp_new_i64();
11161 gen_load_fpr64(ctx, fp0, fs);
11162 gen_load_fpr64(ctx, fp1, ft);
11163 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11164 tcg_temp_free_i64(fp1);
11165 gen_store_fpr64(ctx, fp0, fd);
11166 tcg_temp_free_i64(fp0);
11168 break;
11169 case OPC_SUB_D:
11170 check_cp1_registers(ctx, fs | ft | fd);
11172 TCGv_i64 fp0 = tcg_temp_new_i64();
11173 TCGv_i64 fp1 = tcg_temp_new_i64();
11175 gen_load_fpr64(ctx, fp0, fs);
11176 gen_load_fpr64(ctx, fp1, ft);
11177 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11178 tcg_temp_free_i64(fp1);
11179 gen_store_fpr64(ctx, fp0, fd);
11180 tcg_temp_free_i64(fp0);
11182 break;
11183 case OPC_MUL_D:
11184 check_cp1_registers(ctx, fs | ft | fd);
11186 TCGv_i64 fp0 = tcg_temp_new_i64();
11187 TCGv_i64 fp1 = tcg_temp_new_i64();
11189 gen_load_fpr64(ctx, fp0, fs);
11190 gen_load_fpr64(ctx, fp1, ft);
11191 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11192 tcg_temp_free_i64(fp1);
11193 gen_store_fpr64(ctx, fp0, fd);
11194 tcg_temp_free_i64(fp0);
11196 break;
11197 case OPC_DIV_D:
11198 check_cp1_registers(ctx, fs | ft | fd);
11200 TCGv_i64 fp0 = tcg_temp_new_i64();
11201 TCGv_i64 fp1 = tcg_temp_new_i64();
11203 gen_load_fpr64(ctx, fp0, fs);
11204 gen_load_fpr64(ctx, fp1, ft);
11205 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11206 tcg_temp_free_i64(fp1);
11207 gen_store_fpr64(ctx, fp0, fd);
11208 tcg_temp_free_i64(fp0);
11210 break;
11211 case OPC_SQRT_D:
11212 check_cp1_registers(ctx, fs | fd);
11214 TCGv_i64 fp0 = tcg_temp_new_i64();
11216 gen_load_fpr64(ctx, fp0, fs);
11217 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11218 gen_store_fpr64(ctx, fp0, fd);
11219 tcg_temp_free_i64(fp0);
11221 break;
11222 case OPC_ABS_D:
11223 check_cp1_registers(ctx, fs | fd);
11225 TCGv_i64 fp0 = tcg_temp_new_i64();
11227 gen_load_fpr64(ctx, fp0, fs);
11228 if (ctx->abs2008) {
11229 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11230 } else {
11231 gen_helper_float_abs_d(fp0, fp0);
11233 gen_store_fpr64(ctx, fp0, fd);
11234 tcg_temp_free_i64(fp0);
11236 break;
11237 case OPC_MOV_D:
11238 check_cp1_registers(ctx, fs | fd);
11240 TCGv_i64 fp0 = tcg_temp_new_i64();
11242 gen_load_fpr64(ctx, fp0, fs);
11243 gen_store_fpr64(ctx, fp0, fd);
11244 tcg_temp_free_i64(fp0);
11246 break;
11247 case OPC_NEG_D:
11248 check_cp1_registers(ctx, fs | fd);
11250 TCGv_i64 fp0 = tcg_temp_new_i64();
11252 gen_load_fpr64(ctx, fp0, fs);
11253 if (ctx->abs2008) {
11254 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11255 } else {
11256 gen_helper_float_chs_d(fp0, fp0);
11258 gen_store_fpr64(ctx, fp0, fd);
11259 tcg_temp_free_i64(fp0);
11261 break;
11262 case OPC_ROUND_L_D:
11263 check_cp1_64bitmode(ctx);
11265 TCGv_i64 fp0 = tcg_temp_new_i64();
11267 gen_load_fpr64(ctx, fp0, fs);
11268 if (ctx->nan2008) {
11269 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11270 } else {
11271 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11273 gen_store_fpr64(ctx, fp0, fd);
11274 tcg_temp_free_i64(fp0);
11276 break;
11277 case OPC_TRUNC_L_D:
11278 check_cp1_64bitmode(ctx);
11280 TCGv_i64 fp0 = tcg_temp_new_i64();
11282 gen_load_fpr64(ctx, fp0, fs);
11283 if (ctx->nan2008) {
11284 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11285 } else {
11286 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11288 gen_store_fpr64(ctx, fp0, fd);
11289 tcg_temp_free_i64(fp0);
11291 break;
11292 case OPC_CEIL_L_D:
11293 check_cp1_64bitmode(ctx);
11295 TCGv_i64 fp0 = tcg_temp_new_i64();
11297 gen_load_fpr64(ctx, fp0, fs);
11298 if (ctx->nan2008) {
11299 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11300 } else {
11301 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11303 gen_store_fpr64(ctx, fp0, fd);
11304 tcg_temp_free_i64(fp0);
11306 break;
11307 case OPC_FLOOR_L_D:
11308 check_cp1_64bitmode(ctx);
11310 TCGv_i64 fp0 = tcg_temp_new_i64();
11312 gen_load_fpr64(ctx, fp0, fs);
11313 if (ctx->nan2008) {
11314 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11315 } else {
11316 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11318 gen_store_fpr64(ctx, fp0, fd);
11319 tcg_temp_free_i64(fp0);
11321 break;
11322 case OPC_ROUND_W_D:
11323 check_cp1_registers(ctx, fs);
11325 TCGv_i32 fp32 = tcg_temp_new_i32();
11326 TCGv_i64 fp64 = tcg_temp_new_i64();
11328 gen_load_fpr64(ctx, fp64, fs);
11329 if (ctx->nan2008) {
11330 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11331 } else {
11332 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11334 tcg_temp_free_i64(fp64);
11335 gen_store_fpr32(ctx, fp32, fd);
11336 tcg_temp_free_i32(fp32);
11338 break;
11339 case OPC_TRUNC_W_D:
11340 check_cp1_registers(ctx, fs);
11342 TCGv_i32 fp32 = tcg_temp_new_i32();
11343 TCGv_i64 fp64 = tcg_temp_new_i64();
11345 gen_load_fpr64(ctx, fp64, fs);
11346 if (ctx->nan2008) {
11347 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11348 } else {
11349 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11351 tcg_temp_free_i64(fp64);
11352 gen_store_fpr32(ctx, fp32, fd);
11353 tcg_temp_free_i32(fp32);
11355 break;
11356 case OPC_CEIL_W_D:
11357 check_cp1_registers(ctx, fs);
11359 TCGv_i32 fp32 = tcg_temp_new_i32();
11360 TCGv_i64 fp64 = tcg_temp_new_i64();
11362 gen_load_fpr64(ctx, fp64, fs);
11363 if (ctx->nan2008) {
11364 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11365 } else {
11366 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11368 tcg_temp_free_i64(fp64);
11369 gen_store_fpr32(ctx, fp32, fd);
11370 tcg_temp_free_i32(fp32);
11372 break;
11373 case OPC_FLOOR_W_D:
11374 check_cp1_registers(ctx, fs);
11376 TCGv_i32 fp32 = tcg_temp_new_i32();
11377 TCGv_i64 fp64 = tcg_temp_new_i64();
11379 gen_load_fpr64(ctx, fp64, fs);
11380 if (ctx->nan2008) {
11381 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11382 } else {
11383 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11385 tcg_temp_free_i64(fp64);
11386 gen_store_fpr32(ctx, fp32, fd);
11387 tcg_temp_free_i32(fp32);
11389 break;
11390 case OPC_SEL_D:
11391 check_insn(ctx, ISA_MIPS32R6);
11392 gen_sel_d(ctx, op1, fd, ft, fs);
11393 break;
11394 case OPC_SELEQZ_D:
11395 check_insn(ctx, ISA_MIPS32R6);
11396 gen_sel_d(ctx, op1, fd, ft, fs);
11397 break;
11398 case OPC_SELNEZ_D:
11399 check_insn(ctx, ISA_MIPS32R6);
11400 gen_sel_d(ctx, op1, fd, ft, fs);
11401 break;
11402 case OPC_MOVCF_D:
11403 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11404 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11405 break;
11406 case OPC_MOVZ_D:
11407 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11409 TCGLabel *l1 = gen_new_label();
11410 TCGv_i64 fp0;
11412 if (ft != 0) {
11413 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11415 fp0 = tcg_temp_new_i64();
11416 gen_load_fpr64(ctx, fp0, fs);
11417 gen_store_fpr64(ctx, fp0, fd);
11418 tcg_temp_free_i64(fp0);
11419 gen_set_label(l1);
11421 break;
11422 case OPC_MOVN_D:
11423 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11425 TCGLabel *l1 = gen_new_label();
11426 TCGv_i64 fp0;
11428 if (ft != 0) {
11429 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11430 fp0 = tcg_temp_new_i64();
11431 gen_load_fpr64(ctx, fp0, fs);
11432 gen_store_fpr64(ctx, fp0, fd);
11433 tcg_temp_free_i64(fp0);
11434 gen_set_label(l1);
11437 break;
11438 case OPC_RECIP_D:
11439 check_cp1_registers(ctx, fs | fd);
11441 TCGv_i64 fp0 = tcg_temp_new_i64();
11443 gen_load_fpr64(ctx, fp0, fs);
11444 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11445 gen_store_fpr64(ctx, fp0, fd);
11446 tcg_temp_free_i64(fp0);
11448 break;
11449 case OPC_RSQRT_D:
11450 check_cp1_registers(ctx, fs | fd);
11452 TCGv_i64 fp0 = tcg_temp_new_i64();
11454 gen_load_fpr64(ctx, fp0, fs);
11455 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11456 gen_store_fpr64(ctx, fp0, fd);
11457 tcg_temp_free_i64(fp0);
11459 break;
11460 case OPC_MADDF_D:
11461 check_insn(ctx, ISA_MIPS32R6);
11463 TCGv_i64 fp0 = tcg_temp_new_i64();
11464 TCGv_i64 fp1 = tcg_temp_new_i64();
11465 TCGv_i64 fp2 = tcg_temp_new_i64();
11466 gen_load_fpr64(ctx, fp0, fs);
11467 gen_load_fpr64(ctx, fp1, ft);
11468 gen_load_fpr64(ctx, fp2, fd);
11469 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11470 gen_store_fpr64(ctx, fp2, fd);
11471 tcg_temp_free_i64(fp2);
11472 tcg_temp_free_i64(fp1);
11473 tcg_temp_free_i64(fp0);
11475 break;
11476 case OPC_MSUBF_D:
11477 check_insn(ctx, ISA_MIPS32R6);
11479 TCGv_i64 fp0 = tcg_temp_new_i64();
11480 TCGv_i64 fp1 = tcg_temp_new_i64();
11481 TCGv_i64 fp2 = tcg_temp_new_i64();
11482 gen_load_fpr64(ctx, fp0, fs);
11483 gen_load_fpr64(ctx, fp1, ft);
11484 gen_load_fpr64(ctx, fp2, fd);
11485 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11486 gen_store_fpr64(ctx, fp2, fd);
11487 tcg_temp_free_i64(fp2);
11488 tcg_temp_free_i64(fp1);
11489 tcg_temp_free_i64(fp0);
11491 break;
11492 case OPC_RINT_D:
11493 check_insn(ctx, ISA_MIPS32R6);
11495 TCGv_i64 fp0 = tcg_temp_new_i64();
11496 gen_load_fpr64(ctx, fp0, fs);
11497 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11498 gen_store_fpr64(ctx, fp0, fd);
11499 tcg_temp_free_i64(fp0);
11501 break;
11502 case OPC_CLASS_D:
11503 check_insn(ctx, ISA_MIPS32R6);
11505 TCGv_i64 fp0 = tcg_temp_new_i64();
11506 gen_load_fpr64(ctx, fp0, fs);
11507 gen_helper_float_class_d(fp0, cpu_env, fp0);
11508 gen_store_fpr64(ctx, fp0, fd);
11509 tcg_temp_free_i64(fp0);
11511 break;
11512 case OPC_MIN_D: /* OPC_RECIP2_D */
11513 if (ctx->insn_flags & ISA_MIPS32R6) {
11514 /* OPC_MIN_D */
11515 TCGv_i64 fp0 = tcg_temp_new_i64();
11516 TCGv_i64 fp1 = tcg_temp_new_i64();
11517 gen_load_fpr64(ctx, fp0, fs);
11518 gen_load_fpr64(ctx, fp1, ft);
11519 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11520 gen_store_fpr64(ctx, fp1, fd);
11521 tcg_temp_free_i64(fp1);
11522 tcg_temp_free_i64(fp0);
11523 } else {
11524 /* OPC_RECIP2_D */
11525 check_cp1_64bitmode(ctx);
11527 TCGv_i64 fp0 = tcg_temp_new_i64();
11528 TCGv_i64 fp1 = tcg_temp_new_i64();
11530 gen_load_fpr64(ctx, fp0, fs);
11531 gen_load_fpr64(ctx, fp1, ft);
11532 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11533 tcg_temp_free_i64(fp1);
11534 gen_store_fpr64(ctx, fp0, fd);
11535 tcg_temp_free_i64(fp0);
11538 break;
11539 case OPC_MINA_D: /* OPC_RECIP1_D */
11540 if (ctx->insn_flags & ISA_MIPS32R6) {
11541 /* OPC_MINA_D */
11542 TCGv_i64 fp0 = tcg_temp_new_i64();
11543 TCGv_i64 fp1 = tcg_temp_new_i64();
11544 gen_load_fpr64(ctx, fp0, fs);
11545 gen_load_fpr64(ctx, fp1, ft);
11546 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11547 gen_store_fpr64(ctx, fp1, fd);
11548 tcg_temp_free_i64(fp1);
11549 tcg_temp_free_i64(fp0);
11550 } else {
11551 /* OPC_RECIP1_D */
11552 check_cp1_64bitmode(ctx);
11554 TCGv_i64 fp0 = tcg_temp_new_i64();
11556 gen_load_fpr64(ctx, fp0, fs);
11557 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11558 gen_store_fpr64(ctx, fp0, fd);
11559 tcg_temp_free_i64(fp0);
11562 break;
11563 case OPC_MAX_D: /* OPC_RSQRT1_D */
11564 if (ctx->insn_flags & ISA_MIPS32R6) {
11565 /* OPC_MAX_D */
11566 TCGv_i64 fp0 = tcg_temp_new_i64();
11567 TCGv_i64 fp1 = tcg_temp_new_i64();
11568 gen_load_fpr64(ctx, fp0, fs);
11569 gen_load_fpr64(ctx, fp1, ft);
11570 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11571 gen_store_fpr64(ctx, fp1, fd);
11572 tcg_temp_free_i64(fp1);
11573 tcg_temp_free_i64(fp0);
11574 } else {
11575 /* OPC_RSQRT1_D */
11576 check_cp1_64bitmode(ctx);
11578 TCGv_i64 fp0 = tcg_temp_new_i64();
11580 gen_load_fpr64(ctx, fp0, fs);
11581 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11582 gen_store_fpr64(ctx, fp0, fd);
11583 tcg_temp_free_i64(fp0);
11586 break;
11587 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11588 if (ctx->insn_flags & ISA_MIPS32R6) {
11589 /* OPC_MAXA_D */
11590 TCGv_i64 fp0 = tcg_temp_new_i64();
11591 TCGv_i64 fp1 = tcg_temp_new_i64();
11592 gen_load_fpr64(ctx, fp0, fs);
11593 gen_load_fpr64(ctx, fp1, ft);
11594 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11595 gen_store_fpr64(ctx, fp1, fd);
11596 tcg_temp_free_i64(fp1);
11597 tcg_temp_free_i64(fp0);
11598 } else {
11599 /* OPC_RSQRT2_D */
11600 check_cp1_64bitmode(ctx);
11602 TCGv_i64 fp0 = tcg_temp_new_i64();
11603 TCGv_i64 fp1 = tcg_temp_new_i64();
11605 gen_load_fpr64(ctx, fp0, fs);
11606 gen_load_fpr64(ctx, fp1, ft);
11607 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11608 tcg_temp_free_i64(fp1);
11609 gen_store_fpr64(ctx, fp0, fd);
11610 tcg_temp_free_i64(fp0);
11613 break;
11614 case OPC_CMP_F_D:
11615 case OPC_CMP_UN_D:
11616 case OPC_CMP_EQ_D:
11617 case OPC_CMP_UEQ_D:
11618 case OPC_CMP_OLT_D:
11619 case OPC_CMP_ULT_D:
11620 case OPC_CMP_OLE_D:
11621 case OPC_CMP_ULE_D:
11622 case OPC_CMP_SF_D:
11623 case OPC_CMP_NGLE_D:
11624 case OPC_CMP_SEQ_D:
11625 case OPC_CMP_NGL_D:
11626 case OPC_CMP_LT_D:
11627 case OPC_CMP_NGE_D:
11628 case OPC_CMP_LE_D:
11629 case OPC_CMP_NGT_D:
11630 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11631 if (ctx->opcode & (1 << 6)) {
11632 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11633 } else {
11634 gen_cmp_d(ctx, func-48, ft, fs, cc);
11636 break;
11637 case OPC_CVT_S_D:
11638 check_cp1_registers(ctx, fs);
11640 TCGv_i32 fp32 = tcg_temp_new_i32();
11641 TCGv_i64 fp64 = tcg_temp_new_i64();
11643 gen_load_fpr64(ctx, fp64, fs);
11644 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11645 tcg_temp_free_i64(fp64);
11646 gen_store_fpr32(ctx, fp32, fd);
11647 tcg_temp_free_i32(fp32);
11649 break;
11650 case OPC_CVT_W_D:
11651 check_cp1_registers(ctx, fs);
11653 TCGv_i32 fp32 = tcg_temp_new_i32();
11654 TCGv_i64 fp64 = tcg_temp_new_i64();
11656 gen_load_fpr64(ctx, fp64, fs);
11657 if (ctx->nan2008) {
11658 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11659 } else {
11660 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11662 tcg_temp_free_i64(fp64);
11663 gen_store_fpr32(ctx, fp32, fd);
11664 tcg_temp_free_i32(fp32);
11666 break;
11667 case OPC_CVT_L_D:
11668 check_cp1_64bitmode(ctx);
11670 TCGv_i64 fp0 = tcg_temp_new_i64();
11672 gen_load_fpr64(ctx, fp0, fs);
11673 if (ctx->nan2008) {
11674 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11675 } else {
11676 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11678 gen_store_fpr64(ctx, fp0, fd);
11679 tcg_temp_free_i64(fp0);
11681 break;
11682 case OPC_CVT_S_W:
11684 TCGv_i32 fp0 = tcg_temp_new_i32();
11686 gen_load_fpr32(ctx, fp0, fs);
11687 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11688 gen_store_fpr32(ctx, fp0, fd);
11689 tcg_temp_free_i32(fp0);
11691 break;
11692 case OPC_CVT_D_W:
11693 check_cp1_registers(ctx, fd);
11695 TCGv_i32 fp32 = tcg_temp_new_i32();
11696 TCGv_i64 fp64 = tcg_temp_new_i64();
11698 gen_load_fpr32(ctx, fp32, fs);
11699 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11700 tcg_temp_free_i32(fp32);
11701 gen_store_fpr64(ctx, fp64, fd);
11702 tcg_temp_free_i64(fp64);
11704 break;
11705 case OPC_CVT_S_L:
11706 check_cp1_64bitmode(ctx);
11708 TCGv_i32 fp32 = tcg_temp_new_i32();
11709 TCGv_i64 fp64 = tcg_temp_new_i64();
11711 gen_load_fpr64(ctx, fp64, fs);
11712 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11713 tcg_temp_free_i64(fp64);
11714 gen_store_fpr32(ctx, fp32, fd);
11715 tcg_temp_free_i32(fp32);
11717 break;
11718 case OPC_CVT_D_L:
11719 check_cp1_64bitmode(ctx);
11721 TCGv_i64 fp0 = tcg_temp_new_i64();
11723 gen_load_fpr64(ctx, fp0, fs);
11724 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11725 gen_store_fpr64(ctx, fp0, fd);
11726 tcg_temp_free_i64(fp0);
11728 break;
11729 case OPC_CVT_PS_PW:
11730 check_ps(ctx);
11732 TCGv_i64 fp0 = tcg_temp_new_i64();
11734 gen_load_fpr64(ctx, fp0, fs);
11735 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11736 gen_store_fpr64(ctx, fp0, fd);
11737 tcg_temp_free_i64(fp0);
11739 break;
11740 case OPC_ADD_PS:
11741 check_ps(ctx);
11743 TCGv_i64 fp0 = tcg_temp_new_i64();
11744 TCGv_i64 fp1 = tcg_temp_new_i64();
11746 gen_load_fpr64(ctx, fp0, fs);
11747 gen_load_fpr64(ctx, fp1, ft);
11748 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11749 tcg_temp_free_i64(fp1);
11750 gen_store_fpr64(ctx, fp0, fd);
11751 tcg_temp_free_i64(fp0);
11753 break;
11754 case OPC_SUB_PS:
11755 check_ps(ctx);
11757 TCGv_i64 fp0 = tcg_temp_new_i64();
11758 TCGv_i64 fp1 = tcg_temp_new_i64();
11760 gen_load_fpr64(ctx, fp0, fs);
11761 gen_load_fpr64(ctx, fp1, ft);
11762 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11763 tcg_temp_free_i64(fp1);
11764 gen_store_fpr64(ctx, fp0, fd);
11765 tcg_temp_free_i64(fp0);
11767 break;
11768 case OPC_MUL_PS:
11769 check_ps(ctx);
11771 TCGv_i64 fp0 = tcg_temp_new_i64();
11772 TCGv_i64 fp1 = tcg_temp_new_i64();
11774 gen_load_fpr64(ctx, fp0, fs);
11775 gen_load_fpr64(ctx, fp1, ft);
11776 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11777 tcg_temp_free_i64(fp1);
11778 gen_store_fpr64(ctx, fp0, fd);
11779 tcg_temp_free_i64(fp0);
11781 break;
11782 case OPC_ABS_PS:
11783 check_ps(ctx);
11785 TCGv_i64 fp0 = tcg_temp_new_i64();
11787 gen_load_fpr64(ctx, fp0, fs);
11788 gen_helper_float_abs_ps(fp0, fp0);
11789 gen_store_fpr64(ctx, fp0, fd);
11790 tcg_temp_free_i64(fp0);
11792 break;
11793 case OPC_MOV_PS:
11794 check_ps(ctx);
11796 TCGv_i64 fp0 = tcg_temp_new_i64();
11798 gen_load_fpr64(ctx, fp0, fs);
11799 gen_store_fpr64(ctx, fp0, fd);
11800 tcg_temp_free_i64(fp0);
11802 break;
11803 case OPC_NEG_PS:
11804 check_ps(ctx);
11806 TCGv_i64 fp0 = tcg_temp_new_i64();
11808 gen_load_fpr64(ctx, fp0, fs);
11809 gen_helper_float_chs_ps(fp0, fp0);
11810 gen_store_fpr64(ctx, fp0, fd);
11811 tcg_temp_free_i64(fp0);
11813 break;
11814 case OPC_MOVCF_PS:
11815 check_ps(ctx);
11816 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11817 break;
11818 case OPC_MOVZ_PS:
11819 check_ps(ctx);
11821 TCGLabel *l1 = gen_new_label();
11822 TCGv_i64 fp0;
11824 if (ft != 0)
11825 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11826 fp0 = tcg_temp_new_i64();
11827 gen_load_fpr64(ctx, fp0, fs);
11828 gen_store_fpr64(ctx, fp0, fd);
11829 tcg_temp_free_i64(fp0);
11830 gen_set_label(l1);
11832 break;
11833 case OPC_MOVN_PS:
11834 check_ps(ctx);
11836 TCGLabel *l1 = gen_new_label();
11837 TCGv_i64 fp0;
11839 if (ft != 0) {
11840 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11841 fp0 = tcg_temp_new_i64();
11842 gen_load_fpr64(ctx, fp0, fs);
11843 gen_store_fpr64(ctx, fp0, fd);
11844 tcg_temp_free_i64(fp0);
11845 gen_set_label(l1);
11848 break;
11849 case OPC_ADDR_PS:
11850 check_ps(ctx);
11852 TCGv_i64 fp0 = tcg_temp_new_i64();
11853 TCGv_i64 fp1 = tcg_temp_new_i64();
11855 gen_load_fpr64(ctx, fp0, ft);
11856 gen_load_fpr64(ctx, fp1, fs);
11857 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11858 tcg_temp_free_i64(fp1);
11859 gen_store_fpr64(ctx, fp0, fd);
11860 tcg_temp_free_i64(fp0);
11862 break;
11863 case OPC_MULR_PS:
11864 check_ps(ctx);
11866 TCGv_i64 fp0 = tcg_temp_new_i64();
11867 TCGv_i64 fp1 = tcg_temp_new_i64();
11869 gen_load_fpr64(ctx, fp0, ft);
11870 gen_load_fpr64(ctx, fp1, fs);
11871 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11872 tcg_temp_free_i64(fp1);
11873 gen_store_fpr64(ctx, fp0, fd);
11874 tcg_temp_free_i64(fp0);
11876 break;
11877 case OPC_RECIP2_PS:
11878 check_ps(ctx);
11880 TCGv_i64 fp0 = tcg_temp_new_i64();
11881 TCGv_i64 fp1 = tcg_temp_new_i64();
11883 gen_load_fpr64(ctx, fp0, fs);
11884 gen_load_fpr64(ctx, fp1, ft);
11885 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11886 tcg_temp_free_i64(fp1);
11887 gen_store_fpr64(ctx, fp0, fd);
11888 tcg_temp_free_i64(fp0);
11890 break;
11891 case OPC_RECIP1_PS:
11892 check_ps(ctx);
11894 TCGv_i64 fp0 = tcg_temp_new_i64();
11896 gen_load_fpr64(ctx, fp0, fs);
11897 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11898 gen_store_fpr64(ctx, fp0, fd);
11899 tcg_temp_free_i64(fp0);
11901 break;
11902 case OPC_RSQRT1_PS:
11903 check_ps(ctx);
11905 TCGv_i64 fp0 = tcg_temp_new_i64();
11907 gen_load_fpr64(ctx, fp0, fs);
11908 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11909 gen_store_fpr64(ctx, fp0, fd);
11910 tcg_temp_free_i64(fp0);
11912 break;
11913 case OPC_RSQRT2_PS:
11914 check_ps(ctx);
11916 TCGv_i64 fp0 = tcg_temp_new_i64();
11917 TCGv_i64 fp1 = tcg_temp_new_i64();
11919 gen_load_fpr64(ctx, fp0, fs);
11920 gen_load_fpr64(ctx, fp1, ft);
11921 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11922 tcg_temp_free_i64(fp1);
11923 gen_store_fpr64(ctx, fp0, fd);
11924 tcg_temp_free_i64(fp0);
11926 break;
11927 case OPC_CVT_S_PU:
11928 check_cp1_64bitmode(ctx);
11930 TCGv_i32 fp0 = tcg_temp_new_i32();
11932 gen_load_fpr32h(ctx, fp0, fs);
11933 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11934 gen_store_fpr32(ctx, fp0, fd);
11935 tcg_temp_free_i32(fp0);
11937 break;
11938 case OPC_CVT_PW_PS:
11939 check_ps(ctx);
11941 TCGv_i64 fp0 = tcg_temp_new_i64();
11943 gen_load_fpr64(ctx, fp0, fs);
11944 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11945 gen_store_fpr64(ctx, fp0, fd);
11946 tcg_temp_free_i64(fp0);
11948 break;
11949 case OPC_CVT_S_PL:
11950 check_cp1_64bitmode(ctx);
11952 TCGv_i32 fp0 = tcg_temp_new_i32();
11954 gen_load_fpr32(ctx, fp0, fs);
11955 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11956 gen_store_fpr32(ctx, fp0, fd);
11957 tcg_temp_free_i32(fp0);
11959 break;
11960 case OPC_PLL_PS:
11961 check_ps(ctx);
11963 TCGv_i32 fp0 = tcg_temp_new_i32();
11964 TCGv_i32 fp1 = tcg_temp_new_i32();
11966 gen_load_fpr32(ctx, fp0, fs);
11967 gen_load_fpr32(ctx, fp1, ft);
11968 gen_store_fpr32h(ctx, fp0, fd);
11969 gen_store_fpr32(ctx, fp1, fd);
11970 tcg_temp_free_i32(fp0);
11971 tcg_temp_free_i32(fp1);
11973 break;
11974 case OPC_PLU_PS:
11975 check_ps(ctx);
11977 TCGv_i32 fp0 = tcg_temp_new_i32();
11978 TCGv_i32 fp1 = tcg_temp_new_i32();
11980 gen_load_fpr32(ctx, fp0, fs);
11981 gen_load_fpr32h(ctx, fp1, ft);
11982 gen_store_fpr32(ctx, fp1, fd);
11983 gen_store_fpr32h(ctx, fp0, fd);
11984 tcg_temp_free_i32(fp0);
11985 tcg_temp_free_i32(fp1);
11987 break;
11988 case OPC_PUL_PS:
11989 check_ps(ctx);
11991 TCGv_i32 fp0 = tcg_temp_new_i32();
11992 TCGv_i32 fp1 = tcg_temp_new_i32();
11994 gen_load_fpr32h(ctx, fp0, fs);
11995 gen_load_fpr32(ctx, fp1, ft);
11996 gen_store_fpr32(ctx, fp1, fd);
11997 gen_store_fpr32h(ctx, fp0, fd);
11998 tcg_temp_free_i32(fp0);
11999 tcg_temp_free_i32(fp1);
12001 break;
12002 case OPC_PUU_PS:
12003 check_ps(ctx);
12005 TCGv_i32 fp0 = tcg_temp_new_i32();
12006 TCGv_i32 fp1 = tcg_temp_new_i32();
12008 gen_load_fpr32h(ctx, fp0, fs);
12009 gen_load_fpr32h(ctx, fp1, ft);
12010 gen_store_fpr32(ctx, fp1, fd);
12011 gen_store_fpr32h(ctx, fp0, fd);
12012 tcg_temp_free_i32(fp0);
12013 tcg_temp_free_i32(fp1);
12015 break;
12016 case OPC_CMP_F_PS:
12017 case OPC_CMP_UN_PS:
12018 case OPC_CMP_EQ_PS:
12019 case OPC_CMP_UEQ_PS:
12020 case OPC_CMP_OLT_PS:
12021 case OPC_CMP_ULT_PS:
12022 case OPC_CMP_OLE_PS:
12023 case OPC_CMP_ULE_PS:
12024 case OPC_CMP_SF_PS:
12025 case OPC_CMP_NGLE_PS:
12026 case OPC_CMP_SEQ_PS:
12027 case OPC_CMP_NGL_PS:
12028 case OPC_CMP_LT_PS:
12029 case OPC_CMP_NGE_PS:
12030 case OPC_CMP_LE_PS:
12031 case OPC_CMP_NGT_PS:
12032 if (ctx->opcode & (1 << 6)) {
12033 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
12034 } else {
12035 gen_cmp_ps(ctx, func-48, ft, fs, cc);
12037 break;
12038 default:
12039 MIPS_INVAL("farith");
12040 generate_exception_end(ctx, EXCP_RI);
12041 return;
12045 /* Coprocessor 3 (FPU) */
12046 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12047 int fd, int fs, int base, int index)
12049 TCGv t0 = tcg_temp_new();
12051 if (base == 0) {
12052 gen_load_gpr(t0, index);
12053 } else if (index == 0) {
12054 gen_load_gpr(t0, base);
12055 } else {
12056 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12058 /* Don't do NOP if destination is zero: we must perform the actual
12059 memory access. */
12060 switch (opc) {
12061 case OPC_LWXC1:
12062 check_cop1x(ctx);
12064 TCGv_i32 fp0 = tcg_temp_new_i32();
12066 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12067 tcg_gen_trunc_tl_i32(fp0, t0);
12068 gen_store_fpr32(ctx, fp0, fd);
12069 tcg_temp_free_i32(fp0);
12071 break;
12072 case OPC_LDXC1:
12073 check_cop1x(ctx);
12074 check_cp1_registers(ctx, fd);
12076 TCGv_i64 fp0 = tcg_temp_new_i64();
12077 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12078 gen_store_fpr64(ctx, fp0, fd);
12079 tcg_temp_free_i64(fp0);
12081 break;
12082 case OPC_LUXC1:
12083 check_cp1_64bitmode(ctx);
12084 tcg_gen_andi_tl(t0, t0, ~0x7);
12086 TCGv_i64 fp0 = tcg_temp_new_i64();
12088 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12089 gen_store_fpr64(ctx, fp0, fd);
12090 tcg_temp_free_i64(fp0);
12092 break;
12093 case OPC_SWXC1:
12094 check_cop1x(ctx);
12096 TCGv_i32 fp0 = tcg_temp_new_i32();
12097 gen_load_fpr32(ctx, fp0, fs);
12098 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12099 tcg_temp_free_i32(fp0);
12101 break;
12102 case OPC_SDXC1:
12103 check_cop1x(ctx);
12104 check_cp1_registers(ctx, fs);
12106 TCGv_i64 fp0 = tcg_temp_new_i64();
12107 gen_load_fpr64(ctx, fp0, fs);
12108 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12109 tcg_temp_free_i64(fp0);
12111 break;
12112 case OPC_SUXC1:
12113 check_cp1_64bitmode(ctx);
12114 tcg_gen_andi_tl(t0, t0, ~0x7);
12116 TCGv_i64 fp0 = tcg_temp_new_i64();
12117 gen_load_fpr64(ctx, fp0, fs);
12118 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12119 tcg_temp_free_i64(fp0);
12121 break;
12123 tcg_temp_free(t0);
12126 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12127 int fd, int fr, int fs, int ft)
12129 switch (opc) {
12130 case OPC_ALNV_PS:
12131 check_ps(ctx);
12133 TCGv t0 = tcg_temp_local_new();
12134 TCGv_i32 fp = tcg_temp_new_i32();
12135 TCGv_i32 fph = tcg_temp_new_i32();
12136 TCGLabel *l1 = gen_new_label();
12137 TCGLabel *l2 = gen_new_label();
12139 gen_load_gpr(t0, fr);
12140 tcg_gen_andi_tl(t0, t0, 0x7);
12142 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12143 gen_load_fpr32(ctx, fp, fs);
12144 gen_load_fpr32h(ctx, fph, fs);
12145 gen_store_fpr32(ctx, fp, fd);
12146 gen_store_fpr32h(ctx, fph, fd);
12147 tcg_gen_br(l2);
12148 gen_set_label(l1);
12149 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12150 tcg_temp_free(t0);
12151 #ifdef TARGET_WORDS_BIGENDIAN
12152 gen_load_fpr32(ctx, fp, fs);
12153 gen_load_fpr32h(ctx, fph, ft);
12154 gen_store_fpr32h(ctx, fp, fd);
12155 gen_store_fpr32(ctx, fph, fd);
12156 #else
12157 gen_load_fpr32h(ctx, fph, fs);
12158 gen_load_fpr32(ctx, fp, ft);
12159 gen_store_fpr32(ctx, fph, fd);
12160 gen_store_fpr32h(ctx, fp, fd);
12161 #endif
12162 gen_set_label(l2);
12163 tcg_temp_free_i32(fp);
12164 tcg_temp_free_i32(fph);
12166 break;
12167 case OPC_MADD_S:
12168 check_cop1x(ctx);
12170 TCGv_i32 fp0 = tcg_temp_new_i32();
12171 TCGv_i32 fp1 = tcg_temp_new_i32();
12172 TCGv_i32 fp2 = tcg_temp_new_i32();
12174 gen_load_fpr32(ctx, fp0, fs);
12175 gen_load_fpr32(ctx, fp1, ft);
12176 gen_load_fpr32(ctx, fp2, fr);
12177 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12178 tcg_temp_free_i32(fp0);
12179 tcg_temp_free_i32(fp1);
12180 gen_store_fpr32(ctx, fp2, fd);
12181 tcg_temp_free_i32(fp2);
12183 break;
12184 case OPC_MADD_D:
12185 check_cop1x(ctx);
12186 check_cp1_registers(ctx, fd | fs | ft | fr);
12188 TCGv_i64 fp0 = tcg_temp_new_i64();
12189 TCGv_i64 fp1 = tcg_temp_new_i64();
12190 TCGv_i64 fp2 = tcg_temp_new_i64();
12192 gen_load_fpr64(ctx, fp0, fs);
12193 gen_load_fpr64(ctx, fp1, ft);
12194 gen_load_fpr64(ctx, fp2, fr);
12195 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12196 tcg_temp_free_i64(fp0);
12197 tcg_temp_free_i64(fp1);
12198 gen_store_fpr64(ctx, fp2, fd);
12199 tcg_temp_free_i64(fp2);
12201 break;
12202 case OPC_MADD_PS:
12203 check_ps(ctx);
12205 TCGv_i64 fp0 = tcg_temp_new_i64();
12206 TCGv_i64 fp1 = tcg_temp_new_i64();
12207 TCGv_i64 fp2 = tcg_temp_new_i64();
12209 gen_load_fpr64(ctx, fp0, fs);
12210 gen_load_fpr64(ctx, fp1, ft);
12211 gen_load_fpr64(ctx, fp2, fr);
12212 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12213 tcg_temp_free_i64(fp0);
12214 tcg_temp_free_i64(fp1);
12215 gen_store_fpr64(ctx, fp2, fd);
12216 tcg_temp_free_i64(fp2);
12218 break;
12219 case OPC_MSUB_S:
12220 check_cop1x(ctx);
12222 TCGv_i32 fp0 = tcg_temp_new_i32();
12223 TCGv_i32 fp1 = tcg_temp_new_i32();
12224 TCGv_i32 fp2 = tcg_temp_new_i32();
12226 gen_load_fpr32(ctx, fp0, fs);
12227 gen_load_fpr32(ctx, fp1, ft);
12228 gen_load_fpr32(ctx, fp2, fr);
12229 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12230 tcg_temp_free_i32(fp0);
12231 tcg_temp_free_i32(fp1);
12232 gen_store_fpr32(ctx, fp2, fd);
12233 tcg_temp_free_i32(fp2);
12235 break;
12236 case OPC_MSUB_D:
12237 check_cop1x(ctx);
12238 check_cp1_registers(ctx, fd | fs | ft | fr);
12240 TCGv_i64 fp0 = tcg_temp_new_i64();
12241 TCGv_i64 fp1 = tcg_temp_new_i64();
12242 TCGv_i64 fp2 = tcg_temp_new_i64();
12244 gen_load_fpr64(ctx, fp0, fs);
12245 gen_load_fpr64(ctx, fp1, ft);
12246 gen_load_fpr64(ctx, fp2, fr);
12247 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12248 tcg_temp_free_i64(fp0);
12249 tcg_temp_free_i64(fp1);
12250 gen_store_fpr64(ctx, fp2, fd);
12251 tcg_temp_free_i64(fp2);
12253 break;
12254 case OPC_MSUB_PS:
12255 check_ps(ctx);
12257 TCGv_i64 fp0 = tcg_temp_new_i64();
12258 TCGv_i64 fp1 = tcg_temp_new_i64();
12259 TCGv_i64 fp2 = tcg_temp_new_i64();
12261 gen_load_fpr64(ctx, fp0, fs);
12262 gen_load_fpr64(ctx, fp1, ft);
12263 gen_load_fpr64(ctx, fp2, fr);
12264 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12265 tcg_temp_free_i64(fp0);
12266 tcg_temp_free_i64(fp1);
12267 gen_store_fpr64(ctx, fp2, fd);
12268 tcg_temp_free_i64(fp2);
12270 break;
12271 case OPC_NMADD_S:
12272 check_cop1x(ctx);
12274 TCGv_i32 fp0 = tcg_temp_new_i32();
12275 TCGv_i32 fp1 = tcg_temp_new_i32();
12276 TCGv_i32 fp2 = tcg_temp_new_i32();
12278 gen_load_fpr32(ctx, fp0, fs);
12279 gen_load_fpr32(ctx, fp1, ft);
12280 gen_load_fpr32(ctx, fp2, fr);
12281 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12282 tcg_temp_free_i32(fp0);
12283 tcg_temp_free_i32(fp1);
12284 gen_store_fpr32(ctx, fp2, fd);
12285 tcg_temp_free_i32(fp2);
12287 break;
12288 case OPC_NMADD_D:
12289 check_cop1x(ctx);
12290 check_cp1_registers(ctx, fd | fs | ft | fr);
12292 TCGv_i64 fp0 = tcg_temp_new_i64();
12293 TCGv_i64 fp1 = tcg_temp_new_i64();
12294 TCGv_i64 fp2 = tcg_temp_new_i64();
12296 gen_load_fpr64(ctx, fp0, fs);
12297 gen_load_fpr64(ctx, fp1, ft);
12298 gen_load_fpr64(ctx, fp2, fr);
12299 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12300 tcg_temp_free_i64(fp0);
12301 tcg_temp_free_i64(fp1);
12302 gen_store_fpr64(ctx, fp2, fd);
12303 tcg_temp_free_i64(fp2);
12305 break;
12306 case OPC_NMADD_PS:
12307 check_ps(ctx);
12309 TCGv_i64 fp0 = tcg_temp_new_i64();
12310 TCGv_i64 fp1 = tcg_temp_new_i64();
12311 TCGv_i64 fp2 = tcg_temp_new_i64();
12313 gen_load_fpr64(ctx, fp0, fs);
12314 gen_load_fpr64(ctx, fp1, ft);
12315 gen_load_fpr64(ctx, fp2, fr);
12316 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12317 tcg_temp_free_i64(fp0);
12318 tcg_temp_free_i64(fp1);
12319 gen_store_fpr64(ctx, fp2, fd);
12320 tcg_temp_free_i64(fp2);
12322 break;
12323 case OPC_NMSUB_S:
12324 check_cop1x(ctx);
12326 TCGv_i32 fp0 = tcg_temp_new_i32();
12327 TCGv_i32 fp1 = tcg_temp_new_i32();
12328 TCGv_i32 fp2 = tcg_temp_new_i32();
12330 gen_load_fpr32(ctx, fp0, fs);
12331 gen_load_fpr32(ctx, fp1, ft);
12332 gen_load_fpr32(ctx, fp2, fr);
12333 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12334 tcg_temp_free_i32(fp0);
12335 tcg_temp_free_i32(fp1);
12336 gen_store_fpr32(ctx, fp2, fd);
12337 tcg_temp_free_i32(fp2);
12339 break;
12340 case OPC_NMSUB_D:
12341 check_cop1x(ctx);
12342 check_cp1_registers(ctx, fd | fs | ft | fr);
12344 TCGv_i64 fp0 = tcg_temp_new_i64();
12345 TCGv_i64 fp1 = tcg_temp_new_i64();
12346 TCGv_i64 fp2 = tcg_temp_new_i64();
12348 gen_load_fpr64(ctx, fp0, fs);
12349 gen_load_fpr64(ctx, fp1, ft);
12350 gen_load_fpr64(ctx, fp2, fr);
12351 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12352 tcg_temp_free_i64(fp0);
12353 tcg_temp_free_i64(fp1);
12354 gen_store_fpr64(ctx, fp2, fd);
12355 tcg_temp_free_i64(fp2);
12357 break;
12358 case OPC_NMSUB_PS:
12359 check_ps(ctx);
12361 TCGv_i64 fp0 = tcg_temp_new_i64();
12362 TCGv_i64 fp1 = tcg_temp_new_i64();
12363 TCGv_i64 fp2 = tcg_temp_new_i64();
12365 gen_load_fpr64(ctx, fp0, fs);
12366 gen_load_fpr64(ctx, fp1, ft);
12367 gen_load_fpr64(ctx, fp2, fr);
12368 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12369 tcg_temp_free_i64(fp0);
12370 tcg_temp_free_i64(fp1);
12371 gen_store_fpr64(ctx, fp2, fd);
12372 tcg_temp_free_i64(fp2);
12374 break;
12375 default:
12376 MIPS_INVAL("flt3_arith");
12377 generate_exception_end(ctx, EXCP_RI);
12378 return;
12382 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12384 TCGv t0;
12386 #if !defined(CONFIG_USER_ONLY)
12387 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12388 Therefore only check the ISA in system mode. */
12389 check_insn(ctx, ISA_MIPS32R2);
12390 #endif
12391 t0 = tcg_temp_new();
12393 switch (rd) {
12394 case 0:
12395 gen_helper_rdhwr_cpunum(t0, cpu_env);
12396 gen_store_gpr(t0, rt);
12397 break;
12398 case 1:
12399 gen_helper_rdhwr_synci_step(t0, cpu_env);
12400 gen_store_gpr(t0, rt);
12401 break;
12402 case 2:
12403 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12404 gen_io_start();
12406 gen_helper_rdhwr_cc(t0, cpu_env);
12407 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12408 gen_io_end();
12410 gen_store_gpr(t0, rt);
12411 /* Break the TB to be able to take timer interrupts immediately
12412 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12413 we break completely out of translated code. */
12414 gen_save_pc(ctx->base.pc_next + 4);
12415 ctx->base.is_jmp = DISAS_EXIT;
12416 break;
12417 case 3:
12418 gen_helper_rdhwr_ccres(t0, cpu_env);
12419 gen_store_gpr(t0, rt);
12420 break;
12421 case 4:
12422 check_insn(ctx, ISA_MIPS32R6);
12423 if (sel != 0) {
12424 /* Performance counter registers are not implemented other than
12425 * control register 0.
12427 generate_exception(ctx, EXCP_RI);
12429 gen_helper_rdhwr_performance(t0, cpu_env);
12430 gen_store_gpr(t0, rt);
12431 break;
12432 case 5:
12433 check_insn(ctx, ISA_MIPS32R6);
12434 gen_helper_rdhwr_xnp(t0, cpu_env);
12435 gen_store_gpr(t0, rt);
12436 break;
12437 case 29:
12438 #if defined(CONFIG_USER_ONLY)
12439 tcg_gen_ld_tl(t0, cpu_env,
12440 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12441 gen_store_gpr(t0, rt);
12442 break;
12443 #else
12444 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12445 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12446 tcg_gen_ld_tl(t0, cpu_env,
12447 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12448 gen_store_gpr(t0, rt);
12449 } else {
12450 generate_exception_end(ctx, EXCP_RI);
12452 break;
12453 #endif
12454 default: /* Invalid */
12455 MIPS_INVAL("rdhwr");
12456 generate_exception_end(ctx, EXCP_RI);
12457 break;
12459 tcg_temp_free(t0);
12462 static inline void clear_branch_hflags(DisasContext *ctx)
12464 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12465 if (ctx->base.is_jmp == DISAS_NEXT) {
12466 save_cpu_state(ctx, 0);
12467 } else {
12468 /* it is not safe to save ctx->hflags as hflags may be changed
12469 in execution time by the instruction in delay / forbidden slot. */
12470 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12474 static void gen_branch(DisasContext *ctx, int insn_bytes)
12476 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12477 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12478 /* Branches completion */
12479 clear_branch_hflags(ctx);
12480 ctx->base.is_jmp = DISAS_NORETURN;
12481 /* FIXME: Need to clear can_do_io. */
12482 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12483 case MIPS_HFLAG_FBNSLOT:
12484 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12485 break;
12486 case MIPS_HFLAG_B:
12487 /* unconditional branch */
12488 if (proc_hflags & MIPS_HFLAG_BX) {
12489 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12491 gen_goto_tb(ctx, 0, ctx->btarget);
12492 break;
12493 case MIPS_HFLAG_BL:
12494 /* blikely taken case */
12495 gen_goto_tb(ctx, 0, ctx->btarget);
12496 break;
12497 case MIPS_HFLAG_BC:
12498 /* Conditional branch */
12500 TCGLabel *l1 = gen_new_label();
12502 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12503 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12504 gen_set_label(l1);
12505 gen_goto_tb(ctx, 0, ctx->btarget);
12507 break;
12508 case MIPS_HFLAG_BR:
12509 /* unconditional branch to register */
12510 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12511 TCGv t0 = tcg_temp_new();
12512 TCGv_i32 t1 = tcg_temp_new_i32();
12514 tcg_gen_andi_tl(t0, btarget, 0x1);
12515 tcg_gen_trunc_tl_i32(t1, t0);
12516 tcg_temp_free(t0);
12517 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12518 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12519 tcg_gen_or_i32(hflags, hflags, t1);
12520 tcg_temp_free_i32(t1);
12522 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12523 } else {
12524 tcg_gen_mov_tl(cpu_PC, btarget);
12526 if (ctx->base.singlestep_enabled) {
12527 save_cpu_state(ctx, 0);
12528 gen_helper_raise_exception_debug(cpu_env);
12530 tcg_gen_lookup_and_goto_ptr();
12531 break;
12532 default:
12533 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12534 abort();
12539 /* Compact Branches */
12540 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12541 int rs, int rt, int32_t offset)
12543 int bcond_compute = 0;
12544 TCGv t0 = tcg_temp_new();
12545 TCGv t1 = tcg_temp_new();
12546 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12548 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12549 #ifdef MIPS_DEBUG_DISAS
12550 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12551 "\n", ctx->base.pc_next);
12552 #endif
12553 generate_exception_end(ctx, EXCP_RI);
12554 goto out;
12557 /* Load needed operands and calculate btarget */
12558 switch (opc) {
12559 /* compact branch */
12560 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12561 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12562 gen_load_gpr(t0, rs);
12563 gen_load_gpr(t1, rt);
12564 bcond_compute = 1;
12565 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12566 if (rs <= rt && rs == 0) {
12567 /* OPC_BEQZALC, OPC_BNEZALC */
12568 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12570 break;
12571 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12572 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12573 gen_load_gpr(t0, rs);
12574 gen_load_gpr(t1, rt);
12575 bcond_compute = 1;
12576 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12577 break;
12578 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12579 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12580 if (rs == 0 || rs == rt) {
12581 /* OPC_BLEZALC, OPC_BGEZALC */
12582 /* OPC_BGTZALC, OPC_BLTZALC */
12583 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12585 gen_load_gpr(t0, rs);
12586 gen_load_gpr(t1, rt);
12587 bcond_compute = 1;
12588 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12589 break;
12590 case OPC_BC:
12591 case OPC_BALC:
12592 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12593 break;
12594 case OPC_BEQZC:
12595 case OPC_BNEZC:
12596 if (rs != 0) {
12597 /* OPC_BEQZC, OPC_BNEZC */
12598 gen_load_gpr(t0, rs);
12599 bcond_compute = 1;
12600 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12601 } else {
12602 /* OPC_JIC, OPC_JIALC */
12603 TCGv tbase = tcg_temp_new();
12604 TCGv toffset = tcg_temp_new();
12606 gen_load_gpr(tbase, rt);
12607 tcg_gen_movi_tl(toffset, offset);
12608 gen_op_addr_add(ctx, btarget, tbase, toffset);
12609 tcg_temp_free(tbase);
12610 tcg_temp_free(toffset);
12612 break;
12613 default:
12614 MIPS_INVAL("Compact branch/jump");
12615 generate_exception_end(ctx, EXCP_RI);
12616 goto out;
12619 if (bcond_compute == 0) {
12620 /* Uncoditional compact branch */
12621 switch (opc) {
12622 case OPC_JIALC:
12623 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12624 /* Fallthrough */
12625 case OPC_JIC:
12626 ctx->hflags |= MIPS_HFLAG_BR;
12627 break;
12628 case OPC_BALC:
12629 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12630 /* Fallthrough */
12631 case OPC_BC:
12632 ctx->hflags |= MIPS_HFLAG_B;
12633 break;
12634 default:
12635 MIPS_INVAL("Compact branch/jump");
12636 generate_exception_end(ctx, EXCP_RI);
12637 goto out;
12640 /* Generating branch here as compact branches don't have delay slot */
12641 gen_branch(ctx, 4);
12642 } else {
12643 /* Conditional compact branch */
12644 TCGLabel *fs = gen_new_label();
12645 save_cpu_state(ctx, 0);
12647 switch (opc) {
12648 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12649 if (rs == 0 && rt != 0) {
12650 /* OPC_BLEZALC */
12651 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12652 } else if (rs != 0 && rt != 0 && rs == rt) {
12653 /* OPC_BGEZALC */
12654 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12655 } else {
12656 /* OPC_BGEUC */
12657 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12659 break;
12660 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12661 if (rs == 0 && rt != 0) {
12662 /* OPC_BGTZALC */
12663 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12664 } else if (rs != 0 && rt != 0 && rs == rt) {
12665 /* OPC_BLTZALC */
12666 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12667 } else {
12668 /* OPC_BLTUC */
12669 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12671 break;
12672 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12673 if (rs == 0 && rt != 0) {
12674 /* OPC_BLEZC */
12675 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12676 } else if (rs != 0 && rt != 0 && rs == rt) {
12677 /* OPC_BGEZC */
12678 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12679 } else {
12680 /* OPC_BGEC */
12681 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12683 break;
12684 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12685 if (rs == 0 && rt != 0) {
12686 /* OPC_BGTZC */
12687 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12688 } else if (rs != 0 && rt != 0 && rs == rt) {
12689 /* OPC_BLTZC */
12690 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12691 } else {
12692 /* OPC_BLTC */
12693 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12695 break;
12696 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12697 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12698 if (rs >= rt) {
12699 /* OPC_BOVC, OPC_BNVC */
12700 TCGv t2 = tcg_temp_new();
12701 TCGv t3 = tcg_temp_new();
12702 TCGv t4 = tcg_temp_new();
12703 TCGv input_overflow = tcg_temp_new();
12705 gen_load_gpr(t0, rs);
12706 gen_load_gpr(t1, rt);
12707 tcg_gen_ext32s_tl(t2, t0);
12708 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12709 tcg_gen_ext32s_tl(t3, t1);
12710 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12711 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12713 tcg_gen_add_tl(t4, t2, t3);
12714 tcg_gen_ext32s_tl(t4, t4);
12715 tcg_gen_xor_tl(t2, t2, t3);
12716 tcg_gen_xor_tl(t3, t4, t3);
12717 tcg_gen_andc_tl(t2, t3, t2);
12718 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12719 tcg_gen_or_tl(t4, t4, input_overflow);
12720 if (opc == OPC_BOVC) {
12721 /* OPC_BOVC */
12722 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12723 } else {
12724 /* OPC_BNVC */
12725 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12727 tcg_temp_free(input_overflow);
12728 tcg_temp_free(t4);
12729 tcg_temp_free(t3);
12730 tcg_temp_free(t2);
12731 } else if (rs < rt && rs == 0) {
12732 /* OPC_BEQZALC, OPC_BNEZALC */
12733 if (opc == OPC_BEQZALC) {
12734 /* OPC_BEQZALC */
12735 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12736 } else {
12737 /* OPC_BNEZALC */
12738 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12740 } else {
12741 /* OPC_BEQC, OPC_BNEC */
12742 if (opc == OPC_BEQC) {
12743 /* OPC_BEQC */
12744 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12745 } else {
12746 /* OPC_BNEC */
12747 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12750 break;
12751 case OPC_BEQZC:
12752 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12753 break;
12754 case OPC_BNEZC:
12755 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12756 break;
12757 default:
12758 MIPS_INVAL("Compact conditional branch/jump");
12759 generate_exception_end(ctx, EXCP_RI);
12760 goto out;
12763 /* Generating branch here as compact branches don't have delay slot */
12764 gen_goto_tb(ctx, 1, ctx->btarget);
12765 gen_set_label(fs);
12767 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12770 out:
12771 tcg_temp_free(t0);
12772 tcg_temp_free(t1);
12775 /* ISA extensions (ASEs) */
12776 /* MIPS16 extension to MIPS32 */
12778 /* MIPS16 major opcodes */
12779 enum {
12780 M16_OPC_ADDIUSP = 0x00,
12781 M16_OPC_ADDIUPC = 0x01,
12782 M16_OPC_B = 0x02,
12783 M16_OPC_JAL = 0x03,
12784 M16_OPC_BEQZ = 0x04,
12785 M16_OPC_BNEQZ = 0x05,
12786 M16_OPC_SHIFT = 0x06,
12787 M16_OPC_LD = 0x07,
12788 M16_OPC_RRIA = 0x08,
12789 M16_OPC_ADDIU8 = 0x09,
12790 M16_OPC_SLTI = 0x0a,
12791 M16_OPC_SLTIU = 0x0b,
12792 M16_OPC_I8 = 0x0c,
12793 M16_OPC_LI = 0x0d,
12794 M16_OPC_CMPI = 0x0e,
12795 M16_OPC_SD = 0x0f,
12796 M16_OPC_LB = 0x10,
12797 M16_OPC_LH = 0x11,
12798 M16_OPC_LWSP = 0x12,
12799 M16_OPC_LW = 0x13,
12800 M16_OPC_LBU = 0x14,
12801 M16_OPC_LHU = 0x15,
12802 M16_OPC_LWPC = 0x16,
12803 M16_OPC_LWU = 0x17,
12804 M16_OPC_SB = 0x18,
12805 M16_OPC_SH = 0x19,
12806 M16_OPC_SWSP = 0x1a,
12807 M16_OPC_SW = 0x1b,
12808 M16_OPC_RRR = 0x1c,
12809 M16_OPC_RR = 0x1d,
12810 M16_OPC_EXTEND = 0x1e,
12811 M16_OPC_I64 = 0x1f
12814 /* I8 funct field */
12815 enum {
12816 I8_BTEQZ = 0x0,
12817 I8_BTNEZ = 0x1,
12818 I8_SWRASP = 0x2,
12819 I8_ADJSP = 0x3,
12820 I8_SVRS = 0x4,
12821 I8_MOV32R = 0x5,
12822 I8_MOVR32 = 0x7
12825 /* RRR f field */
12826 enum {
12827 RRR_DADDU = 0x0,
12828 RRR_ADDU = 0x1,
12829 RRR_DSUBU = 0x2,
12830 RRR_SUBU = 0x3
12833 /* RR funct field */
12834 enum {
12835 RR_JR = 0x00,
12836 RR_SDBBP = 0x01,
12837 RR_SLT = 0x02,
12838 RR_SLTU = 0x03,
12839 RR_SLLV = 0x04,
12840 RR_BREAK = 0x05,
12841 RR_SRLV = 0x06,
12842 RR_SRAV = 0x07,
12843 RR_DSRL = 0x08,
12844 RR_CMP = 0x0a,
12845 RR_NEG = 0x0b,
12846 RR_AND = 0x0c,
12847 RR_OR = 0x0d,
12848 RR_XOR = 0x0e,
12849 RR_NOT = 0x0f,
12850 RR_MFHI = 0x10,
12851 RR_CNVT = 0x11,
12852 RR_MFLO = 0x12,
12853 RR_DSRA = 0x13,
12854 RR_DSLLV = 0x14,
12855 RR_DSRLV = 0x16,
12856 RR_DSRAV = 0x17,
12857 RR_MULT = 0x18,
12858 RR_MULTU = 0x19,
12859 RR_DIV = 0x1a,
12860 RR_DIVU = 0x1b,
12861 RR_DMULT = 0x1c,
12862 RR_DMULTU = 0x1d,
12863 RR_DDIV = 0x1e,
12864 RR_DDIVU = 0x1f
12867 /* I64 funct field */
12868 enum {
12869 I64_LDSP = 0x0,
12870 I64_SDSP = 0x1,
12871 I64_SDRASP = 0x2,
12872 I64_DADJSP = 0x3,
12873 I64_LDPC = 0x4,
12874 I64_DADDIU5 = 0x5,
12875 I64_DADDIUPC = 0x6,
12876 I64_DADDIUSP = 0x7
12879 /* RR ry field for CNVT */
12880 enum {
12881 RR_RY_CNVT_ZEB = 0x0,
12882 RR_RY_CNVT_ZEH = 0x1,
12883 RR_RY_CNVT_ZEW = 0x2,
12884 RR_RY_CNVT_SEB = 0x4,
12885 RR_RY_CNVT_SEH = 0x5,
12886 RR_RY_CNVT_SEW = 0x6,
12889 static int xlat (int r)
12891 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12893 return map[r];
12896 static void gen_mips16_save (DisasContext *ctx,
12897 int xsregs, int aregs,
12898 int do_ra, int do_s0, int do_s1,
12899 int framesize)
12901 TCGv t0 = tcg_temp_new();
12902 TCGv t1 = tcg_temp_new();
12903 TCGv t2 = tcg_temp_new();
12904 int args, astatic;
12906 switch (aregs) {
12907 case 0:
12908 case 1:
12909 case 2:
12910 case 3:
12911 case 11:
12912 args = 0;
12913 break;
12914 case 4:
12915 case 5:
12916 case 6:
12917 case 7:
12918 args = 1;
12919 break;
12920 case 8:
12921 case 9:
12922 case 10:
12923 args = 2;
12924 break;
12925 case 12:
12926 case 13:
12927 args = 3;
12928 break;
12929 case 14:
12930 args = 4;
12931 break;
12932 default:
12933 generate_exception_end(ctx, EXCP_RI);
12934 return;
12937 switch (args) {
12938 case 4:
12939 gen_base_offset_addr(ctx, t0, 29, 12);
12940 gen_load_gpr(t1, 7);
12941 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12942 /* Fall through */
12943 case 3:
12944 gen_base_offset_addr(ctx, t0, 29, 8);
12945 gen_load_gpr(t1, 6);
12946 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12947 /* Fall through */
12948 case 2:
12949 gen_base_offset_addr(ctx, t0, 29, 4);
12950 gen_load_gpr(t1, 5);
12951 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12952 /* Fall through */
12953 case 1:
12954 gen_base_offset_addr(ctx, t0, 29, 0);
12955 gen_load_gpr(t1, 4);
12956 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12959 gen_load_gpr(t0, 29);
12961 #define DECR_AND_STORE(reg) do { \
12962 tcg_gen_movi_tl(t2, -4); \
12963 gen_op_addr_add(ctx, t0, t0, t2); \
12964 gen_load_gpr(t1, reg); \
12965 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12966 } while (0)
12968 if (do_ra) {
12969 DECR_AND_STORE(31);
12972 switch (xsregs) {
12973 case 7:
12974 DECR_AND_STORE(30);
12975 /* Fall through */
12976 case 6:
12977 DECR_AND_STORE(23);
12978 /* Fall through */
12979 case 5:
12980 DECR_AND_STORE(22);
12981 /* Fall through */
12982 case 4:
12983 DECR_AND_STORE(21);
12984 /* Fall through */
12985 case 3:
12986 DECR_AND_STORE(20);
12987 /* Fall through */
12988 case 2:
12989 DECR_AND_STORE(19);
12990 /* Fall through */
12991 case 1:
12992 DECR_AND_STORE(18);
12995 if (do_s1) {
12996 DECR_AND_STORE(17);
12998 if (do_s0) {
12999 DECR_AND_STORE(16);
13002 switch (aregs) {
13003 case 0:
13004 case 4:
13005 case 8:
13006 case 12:
13007 case 14:
13008 astatic = 0;
13009 break;
13010 case 1:
13011 case 5:
13012 case 9:
13013 case 13:
13014 astatic = 1;
13015 break;
13016 case 2:
13017 case 6:
13018 case 10:
13019 astatic = 2;
13020 break;
13021 case 3:
13022 case 7:
13023 astatic = 3;
13024 break;
13025 case 11:
13026 astatic = 4;
13027 break;
13028 default:
13029 generate_exception_end(ctx, EXCP_RI);
13030 return;
13033 if (astatic > 0) {
13034 DECR_AND_STORE(7);
13035 if (astatic > 1) {
13036 DECR_AND_STORE(6);
13037 if (astatic > 2) {
13038 DECR_AND_STORE(5);
13039 if (astatic > 3) {
13040 DECR_AND_STORE(4);
13045 #undef DECR_AND_STORE
13047 tcg_gen_movi_tl(t2, -framesize);
13048 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13049 tcg_temp_free(t0);
13050 tcg_temp_free(t1);
13051 tcg_temp_free(t2);
13054 static void gen_mips16_restore (DisasContext *ctx,
13055 int xsregs, int aregs,
13056 int do_ra, int do_s0, int do_s1,
13057 int framesize)
13059 int astatic;
13060 TCGv t0 = tcg_temp_new();
13061 TCGv t1 = tcg_temp_new();
13062 TCGv t2 = tcg_temp_new();
13064 tcg_gen_movi_tl(t2, framesize);
13065 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13067 #define DECR_AND_LOAD(reg) do { \
13068 tcg_gen_movi_tl(t2, -4); \
13069 gen_op_addr_add(ctx, t0, t0, t2); \
13070 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13071 gen_store_gpr(t1, reg); \
13072 } while (0)
13074 if (do_ra) {
13075 DECR_AND_LOAD(31);
13078 switch (xsregs) {
13079 case 7:
13080 DECR_AND_LOAD(30);
13081 /* Fall through */
13082 case 6:
13083 DECR_AND_LOAD(23);
13084 /* Fall through */
13085 case 5:
13086 DECR_AND_LOAD(22);
13087 /* Fall through */
13088 case 4:
13089 DECR_AND_LOAD(21);
13090 /* Fall through */
13091 case 3:
13092 DECR_AND_LOAD(20);
13093 /* Fall through */
13094 case 2:
13095 DECR_AND_LOAD(19);
13096 /* Fall through */
13097 case 1:
13098 DECR_AND_LOAD(18);
13101 if (do_s1) {
13102 DECR_AND_LOAD(17);
13104 if (do_s0) {
13105 DECR_AND_LOAD(16);
13108 switch (aregs) {
13109 case 0:
13110 case 4:
13111 case 8:
13112 case 12:
13113 case 14:
13114 astatic = 0;
13115 break;
13116 case 1:
13117 case 5:
13118 case 9:
13119 case 13:
13120 astatic = 1;
13121 break;
13122 case 2:
13123 case 6:
13124 case 10:
13125 astatic = 2;
13126 break;
13127 case 3:
13128 case 7:
13129 astatic = 3;
13130 break;
13131 case 11:
13132 astatic = 4;
13133 break;
13134 default:
13135 generate_exception_end(ctx, EXCP_RI);
13136 return;
13139 if (astatic > 0) {
13140 DECR_AND_LOAD(7);
13141 if (astatic > 1) {
13142 DECR_AND_LOAD(6);
13143 if (astatic > 2) {
13144 DECR_AND_LOAD(5);
13145 if (astatic > 3) {
13146 DECR_AND_LOAD(4);
13151 #undef DECR_AND_LOAD
13153 tcg_gen_movi_tl(t2, framesize);
13154 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13155 tcg_temp_free(t0);
13156 tcg_temp_free(t1);
13157 tcg_temp_free(t2);
13160 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13161 int is_64_bit, int extended)
13163 TCGv t0;
13165 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13166 generate_exception_end(ctx, EXCP_RI);
13167 return;
13170 t0 = tcg_temp_new();
13172 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13173 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13174 if (!is_64_bit) {
13175 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13178 tcg_temp_free(t0);
13181 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13182 int16_t offset)
13184 TCGv_i32 t0 = tcg_const_i32(op);
13185 TCGv t1 = tcg_temp_new();
13186 gen_base_offset_addr(ctx, t1, base, offset);
13187 gen_helper_cache(cpu_env, t1, t0);
13190 #if defined(TARGET_MIPS64)
13191 static void decode_i64_mips16 (DisasContext *ctx,
13192 int ry, int funct, int16_t offset,
13193 int extended)
13195 switch (funct) {
13196 case I64_LDSP:
13197 check_insn(ctx, ISA_MIPS3);
13198 check_mips_64(ctx);
13199 offset = extended ? offset : offset << 3;
13200 gen_ld(ctx, OPC_LD, ry, 29, offset);
13201 break;
13202 case I64_SDSP:
13203 check_insn(ctx, ISA_MIPS3);
13204 check_mips_64(ctx);
13205 offset = extended ? offset : offset << 3;
13206 gen_st(ctx, OPC_SD, ry, 29, offset);
13207 break;
13208 case I64_SDRASP:
13209 check_insn(ctx, ISA_MIPS3);
13210 check_mips_64(ctx);
13211 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13212 gen_st(ctx, OPC_SD, 31, 29, offset);
13213 break;
13214 case I64_DADJSP:
13215 check_insn(ctx, ISA_MIPS3);
13216 check_mips_64(ctx);
13217 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13218 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13219 break;
13220 case I64_LDPC:
13221 check_insn(ctx, ISA_MIPS3);
13222 check_mips_64(ctx);
13223 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13224 generate_exception_end(ctx, EXCP_RI);
13225 } else {
13226 offset = extended ? offset : offset << 3;
13227 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13229 break;
13230 case I64_DADDIU5:
13231 check_insn(ctx, ISA_MIPS3);
13232 check_mips_64(ctx);
13233 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13234 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13235 break;
13236 case I64_DADDIUPC:
13237 check_insn(ctx, ISA_MIPS3);
13238 check_mips_64(ctx);
13239 offset = extended ? offset : offset << 2;
13240 gen_addiupc(ctx, ry, offset, 1, extended);
13241 break;
13242 case I64_DADDIUSP:
13243 check_insn(ctx, ISA_MIPS3);
13244 check_mips_64(ctx);
13245 offset = extended ? offset : offset << 2;
13246 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13247 break;
13250 #endif
13252 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13254 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13255 int op, rx, ry, funct, sa;
13256 int16_t imm, offset;
13258 ctx->opcode = (ctx->opcode << 16) | extend;
13259 op = (ctx->opcode >> 11) & 0x1f;
13260 sa = (ctx->opcode >> 22) & 0x1f;
13261 funct = (ctx->opcode >> 8) & 0x7;
13262 rx = xlat((ctx->opcode >> 8) & 0x7);
13263 ry = xlat((ctx->opcode >> 5) & 0x7);
13264 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13265 | ((ctx->opcode >> 21) & 0x3f) << 5
13266 | (ctx->opcode & 0x1f));
13268 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13269 counterparts. */
13270 switch (op) {
13271 case M16_OPC_ADDIUSP:
13272 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13273 break;
13274 case M16_OPC_ADDIUPC:
13275 gen_addiupc(ctx, rx, imm, 0, 1);
13276 break;
13277 case M16_OPC_B:
13278 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13279 /* No delay slot, so just process as a normal instruction */
13280 break;
13281 case M16_OPC_BEQZ:
13282 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13283 /* No delay slot, so just process as a normal instruction */
13284 break;
13285 case M16_OPC_BNEQZ:
13286 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13287 /* No delay slot, so just process as a normal instruction */
13288 break;
13289 case M16_OPC_SHIFT:
13290 switch (ctx->opcode & 0x3) {
13291 case 0x0:
13292 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13293 break;
13294 case 0x1:
13295 #if defined(TARGET_MIPS64)
13296 check_mips_64(ctx);
13297 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13298 #else
13299 generate_exception_end(ctx, EXCP_RI);
13300 #endif
13301 break;
13302 case 0x2:
13303 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13304 break;
13305 case 0x3:
13306 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13307 break;
13309 break;
13310 #if defined(TARGET_MIPS64)
13311 case M16_OPC_LD:
13312 check_insn(ctx, ISA_MIPS3);
13313 check_mips_64(ctx);
13314 gen_ld(ctx, OPC_LD, ry, rx, offset);
13315 break;
13316 #endif
13317 case M16_OPC_RRIA:
13318 imm = ctx->opcode & 0xf;
13319 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13320 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13321 imm = (int16_t) (imm << 1) >> 1;
13322 if ((ctx->opcode >> 4) & 0x1) {
13323 #if defined(TARGET_MIPS64)
13324 check_mips_64(ctx);
13325 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13326 #else
13327 generate_exception_end(ctx, EXCP_RI);
13328 #endif
13329 } else {
13330 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13332 break;
13333 case M16_OPC_ADDIU8:
13334 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13335 break;
13336 case M16_OPC_SLTI:
13337 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13338 break;
13339 case M16_OPC_SLTIU:
13340 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13341 break;
13342 case M16_OPC_I8:
13343 switch (funct) {
13344 case I8_BTEQZ:
13345 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13346 break;
13347 case I8_BTNEZ:
13348 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13349 break;
13350 case I8_SWRASP:
13351 gen_st(ctx, OPC_SW, 31, 29, imm);
13352 break;
13353 case I8_ADJSP:
13354 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13355 break;
13356 case I8_SVRS:
13357 check_insn(ctx, ISA_MIPS32);
13359 int xsregs = (ctx->opcode >> 24) & 0x7;
13360 int aregs = (ctx->opcode >> 16) & 0xf;
13361 int do_ra = (ctx->opcode >> 6) & 0x1;
13362 int do_s0 = (ctx->opcode >> 5) & 0x1;
13363 int do_s1 = (ctx->opcode >> 4) & 0x1;
13364 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13365 | (ctx->opcode & 0xf)) << 3;
13367 if (ctx->opcode & (1 << 7)) {
13368 gen_mips16_save(ctx, xsregs, aregs,
13369 do_ra, do_s0, do_s1,
13370 framesize);
13371 } else {
13372 gen_mips16_restore(ctx, xsregs, aregs,
13373 do_ra, do_s0, do_s1,
13374 framesize);
13377 break;
13378 default:
13379 generate_exception_end(ctx, EXCP_RI);
13380 break;
13382 break;
13383 case M16_OPC_LI:
13384 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13385 break;
13386 case M16_OPC_CMPI:
13387 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13388 break;
13389 #if defined(TARGET_MIPS64)
13390 case M16_OPC_SD:
13391 check_insn(ctx, ISA_MIPS3);
13392 check_mips_64(ctx);
13393 gen_st(ctx, OPC_SD, ry, rx, offset);
13394 break;
13395 #endif
13396 case M16_OPC_LB:
13397 gen_ld(ctx, OPC_LB, ry, rx, offset);
13398 break;
13399 case M16_OPC_LH:
13400 gen_ld(ctx, OPC_LH, ry, rx, offset);
13401 break;
13402 case M16_OPC_LWSP:
13403 gen_ld(ctx, OPC_LW, rx, 29, offset);
13404 break;
13405 case M16_OPC_LW:
13406 gen_ld(ctx, OPC_LW, ry, rx, offset);
13407 break;
13408 case M16_OPC_LBU:
13409 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13410 break;
13411 case M16_OPC_LHU:
13412 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13413 break;
13414 case M16_OPC_LWPC:
13415 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13416 break;
13417 #if defined(TARGET_MIPS64)
13418 case M16_OPC_LWU:
13419 check_insn(ctx, ISA_MIPS3);
13420 check_mips_64(ctx);
13421 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13422 break;
13423 #endif
13424 case M16_OPC_SB:
13425 gen_st(ctx, OPC_SB, ry, rx, offset);
13426 break;
13427 case M16_OPC_SH:
13428 gen_st(ctx, OPC_SH, ry, rx, offset);
13429 break;
13430 case M16_OPC_SWSP:
13431 gen_st(ctx, OPC_SW, rx, 29, offset);
13432 break;
13433 case M16_OPC_SW:
13434 gen_st(ctx, OPC_SW, ry, rx, offset);
13435 break;
13436 #if defined(TARGET_MIPS64)
13437 case M16_OPC_I64:
13438 decode_i64_mips16(ctx, ry, funct, offset, 1);
13439 break;
13440 #endif
13441 default:
13442 generate_exception_end(ctx, EXCP_RI);
13443 break;
13446 return 4;
13449 static inline bool is_uhi(int sdbbp_code)
13451 #ifdef CONFIG_USER_ONLY
13452 return false;
13453 #else
13454 return semihosting_enabled() && sdbbp_code == 1;
13455 #endif
13458 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13460 int rx, ry;
13461 int sa;
13462 int op, cnvt_op, op1, offset;
13463 int funct;
13464 int n_bytes;
13466 op = (ctx->opcode >> 11) & 0x1f;
13467 sa = (ctx->opcode >> 2) & 0x7;
13468 sa = sa == 0 ? 8 : sa;
13469 rx = xlat((ctx->opcode >> 8) & 0x7);
13470 cnvt_op = (ctx->opcode >> 5) & 0x7;
13471 ry = xlat((ctx->opcode >> 5) & 0x7);
13472 op1 = offset = ctx->opcode & 0x1f;
13474 n_bytes = 2;
13476 switch (op) {
13477 case M16_OPC_ADDIUSP:
13479 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13481 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13483 break;
13484 case M16_OPC_ADDIUPC:
13485 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13486 break;
13487 case M16_OPC_B:
13488 offset = (ctx->opcode & 0x7ff) << 1;
13489 offset = (int16_t)(offset << 4) >> 4;
13490 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13491 /* No delay slot, so just process as a normal instruction */
13492 break;
13493 case M16_OPC_JAL:
13494 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13495 offset = (((ctx->opcode & 0x1f) << 21)
13496 | ((ctx->opcode >> 5) & 0x1f) << 16
13497 | offset) << 2;
13498 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13499 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13500 n_bytes = 4;
13501 break;
13502 case M16_OPC_BEQZ:
13503 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13504 ((int8_t)ctx->opcode) << 1, 0);
13505 /* No delay slot, so just process as a normal instruction */
13506 break;
13507 case M16_OPC_BNEQZ:
13508 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13509 ((int8_t)ctx->opcode) << 1, 0);
13510 /* No delay slot, so just process as a normal instruction */
13511 break;
13512 case M16_OPC_SHIFT:
13513 switch (ctx->opcode & 0x3) {
13514 case 0x0:
13515 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13516 break;
13517 case 0x1:
13518 #if defined(TARGET_MIPS64)
13519 check_insn(ctx, ISA_MIPS3);
13520 check_mips_64(ctx);
13521 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13522 #else
13523 generate_exception_end(ctx, EXCP_RI);
13524 #endif
13525 break;
13526 case 0x2:
13527 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13528 break;
13529 case 0x3:
13530 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13531 break;
13533 break;
13534 #if defined(TARGET_MIPS64)
13535 case M16_OPC_LD:
13536 check_insn(ctx, ISA_MIPS3);
13537 check_mips_64(ctx);
13538 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13539 break;
13540 #endif
13541 case M16_OPC_RRIA:
13543 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13545 if ((ctx->opcode >> 4) & 1) {
13546 #if defined(TARGET_MIPS64)
13547 check_insn(ctx, ISA_MIPS3);
13548 check_mips_64(ctx);
13549 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13550 #else
13551 generate_exception_end(ctx, EXCP_RI);
13552 #endif
13553 } else {
13554 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13557 break;
13558 case M16_OPC_ADDIU8:
13560 int16_t imm = (int8_t) ctx->opcode;
13562 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13564 break;
13565 case M16_OPC_SLTI:
13567 int16_t imm = (uint8_t) ctx->opcode;
13568 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13570 break;
13571 case M16_OPC_SLTIU:
13573 int16_t imm = (uint8_t) ctx->opcode;
13574 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13576 break;
13577 case M16_OPC_I8:
13579 int reg32;
13581 funct = (ctx->opcode >> 8) & 0x7;
13582 switch (funct) {
13583 case I8_BTEQZ:
13584 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13585 ((int8_t)ctx->opcode) << 1, 0);
13586 break;
13587 case I8_BTNEZ:
13588 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13589 ((int8_t)ctx->opcode) << 1, 0);
13590 break;
13591 case I8_SWRASP:
13592 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13593 break;
13594 case I8_ADJSP:
13595 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13596 ((int8_t)ctx->opcode) << 3);
13597 break;
13598 case I8_SVRS:
13599 check_insn(ctx, ISA_MIPS32);
13601 int do_ra = ctx->opcode & (1 << 6);
13602 int do_s0 = ctx->opcode & (1 << 5);
13603 int do_s1 = ctx->opcode & (1 << 4);
13604 int framesize = ctx->opcode & 0xf;
13606 if (framesize == 0) {
13607 framesize = 128;
13608 } else {
13609 framesize = framesize << 3;
13612 if (ctx->opcode & (1 << 7)) {
13613 gen_mips16_save(ctx, 0, 0,
13614 do_ra, do_s0, do_s1, framesize);
13615 } else {
13616 gen_mips16_restore(ctx, 0, 0,
13617 do_ra, do_s0, do_s1, framesize);
13620 break;
13621 case I8_MOV32R:
13623 int rz = xlat(ctx->opcode & 0x7);
13625 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13626 ((ctx->opcode >> 5) & 0x7);
13627 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13629 break;
13630 case I8_MOVR32:
13631 reg32 = ctx->opcode & 0x1f;
13632 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13633 break;
13634 default:
13635 generate_exception_end(ctx, EXCP_RI);
13636 break;
13639 break;
13640 case M16_OPC_LI:
13642 int16_t imm = (uint8_t) ctx->opcode;
13644 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13646 break;
13647 case M16_OPC_CMPI:
13649 int16_t imm = (uint8_t) ctx->opcode;
13650 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13652 break;
13653 #if defined(TARGET_MIPS64)
13654 case M16_OPC_SD:
13655 check_insn(ctx, ISA_MIPS3);
13656 check_mips_64(ctx);
13657 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13658 break;
13659 #endif
13660 case M16_OPC_LB:
13661 gen_ld(ctx, OPC_LB, ry, rx, offset);
13662 break;
13663 case M16_OPC_LH:
13664 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13665 break;
13666 case M16_OPC_LWSP:
13667 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13668 break;
13669 case M16_OPC_LW:
13670 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13671 break;
13672 case M16_OPC_LBU:
13673 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13674 break;
13675 case M16_OPC_LHU:
13676 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13677 break;
13678 case M16_OPC_LWPC:
13679 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13680 break;
13681 #if defined (TARGET_MIPS64)
13682 case M16_OPC_LWU:
13683 check_insn(ctx, ISA_MIPS3);
13684 check_mips_64(ctx);
13685 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13686 break;
13687 #endif
13688 case M16_OPC_SB:
13689 gen_st(ctx, OPC_SB, ry, rx, offset);
13690 break;
13691 case M16_OPC_SH:
13692 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13693 break;
13694 case M16_OPC_SWSP:
13695 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13696 break;
13697 case M16_OPC_SW:
13698 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13699 break;
13700 case M16_OPC_RRR:
13702 int rz = xlat((ctx->opcode >> 2) & 0x7);
13703 int mips32_op;
13705 switch (ctx->opcode & 0x3) {
13706 case RRR_ADDU:
13707 mips32_op = OPC_ADDU;
13708 break;
13709 case RRR_SUBU:
13710 mips32_op = OPC_SUBU;
13711 break;
13712 #if defined(TARGET_MIPS64)
13713 case RRR_DADDU:
13714 mips32_op = OPC_DADDU;
13715 check_insn(ctx, ISA_MIPS3);
13716 check_mips_64(ctx);
13717 break;
13718 case RRR_DSUBU:
13719 mips32_op = OPC_DSUBU;
13720 check_insn(ctx, ISA_MIPS3);
13721 check_mips_64(ctx);
13722 break;
13723 #endif
13724 default:
13725 generate_exception_end(ctx, EXCP_RI);
13726 goto done;
13729 gen_arith(ctx, mips32_op, rz, rx, ry);
13730 done:
13733 break;
13734 case M16_OPC_RR:
13735 switch (op1) {
13736 case RR_JR:
13738 int nd = (ctx->opcode >> 7) & 0x1;
13739 int link = (ctx->opcode >> 6) & 0x1;
13740 int ra = (ctx->opcode >> 5) & 0x1;
13742 if (nd) {
13743 check_insn(ctx, ISA_MIPS32);
13746 if (link) {
13747 op = OPC_JALR;
13748 } else {
13749 op = OPC_JR;
13752 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13753 (nd ? 0 : 2));
13755 break;
13756 case RR_SDBBP:
13757 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13758 gen_helper_do_semihosting(cpu_env);
13759 } else {
13760 /* XXX: not clear which exception should be raised
13761 * when in debug mode...
13763 check_insn(ctx, ISA_MIPS32);
13764 generate_exception_end(ctx, EXCP_DBp);
13766 break;
13767 case RR_SLT:
13768 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13769 break;
13770 case RR_SLTU:
13771 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13772 break;
13773 case RR_BREAK:
13774 generate_exception_end(ctx, EXCP_BREAK);
13775 break;
13776 case RR_SLLV:
13777 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13778 break;
13779 case RR_SRLV:
13780 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13781 break;
13782 case RR_SRAV:
13783 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13784 break;
13785 #if defined (TARGET_MIPS64)
13786 case RR_DSRL:
13787 check_insn(ctx, ISA_MIPS3);
13788 check_mips_64(ctx);
13789 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13790 break;
13791 #endif
13792 case RR_CMP:
13793 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13794 break;
13795 case RR_NEG:
13796 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13797 break;
13798 case RR_AND:
13799 gen_logic(ctx, OPC_AND, rx, rx, ry);
13800 break;
13801 case RR_OR:
13802 gen_logic(ctx, OPC_OR, rx, rx, ry);
13803 break;
13804 case RR_XOR:
13805 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13806 break;
13807 case RR_NOT:
13808 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13809 break;
13810 case RR_MFHI:
13811 gen_HILO(ctx, OPC_MFHI, 0, rx);
13812 break;
13813 case RR_CNVT:
13814 check_insn(ctx, ISA_MIPS32);
13815 switch (cnvt_op) {
13816 case RR_RY_CNVT_ZEB:
13817 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13818 break;
13819 case RR_RY_CNVT_ZEH:
13820 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13821 break;
13822 case RR_RY_CNVT_SEB:
13823 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13824 break;
13825 case RR_RY_CNVT_SEH:
13826 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13827 break;
13828 #if defined (TARGET_MIPS64)
13829 case RR_RY_CNVT_ZEW:
13830 check_insn(ctx, ISA_MIPS64);
13831 check_mips_64(ctx);
13832 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13833 break;
13834 case RR_RY_CNVT_SEW:
13835 check_insn(ctx, ISA_MIPS64);
13836 check_mips_64(ctx);
13837 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13838 break;
13839 #endif
13840 default:
13841 generate_exception_end(ctx, EXCP_RI);
13842 break;
13844 break;
13845 case RR_MFLO:
13846 gen_HILO(ctx, OPC_MFLO, 0, rx);
13847 break;
13848 #if defined (TARGET_MIPS64)
13849 case RR_DSRA:
13850 check_insn(ctx, ISA_MIPS3);
13851 check_mips_64(ctx);
13852 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13853 break;
13854 case RR_DSLLV:
13855 check_insn(ctx, ISA_MIPS3);
13856 check_mips_64(ctx);
13857 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13858 break;
13859 case RR_DSRLV:
13860 check_insn(ctx, ISA_MIPS3);
13861 check_mips_64(ctx);
13862 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13863 break;
13864 case RR_DSRAV:
13865 check_insn(ctx, ISA_MIPS3);
13866 check_mips_64(ctx);
13867 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13868 break;
13869 #endif
13870 case RR_MULT:
13871 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13872 break;
13873 case RR_MULTU:
13874 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13875 break;
13876 case RR_DIV:
13877 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13878 break;
13879 case RR_DIVU:
13880 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13881 break;
13882 #if defined (TARGET_MIPS64)
13883 case RR_DMULT:
13884 check_insn(ctx, ISA_MIPS3);
13885 check_mips_64(ctx);
13886 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13887 break;
13888 case RR_DMULTU:
13889 check_insn(ctx, ISA_MIPS3);
13890 check_mips_64(ctx);
13891 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13892 break;
13893 case RR_DDIV:
13894 check_insn(ctx, ISA_MIPS3);
13895 check_mips_64(ctx);
13896 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13897 break;
13898 case RR_DDIVU:
13899 check_insn(ctx, ISA_MIPS3);
13900 check_mips_64(ctx);
13901 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13902 break;
13903 #endif
13904 default:
13905 generate_exception_end(ctx, EXCP_RI);
13906 break;
13908 break;
13909 case M16_OPC_EXTEND:
13910 decode_extended_mips16_opc(env, ctx);
13911 n_bytes = 4;
13912 break;
13913 #if defined(TARGET_MIPS64)
13914 case M16_OPC_I64:
13915 funct = (ctx->opcode >> 8) & 0x7;
13916 decode_i64_mips16(ctx, ry, funct, offset, 0);
13917 break;
13918 #endif
13919 default:
13920 generate_exception_end(ctx, EXCP_RI);
13921 break;
13924 return n_bytes;
13927 /* microMIPS extension to MIPS32/MIPS64 */
13930 * microMIPS32/microMIPS64 major opcodes
13932 * 1. MIPS Architecture for Programmers Volume II-B:
13933 * The microMIPS32 Instruction Set (Revision 3.05)
13935 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13937 * 2. MIPS Architecture For Programmers Volume II-A:
13938 * The MIPS64 Instruction Set (Revision 3.51)
13941 enum {
13942 POOL32A = 0x00,
13943 POOL16A = 0x01,
13944 LBU16 = 0x02,
13945 MOVE16 = 0x03,
13946 ADDI32 = 0x04,
13947 R6_LUI = 0x04,
13948 AUI = 0x04,
13949 LBU32 = 0x05,
13950 SB32 = 0x06,
13951 LB32 = 0x07,
13953 POOL32B = 0x08,
13954 POOL16B = 0x09,
13955 LHU16 = 0x0a,
13956 ANDI16 = 0x0b,
13957 ADDIU32 = 0x0c,
13958 LHU32 = 0x0d,
13959 SH32 = 0x0e,
13960 LH32 = 0x0f,
13962 POOL32I = 0x10,
13963 POOL16C = 0x11,
13964 LWSP16 = 0x12,
13965 POOL16D = 0x13,
13966 ORI32 = 0x14,
13967 POOL32F = 0x15,
13968 POOL32S = 0x16, /* MIPS64 */
13969 DADDIU32 = 0x17, /* MIPS64 */
13971 POOL32C = 0x18,
13972 LWGP16 = 0x19,
13973 LW16 = 0x1a,
13974 POOL16E = 0x1b,
13975 XORI32 = 0x1c,
13976 JALS32 = 0x1d,
13977 BOVC = 0x1d,
13978 BEQC = 0x1d,
13979 BEQZALC = 0x1d,
13980 ADDIUPC = 0x1e,
13981 PCREL = 0x1e,
13982 BNVC = 0x1f,
13983 BNEC = 0x1f,
13984 BNEZALC = 0x1f,
13986 R6_BEQZC = 0x20,
13987 JIC = 0x20,
13988 POOL16F = 0x21,
13989 SB16 = 0x22,
13990 BEQZ16 = 0x23,
13991 BEQZC16 = 0x23,
13992 SLTI32 = 0x24,
13993 BEQ32 = 0x25,
13994 BC = 0x25,
13995 SWC132 = 0x26,
13996 LWC132 = 0x27,
13998 /* 0x29 is reserved */
13999 RES_29 = 0x29,
14000 R6_BNEZC = 0x28,
14001 JIALC = 0x28,
14002 SH16 = 0x2a,
14003 BNEZ16 = 0x2b,
14004 BNEZC16 = 0x2b,
14005 SLTIU32 = 0x2c,
14006 BNE32 = 0x2d,
14007 BALC = 0x2d,
14008 SDC132 = 0x2e,
14009 LDC132 = 0x2f,
14011 /* 0x31 is reserved */
14012 RES_31 = 0x31,
14013 BLEZALC = 0x30,
14014 BGEZALC = 0x30,
14015 BGEUC = 0x30,
14016 SWSP16 = 0x32,
14017 B16 = 0x33,
14018 BC16 = 0x33,
14019 ANDI32 = 0x34,
14020 J32 = 0x35,
14021 BGTZC = 0x35,
14022 BLTZC = 0x35,
14023 BLTC = 0x35,
14024 SD32 = 0x36, /* MIPS64 */
14025 LD32 = 0x37, /* MIPS64 */
14027 /* 0x39 is reserved */
14028 RES_39 = 0x39,
14029 BGTZALC = 0x38,
14030 BLTZALC = 0x38,
14031 BLTUC = 0x38,
14032 SW16 = 0x3a,
14033 LI16 = 0x3b,
14034 JALX32 = 0x3c,
14035 JAL32 = 0x3d,
14036 BLEZC = 0x3d,
14037 BGEZC = 0x3d,
14038 BGEC = 0x3d,
14039 SW32 = 0x3e,
14040 LW32 = 0x3f
14043 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14044 enum {
14045 ADDIUPC_00 = 0x00,
14046 ADDIUPC_01 = 0x01,
14047 ADDIUPC_02 = 0x02,
14048 ADDIUPC_03 = 0x03,
14049 ADDIUPC_04 = 0x04,
14050 ADDIUPC_05 = 0x05,
14051 ADDIUPC_06 = 0x06,
14052 ADDIUPC_07 = 0x07,
14053 AUIPC = 0x1e,
14054 ALUIPC = 0x1f,
14055 LWPC_08 = 0x08,
14056 LWPC_09 = 0x09,
14057 LWPC_0A = 0x0A,
14058 LWPC_0B = 0x0B,
14059 LWPC_0C = 0x0C,
14060 LWPC_0D = 0x0D,
14061 LWPC_0E = 0x0E,
14062 LWPC_0F = 0x0F,
14065 /* POOL32A encoding of minor opcode field */
14067 enum {
14068 /* These opcodes are distinguished only by bits 9..6; those bits are
14069 * what are recorded below. */
14070 SLL32 = 0x0,
14071 SRL32 = 0x1,
14072 SRA = 0x2,
14073 ROTR = 0x3,
14074 SELEQZ = 0x5,
14075 SELNEZ = 0x6,
14076 R6_RDHWR = 0x7,
14078 SLLV = 0x0,
14079 SRLV = 0x1,
14080 SRAV = 0x2,
14081 ROTRV = 0x3,
14082 ADD = 0x4,
14083 ADDU32 = 0x5,
14084 SUB = 0x6,
14085 SUBU32 = 0x7,
14086 MUL = 0x8,
14087 AND = 0x9,
14088 OR32 = 0xa,
14089 NOR = 0xb,
14090 XOR32 = 0xc,
14091 SLT = 0xd,
14092 SLTU = 0xe,
14094 MOVN = 0x0,
14095 R6_MUL = 0x0,
14096 MOVZ = 0x1,
14097 MUH = 0x1,
14098 MULU = 0x2,
14099 MUHU = 0x3,
14100 LWXS = 0x4,
14101 R6_DIV = 0x4,
14102 MOD = 0x5,
14103 R6_DIVU = 0x6,
14104 MODU = 0x7,
14106 /* The following can be distinguished by their lower 6 bits. */
14107 BREAK32 = 0x07,
14108 INS = 0x0c,
14109 LSA = 0x0f,
14110 ALIGN = 0x1f,
14111 EXT = 0x2c,
14112 POOL32AXF = 0x3c,
14113 SIGRIE = 0x3f
14116 /* POOL32AXF encoding of minor opcode field extension */
14119 * 1. MIPS Architecture for Programmers Volume II-B:
14120 * The microMIPS32 Instruction Set (Revision 3.05)
14122 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14124 * 2. MIPS Architecture for Programmers VolumeIV-e:
14125 * The MIPS DSP Application-Specific Extension
14126 * to the microMIPS32 Architecture (Revision 2.34)
14128 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14131 enum {
14132 /* bits 11..6 */
14133 TEQ = 0x00,
14134 TGE = 0x08,
14135 TGEU = 0x10,
14136 TLT = 0x20,
14137 TLTU = 0x28,
14138 TNE = 0x30,
14140 MFC0 = 0x03,
14141 MTC0 = 0x0b,
14143 /* begin of microMIPS32 DSP */
14145 /* bits 13..12 for 0x01 */
14146 MFHI_ACC = 0x0,
14147 MFLO_ACC = 0x1,
14148 MTHI_ACC = 0x2,
14149 MTLO_ACC = 0x3,
14151 /* bits 13..12 for 0x2a */
14152 MADD_ACC = 0x0,
14153 MADDU_ACC = 0x1,
14154 MSUB_ACC = 0x2,
14155 MSUBU_ACC = 0x3,
14157 /* bits 13..12 for 0x32 */
14158 MULT_ACC = 0x0,
14159 MULTU_ACC = 0x1,
14161 /* end of microMIPS32 DSP */
14163 /* bits 15..12 for 0x2c */
14164 BITSWAP = 0x0,
14165 SEB = 0x2,
14166 SEH = 0x3,
14167 CLO = 0x4,
14168 CLZ = 0x5,
14169 RDHWR = 0x6,
14170 WSBH = 0x7,
14171 MULT = 0x8,
14172 MULTU = 0x9,
14173 DIV = 0xa,
14174 DIVU = 0xb,
14175 MADD = 0xc,
14176 MADDU = 0xd,
14177 MSUB = 0xe,
14178 MSUBU = 0xf,
14180 /* bits 15..12 for 0x34 */
14181 MFC2 = 0x4,
14182 MTC2 = 0x5,
14183 MFHC2 = 0x8,
14184 MTHC2 = 0x9,
14185 CFC2 = 0xc,
14186 CTC2 = 0xd,
14188 /* bits 15..12 for 0x3c */
14189 JALR = 0x0,
14190 JR = 0x0, /* alias */
14191 JALRC = 0x0,
14192 JRC = 0x0,
14193 JALR_HB = 0x1,
14194 JALRC_HB = 0x1,
14195 JALRS = 0x4,
14196 JALRS_HB = 0x5,
14198 /* bits 15..12 for 0x05 */
14199 RDPGPR = 0xe,
14200 WRPGPR = 0xf,
14202 /* bits 15..12 for 0x0d */
14203 TLBP = 0x0,
14204 TLBR = 0x1,
14205 TLBWI = 0x2,
14206 TLBWR = 0x3,
14207 TLBINV = 0x4,
14208 TLBINVF = 0x5,
14209 WAIT = 0x9,
14210 IRET = 0xd,
14211 DERET = 0xe,
14212 ERET = 0xf,
14214 /* bits 15..12 for 0x15 */
14215 DMT = 0x0,
14216 DVPE = 0x1,
14217 EMT = 0x2,
14218 EVPE = 0x3,
14220 /* bits 15..12 for 0x1d */
14221 DI = 0x4,
14222 EI = 0x5,
14224 /* bits 15..12 for 0x2d */
14225 SYNC = 0x6,
14226 SYSCALL = 0x8,
14227 SDBBP = 0xd,
14229 /* bits 15..12 for 0x35 */
14230 MFHI32 = 0x0,
14231 MFLO32 = 0x1,
14232 MTHI32 = 0x2,
14233 MTLO32 = 0x3,
14236 /* POOL32B encoding of minor opcode field (bits 15..12) */
14238 enum {
14239 LWC2 = 0x0,
14240 LWP = 0x1,
14241 LDP = 0x4,
14242 LWM32 = 0x5,
14243 CACHE = 0x6,
14244 LDM = 0x7,
14245 SWC2 = 0x8,
14246 SWP = 0x9,
14247 SDP = 0xc,
14248 SWM32 = 0xd,
14249 SDM = 0xf
14252 /* POOL32C encoding of minor opcode field (bits 15..12) */
14254 enum {
14255 LWL = 0x0,
14256 SWL = 0x8,
14257 LWR = 0x1,
14258 SWR = 0x9,
14259 PREF = 0x2,
14260 ST_EVA = 0xa,
14261 LL = 0x3,
14262 SC = 0xb,
14263 LDL = 0x4,
14264 SDL = 0xc,
14265 LDR = 0x5,
14266 SDR = 0xd,
14267 LD_EVA = 0x6,
14268 LWU = 0xe,
14269 LLD = 0x7,
14270 SCD = 0xf
14273 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14275 enum {
14276 LBUE = 0x0,
14277 LHUE = 0x1,
14278 LWLE = 0x2,
14279 LWRE = 0x3,
14280 LBE = 0x4,
14281 LHE = 0x5,
14282 LLE = 0x6,
14283 LWE = 0x7,
14286 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14288 enum {
14289 SWLE = 0x0,
14290 SWRE = 0x1,
14291 PREFE = 0x2,
14292 CACHEE = 0x3,
14293 SBE = 0x4,
14294 SHE = 0x5,
14295 SCE = 0x6,
14296 SWE = 0x7,
14299 /* POOL32F encoding of minor opcode field (bits 5..0) */
14301 enum {
14302 /* These are the bit 7..6 values */
14303 ADD_FMT = 0x0,
14305 SUB_FMT = 0x1,
14307 MUL_FMT = 0x2,
14309 DIV_FMT = 0x3,
14311 /* These are the bit 8..6 values */
14312 MOVN_FMT = 0x0,
14313 RSQRT2_FMT = 0x0,
14314 MOVF_FMT = 0x0,
14315 RINT_FMT = 0x0,
14316 SELNEZ_FMT = 0x0,
14318 MOVZ_FMT = 0x1,
14319 LWXC1 = 0x1,
14320 MOVT_FMT = 0x1,
14321 CLASS_FMT = 0x1,
14322 SELEQZ_FMT = 0x1,
14324 PLL_PS = 0x2,
14325 SWXC1 = 0x2,
14326 SEL_FMT = 0x2,
14328 PLU_PS = 0x3,
14329 LDXC1 = 0x3,
14331 MOVN_FMT_04 = 0x4,
14332 PUL_PS = 0x4,
14333 SDXC1 = 0x4,
14334 RECIP2_FMT = 0x4,
14336 MOVZ_FMT_05 = 0x05,
14337 PUU_PS = 0x5,
14338 LUXC1 = 0x5,
14340 CVT_PS_S = 0x6,
14341 SUXC1 = 0x6,
14342 ADDR_PS = 0x6,
14343 PREFX = 0x6,
14344 MADDF_FMT = 0x6,
14346 MULR_PS = 0x7,
14347 MSUBF_FMT = 0x7,
14349 MADD_S = 0x01,
14350 MADD_D = 0x09,
14351 MADD_PS = 0x11,
14352 ALNV_PS = 0x19,
14353 MSUB_S = 0x21,
14354 MSUB_D = 0x29,
14355 MSUB_PS = 0x31,
14357 NMADD_S = 0x02,
14358 NMADD_D = 0x0a,
14359 NMADD_PS = 0x12,
14360 NMSUB_S = 0x22,
14361 NMSUB_D = 0x2a,
14362 NMSUB_PS = 0x32,
14364 MIN_FMT = 0x3,
14365 MAX_FMT = 0xb,
14366 MINA_FMT = 0x23,
14367 MAXA_FMT = 0x2b,
14368 POOL32FXF = 0x3b,
14370 CABS_COND_FMT = 0x1c, /* MIPS3D */
14371 C_COND_FMT = 0x3c,
14373 CMP_CONDN_S = 0x5,
14374 CMP_CONDN_D = 0x15
14377 /* POOL32Fxf encoding of minor opcode extension field */
14379 enum {
14380 CVT_L = 0x04,
14381 RSQRT_FMT = 0x08,
14382 FLOOR_L = 0x0c,
14383 CVT_PW_PS = 0x1c,
14384 CVT_W = 0x24,
14385 SQRT_FMT = 0x28,
14386 FLOOR_W = 0x2c,
14387 CVT_PS_PW = 0x3c,
14388 CFC1 = 0x40,
14389 RECIP_FMT = 0x48,
14390 CEIL_L = 0x4c,
14391 CTC1 = 0x60,
14392 CEIL_W = 0x6c,
14393 MFC1 = 0x80,
14394 CVT_S_PL = 0x84,
14395 TRUNC_L = 0x8c,
14396 MTC1 = 0xa0,
14397 CVT_S_PU = 0xa4,
14398 TRUNC_W = 0xac,
14399 MFHC1 = 0xc0,
14400 ROUND_L = 0xcc,
14401 MTHC1 = 0xe0,
14402 ROUND_W = 0xec,
14404 MOV_FMT = 0x01,
14405 MOVF = 0x05,
14406 ABS_FMT = 0x0d,
14407 RSQRT1_FMT = 0x1d,
14408 MOVT = 0x25,
14409 NEG_FMT = 0x2d,
14410 CVT_D = 0x4d,
14411 RECIP1_FMT = 0x5d,
14412 CVT_S = 0x6d
14415 /* POOL32I encoding of minor opcode field (bits 25..21) */
14417 enum {
14418 BLTZ = 0x00,
14419 BLTZAL = 0x01,
14420 BGEZ = 0x02,
14421 BGEZAL = 0x03,
14422 BLEZ = 0x04,
14423 BNEZC = 0x05,
14424 BGTZ = 0x06,
14425 BEQZC = 0x07,
14426 TLTI = 0x08,
14427 BC1EQZC = 0x08,
14428 TGEI = 0x09,
14429 BC1NEZC = 0x09,
14430 TLTIU = 0x0a,
14431 BC2EQZC = 0x0a,
14432 TGEIU = 0x0b,
14433 BC2NEZC = 0x0a,
14434 TNEI = 0x0c,
14435 R6_SYNCI = 0x0c,
14436 LUI = 0x0d,
14437 TEQI = 0x0e,
14438 SYNCI = 0x10,
14439 BLTZALS = 0x11,
14440 BGEZALS = 0x13,
14441 BC2F = 0x14,
14442 BC2T = 0x15,
14443 BPOSGE64 = 0x1a,
14444 BPOSGE32 = 0x1b,
14445 /* These overlap and are distinguished by bit16 of the instruction */
14446 BC1F = 0x1c,
14447 BC1T = 0x1d,
14448 BC1ANY2F = 0x1c,
14449 BC1ANY2T = 0x1d,
14450 BC1ANY4F = 0x1e,
14451 BC1ANY4T = 0x1f
14454 /* POOL16A encoding of minor opcode field */
14456 enum {
14457 ADDU16 = 0x0,
14458 SUBU16 = 0x1
14461 /* POOL16B encoding of minor opcode field */
14463 enum {
14464 SLL16 = 0x0,
14465 SRL16 = 0x1
14468 /* POOL16C encoding of minor opcode field */
14470 enum {
14471 NOT16 = 0x00,
14472 XOR16 = 0x04,
14473 AND16 = 0x08,
14474 OR16 = 0x0c,
14475 LWM16 = 0x10,
14476 SWM16 = 0x14,
14477 JR16 = 0x18,
14478 JRC16 = 0x1a,
14479 JALR16 = 0x1c,
14480 JALR16S = 0x1e,
14481 MFHI16 = 0x20,
14482 MFLO16 = 0x24,
14483 BREAK16 = 0x28,
14484 SDBBP16 = 0x2c,
14485 JRADDIUSP = 0x30
14488 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14490 enum {
14491 R6_NOT16 = 0x00,
14492 R6_AND16 = 0x01,
14493 R6_LWM16 = 0x02,
14494 R6_JRC16 = 0x03,
14495 MOVEP = 0x04,
14496 MOVEP_05 = 0x05,
14497 MOVEP_06 = 0x06,
14498 MOVEP_07 = 0x07,
14499 R6_XOR16 = 0x08,
14500 R6_OR16 = 0x09,
14501 R6_SWM16 = 0x0a,
14502 JALRC16 = 0x0b,
14503 MOVEP_0C = 0x0c,
14504 MOVEP_0D = 0x0d,
14505 MOVEP_0E = 0x0e,
14506 MOVEP_0F = 0x0f,
14507 JRCADDIUSP = 0x13,
14508 R6_BREAK16 = 0x1b,
14509 R6_SDBBP16 = 0x3b
14512 /* POOL16D encoding of minor opcode field */
14514 enum {
14515 ADDIUS5 = 0x0,
14516 ADDIUSP = 0x1
14519 /* POOL16E encoding of minor opcode field */
14521 enum {
14522 ADDIUR2 = 0x0,
14523 ADDIUR1SP = 0x1
14526 static int mmreg (int r)
14528 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14530 return map[r];
14533 /* Used for 16-bit store instructions. */
14534 static int mmreg2 (int r)
14536 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14538 return map[r];
14541 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14542 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14543 #define uMIPS_RS2(op) uMIPS_RS(op)
14544 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14545 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14546 #define uMIPS_RS5(op) (op & 0x1f)
14548 /* Signed immediate */
14549 #define SIMM(op, start, width) \
14550 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14551 << (32-width)) \
14552 >> (32-width))
14553 /* Zero-extended immediate */
14554 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14556 static void gen_addiur1sp(DisasContext *ctx)
14558 int rd = mmreg(uMIPS_RD(ctx->opcode));
14560 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14563 static void gen_addiur2(DisasContext *ctx)
14565 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14566 int rd = mmreg(uMIPS_RD(ctx->opcode));
14567 int rs = mmreg(uMIPS_RS(ctx->opcode));
14569 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14572 static void gen_addiusp(DisasContext *ctx)
14574 int encoded = ZIMM(ctx->opcode, 1, 9);
14575 int decoded;
14577 if (encoded <= 1) {
14578 decoded = 256 + encoded;
14579 } else if (encoded <= 255) {
14580 decoded = encoded;
14581 } else if (encoded <= 509) {
14582 decoded = encoded - 512;
14583 } else {
14584 decoded = encoded - 768;
14587 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14590 static void gen_addius5(DisasContext *ctx)
14592 int imm = SIMM(ctx->opcode, 1, 4);
14593 int rd = (ctx->opcode >> 5) & 0x1f;
14595 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14598 static void gen_andi16(DisasContext *ctx)
14600 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14601 31, 32, 63, 64, 255, 32768, 65535 };
14602 int rd = mmreg(uMIPS_RD(ctx->opcode));
14603 int rs = mmreg(uMIPS_RS(ctx->opcode));
14604 int encoded = ZIMM(ctx->opcode, 0, 4);
14606 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14609 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14610 int base, int16_t offset)
14612 TCGv t0, t1;
14613 TCGv_i32 t2;
14615 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14616 generate_exception_end(ctx, EXCP_RI);
14617 return;
14620 t0 = tcg_temp_new();
14622 gen_base_offset_addr(ctx, t0, base, offset);
14624 t1 = tcg_const_tl(reglist);
14625 t2 = tcg_const_i32(ctx->mem_idx);
14627 save_cpu_state(ctx, 1);
14628 switch (opc) {
14629 case LWM32:
14630 gen_helper_lwm(cpu_env, t0, t1, t2);
14631 break;
14632 case SWM32:
14633 gen_helper_swm(cpu_env, t0, t1, t2);
14634 break;
14635 #ifdef TARGET_MIPS64
14636 case LDM:
14637 gen_helper_ldm(cpu_env, t0, t1, t2);
14638 break;
14639 case SDM:
14640 gen_helper_sdm(cpu_env, t0, t1, t2);
14641 break;
14642 #endif
14644 tcg_temp_free(t0);
14645 tcg_temp_free(t1);
14646 tcg_temp_free_i32(t2);
14650 static void gen_pool16c_insn(DisasContext *ctx)
14652 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14653 int rs = mmreg(ctx->opcode & 0x7);
14655 switch (((ctx->opcode) >> 4) & 0x3f) {
14656 case NOT16 + 0:
14657 case NOT16 + 1:
14658 case NOT16 + 2:
14659 case NOT16 + 3:
14660 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14661 break;
14662 case XOR16 + 0:
14663 case XOR16 + 1:
14664 case XOR16 + 2:
14665 case XOR16 + 3:
14666 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14667 break;
14668 case AND16 + 0:
14669 case AND16 + 1:
14670 case AND16 + 2:
14671 case AND16 + 3:
14672 gen_logic(ctx, OPC_AND, rd, rd, rs);
14673 break;
14674 case OR16 + 0:
14675 case OR16 + 1:
14676 case OR16 + 2:
14677 case OR16 + 3:
14678 gen_logic(ctx, OPC_OR, rd, rd, rs);
14679 break;
14680 case LWM16 + 0:
14681 case LWM16 + 1:
14682 case LWM16 + 2:
14683 case LWM16 + 3:
14685 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14686 int offset = ZIMM(ctx->opcode, 0, 4);
14688 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14689 29, offset << 2);
14691 break;
14692 case SWM16 + 0:
14693 case SWM16 + 1:
14694 case SWM16 + 2:
14695 case SWM16 + 3:
14697 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14698 int offset = ZIMM(ctx->opcode, 0, 4);
14700 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14701 29, offset << 2);
14703 break;
14704 case JR16 + 0:
14705 case JR16 + 1:
14707 int reg = ctx->opcode & 0x1f;
14709 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14711 break;
14712 case JRC16 + 0:
14713 case JRC16 + 1:
14715 int reg = ctx->opcode & 0x1f;
14716 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14717 /* Let normal delay slot handling in our caller take us
14718 to the branch target. */
14720 break;
14721 case JALR16 + 0:
14722 case JALR16 + 1:
14723 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14724 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14725 break;
14726 case JALR16S + 0:
14727 case JALR16S + 1:
14728 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14729 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14730 break;
14731 case MFHI16 + 0:
14732 case MFHI16 + 1:
14733 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14734 break;
14735 case MFLO16 + 0:
14736 case MFLO16 + 1:
14737 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14738 break;
14739 case BREAK16:
14740 generate_exception_end(ctx, EXCP_BREAK);
14741 break;
14742 case SDBBP16:
14743 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14744 gen_helper_do_semihosting(cpu_env);
14745 } else {
14746 /* XXX: not clear which exception should be raised
14747 * when in debug mode...
14749 check_insn(ctx, ISA_MIPS32);
14750 generate_exception_end(ctx, EXCP_DBp);
14752 break;
14753 case JRADDIUSP + 0:
14754 case JRADDIUSP + 1:
14756 int imm = ZIMM(ctx->opcode, 0, 5);
14757 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14758 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14759 /* Let normal delay slot handling in our caller take us
14760 to the branch target. */
14762 break;
14763 default:
14764 generate_exception_end(ctx, EXCP_RI);
14765 break;
14769 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14770 int enc_rs)
14772 int rd, rs, re, rt;
14773 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14774 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14775 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14776 rd = rd_enc[enc_dest];
14777 re = re_enc[enc_dest];
14778 rs = rs_rt_enc[enc_rs];
14779 rt = rs_rt_enc[enc_rt];
14780 if (rs) {
14781 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14782 } else {
14783 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14785 if (rt) {
14786 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14787 } else {
14788 tcg_gen_movi_tl(cpu_gpr[re], 0);
14792 static void gen_pool16c_r6_insn(DisasContext *ctx)
14794 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14795 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14797 switch (ctx->opcode & 0xf) {
14798 case R6_NOT16:
14799 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14800 break;
14801 case R6_AND16:
14802 gen_logic(ctx, OPC_AND, rt, rt, rs);
14803 break;
14804 case R6_LWM16:
14806 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14807 int offset = extract32(ctx->opcode, 4, 4);
14808 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14810 break;
14811 case R6_JRC16: /* JRCADDIUSP */
14812 if ((ctx->opcode >> 4) & 1) {
14813 /* JRCADDIUSP */
14814 int imm = extract32(ctx->opcode, 5, 5);
14815 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14816 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14817 } else {
14818 /* JRC16 */
14819 rs = extract32(ctx->opcode, 5, 5);
14820 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14822 break;
14823 case MOVEP:
14824 case MOVEP_05:
14825 case MOVEP_06:
14826 case MOVEP_07:
14827 case MOVEP_0C:
14828 case MOVEP_0D:
14829 case MOVEP_0E:
14830 case MOVEP_0F:
14832 int enc_dest = uMIPS_RD(ctx->opcode);
14833 int enc_rt = uMIPS_RS2(ctx->opcode);
14834 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14835 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14837 break;
14838 case R6_XOR16:
14839 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14840 break;
14841 case R6_OR16:
14842 gen_logic(ctx, OPC_OR, rt, rt, rs);
14843 break;
14844 case R6_SWM16:
14846 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14847 int offset = extract32(ctx->opcode, 4, 4);
14848 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14850 break;
14851 case JALRC16: /* BREAK16, SDBBP16 */
14852 switch (ctx->opcode & 0x3f) {
14853 case JALRC16:
14854 case JALRC16 + 0x20:
14855 /* JALRC16 */
14856 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14857 31, 0, 0);
14858 break;
14859 case R6_BREAK16:
14860 /* BREAK16 */
14861 generate_exception(ctx, EXCP_BREAK);
14862 break;
14863 case R6_SDBBP16:
14864 /* SDBBP16 */
14865 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14866 gen_helper_do_semihosting(cpu_env);
14867 } else {
14868 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14869 generate_exception(ctx, EXCP_RI);
14870 } else {
14871 generate_exception(ctx, EXCP_DBp);
14874 break;
14876 break;
14877 default:
14878 generate_exception(ctx, EXCP_RI);
14879 break;
14883 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14885 TCGv t0 = tcg_temp_new();
14886 TCGv t1 = tcg_temp_new();
14888 gen_load_gpr(t0, base);
14890 if (index != 0) {
14891 gen_load_gpr(t1, index);
14892 tcg_gen_shli_tl(t1, t1, 2);
14893 gen_op_addr_add(ctx, t0, t1, t0);
14896 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14897 gen_store_gpr(t1, rd);
14899 tcg_temp_free(t0);
14900 tcg_temp_free(t1);
14903 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14904 int base, int16_t offset)
14906 TCGv t0, t1;
14908 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14909 generate_exception_end(ctx, EXCP_RI);
14910 return;
14913 t0 = tcg_temp_new();
14914 t1 = tcg_temp_new();
14916 gen_base_offset_addr(ctx, t0, base, offset);
14918 switch (opc) {
14919 case LWP:
14920 if (rd == base) {
14921 generate_exception_end(ctx, EXCP_RI);
14922 return;
14924 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14925 gen_store_gpr(t1, rd);
14926 tcg_gen_movi_tl(t1, 4);
14927 gen_op_addr_add(ctx, t0, t0, t1);
14928 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14929 gen_store_gpr(t1, rd+1);
14930 break;
14931 case SWP:
14932 gen_load_gpr(t1, rd);
14933 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14934 tcg_gen_movi_tl(t1, 4);
14935 gen_op_addr_add(ctx, t0, t0, t1);
14936 gen_load_gpr(t1, rd+1);
14937 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14938 break;
14939 #ifdef TARGET_MIPS64
14940 case LDP:
14941 if (rd == base) {
14942 generate_exception_end(ctx, EXCP_RI);
14943 return;
14945 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14946 gen_store_gpr(t1, rd);
14947 tcg_gen_movi_tl(t1, 8);
14948 gen_op_addr_add(ctx, t0, t0, t1);
14949 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14950 gen_store_gpr(t1, rd+1);
14951 break;
14952 case SDP:
14953 gen_load_gpr(t1, rd);
14954 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14955 tcg_gen_movi_tl(t1, 8);
14956 gen_op_addr_add(ctx, t0, t0, t1);
14957 gen_load_gpr(t1, rd+1);
14958 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14959 break;
14960 #endif
14962 tcg_temp_free(t0);
14963 tcg_temp_free(t1);
14966 static void gen_sync(int stype)
14968 TCGBar tcg_mo = TCG_BAR_SC;
14970 switch (stype) {
14971 case 0x4: /* SYNC_WMB */
14972 tcg_mo |= TCG_MO_ST_ST;
14973 break;
14974 case 0x10: /* SYNC_MB */
14975 tcg_mo |= TCG_MO_ALL;
14976 break;
14977 case 0x11: /* SYNC_ACQUIRE */
14978 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14979 break;
14980 case 0x12: /* SYNC_RELEASE */
14981 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14982 break;
14983 case 0x13: /* SYNC_RMB */
14984 tcg_mo |= TCG_MO_LD_LD;
14985 break;
14986 default:
14987 tcg_mo |= TCG_MO_ALL;
14988 break;
14991 tcg_gen_mb(tcg_mo);
14994 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14996 int extension = (ctx->opcode >> 6) & 0x3f;
14997 int minor = (ctx->opcode >> 12) & 0xf;
14998 uint32_t mips32_op;
15000 switch (extension) {
15001 case TEQ:
15002 mips32_op = OPC_TEQ;
15003 goto do_trap;
15004 case TGE:
15005 mips32_op = OPC_TGE;
15006 goto do_trap;
15007 case TGEU:
15008 mips32_op = OPC_TGEU;
15009 goto do_trap;
15010 case TLT:
15011 mips32_op = OPC_TLT;
15012 goto do_trap;
15013 case TLTU:
15014 mips32_op = OPC_TLTU;
15015 goto do_trap;
15016 case TNE:
15017 mips32_op = OPC_TNE;
15018 do_trap:
15019 gen_trap(ctx, mips32_op, rs, rt, -1);
15020 break;
15021 #ifndef CONFIG_USER_ONLY
15022 case MFC0:
15023 case MFC0 + 32:
15024 check_cp0_enabled(ctx);
15025 if (rt == 0) {
15026 /* Treat as NOP. */
15027 break;
15029 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15030 break;
15031 case MTC0:
15032 case MTC0 + 32:
15033 check_cp0_enabled(ctx);
15035 TCGv t0 = tcg_temp_new();
15037 gen_load_gpr(t0, rt);
15038 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15039 tcg_temp_free(t0);
15041 break;
15042 #endif
15043 case 0x2a:
15044 switch (minor & 3) {
15045 case MADD_ACC:
15046 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15047 break;
15048 case MADDU_ACC:
15049 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15050 break;
15051 case MSUB_ACC:
15052 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15053 break;
15054 case MSUBU_ACC:
15055 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15056 break;
15057 default:
15058 goto pool32axf_invalid;
15060 break;
15061 case 0x32:
15062 switch (minor & 3) {
15063 case MULT_ACC:
15064 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15065 break;
15066 case MULTU_ACC:
15067 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15068 break;
15069 default:
15070 goto pool32axf_invalid;
15072 break;
15073 case 0x2c:
15074 switch (minor) {
15075 case BITSWAP:
15076 check_insn(ctx, ISA_MIPS32R6);
15077 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15078 break;
15079 case SEB:
15080 gen_bshfl(ctx, OPC_SEB, rs, rt);
15081 break;
15082 case SEH:
15083 gen_bshfl(ctx, OPC_SEH, rs, rt);
15084 break;
15085 case CLO:
15086 mips32_op = OPC_CLO;
15087 goto do_cl;
15088 case CLZ:
15089 mips32_op = OPC_CLZ;
15090 do_cl:
15091 check_insn(ctx, ISA_MIPS32);
15092 gen_cl(ctx, mips32_op, rt, rs);
15093 break;
15094 case RDHWR:
15095 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15096 gen_rdhwr(ctx, rt, rs, 0);
15097 break;
15098 case WSBH:
15099 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15100 break;
15101 case MULT:
15102 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15103 mips32_op = OPC_MULT;
15104 goto do_mul;
15105 case MULTU:
15106 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15107 mips32_op = OPC_MULTU;
15108 goto do_mul;
15109 case DIV:
15110 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15111 mips32_op = OPC_DIV;
15112 goto do_div;
15113 case DIVU:
15114 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15115 mips32_op = OPC_DIVU;
15116 goto do_div;
15117 do_div:
15118 check_insn(ctx, ISA_MIPS32);
15119 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15120 break;
15121 case MADD:
15122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15123 mips32_op = OPC_MADD;
15124 goto do_mul;
15125 case MADDU:
15126 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15127 mips32_op = OPC_MADDU;
15128 goto do_mul;
15129 case MSUB:
15130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15131 mips32_op = OPC_MSUB;
15132 goto do_mul;
15133 case MSUBU:
15134 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15135 mips32_op = OPC_MSUBU;
15136 do_mul:
15137 check_insn(ctx, ISA_MIPS32);
15138 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15139 break;
15140 default:
15141 goto pool32axf_invalid;
15143 break;
15144 case 0x34:
15145 switch (minor) {
15146 case MFC2:
15147 case MTC2:
15148 case MFHC2:
15149 case MTHC2:
15150 case CFC2:
15151 case CTC2:
15152 generate_exception_err(ctx, EXCP_CpU, 2);
15153 break;
15154 default:
15155 goto pool32axf_invalid;
15157 break;
15158 case 0x3c:
15159 switch (minor) {
15160 case JALR: /* JALRC */
15161 case JALR_HB: /* JALRC_HB */
15162 if (ctx->insn_flags & ISA_MIPS32R6) {
15163 /* JALRC, JALRC_HB */
15164 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15165 } else {
15166 /* JALR, JALR_HB */
15167 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15168 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15170 break;
15171 case JALRS:
15172 case JALRS_HB:
15173 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15174 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15175 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15176 break;
15177 default:
15178 goto pool32axf_invalid;
15180 break;
15181 case 0x05:
15182 switch (minor) {
15183 case RDPGPR:
15184 check_cp0_enabled(ctx);
15185 check_insn(ctx, ISA_MIPS32R2);
15186 gen_load_srsgpr(rs, rt);
15187 break;
15188 case WRPGPR:
15189 check_cp0_enabled(ctx);
15190 check_insn(ctx, ISA_MIPS32R2);
15191 gen_store_srsgpr(rs, rt);
15192 break;
15193 default:
15194 goto pool32axf_invalid;
15196 break;
15197 #ifndef CONFIG_USER_ONLY
15198 case 0x0d:
15199 switch (minor) {
15200 case TLBP:
15201 mips32_op = OPC_TLBP;
15202 goto do_cp0;
15203 case TLBR:
15204 mips32_op = OPC_TLBR;
15205 goto do_cp0;
15206 case TLBWI:
15207 mips32_op = OPC_TLBWI;
15208 goto do_cp0;
15209 case TLBWR:
15210 mips32_op = OPC_TLBWR;
15211 goto do_cp0;
15212 case TLBINV:
15213 mips32_op = OPC_TLBINV;
15214 goto do_cp0;
15215 case TLBINVF:
15216 mips32_op = OPC_TLBINVF;
15217 goto do_cp0;
15218 case WAIT:
15219 mips32_op = OPC_WAIT;
15220 goto do_cp0;
15221 case DERET:
15222 mips32_op = OPC_DERET;
15223 goto do_cp0;
15224 case ERET:
15225 mips32_op = OPC_ERET;
15226 do_cp0:
15227 gen_cp0(env, ctx, mips32_op, rt, rs);
15228 break;
15229 default:
15230 goto pool32axf_invalid;
15232 break;
15233 case 0x1d:
15234 switch (minor) {
15235 case DI:
15236 check_cp0_enabled(ctx);
15238 TCGv t0 = tcg_temp_new();
15240 save_cpu_state(ctx, 1);
15241 gen_helper_di(t0, cpu_env);
15242 gen_store_gpr(t0, rs);
15243 /* Stop translation as we may have switched the execution mode */
15244 ctx->base.is_jmp = DISAS_STOP;
15245 tcg_temp_free(t0);
15247 break;
15248 case EI:
15249 check_cp0_enabled(ctx);
15251 TCGv t0 = tcg_temp_new();
15253 save_cpu_state(ctx, 1);
15254 gen_helper_ei(t0, cpu_env);
15255 gen_store_gpr(t0, rs);
15256 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15257 of translated code to check for pending interrupts. */
15258 gen_save_pc(ctx->base.pc_next + 4);
15259 ctx->base.is_jmp = DISAS_EXIT;
15260 tcg_temp_free(t0);
15262 break;
15263 default:
15264 goto pool32axf_invalid;
15266 break;
15267 #endif
15268 case 0x2d:
15269 switch (minor) {
15270 case SYNC:
15271 gen_sync(extract32(ctx->opcode, 16, 5));
15272 break;
15273 case SYSCALL:
15274 generate_exception_end(ctx, EXCP_SYSCALL);
15275 break;
15276 case SDBBP:
15277 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15278 gen_helper_do_semihosting(cpu_env);
15279 } else {
15280 check_insn(ctx, ISA_MIPS32);
15281 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15282 generate_exception_end(ctx, EXCP_RI);
15283 } else {
15284 generate_exception_end(ctx, EXCP_DBp);
15287 break;
15288 default:
15289 goto pool32axf_invalid;
15291 break;
15292 case 0x01:
15293 switch (minor & 3) {
15294 case MFHI_ACC:
15295 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15296 break;
15297 case MFLO_ACC:
15298 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15299 break;
15300 case MTHI_ACC:
15301 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15302 break;
15303 case MTLO_ACC:
15304 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15305 break;
15306 default:
15307 goto pool32axf_invalid;
15309 break;
15310 case 0x35:
15311 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15312 switch (minor) {
15313 case MFHI32:
15314 gen_HILO(ctx, OPC_MFHI, 0, rs);
15315 break;
15316 case MFLO32:
15317 gen_HILO(ctx, OPC_MFLO, 0, rs);
15318 break;
15319 case MTHI32:
15320 gen_HILO(ctx, OPC_MTHI, 0, rs);
15321 break;
15322 case MTLO32:
15323 gen_HILO(ctx, OPC_MTLO, 0, rs);
15324 break;
15325 default:
15326 goto pool32axf_invalid;
15328 break;
15329 default:
15330 pool32axf_invalid:
15331 MIPS_INVAL("pool32axf");
15332 generate_exception_end(ctx, EXCP_RI);
15333 break;
15337 /* Values for microMIPS fmt field. Variable-width, depending on which
15338 formats the instruction supports. */
15340 enum {
15341 FMT_SD_S = 0,
15342 FMT_SD_D = 1,
15344 FMT_SDPS_S = 0,
15345 FMT_SDPS_D = 1,
15346 FMT_SDPS_PS = 2,
15348 FMT_SWL_S = 0,
15349 FMT_SWL_W = 1,
15350 FMT_SWL_L = 2,
15352 FMT_DWL_D = 0,
15353 FMT_DWL_W = 1,
15354 FMT_DWL_L = 2
15357 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15359 int extension = (ctx->opcode >> 6) & 0x3ff;
15360 uint32_t mips32_op;
15362 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15363 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15364 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15366 switch (extension) {
15367 case FLOAT_1BIT_FMT(CFC1, 0):
15368 mips32_op = OPC_CFC1;
15369 goto do_cp1;
15370 case FLOAT_1BIT_FMT(CTC1, 0):
15371 mips32_op = OPC_CTC1;
15372 goto do_cp1;
15373 case FLOAT_1BIT_FMT(MFC1, 0):
15374 mips32_op = OPC_MFC1;
15375 goto do_cp1;
15376 case FLOAT_1BIT_FMT(MTC1, 0):
15377 mips32_op = OPC_MTC1;
15378 goto do_cp1;
15379 case FLOAT_1BIT_FMT(MFHC1, 0):
15380 mips32_op = OPC_MFHC1;
15381 goto do_cp1;
15382 case FLOAT_1BIT_FMT(MTHC1, 0):
15383 mips32_op = OPC_MTHC1;
15384 do_cp1:
15385 gen_cp1(ctx, mips32_op, rt, rs);
15386 break;
15388 /* Reciprocal square root */
15389 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15390 mips32_op = OPC_RSQRT_S;
15391 goto do_unaryfp;
15392 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15393 mips32_op = OPC_RSQRT_D;
15394 goto do_unaryfp;
15396 /* Square root */
15397 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15398 mips32_op = OPC_SQRT_S;
15399 goto do_unaryfp;
15400 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15401 mips32_op = OPC_SQRT_D;
15402 goto do_unaryfp;
15404 /* Reciprocal */
15405 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15406 mips32_op = OPC_RECIP_S;
15407 goto do_unaryfp;
15408 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15409 mips32_op = OPC_RECIP_D;
15410 goto do_unaryfp;
15412 /* Floor */
15413 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15414 mips32_op = OPC_FLOOR_L_S;
15415 goto do_unaryfp;
15416 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15417 mips32_op = OPC_FLOOR_L_D;
15418 goto do_unaryfp;
15419 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15420 mips32_op = OPC_FLOOR_W_S;
15421 goto do_unaryfp;
15422 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15423 mips32_op = OPC_FLOOR_W_D;
15424 goto do_unaryfp;
15426 /* Ceiling */
15427 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15428 mips32_op = OPC_CEIL_L_S;
15429 goto do_unaryfp;
15430 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15431 mips32_op = OPC_CEIL_L_D;
15432 goto do_unaryfp;
15433 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15434 mips32_op = OPC_CEIL_W_S;
15435 goto do_unaryfp;
15436 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15437 mips32_op = OPC_CEIL_W_D;
15438 goto do_unaryfp;
15440 /* Truncation */
15441 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15442 mips32_op = OPC_TRUNC_L_S;
15443 goto do_unaryfp;
15444 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15445 mips32_op = OPC_TRUNC_L_D;
15446 goto do_unaryfp;
15447 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15448 mips32_op = OPC_TRUNC_W_S;
15449 goto do_unaryfp;
15450 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15451 mips32_op = OPC_TRUNC_W_D;
15452 goto do_unaryfp;
15454 /* Round */
15455 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15456 mips32_op = OPC_ROUND_L_S;
15457 goto do_unaryfp;
15458 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15459 mips32_op = OPC_ROUND_L_D;
15460 goto do_unaryfp;
15461 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15462 mips32_op = OPC_ROUND_W_S;
15463 goto do_unaryfp;
15464 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15465 mips32_op = OPC_ROUND_W_D;
15466 goto do_unaryfp;
15468 /* Integer to floating-point conversion */
15469 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15470 mips32_op = OPC_CVT_L_S;
15471 goto do_unaryfp;
15472 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15473 mips32_op = OPC_CVT_L_D;
15474 goto do_unaryfp;
15475 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15476 mips32_op = OPC_CVT_W_S;
15477 goto do_unaryfp;
15478 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15479 mips32_op = OPC_CVT_W_D;
15480 goto do_unaryfp;
15482 /* Paired-foo conversions */
15483 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15484 mips32_op = OPC_CVT_S_PL;
15485 goto do_unaryfp;
15486 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15487 mips32_op = OPC_CVT_S_PU;
15488 goto do_unaryfp;
15489 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15490 mips32_op = OPC_CVT_PW_PS;
15491 goto do_unaryfp;
15492 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15493 mips32_op = OPC_CVT_PS_PW;
15494 goto do_unaryfp;
15496 /* Floating-point moves */
15497 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15498 mips32_op = OPC_MOV_S;
15499 goto do_unaryfp;
15500 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15501 mips32_op = OPC_MOV_D;
15502 goto do_unaryfp;
15503 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15504 mips32_op = OPC_MOV_PS;
15505 goto do_unaryfp;
15507 /* Absolute value */
15508 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15509 mips32_op = OPC_ABS_S;
15510 goto do_unaryfp;
15511 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15512 mips32_op = OPC_ABS_D;
15513 goto do_unaryfp;
15514 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15515 mips32_op = OPC_ABS_PS;
15516 goto do_unaryfp;
15518 /* Negation */
15519 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15520 mips32_op = OPC_NEG_S;
15521 goto do_unaryfp;
15522 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15523 mips32_op = OPC_NEG_D;
15524 goto do_unaryfp;
15525 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15526 mips32_op = OPC_NEG_PS;
15527 goto do_unaryfp;
15529 /* Reciprocal square root step */
15530 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15531 mips32_op = OPC_RSQRT1_S;
15532 goto do_unaryfp;
15533 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15534 mips32_op = OPC_RSQRT1_D;
15535 goto do_unaryfp;
15536 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15537 mips32_op = OPC_RSQRT1_PS;
15538 goto do_unaryfp;
15540 /* Reciprocal step */
15541 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15542 mips32_op = OPC_RECIP1_S;
15543 goto do_unaryfp;
15544 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15545 mips32_op = OPC_RECIP1_S;
15546 goto do_unaryfp;
15547 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15548 mips32_op = OPC_RECIP1_PS;
15549 goto do_unaryfp;
15551 /* Conversions from double */
15552 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15553 mips32_op = OPC_CVT_D_S;
15554 goto do_unaryfp;
15555 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15556 mips32_op = OPC_CVT_D_W;
15557 goto do_unaryfp;
15558 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15559 mips32_op = OPC_CVT_D_L;
15560 goto do_unaryfp;
15562 /* Conversions from single */
15563 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15564 mips32_op = OPC_CVT_S_D;
15565 goto do_unaryfp;
15566 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15567 mips32_op = OPC_CVT_S_W;
15568 goto do_unaryfp;
15569 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15570 mips32_op = OPC_CVT_S_L;
15571 do_unaryfp:
15572 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15573 break;
15575 /* Conditional moves on floating-point codes */
15576 case COND_FLOAT_MOV(MOVT, 0):
15577 case COND_FLOAT_MOV(MOVT, 1):
15578 case COND_FLOAT_MOV(MOVT, 2):
15579 case COND_FLOAT_MOV(MOVT, 3):
15580 case COND_FLOAT_MOV(MOVT, 4):
15581 case COND_FLOAT_MOV(MOVT, 5):
15582 case COND_FLOAT_MOV(MOVT, 6):
15583 case COND_FLOAT_MOV(MOVT, 7):
15584 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15585 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15586 break;
15587 case COND_FLOAT_MOV(MOVF, 0):
15588 case COND_FLOAT_MOV(MOVF, 1):
15589 case COND_FLOAT_MOV(MOVF, 2):
15590 case COND_FLOAT_MOV(MOVF, 3):
15591 case COND_FLOAT_MOV(MOVF, 4):
15592 case COND_FLOAT_MOV(MOVF, 5):
15593 case COND_FLOAT_MOV(MOVF, 6):
15594 case COND_FLOAT_MOV(MOVF, 7):
15595 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15596 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15597 break;
15598 default:
15599 MIPS_INVAL("pool32fxf");
15600 generate_exception_end(ctx, EXCP_RI);
15601 break;
15605 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15607 int32_t offset;
15608 uint16_t insn;
15609 int rt, rs, rd, rr;
15610 int16_t imm;
15611 uint32_t op, minor, minor2, mips32_op;
15612 uint32_t cond, fmt, cc;
15614 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15615 ctx->opcode = (ctx->opcode << 16) | insn;
15617 rt = (ctx->opcode >> 21) & 0x1f;
15618 rs = (ctx->opcode >> 16) & 0x1f;
15619 rd = (ctx->opcode >> 11) & 0x1f;
15620 rr = (ctx->opcode >> 6) & 0x1f;
15621 imm = (int16_t) ctx->opcode;
15623 op = (ctx->opcode >> 26) & 0x3f;
15624 switch (op) {
15625 case POOL32A:
15626 minor = ctx->opcode & 0x3f;
15627 switch (minor) {
15628 case 0x00:
15629 minor = (ctx->opcode >> 6) & 0xf;
15630 switch (minor) {
15631 case SLL32:
15632 mips32_op = OPC_SLL;
15633 goto do_shifti;
15634 case SRA:
15635 mips32_op = OPC_SRA;
15636 goto do_shifti;
15637 case SRL32:
15638 mips32_op = OPC_SRL;
15639 goto do_shifti;
15640 case ROTR:
15641 mips32_op = OPC_ROTR;
15642 do_shifti:
15643 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15644 break;
15645 case SELEQZ:
15646 check_insn(ctx, ISA_MIPS32R6);
15647 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15648 break;
15649 case SELNEZ:
15650 check_insn(ctx, ISA_MIPS32R6);
15651 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15652 break;
15653 case R6_RDHWR:
15654 check_insn(ctx, ISA_MIPS32R6);
15655 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15656 break;
15657 default:
15658 goto pool32a_invalid;
15660 break;
15661 case 0x10:
15662 minor = (ctx->opcode >> 6) & 0xf;
15663 switch (minor) {
15664 /* Arithmetic */
15665 case ADD:
15666 mips32_op = OPC_ADD;
15667 goto do_arith;
15668 case ADDU32:
15669 mips32_op = OPC_ADDU;
15670 goto do_arith;
15671 case SUB:
15672 mips32_op = OPC_SUB;
15673 goto do_arith;
15674 case SUBU32:
15675 mips32_op = OPC_SUBU;
15676 goto do_arith;
15677 case MUL:
15678 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15679 mips32_op = OPC_MUL;
15680 do_arith:
15681 gen_arith(ctx, mips32_op, rd, rs, rt);
15682 break;
15683 /* Shifts */
15684 case SLLV:
15685 mips32_op = OPC_SLLV;
15686 goto do_shift;
15687 case SRLV:
15688 mips32_op = OPC_SRLV;
15689 goto do_shift;
15690 case SRAV:
15691 mips32_op = OPC_SRAV;
15692 goto do_shift;
15693 case ROTRV:
15694 mips32_op = OPC_ROTRV;
15695 do_shift:
15696 gen_shift(ctx, mips32_op, rd, rs, rt);
15697 break;
15698 /* Logical operations */
15699 case AND:
15700 mips32_op = OPC_AND;
15701 goto do_logic;
15702 case OR32:
15703 mips32_op = OPC_OR;
15704 goto do_logic;
15705 case NOR:
15706 mips32_op = OPC_NOR;
15707 goto do_logic;
15708 case XOR32:
15709 mips32_op = OPC_XOR;
15710 do_logic:
15711 gen_logic(ctx, mips32_op, rd, rs, rt);
15712 break;
15713 /* Set less than */
15714 case SLT:
15715 mips32_op = OPC_SLT;
15716 goto do_slt;
15717 case SLTU:
15718 mips32_op = OPC_SLTU;
15719 do_slt:
15720 gen_slt(ctx, mips32_op, rd, rs, rt);
15721 break;
15722 default:
15723 goto pool32a_invalid;
15725 break;
15726 case 0x18:
15727 minor = (ctx->opcode >> 6) & 0xf;
15728 switch (minor) {
15729 /* Conditional moves */
15730 case MOVN: /* MUL */
15731 if (ctx->insn_flags & ISA_MIPS32R6) {
15732 /* MUL */
15733 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15734 } else {
15735 /* MOVN */
15736 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15738 break;
15739 case MOVZ: /* MUH */
15740 if (ctx->insn_flags & ISA_MIPS32R6) {
15741 /* MUH */
15742 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15743 } else {
15744 /* MOVZ */
15745 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15747 break;
15748 case MULU:
15749 check_insn(ctx, ISA_MIPS32R6);
15750 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15751 break;
15752 case MUHU:
15753 check_insn(ctx, ISA_MIPS32R6);
15754 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15755 break;
15756 case LWXS: /* DIV */
15757 if (ctx->insn_flags & ISA_MIPS32R6) {
15758 /* DIV */
15759 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15760 } else {
15761 /* LWXS */
15762 gen_ldxs(ctx, rs, rt, rd);
15764 break;
15765 case MOD:
15766 check_insn(ctx, ISA_MIPS32R6);
15767 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15768 break;
15769 case R6_DIVU:
15770 check_insn(ctx, ISA_MIPS32R6);
15771 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15772 break;
15773 case MODU:
15774 check_insn(ctx, ISA_MIPS32R6);
15775 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15776 break;
15777 default:
15778 goto pool32a_invalid;
15780 break;
15781 case INS:
15782 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15783 return;
15784 case LSA:
15785 check_insn(ctx, ISA_MIPS32R6);
15786 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15787 extract32(ctx->opcode, 9, 2));
15788 break;
15789 case ALIGN:
15790 check_insn(ctx, ISA_MIPS32R6);
15791 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15792 break;
15793 case EXT:
15794 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15795 return;
15796 case POOL32AXF:
15797 gen_pool32axf(env, ctx, rt, rs);
15798 break;
15799 case BREAK32:
15800 generate_exception_end(ctx, EXCP_BREAK);
15801 break;
15802 case SIGRIE:
15803 check_insn(ctx, ISA_MIPS32R6);
15804 generate_exception_end(ctx, EXCP_RI);
15805 break;
15806 default:
15807 pool32a_invalid:
15808 MIPS_INVAL("pool32a");
15809 generate_exception_end(ctx, EXCP_RI);
15810 break;
15812 break;
15813 case POOL32B:
15814 minor = (ctx->opcode >> 12) & 0xf;
15815 switch (minor) {
15816 case CACHE:
15817 check_cp0_enabled(ctx);
15818 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15819 gen_cache_operation(ctx, rt, rs, imm);
15821 break;
15822 case LWC2:
15823 case SWC2:
15824 /* COP2: Not implemented. */
15825 generate_exception_err(ctx, EXCP_CpU, 2);
15826 break;
15827 #ifdef TARGET_MIPS64
15828 case LDP:
15829 case SDP:
15830 check_insn(ctx, ISA_MIPS3);
15831 check_mips_64(ctx);
15832 #endif
15833 /* fall through */
15834 case LWP:
15835 case SWP:
15836 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15837 break;
15838 #ifdef TARGET_MIPS64
15839 case LDM:
15840 case SDM:
15841 check_insn(ctx, ISA_MIPS3);
15842 check_mips_64(ctx);
15843 #endif
15844 /* fall through */
15845 case LWM32:
15846 case SWM32:
15847 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15848 break;
15849 default:
15850 MIPS_INVAL("pool32b");
15851 generate_exception_end(ctx, EXCP_RI);
15852 break;
15854 break;
15855 case POOL32F:
15856 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15857 minor = ctx->opcode & 0x3f;
15858 check_cp1_enabled(ctx);
15859 switch (minor) {
15860 case ALNV_PS:
15861 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15862 mips32_op = OPC_ALNV_PS;
15863 goto do_madd;
15864 case MADD_S:
15865 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15866 mips32_op = OPC_MADD_S;
15867 goto do_madd;
15868 case MADD_D:
15869 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15870 mips32_op = OPC_MADD_D;
15871 goto do_madd;
15872 case MADD_PS:
15873 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15874 mips32_op = OPC_MADD_PS;
15875 goto do_madd;
15876 case MSUB_S:
15877 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15878 mips32_op = OPC_MSUB_S;
15879 goto do_madd;
15880 case MSUB_D:
15881 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15882 mips32_op = OPC_MSUB_D;
15883 goto do_madd;
15884 case MSUB_PS:
15885 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15886 mips32_op = OPC_MSUB_PS;
15887 goto do_madd;
15888 case NMADD_S:
15889 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15890 mips32_op = OPC_NMADD_S;
15891 goto do_madd;
15892 case NMADD_D:
15893 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15894 mips32_op = OPC_NMADD_D;
15895 goto do_madd;
15896 case NMADD_PS:
15897 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15898 mips32_op = OPC_NMADD_PS;
15899 goto do_madd;
15900 case NMSUB_S:
15901 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15902 mips32_op = OPC_NMSUB_S;
15903 goto do_madd;
15904 case NMSUB_D:
15905 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15906 mips32_op = OPC_NMSUB_D;
15907 goto do_madd;
15908 case NMSUB_PS:
15909 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15910 mips32_op = OPC_NMSUB_PS;
15911 do_madd:
15912 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15913 break;
15914 case CABS_COND_FMT:
15915 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15916 cond = (ctx->opcode >> 6) & 0xf;
15917 cc = (ctx->opcode >> 13) & 0x7;
15918 fmt = (ctx->opcode >> 10) & 0x3;
15919 switch (fmt) {
15920 case 0x0:
15921 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15922 break;
15923 case 0x1:
15924 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15925 break;
15926 case 0x2:
15927 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15928 break;
15929 default:
15930 goto pool32f_invalid;
15932 break;
15933 case C_COND_FMT:
15934 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15935 cond = (ctx->opcode >> 6) & 0xf;
15936 cc = (ctx->opcode >> 13) & 0x7;
15937 fmt = (ctx->opcode >> 10) & 0x3;
15938 switch (fmt) {
15939 case 0x0:
15940 gen_cmp_s(ctx, cond, rt, rs, cc);
15941 break;
15942 case 0x1:
15943 gen_cmp_d(ctx, cond, rt, rs, cc);
15944 break;
15945 case 0x2:
15946 gen_cmp_ps(ctx, cond, rt, rs, cc);
15947 break;
15948 default:
15949 goto pool32f_invalid;
15951 break;
15952 case CMP_CONDN_S:
15953 check_insn(ctx, ISA_MIPS32R6);
15954 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15955 break;
15956 case CMP_CONDN_D:
15957 check_insn(ctx, ISA_MIPS32R6);
15958 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15959 break;
15960 case POOL32FXF:
15961 gen_pool32fxf(ctx, rt, rs);
15962 break;
15963 case 0x00:
15964 /* PLL foo */
15965 switch ((ctx->opcode >> 6) & 0x7) {
15966 case PLL_PS:
15967 mips32_op = OPC_PLL_PS;
15968 goto do_ps;
15969 case PLU_PS:
15970 mips32_op = OPC_PLU_PS;
15971 goto do_ps;
15972 case PUL_PS:
15973 mips32_op = OPC_PUL_PS;
15974 goto do_ps;
15975 case PUU_PS:
15976 mips32_op = OPC_PUU_PS;
15977 goto do_ps;
15978 case CVT_PS_S:
15979 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15980 mips32_op = OPC_CVT_PS_S;
15981 do_ps:
15982 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15983 break;
15984 default:
15985 goto pool32f_invalid;
15987 break;
15988 case MIN_FMT:
15989 check_insn(ctx, ISA_MIPS32R6);
15990 switch ((ctx->opcode >> 9) & 0x3) {
15991 case FMT_SDPS_S:
15992 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15993 break;
15994 case FMT_SDPS_D:
15995 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15996 break;
15997 default:
15998 goto pool32f_invalid;
16000 break;
16001 case 0x08:
16002 /* [LS][WDU]XC1 */
16003 switch ((ctx->opcode >> 6) & 0x7) {
16004 case LWXC1:
16005 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16006 mips32_op = OPC_LWXC1;
16007 goto do_ldst_cp1;
16008 case SWXC1:
16009 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16010 mips32_op = OPC_SWXC1;
16011 goto do_ldst_cp1;
16012 case LDXC1:
16013 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16014 mips32_op = OPC_LDXC1;
16015 goto do_ldst_cp1;
16016 case SDXC1:
16017 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16018 mips32_op = OPC_SDXC1;
16019 goto do_ldst_cp1;
16020 case LUXC1:
16021 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16022 mips32_op = OPC_LUXC1;
16023 goto do_ldst_cp1;
16024 case SUXC1:
16025 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16026 mips32_op = OPC_SUXC1;
16027 do_ldst_cp1:
16028 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16029 break;
16030 default:
16031 goto pool32f_invalid;
16033 break;
16034 case MAX_FMT:
16035 check_insn(ctx, ISA_MIPS32R6);
16036 switch ((ctx->opcode >> 9) & 0x3) {
16037 case FMT_SDPS_S:
16038 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16039 break;
16040 case FMT_SDPS_D:
16041 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16042 break;
16043 default:
16044 goto pool32f_invalid;
16046 break;
16047 case 0x18:
16048 /* 3D insns */
16049 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16050 fmt = (ctx->opcode >> 9) & 0x3;
16051 switch ((ctx->opcode >> 6) & 0x7) {
16052 case RSQRT2_FMT:
16053 switch (fmt) {
16054 case FMT_SDPS_S:
16055 mips32_op = OPC_RSQRT2_S;
16056 goto do_3d;
16057 case FMT_SDPS_D:
16058 mips32_op = OPC_RSQRT2_D;
16059 goto do_3d;
16060 case FMT_SDPS_PS:
16061 mips32_op = OPC_RSQRT2_PS;
16062 goto do_3d;
16063 default:
16064 goto pool32f_invalid;
16066 break;
16067 case RECIP2_FMT:
16068 switch (fmt) {
16069 case FMT_SDPS_S:
16070 mips32_op = OPC_RECIP2_S;
16071 goto do_3d;
16072 case FMT_SDPS_D:
16073 mips32_op = OPC_RECIP2_D;
16074 goto do_3d;
16075 case FMT_SDPS_PS:
16076 mips32_op = OPC_RECIP2_PS;
16077 goto do_3d;
16078 default:
16079 goto pool32f_invalid;
16081 break;
16082 case ADDR_PS:
16083 mips32_op = OPC_ADDR_PS;
16084 goto do_3d;
16085 case MULR_PS:
16086 mips32_op = OPC_MULR_PS;
16087 do_3d:
16088 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16089 break;
16090 default:
16091 goto pool32f_invalid;
16093 break;
16094 case 0x20:
16095 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16096 cc = (ctx->opcode >> 13) & 0x7;
16097 fmt = (ctx->opcode >> 9) & 0x3;
16098 switch ((ctx->opcode >> 6) & 0x7) {
16099 case MOVF_FMT: /* RINT_FMT */
16100 if (ctx->insn_flags & ISA_MIPS32R6) {
16101 /* RINT_FMT */
16102 switch (fmt) {
16103 case FMT_SDPS_S:
16104 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16105 break;
16106 case FMT_SDPS_D:
16107 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16108 break;
16109 default:
16110 goto pool32f_invalid;
16112 } else {
16113 /* MOVF_FMT */
16114 switch (fmt) {
16115 case FMT_SDPS_S:
16116 gen_movcf_s(ctx, rs, rt, cc, 0);
16117 break;
16118 case FMT_SDPS_D:
16119 gen_movcf_d(ctx, rs, rt, cc, 0);
16120 break;
16121 case FMT_SDPS_PS:
16122 check_ps(ctx);
16123 gen_movcf_ps(ctx, rs, rt, cc, 0);
16124 break;
16125 default:
16126 goto pool32f_invalid;
16129 break;
16130 case MOVT_FMT: /* CLASS_FMT */
16131 if (ctx->insn_flags & ISA_MIPS32R6) {
16132 /* CLASS_FMT */
16133 switch (fmt) {
16134 case FMT_SDPS_S:
16135 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16136 break;
16137 case FMT_SDPS_D:
16138 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16139 break;
16140 default:
16141 goto pool32f_invalid;
16143 } else {
16144 /* MOVT_FMT */
16145 switch (fmt) {
16146 case FMT_SDPS_S:
16147 gen_movcf_s(ctx, rs, rt, cc, 1);
16148 break;
16149 case FMT_SDPS_D:
16150 gen_movcf_d(ctx, rs, rt, cc, 1);
16151 break;
16152 case FMT_SDPS_PS:
16153 check_ps(ctx);
16154 gen_movcf_ps(ctx, rs, rt, cc, 1);
16155 break;
16156 default:
16157 goto pool32f_invalid;
16160 break;
16161 case PREFX:
16162 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16163 break;
16164 default:
16165 goto pool32f_invalid;
16167 break;
16168 #define FINSN_3ARG_SDPS(prfx) \
16169 switch ((ctx->opcode >> 8) & 0x3) { \
16170 case FMT_SDPS_S: \
16171 mips32_op = OPC_##prfx##_S; \
16172 goto do_fpop; \
16173 case FMT_SDPS_D: \
16174 mips32_op = OPC_##prfx##_D; \
16175 goto do_fpop; \
16176 case FMT_SDPS_PS: \
16177 check_ps(ctx); \
16178 mips32_op = OPC_##prfx##_PS; \
16179 goto do_fpop; \
16180 default: \
16181 goto pool32f_invalid; \
16183 case MINA_FMT:
16184 check_insn(ctx, ISA_MIPS32R6);
16185 switch ((ctx->opcode >> 9) & 0x3) {
16186 case FMT_SDPS_S:
16187 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16188 break;
16189 case FMT_SDPS_D:
16190 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16191 break;
16192 default:
16193 goto pool32f_invalid;
16195 break;
16196 case MAXA_FMT:
16197 check_insn(ctx, ISA_MIPS32R6);
16198 switch ((ctx->opcode >> 9) & 0x3) {
16199 case FMT_SDPS_S:
16200 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16201 break;
16202 case FMT_SDPS_D:
16203 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16204 break;
16205 default:
16206 goto pool32f_invalid;
16208 break;
16209 case 0x30:
16210 /* regular FP ops */
16211 switch ((ctx->opcode >> 6) & 0x3) {
16212 case ADD_FMT:
16213 FINSN_3ARG_SDPS(ADD);
16214 break;
16215 case SUB_FMT:
16216 FINSN_3ARG_SDPS(SUB);
16217 break;
16218 case MUL_FMT:
16219 FINSN_3ARG_SDPS(MUL);
16220 break;
16221 case DIV_FMT:
16222 fmt = (ctx->opcode >> 8) & 0x3;
16223 if (fmt == 1) {
16224 mips32_op = OPC_DIV_D;
16225 } else if (fmt == 0) {
16226 mips32_op = OPC_DIV_S;
16227 } else {
16228 goto pool32f_invalid;
16230 goto do_fpop;
16231 default:
16232 goto pool32f_invalid;
16234 break;
16235 case 0x38:
16236 /* cmovs */
16237 switch ((ctx->opcode >> 6) & 0x7) {
16238 case MOVN_FMT: /* SELEQZ_FMT */
16239 if (ctx->insn_flags & ISA_MIPS32R6) {
16240 /* SELEQZ_FMT */
16241 switch ((ctx->opcode >> 9) & 0x3) {
16242 case FMT_SDPS_S:
16243 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16244 break;
16245 case FMT_SDPS_D:
16246 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16247 break;
16248 default:
16249 goto pool32f_invalid;
16251 } else {
16252 /* MOVN_FMT */
16253 FINSN_3ARG_SDPS(MOVN);
16255 break;
16256 case MOVN_FMT_04:
16257 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16258 FINSN_3ARG_SDPS(MOVN);
16259 break;
16260 case MOVZ_FMT: /* SELNEZ_FMT */
16261 if (ctx->insn_flags & ISA_MIPS32R6) {
16262 /* SELNEZ_FMT */
16263 switch ((ctx->opcode >> 9) & 0x3) {
16264 case FMT_SDPS_S:
16265 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16266 break;
16267 case FMT_SDPS_D:
16268 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16269 break;
16270 default:
16271 goto pool32f_invalid;
16273 } else {
16274 /* MOVZ_FMT */
16275 FINSN_3ARG_SDPS(MOVZ);
16277 break;
16278 case MOVZ_FMT_05:
16279 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16280 FINSN_3ARG_SDPS(MOVZ);
16281 break;
16282 case SEL_FMT:
16283 check_insn(ctx, ISA_MIPS32R6);
16284 switch ((ctx->opcode >> 9) & 0x3) {
16285 case FMT_SDPS_S:
16286 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16287 break;
16288 case FMT_SDPS_D:
16289 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16290 break;
16291 default:
16292 goto pool32f_invalid;
16294 break;
16295 case MADDF_FMT:
16296 check_insn(ctx, ISA_MIPS32R6);
16297 switch ((ctx->opcode >> 9) & 0x3) {
16298 case FMT_SDPS_S:
16299 mips32_op = OPC_MADDF_S;
16300 goto do_fpop;
16301 case FMT_SDPS_D:
16302 mips32_op = OPC_MADDF_D;
16303 goto do_fpop;
16304 default:
16305 goto pool32f_invalid;
16307 break;
16308 case MSUBF_FMT:
16309 check_insn(ctx, ISA_MIPS32R6);
16310 switch ((ctx->opcode >> 9) & 0x3) {
16311 case FMT_SDPS_S:
16312 mips32_op = OPC_MSUBF_S;
16313 goto do_fpop;
16314 case FMT_SDPS_D:
16315 mips32_op = OPC_MSUBF_D;
16316 goto do_fpop;
16317 default:
16318 goto pool32f_invalid;
16320 break;
16321 default:
16322 goto pool32f_invalid;
16324 break;
16325 do_fpop:
16326 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16327 break;
16328 default:
16329 pool32f_invalid:
16330 MIPS_INVAL("pool32f");
16331 generate_exception_end(ctx, EXCP_RI);
16332 break;
16334 } else {
16335 generate_exception_err(ctx, EXCP_CpU, 1);
16337 break;
16338 case POOL32I:
16339 minor = (ctx->opcode >> 21) & 0x1f;
16340 switch (minor) {
16341 case BLTZ:
16342 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16343 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16344 break;
16345 case BLTZAL:
16346 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16347 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16348 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16349 break;
16350 case BLTZALS:
16351 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16352 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16353 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16354 break;
16355 case BGEZ:
16356 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16357 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16358 break;
16359 case BGEZAL:
16360 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16361 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16362 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16363 break;
16364 case BGEZALS:
16365 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16366 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16367 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16368 break;
16369 case BLEZ:
16370 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16371 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16372 break;
16373 case BGTZ:
16374 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16375 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16376 break;
16378 /* Traps */
16379 case TLTI: /* BC1EQZC */
16380 if (ctx->insn_flags & ISA_MIPS32R6) {
16381 /* BC1EQZC */
16382 check_cp1_enabled(ctx);
16383 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16384 } else {
16385 /* TLTI */
16386 mips32_op = OPC_TLTI;
16387 goto do_trapi;
16389 break;
16390 case TGEI: /* BC1NEZC */
16391 if (ctx->insn_flags & ISA_MIPS32R6) {
16392 /* BC1NEZC */
16393 check_cp1_enabled(ctx);
16394 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16395 } else {
16396 /* TGEI */
16397 mips32_op = OPC_TGEI;
16398 goto do_trapi;
16400 break;
16401 case TLTIU:
16402 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16403 mips32_op = OPC_TLTIU;
16404 goto do_trapi;
16405 case TGEIU:
16406 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16407 mips32_op = OPC_TGEIU;
16408 goto do_trapi;
16409 case TNEI: /* SYNCI */
16410 if (ctx->insn_flags & ISA_MIPS32R6) {
16411 /* SYNCI */
16412 /* Break the TB to be able to sync copied instructions
16413 immediately */
16414 ctx->base.is_jmp = DISAS_STOP;
16415 } else {
16416 /* TNEI */
16417 mips32_op = OPC_TNEI;
16418 goto do_trapi;
16420 break;
16421 case TEQI:
16422 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16423 mips32_op = OPC_TEQI;
16424 do_trapi:
16425 gen_trap(ctx, mips32_op, rs, -1, imm);
16426 break;
16428 case BNEZC:
16429 case BEQZC:
16430 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16431 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16432 4, rs, 0, imm << 1, 0);
16433 /* Compact branches don't have a delay slot, so just let
16434 the normal delay slot handling take us to the branch
16435 target. */
16436 break;
16437 case LUI:
16438 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16439 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16440 break;
16441 case SYNCI:
16442 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16443 /* Break the TB to be able to sync copied instructions
16444 immediately */
16445 ctx->base.is_jmp = DISAS_STOP;
16446 break;
16447 case BC2F:
16448 case BC2T:
16449 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16450 /* COP2: Not implemented. */
16451 generate_exception_err(ctx, EXCP_CpU, 2);
16452 break;
16453 case BC1F:
16454 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16455 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16456 goto do_cp1branch;
16457 case BC1T:
16458 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16459 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16460 goto do_cp1branch;
16461 case BC1ANY4F:
16462 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16463 mips32_op = OPC_BC1FANY4;
16464 goto do_cp1mips3d;
16465 case BC1ANY4T:
16466 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16467 mips32_op = OPC_BC1TANY4;
16468 do_cp1mips3d:
16469 check_cop1x(ctx);
16470 check_insn(ctx, ASE_MIPS3D);
16471 /* Fall through */
16472 do_cp1branch:
16473 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16474 check_cp1_enabled(ctx);
16475 gen_compute_branch1(ctx, mips32_op,
16476 (ctx->opcode >> 18) & 0x7, imm << 1);
16477 } else {
16478 generate_exception_err(ctx, EXCP_CpU, 1);
16480 break;
16481 case BPOSGE64:
16482 case BPOSGE32:
16483 /* MIPS DSP: not implemented */
16484 /* Fall through */
16485 default:
16486 MIPS_INVAL("pool32i");
16487 generate_exception_end(ctx, EXCP_RI);
16488 break;
16490 break;
16491 case POOL32C:
16492 minor = (ctx->opcode >> 12) & 0xf;
16493 offset = sextract32(ctx->opcode, 0,
16494 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16495 switch (minor) {
16496 case LWL:
16497 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16498 mips32_op = OPC_LWL;
16499 goto do_ld_lr;
16500 case SWL:
16501 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16502 mips32_op = OPC_SWL;
16503 goto do_st_lr;
16504 case LWR:
16505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16506 mips32_op = OPC_LWR;
16507 goto do_ld_lr;
16508 case SWR:
16509 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16510 mips32_op = OPC_SWR;
16511 goto do_st_lr;
16512 #if defined(TARGET_MIPS64)
16513 case LDL:
16514 check_insn(ctx, ISA_MIPS3);
16515 check_mips_64(ctx);
16516 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16517 mips32_op = OPC_LDL;
16518 goto do_ld_lr;
16519 case SDL:
16520 check_insn(ctx, ISA_MIPS3);
16521 check_mips_64(ctx);
16522 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16523 mips32_op = OPC_SDL;
16524 goto do_st_lr;
16525 case LDR:
16526 check_insn(ctx, ISA_MIPS3);
16527 check_mips_64(ctx);
16528 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16529 mips32_op = OPC_LDR;
16530 goto do_ld_lr;
16531 case SDR:
16532 check_insn(ctx, ISA_MIPS3);
16533 check_mips_64(ctx);
16534 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16535 mips32_op = OPC_SDR;
16536 goto do_st_lr;
16537 case LWU:
16538 check_insn(ctx, ISA_MIPS3);
16539 check_mips_64(ctx);
16540 mips32_op = OPC_LWU;
16541 goto do_ld_lr;
16542 case LLD:
16543 check_insn(ctx, ISA_MIPS3);
16544 check_mips_64(ctx);
16545 mips32_op = OPC_LLD;
16546 goto do_ld_lr;
16547 #endif
16548 case LL:
16549 mips32_op = OPC_LL;
16550 goto do_ld_lr;
16551 do_ld_lr:
16552 gen_ld(ctx, mips32_op, rt, rs, offset);
16553 break;
16554 do_st_lr:
16555 gen_st(ctx, mips32_op, rt, rs, offset);
16556 break;
16557 case SC:
16558 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16559 break;
16560 #if defined(TARGET_MIPS64)
16561 case SCD:
16562 check_insn(ctx, ISA_MIPS3);
16563 check_mips_64(ctx);
16564 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16565 break;
16566 #endif
16567 case LD_EVA:
16568 if (!ctx->eva) {
16569 MIPS_INVAL("pool32c ld-eva");
16570 generate_exception_end(ctx, EXCP_RI);
16571 break;
16573 check_cp0_enabled(ctx);
16575 minor2 = (ctx->opcode >> 9) & 0x7;
16576 offset = sextract32(ctx->opcode, 0, 9);
16577 switch (minor2) {
16578 case LBUE:
16579 mips32_op = OPC_LBUE;
16580 goto do_ld_lr;
16581 case LHUE:
16582 mips32_op = OPC_LHUE;
16583 goto do_ld_lr;
16584 case LWLE:
16585 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16586 mips32_op = OPC_LWLE;
16587 goto do_ld_lr;
16588 case LWRE:
16589 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16590 mips32_op = OPC_LWRE;
16591 goto do_ld_lr;
16592 case LBE:
16593 mips32_op = OPC_LBE;
16594 goto do_ld_lr;
16595 case LHE:
16596 mips32_op = OPC_LHE;
16597 goto do_ld_lr;
16598 case LLE:
16599 mips32_op = OPC_LLE;
16600 goto do_ld_lr;
16601 case LWE:
16602 mips32_op = OPC_LWE;
16603 goto do_ld_lr;
16605 break;
16606 case ST_EVA:
16607 if (!ctx->eva) {
16608 MIPS_INVAL("pool32c st-eva");
16609 generate_exception_end(ctx, EXCP_RI);
16610 break;
16612 check_cp0_enabled(ctx);
16614 minor2 = (ctx->opcode >> 9) & 0x7;
16615 offset = sextract32(ctx->opcode, 0, 9);
16616 switch (minor2) {
16617 case SWLE:
16618 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16619 mips32_op = OPC_SWLE;
16620 goto do_st_lr;
16621 case SWRE:
16622 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16623 mips32_op = OPC_SWRE;
16624 goto do_st_lr;
16625 case PREFE:
16626 /* Treat as no-op */
16627 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16628 /* hint codes 24-31 are reserved and signal RI */
16629 generate_exception(ctx, EXCP_RI);
16631 break;
16632 case CACHEE:
16633 /* Treat as no-op */
16634 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16635 gen_cache_operation(ctx, rt, rs, offset);
16637 break;
16638 case SBE:
16639 mips32_op = OPC_SBE;
16640 goto do_st_lr;
16641 case SHE:
16642 mips32_op = OPC_SHE;
16643 goto do_st_lr;
16644 case SCE:
16645 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16646 break;
16647 case SWE:
16648 mips32_op = OPC_SWE;
16649 goto do_st_lr;
16651 break;
16652 case PREF:
16653 /* Treat as no-op */
16654 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16655 /* hint codes 24-31 are reserved and signal RI */
16656 generate_exception(ctx, EXCP_RI);
16658 break;
16659 default:
16660 MIPS_INVAL("pool32c");
16661 generate_exception_end(ctx, EXCP_RI);
16662 break;
16664 break;
16665 case ADDI32: /* AUI, LUI */
16666 if (ctx->insn_flags & ISA_MIPS32R6) {
16667 /* AUI, LUI */
16668 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16669 } else {
16670 /* ADDI32 */
16671 mips32_op = OPC_ADDI;
16672 goto do_addi;
16674 break;
16675 case ADDIU32:
16676 mips32_op = OPC_ADDIU;
16677 do_addi:
16678 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16679 break;
16681 /* Logical operations */
16682 case ORI32:
16683 mips32_op = OPC_ORI;
16684 goto do_logici;
16685 case XORI32:
16686 mips32_op = OPC_XORI;
16687 goto do_logici;
16688 case ANDI32:
16689 mips32_op = OPC_ANDI;
16690 do_logici:
16691 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16692 break;
16694 /* Set less than immediate */
16695 case SLTI32:
16696 mips32_op = OPC_SLTI;
16697 goto do_slti;
16698 case SLTIU32:
16699 mips32_op = OPC_SLTIU;
16700 do_slti:
16701 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16702 break;
16703 case JALX32:
16704 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16705 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16706 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16707 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16708 break;
16709 case JALS32: /* BOVC, BEQC, BEQZALC */
16710 if (ctx->insn_flags & ISA_MIPS32R6) {
16711 if (rs >= rt) {
16712 /* BOVC */
16713 mips32_op = OPC_BOVC;
16714 } else if (rs < rt && rs == 0) {
16715 /* BEQZALC */
16716 mips32_op = OPC_BEQZALC;
16717 } else {
16718 /* BEQC */
16719 mips32_op = OPC_BEQC;
16721 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16722 } else {
16723 /* JALS32 */
16724 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16725 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16726 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16728 break;
16729 case BEQ32: /* BC */
16730 if (ctx->insn_flags & ISA_MIPS32R6) {
16731 /* BC */
16732 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16733 sextract32(ctx->opcode << 1, 0, 27));
16734 } else {
16735 /* BEQ32 */
16736 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16738 break;
16739 case BNE32: /* BALC */
16740 if (ctx->insn_flags & ISA_MIPS32R6) {
16741 /* BALC */
16742 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16743 sextract32(ctx->opcode << 1, 0, 27));
16744 } else {
16745 /* BNE32 */
16746 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16748 break;
16749 case J32: /* BGTZC, BLTZC, BLTC */
16750 if (ctx->insn_flags & ISA_MIPS32R6) {
16751 if (rs == 0 && rt != 0) {
16752 /* BGTZC */
16753 mips32_op = OPC_BGTZC;
16754 } else if (rs != 0 && rt != 0 && rs == rt) {
16755 /* BLTZC */
16756 mips32_op = OPC_BLTZC;
16757 } else {
16758 /* BLTC */
16759 mips32_op = OPC_BLTC;
16761 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16762 } else {
16763 /* J32 */
16764 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16765 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16767 break;
16768 case JAL32: /* BLEZC, BGEZC, BGEC */
16769 if (ctx->insn_flags & ISA_MIPS32R6) {
16770 if (rs == 0 && rt != 0) {
16771 /* BLEZC */
16772 mips32_op = OPC_BLEZC;
16773 } else if (rs != 0 && rt != 0 && rs == rt) {
16774 /* BGEZC */
16775 mips32_op = OPC_BGEZC;
16776 } else {
16777 /* BGEC */
16778 mips32_op = OPC_BGEC;
16780 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16781 } else {
16782 /* JAL32 */
16783 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16784 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16785 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16787 break;
16788 /* Floating point (COP1) */
16789 case LWC132:
16790 mips32_op = OPC_LWC1;
16791 goto do_cop1;
16792 case LDC132:
16793 mips32_op = OPC_LDC1;
16794 goto do_cop1;
16795 case SWC132:
16796 mips32_op = OPC_SWC1;
16797 goto do_cop1;
16798 case SDC132:
16799 mips32_op = OPC_SDC1;
16800 do_cop1:
16801 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16802 break;
16803 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16804 if (ctx->insn_flags & ISA_MIPS32R6) {
16805 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16806 switch ((ctx->opcode >> 16) & 0x1f) {
16807 case ADDIUPC_00:
16808 case ADDIUPC_01:
16809 case ADDIUPC_02:
16810 case ADDIUPC_03:
16811 case ADDIUPC_04:
16812 case ADDIUPC_05:
16813 case ADDIUPC_06:
16814 case ADDIUPC_07:
16815 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16816 break;
16817 case AUIPC:
16818 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16819 break;
16820 case ALUIPC:
16821 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16822 break;
16823 case LWPC_08:
16824 case LWPC_09:
16825 case LWPC_0A:
16826 case LWPC_0B:
16827 case LWPC_0C:
16828 case LWPC_0D:
16829 case LWPC_0E:
16830 case LWPC_0F:
16831 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16832 break;
16833 default:
16834 generate_exception(ctx, EXCP_RI);
16835 break;
16837 } else {
16838 /* ADDIUPC */
16839 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16840 offset = SIMM(ctx->opcode, 0, 23) << 2;
16842 gen_addiupc(ctx, reg, offset, 0, 0);
16844 break;
16845 case BNVC: /* BNEC, BNEZALC */
16846 check_insn(ctx, ISA_MIPS32R6);
16847 if (rs >= rt) {
16848 /* BNVC */
16849 mips32_op = OPC_BNVC;
16850 } else if (rs < rt && rs == 0) {
16851 /* BNEZALC */
16852 mips32_op = OPC_BNEZALC;
16853 } else {
16854 /* BNEC */
16855 mips32_op = OPC_BNEC;
16857 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16858 break;
16859 case R6_BNEZC: /* JIALC */
16860 check_insn(ctx, ISA_MIPS32R6);
16861 if (rt != 0) {
16862 /* BNEZC */
16863 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16864 sextract32(ctx->opcode << 1, 0, 22));
16865 } else {
16866 /* JIALC */
16867 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16869 break;
16870 case R6_BEQZC: /* JIC */
16871 check_insn(ctx, ISA_MIPS32R6);
16872 if (rt != 0) {
16873 /* BEQZC */
16874 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16875 sextract32(ctx->opcode << 1, 0, 22));
16876 } else {
16877 /* JIC */
16878 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16880 break;
16881 case BLEZALC: /* BGEZALC, BGEUC */
16882 check_insn(ctx, ISA_MIPS32R6);
16883 if (rs == 0 && rt != 0) {
16884 /* BLEZALC */
16885 mips32_op = OPC_BLEZALC;
16886 } else if (rs != 0 && rt != 0 && rs == rt) {
16887 /* BGEZALC */
16888 mips32_op = OPC_BGEZALC;
16889 } else {
16890 /* BGEUC */
16891 mips32_op = OPC_BGEUC;
16893 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16894 break;
16895 case BGTZALC: /* BLTZALC, BLTUC */
16896 check_insn(ctx, ISA_MIPS32R6);
16897 if (rs == 0 && rt != 0) {
16898 /* BGTZALC */
16899 mips32_op = OPC_BGTZALC;
16900 } else if (rs != 0 && rt != 0 && rs == rt) {
16901 /* BLTZALC */
16902 mips32_op = OPC_BLTZALC;
16903 } else {
16904 /* BLTUC */
16905 mips32_op = OPC_BLTUC;
16907 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16908 break;
16909 /* Loads and stores */
16910 case LB32:
16911 mips32_op = OPC_LB;
16912 goto do_ld;
16913 case LBU32:
16914 mips32_op = OPC_LBU;
16915 goto do_ld;
16916 case LH32:
16917 mips32_op = OPC_LH;
16918 goto do_ld;
16919 case LHU32:
16920 mips32_op = OPC_LHU;
16921 goto do_ld;
16922 case LW32:
16923 mips32_op = OPC_LW;
16924 goto do_ld;
16925 #ifdef TARGET_MIPS64
16926 case LD32:
16927 check_insn(ctx, ISA_MIPS3);
16928 check_mips_64(ctx);
16929 mips32_op = OPC_LD;
16930 goto do_ld;
16931 case SD32:
16932 check_insn(ctx, ISA_MIPS3);
16933 check_mips_64(ctx);
16934 mips32_op = OPC_SD;
16935 goto do_st;
16936 #endif
16937 case SB32:
16938 mips32_op = OPC_SB;
16939 goto do_st;
16940 case SH32:
16941 mips32_op = OPC_SH;
16942 goto do_st;
16943 case SW32:
16944 mips32_op = OPC_SW;
16945 goto do_st;
16946 do_ld:
16947 gen_ld(ctx, mips32_op, rt, rs, imm);
16948 break;
16949 do_st:
16950 gen_st(ctx, mips32_op, rt, rs, imm);
16951 break;
16952 default:
16953 generate_exception_end(ctx, EXCP_RI);
16954 break;
16958 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16960 uint32_t op;
16962 /* make sure instructions are on a halfword boundary */
16963 if (ctx->base.pc_next & 0x1) {
16964 env->CP0_BadVAddr = ctx->base.pc_next;
16965 generate_exception_end(ctx, EXCP_AdEL);
16966 return 2;
16969 op = (ctx->opcode >> 10) & 0x3f;
16970 /* Enforce properly-sized instructions in a delay slot */
16971 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16972 switch (op & 0x7) { /* MSB-3..MSB-5 */
16973 case 0:
16974 /* POOL32A, POOL32B, POOL32I, POOL32C */
16975 case 4:
16976 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16977 case 5:
16978 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16979 case 6:
16980 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16981 case 7:
16982 /* LB32, LH32, LWC132, LDC132, LW32 */
16983 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16984 generate_exception_end(ctx, EXCP_RI);
16985 return 2;
16987 break;
16988 case 1:
16989 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16990 case 2:
16991 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16992 case 3:
16993 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16994 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16995 generate_exception_end(ctx, EXCP_RI);
16996 return 2;
16998 break;
17002 switch (op) {
17003 case POOL16A:
17005 int rd = mmreg(uMIPS_RD(ctx->opcode));
17006 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17007 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17008 uint32_t opc = 0;
17010 switch (ctx->opcode & 0x1) {
17011 case ADDU16:
17012 opc = OPC_ADDU;
17013 break;
17014 case SUBU16:
17015 opc = OPC_SUBU;
17016 break;
17018 if (ctx->insn_flags & ISA_MIPS32R6) {
17019 /* In the Release 6 the register number location in
17020 * the instruction encoding has changed.
17022 gen_arith(ctx, opc, rs1, rd, rs2);
17023 } else {
17024 gen_arith(ctx, opc, rd, rs1, rs2);
17027 break;
17028 case POOL16B:
17030 int rd = mmreg(uMIPS_RD(ctx->opcode));
17031 int rs = mmreg(uMIPS_RS(ctx->opcode));
17032 int amount = (ctx->opcode >> 1) & 0x7;
17033 uint32_t opc = 0;
17034 amount = amount == 0 ? 8 : amount;
17036 switch (ctx->opcode & 0x1) {
17037 case SLL16:
17038 opc = OPC_SLL;
17039 break;
17040 case SRL16:
17041 opc = OPC_SRL;
17042 break;
17045 gen_shift_imm(ctx, opc, rd, rs, amount);
17047 break;
17048 case POOL16C:
17049 if (ctx->insn_flags & ISA_MIPS32R6) {
17050 gen_pool16c_r6_insn(ctx);
17051 } else {
17052 gen_pool16c_insn(ctx);
17054 break;
17055 case LWGP16:
17057 int rd = mmreg(uMIPS_RD(ctx->opcode));
17058 int rb = 28; /* GP */
17059 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17061 gen_ld(ctx, OPC_LW, rd, rb, offset);
17063 break;
17064 case POOL16F:
17065 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17066 if (ctx->opcode & 1) {
17067 generate_exception_end(ctx, EXCP_RI);
17068 } else {
17069 /* MOVEP */
17070 int enc_dest = uMIPS_RD(ctx->opcode);
17071 int enc_rt = uMIPS_RS2(ctx->opcode);
17072 int enc_rs = uMIPS_RS1(ctx->opcode);
17073 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17075 break;
17076 case LBU16:
17078 int rd = mmreg(uMIPS_RD(ctx->opcode));
17079 int rb = mmreg(uMIPS_RS(ctx->opcode));
17080 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17081 offset = (offset == 0xf ? -1 : offset);
17083 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17085 break;
17086 case LHU16:
17088 int rd = mmreg(uMIPS_RD(ctx->opcode));
17089 int rb = mmreg(uMIPS_RS(ctx->opcode));
17090 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17092 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17094 break;
17095 case LWSP16:
17097 int rd = (ctx->opcode >> 5) & 0x1f;
17098 int rb = 29; /* SP */
17099 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17101 gen_ld(ctx, OPC_LW, rd, rb, offset);
17103 break;
17104 case LW16:
17106 int rd = mmreg(uMIPS_RD(ctx->opcode));
17107 int rb = mmreg(uMIPS_RS(ctx->opcode));
17108 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17110 gen_ld(ctx, OPC_LW, rd, rb, offset);
17112 break;
17113 case SB16:
17115 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17116 int rb = mmreg(uMIPS_RS(ctx->opcode));
17117 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17119 gen_st(ctx, OPC_SB, rd, rb, offset);
17121 break;
17122 case SH16:
17124 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17125 int rb = mmreg(uMIPS_RS(ctx->opcode));
17126 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17128 gen_st(ctx, OPC_SH, rd, rb, offset);
17130 break;
17131 case SWSP16:
17133 int rd = (ctx->opcode >> 5) & 0x1f;
17134 int rb = 29; /* SP */
17135 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17137 gen_st(ctx, OPC_SW, rd, rb, offset);
17139 break;
17140 case SW16:
17142 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17143 int rb = mmreg(uMIPS_RS(ctx->opcode));
17144 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17146 gen_st(ctx, OPC_SW, rd, rb, offset);
17148 break;
17149 case MOVE16:
17151 int rd = uMIPS_RD5(ctx->opcode);
17152 int rs = uMIPS_RS5(ctx->opcode);
17154 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17156 break;
17157 case ANDI16:
17158 gen_andi16(ctx);
17159 break;
17160 case POOL16D:
17161 switch (ctx->opcode & 0x1) {
17162 case ADDIUS5:
17163 gen_addius5(ctx);
17164 break;
17165 case ADDIUSP:
17166 gen_addiusp(ctx);
17167 break;
17169 break;
17170 case POOL16E:
17171 switch (ctx->opcode & 0x1) {
17172 case ADDIUR2:
17173 gen_addiur2(ctx);
17174 break;
17175 case ADDIUR1SP:
17176 gen_addiur1sp(ctx);
17177 break;
17179 break;
17180 case B16: /* BC16 */
17181 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17182 sextract32(ctx->opcode, 0, 10) << 1,
17183 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17184 break;
17185 case BNEZ16: /* BNEZC16 */
17186 case BEQZ16: /* BEQZC16 */
17187 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17188 mmreg(uMIPS_RD(ctx->opcode)),
17189 0, sextract32(ctx->opcode, 0, 7) << 1,
17190 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17192 break;
17193 case LI16:
17195 int reg = mmreg(uMIPS_RD(ctx->opcode));
17196 int imm = ZIMM(ctx->opcode, 0, 7);
17198 imm = (imm == 0x7f ? -1 : imm);
17199 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17201 break;
17202 case RES_29:
17203 case RES_31:
17204 case RES_39:
17205 generate_exception_end(ctx, EXCP_RI);
17206 break;
17207 default:
17208 decode_micromips32_opc(env, ctx);
17209 return 4;
17212 return 2;
17217 * nanoMIPS opcodes
17221 /* MAJOR, P16, and P32 pools opcodes */
17222 enum {
17223 NM_P_ADDIU = 0x00,
17224 NM_ADDIUPC = 0x01,
17225 NM_MOVE_BALC = 0x02,
17226 NM_P16_MV = 0x04,
17227 NM_LW16 = 0x05,
17228 NM_BC16 = 0x06,
17229 NM_P16_SR = 0x07,
17231 NM_POOL32A = 0x08,
17232 NM_P_BAL = 0x0a,
17233 NM_P16_SHIFT = 0x0c,
17234 NM_LWSP16 = 0x0d,
17235 NM_BALC16 = 0x0e,
17236 NM_P16_4X4 = 0x0f,
17238 NM_P_GP_W = 0x10,
17239 NM_P_GP_BH = 0x11,
17240 NM_P_J = 0x12,
17241 NM_P16C = 0x14,
17242 NM_LWGP16 = 0x15,
17243 NM_P16_LB = 0x17,
17245 NM_P48I = 0x18,
17246 NM_P16_A1 = 0x1c,
17247 NM_LW4X4 = 0x1d,
17248 NM_P16_LH = 0x1f,
17250 NM_P_U12 = 0x20,
17251 NM_P_LS_U12 = 0x21,
17252 NM_P_BR1 = 0x22,
17253 NM_P16_A2 = 0x24,
17254 NM_SW16 = 0x25,
17255 NM_BEQZC16 = 0x26,
17257 NM_POOL32F = 0x28,
17258 NM_P_LS_S9 = 0x29,
17259 NM_P_BR2 = 0x2a,
17261 NM_P16_ADDU = 0x2c,
17262 NM_SWSP16 = 0x2d,
17263 NM_BNEZC16 = 0x2e,
17264 NM_MOVEP = 0x2f,
17266 NM_POOL32S = 0x30,
17267 NM_P_BRI = 0x32,
17268 NM_LI16 = 0x34,
17269 NM_SWGP16 = 0x35,
17270 NM_P16_BR = 0x36,
17272 NM_P_LUI = 0x38,
17273 NM_ANDI16 = 0x3c,
17274 NM_SW4X4 = 0x3d,
17275 NM_MOVEPREV = 0x3f,
17278 /* POOL32A instruction pool */
17279 enum {
17280 NM_POOL32A0 = 0x00,
17281 NM_SPECIAL2 = 0x01,
17282 NM_COP2_1 = 0x02,
17283 NM_UDI = 0x03,
17284 NM_POOL32A5 = 0x05,
17285 NM_POOL32A7 = 0x07,
17288 /* P.GP.W instruction pool */
17289 enum {
17290 NM_ADDIUGP_W = 0x00,
17291 NM_LWGP = 0x02,
17292 NM_SWGP = 0x03,
17295 /* P48I instruction pool */
17296 enum {
17297 NM_LI48 = 0x00,
17298 NM_ADDIU48 = 0x01,
17299 NM_ADDIUGP48 = 0x02,
17300 NM_ADDIUPC48 = 0x03,
17301 NM_LWPC48 = 0x0b,
17302 NM_SWPC48 = 0x0f,
17305 /* P.U12 instruction pool */
17306 enum {
17307 NM_ORI = 0x00,
17308 NM_XORI = 0x01,
17309 NM_ANDI = 0x02,
17310 NM_P_SR = 0x03,
17311 NM_SLTI = 0x04,
17312 NM_SLTIU = 0x05,
17313 NM_SEQI = 0x06,
17314 NM_ADDIUNEG = 0x08,
17315 NM_P_SHIFT = 0x0c,
17316 NM_P_ROTX = 0x0d,
17317 NM_P_INS = 0x0e,
17318 NM_P_EXT = 0x0f,
17321 /* POOL32F instruction pool */
17322 enum {
17323 NM_POOL32F_0 = 0x00,
17324 NM_POOL32F_3 = 0x03,
17325 NM_POOL32F_5 = 0x05,
17328 /* POOL32S instruction pool */
17329 enum {
17330 NM_POOL32S_0 = 0x00,
17331 NM_POOL32S_4 = 0x04,
17334 /* P.LUI instruction pool */
17335 enum {
17336 NM_LUI = 0x00,
17337 NM_ALUIPC = 0x01,
17340 /* P.GP.BH instruction pool */
17341 enum {
17342 NM_LBGP = 0x00,
17343 NM_SBGP = 0x01,
17344 NM_LBUGP = 0x02,
17345 NM_ADDIUGP_B = 0x03,
17346 NM_P_GP_LH = 0x04,
17347 NM_P_GP_SH = 0x05,
17348 NM_P_GP_CP1 = 0x06,
17351 /* P.LS.U12 instruction pool */
17352 enum {
17353 NM_LB = 0x00,
17354 NM_SB = 0x01,
17355 NM_LBU = 0x02,
17356 NM_P_PREFU12 = 0x03,
17357 NM_LH = 0x04,
17358 NM_SH = 0x05,
17359 NM_LHU = 0x06,
17360 NM_LWU = 0x07,
17361 NM_LW = 0x08,
17362 NM_SW = 0x09,
17363 NM_LWC1 = 0x0a,
17364 NM_SWC1 = 0x0b,
17365 NM_LDC1 = 0x0e,
17366 NM_SDC1 = 0x0f,
17369 /* P.LS.S9 instruction pool */
17370 enum {
17371 NM_P_LS_S0 = 0x00,
17372 NM_P_LS_S1 = 0x01,
17373 NM_P_LS_E0 = 0x02,
17374 NM_P_LS_WM = 0x04,
17375 NM_P_LS_UAWM = 0x05,
17378 /* P.BAL instruction pool */
17379 enum {
17380 NM_BC = 0x00,
17381 NM_BALC = 0x01,
17384 /* P.J instruction pool */
17385 enum {
17386 NM_JALRC = 0x00,
17387 NM_JALRC_HB = 0x01,
17388 NM_P_BALRSC = 0x08,
17391 /* P.BR1 instruction pool */
17392 enum {
17393 NM_BEQC = 0x00,
17394 NM_P_BR3A = 0x01,
17395 NM_BGEC = 0x02,
17396 NM_BGEUC = 0x03,
17399 /* P.BR2 instruction pool */
17400 enum {
17401 NM_BNEC = 0x00,
17402 NM_BLTC = 0x02,
17403 NM_BLTUC = 0x03,
17406 /* P.BRI instruction pool */
17407 enum {
17408 NM_BEQIC = 0x00,
17409 NM_BBEQZC = 0x01,
17410 NM_BGEIC = 0x02,
17411 NM_BGEIUC = 0x03,
17412 NM_BNEIC = 0x04,
17413 NM_BBNEZC = 0x05,
17414 NM_BLTIC = 0x06,
17415 NM_BLTIUC = 0x07,
17418 /* P16.SHIFT instruction pool */
17419 enum {
17420 NM_SLL16 = 0x00,
17421 NM_SRL16 = 0x01,
17424 /* POOL16C instruction pool */
17425 enum {
17426 NM_POOL16C_0 = 0x00,
17427 NM_LWXS16 = 0x01,
17430 /* P16.A1 instruction pool */
17431 enum {
17432 NM_ADDIUR1SP = 0x01,
17435 /* P16.A2 instruction pool */
17436 enum {
17437 NM_ADDIUR2 = 0x00,
17438 NM_P_ADDIURS5 = 0x01,
17441 /* P16.ADDU instruction pool */
17442 enum {
17443 NM_ADDU16 = 0x00,
17444 NM_SUBU16 = 0x01,
17447 /* P16.SR instruction pool */
17448 enum {
17449 NM_SAVE16 = 0x00,
17450 NM_RESTORE_JRC16 = 0x01,
17453 /* P16.4X4 instruction pool */
17454 enum {
17455 NM_ADDU4X4 = 0x00,
17456 NM_MUL4X4 = 0x01,
17459 /* P16.LB instruction pool */
17460 enum {
17461 NM_LB16 = 0x00,
17462 NM_SB16 = 0x01,
17463 NM_LBU16 = 0x02,
17466 /* P16.LH instruction pool */
17467 enum {
17468 NM_LH16 = 0x00,
17469 NM_SH16 = 0x01,
17470 NM_LHU16 = 0x02,
17473 /* P.RI instruction pool */
17474 enum {
17475 NM_SIGRIE = 0x00,
17476 NM_P_SYSCALL = 0x01,
17477 NM_BREAK = 0x02,
17478 NM_SDBBP = 0x03,
17481 /* POOL32A0 instruction pool */
17482 enum {
17483 NM_P_TRAP = 0x00,
17484 NM_SEB = 0x01,
17485 NM_SLLV = 0x02,
17486 NM_MUL = 0x03,
17487 NM_MFC0 = 0x06,
17488 NM_MFHC0 = 0x07,
17489 NM_SEH = 0x09,
17490 NM_SRLV = 0x0a,
17491 NM_MUH = 0x0b,
17492 NM_MTC0 = 0x0e,
17493 NM_MTHC0 = 0x0f,
17494 NM_SRAV = 0x12,
17495 NM_MULU = 0x13,
17496 NM_ROTRV = 0x1a,
17497 NM_MUHU = 0x1b,
17498 NM_ADD = 0x22,
17499 NM_DIV = 0x23,
17500 NM_ADDU = 0x2a,
17501 NM_MOD = 0x2b,
17502 NM_SUB = 0x32,
17503 NM_DIVU = 0x33,
17504 NM_RDHWR = 0x38,
17505 NM_SUBU = 0x3a,
17506 NM_MODU = 0x3b,
17507 NM_P_CMOVE = 0x42,
17508 NM_FORK = 0x45,
17509 NM_MFTR = 0x46,
17510 NM_MFHTR = 0x47,
17511 NM_AND = 0x4a,
17512 NM_YIELD = 0x4d,
17513 NM_MTTR = 0x4e,
17514 NM_MTHTR = 0x4f,
17515 NM_OR = 0x52,
17516 NM_D_E_MT_VPE = 0x56,
17517 NM_NOR = 0x5a,
17518 NM_XOR = 0x62,
17519 NM_SLT = 0x6a,
17520 NM_P_SLTU = 0x72,
17521 NM_SOV = 0x7a,
17524 /* CRC32 instruction pool */
17525 enum {
17526 NM_CRC32B = 0x00,
17527 NM_CRC32H = 0x01,
17528 NM_CRC32W = 0x02,
17529 NM_CRC32CB = 0x04,
17530 NM_CRC32CH = 0x05,
17531 NM_CRC32CW = 0x06,
17534 /* POOL32A5 instruction pool */
17535 enum {
17536 NM_CMP_EQ_PH = 0x00,
17537 NM_CMP_LT_PH = 0x08,
17538 NM_CMP_LE_PH = 0x10,
17539 NM_CMPGU_EQ_QB = 0x18,
17540 NM_CMPGU_LT_QB = 0x20,
17541 NM_CMPGU_LE_QB = 0x28,
17542 NM_CMPGDU_EQ_QB = 0x30,
17543 NM_CMPGDU_LT_QB = 0x38,
17544 NM_CMPGDU_LE_QB = 0x40,
17545 NM_CMPU_EQ_QB = 0x48,
17546 NM_CMPU_LT_QB = 0x50,
17547 NM_CMPU_LE_QB = 0x58,
17548 NM_ADDQ_S_W = 0x60,
17549 NM_SUBQ_S_W = 0x68,
17550 NM_ADDSC = 0x70,
17551 NM_ADDWC = 0x78,
17553 NM_ADDQ_S_PH = 0x01,
17554 NM_ADDQH_R_PH = 0x09,
17555 NM_ADDQH_R_W = 0x11,
17556 NM_ADDU_S_QB = 0x19,
17557 NM_ADDU_S_PH = 0x21,
17558 NM_ADDUH_R_QB = 0x29,
17559 NM_SHRAV_R_PH = 0x31,
17560 NM_SHRAV_R_QB = 0x39,
17561 NM_SUBQ_S_PH = 0x41,
17562 NM_SUBQH_R_PH = 0x49,
17563 NM_SUBQH_R_W = 0x51,
17564 NM_SUBU_S_QB = 0x59,
17565 NM_SUBU_S_PH = 0x61,
17566 NM_SUBUH_R_QB = 0x69,
17567 NM_SHLLV_S_PH = 0x71,
17568 NM_PRECR_SRA_R_PH_W = 0x79,
17570 NM_MULEU_S_PH_QBL = 0x12,
17571 NM_MULEU_S_PH_QBR = 0x1a,
17572 NM_MULQ_RS_PH = 0x22,
17573 NM_MULQ_S_PH = 0x2a,
17574 NM_MULQ_RS_W = 0x32,
17575 NM_MULQ_S_W = 0x3a,
17576 NM_APPEND = 0x42,
17577 NM_MODSUB = 0x52,
17578 NM_SHRAV_R_W = 0x5a,
17579 NM_SHRLV_PH = 0x62,
17580 NM_SHRLV_QB = 0x6a,
17581 NM_SHLLV_QB = 0x72,
17582 NM_SHLLV_S_W = 0x7a,
17584 NM_SHILO = 0x03,
17586 NM_MULEQ_S_W_PHL = 0x04,
17587 NM_MULEQ_S_W_PHR = 0x0c,
17589 NM_MUL_S_PH = 0x05,
17590 NM_PRECR_QB_PH = 0x0d,
17591 NM_PRECRQ_QB_PH = 0x15,
17592 NM_PRECRQ_PH_W = 0x1d,
17593 NM_PRECRQ_RS_PH_W = 0x25,
17594 NM_PRECRQU_S_QB_PH = 0x2d,
17595 NM_PACKRL_PH = 0x35,
17596 NM_PICK_QB = 0x3d,
17597 NM_PICK_PH = 0x45,
17599 NM_SHRA_R_W = 0x5e,
17600 NM_SHRA_R_PH = 0x66,
17601 NM_SHLL_S_PH = 0x76,
17602 NM_SHLL_S_W = 0x7e,
17604 NM_REPL_PH = 0x07
17607 /* POOL32A7 instruction pool */
17608 enum {
17609 NM_P_LSX = 0x00,
17610 NM_LSA = 0x01,
17611 NM_EXTW = 0x03,
17612 NM_POOL32AXF = 0x07,
17615 /* P.SR instruction pool */
17616 enum {
17617 NM_PP_SR = 0x00,
17618 NM_P_SR_F = 0x01,
17621 /* P.SHIFT instruction pool */
17622 enum {
17623 NM_P_SLL = 0x00,
17624 NM_SRL = 0x02,
17625 NM_SRA = 0x04,
17626 NM_ROTR = 0x06,
17629 /* P.ROTX instruction pool */
17630 enum {
17631 NM_ROTX = 0x00,
17634 /* P.INS instruction pool */
17635 enum {
17636 NM_INS = 0x00,
17639 /* P.EXT instruction pool */
17640 enum {
17641 NM_EXT = 0x00,
17644 /* POOL32F_0 (fmt) instruction pool */
17645 enum {
17646 NM_RINT_S = 0x04,
17647 NM_RINT_D = 0x44,
17648 NM_ADD_S = 0x06,
17649 NM_SELEQZ_S = 0x07,
17650 NM_SELEQZ_D = 0x47,
17651 NM_CLASS_S = 0x0c,
17652 NM_CLASS_D = 0x4c,
17653 NM_SUB_S = 0x0e,
17654 NM_SELNEZ_S = 0x0f,
17655 NM_SELNEZ_D = 0x4f,
17656 NM_MUL_S = 0x16,
17657 NM_SEL_S = 0x17,
17658 NM_SEL_D = 0x57,
17659 NM_DIV_S = 0x1e,
17660 NM_ADD_D = 0x26,
17661 NM_SUB_D = 0x2e,
17662 NM_MUL_D = 0x36,
17663 NM_MADDF_S = 0x37,
17664 NM_MADDF_D = 0x77,
17665 NM_DIV_D = 0x3e,
17666 NM_MSUBF_S = 0x3f,
17667 NM_MSUBF_D = 0x7f,
17670 /* POOL32F_3 instruction pool */
17671 enum {
17672 NM_MIN_FMT = 0x00,
17673 NM_MAX_FMT = 0x01,
17674 NM_MINA_FMT = 0x04,
17675 NM_MAXA_FMT = 0x05,
17676 NM_POOL32FXF = 0x07,
17679 /* POOL32F_5 instruction pool */
17680 enum {
17681 NM_CMP_CONDN_S = 0x00,
17682 NM_CMP_CONDN_D = 0x02,
17685 /* P.GP.LH instruction pool */
17686 enum {
17687 NM_LHGP = 0x00,
17688 NM_LHUGP = 0x01,
17691 /* P.GP.SH instruction pool */
17692 enum {
17693 NM_SHGP = 0x00,
17696 /* P.GP.CP1 instruction pool */
17697 enum {
17698 NM_LWC1GP = 0x00,
17699 NM_SWC1GP = 0x01,
17700 NM_LDC1GP = 0x02,
17701 NM_SDC1GP = 0x03,
17704 /* P.LS.S0 instruction pool */
17705 enum {
17706 NM_LBS9 = 0x00,
17707 NM_LHS9 = 0x04,
17708 NM_LWS9 = 0x08,
17709 NM_LDS9 = 0x0c,
17711 NM_SBS9 = 0x01,
17712 NM_SHS9 = 0x05,
17713 NM_SWS9 = 0x09,
17714 NM_SDS9 = 0x0d,
17716 NM_LBUS9 = 0x02,
17717 NM_LHUS9 = 0x06,
17718 NM_LWC1S9 = 0x0a,
17719 NM_LDC1S9 = 0x0e,
17721 NM_P_PREFS9 = 0x03,
17722 NM_LWUS9 = 0x07,
17723 NM_SWC1S9 = 0x0b,
17724 NM_SDC1S9 = 0x0f,
17727 /* P.LS.S1 instruction pool */
17728 enum {
17729 NM_ASET_ACLR = 0x02,
17730 NM_UALH = 0x04,
17731 NM_UASH = 0x05,
17732 NM_CACHE = 0x07,
17733 NM_P_LL = 0x0a,
17734 NM_P_SC = 0x0b,
17737 /* P.LS.E0 instruction pool */
17738 enum {
17739 NM_LBE = 0x00,
17740 NM_SBE = 0x01,
17741 NM_LBUE = 0x02,
17742 NM_P_PREFE = 0x03,
17743 NM_LHE = 0x04,
17744 NM_SHE = 0x05,
17745 NM_LHUE = 0x06,
17746 NM_CACHEE = 0x07,
17747 NM_LWE = 0x08,
17748 NM_SWE = 0x09,
17749 NM_P_LLE = 0x0a,
17750 NM_P_SCE = 0x0b,
17753 /* P.PREFE instruction pool */
17754 enum {
17755 NM_SYNCIE = 0x00,
17756 NM_PREFE = 0x01,
17759 /* P.LLE instruction pool */
17760 enum {
17761 NM_LLE = 0x00,
17762 NM_LLWPE = 0x01,
17765 /* P.SCE instruction pool */
17766 enum {
17767 NM_SCE = 0x00,
17768 NM_SCWPE = 0x01,
17771 /* P.LS.WM instruction pool */
17772 enum {
17773 NM_LWM = 0x00,
17774 NM_SWM = 0x01,
17777 /* P.LS.UAWM instruction pool */
17778 enum {
17779 NM_UALWM = 0x00,
17780 NM_UASWM = 0x01,
17783 /* P.BR3A instruction pool */
17784 enum {
17785 NM_BC1EQZC = 0x00,
17786 NM_BC1NEZC = 0x01,
17787 NM_BC2EQZC = 0x02,
17788 NM_BC2NEZC = 0x03,
17789 NM_BPOSGE32C = 0x04,
17792 /* P16.RI instruction pool */
17793 enum {
17794 NM_P16_SYSCALL = 0x01,
17795 NM_BREAK16 = 0x02,
17796 NM_SDBBP16 = 0x03,
17799 /* POOL16C_0 instruction pool */
17800 enum {
17801 NM_POOL16C_00 = 0x00,
17804 /* P16.JRC instruction pool */
17805 enum {
17806 NM_JRC = 0x00,
17807 NM_JALRC16 = 0x01,
17810 /* P.SYSCALL instruction pool */
17811 enum {
17812 NM_SYSCALL = 0x00,
17813 NM_HYPCALL = 0x01,
17816 /* P.TRAP instruction pool */
17817 enum {
17818 NM_TEQ = 0x00,
17819 NM_TNE = 0x01,
17822 /* P.CMOVE instruction pool */
17823 enum {
17824 NM_MOVZ = 0x00,
17825 NM_MOVN = 0x01,
17828 /* POOL32Axf instruction pool */
17829 enum {
17830 NM_POOL32AXF_1 = 0x01,
17831 NM_POOL32AXF_2 = 0x02,
17832 NM_POOL32AXF_4 = 0x04,
17833 NM_POOL32AXF_5 = 0x05,
17834 NM_POOL32AXF_7 = 0x07,
17837 /* POOL32Axf_1 instruction pool */
17838 enum {
17839 NM_POOL32AXF_1_0 = 0x00,
17840 NM_POOL32AXF_1_1 = 0x01,
17841 NM_POOL32AXF_1_3 = 0x03,
17842 NM_POOL32AXF_1_4 = 0x04,
17843 NM_POOL32AXF_1_5 = 0x05,
17844 NM_POOL32AXF_1_7 = 0x07,
17847 /* POOL32Axf_2 instruction pool */
17848 enum {
17849 NM_POOL32AXF_2_0_7 = 0x00,
17850 NM_POOL32AXF_2_8_15 = 0x01,
17851 NM_POOL32AXF_2_16_23 = 0x02,
17852 NM_POOL32AXF_2_24_31 = 0x03,
17855 /* POOL32Axf_7 instruction pool */
17856 enum {
17857 NM_SHRA_R_QB = 0x0,
17858 NM_SHRL_PH = 0x1,
17859 NM_REPL_QB = 0x2,
17862 /* POOL32Axf_1_0 instruction pool */
17863 enum {
17864 NM_MFHI = 0x0,
17865 NM_MFLO = 0x1,
17866 NM_MTHI = 0x2,
17867 NM_MTLO = 0x3,
17870 /* POOL32Axf_1_1 instruction pool */
17871 enum {
17872 NM_MTHLIP = 0x0,
17873 NM_SHILOV = 0x1,
17876 /* POOL32Axf_1_3 instruction pool */
17877 enum {
17878 NM_RDDSP = 0x0,
17879 NM_WRDSP = 0x1,
17880 NM_EXTP = 0x2,
17881 NM_EXTPDP = 0x3,
17884 /* POOL32Axf_1_4 instruction pool */
17885 enum {
17886 NM_SHLL_QB = 0x0,
17887 NM_SHRL_QB = 0x1,
17890 /* POOL32Axf_1_5 instruction pool */
17891 enum {
17892 NM_MAQ_S_W_PHR = 0x0,
17893 NM_MAQ_S_W_PHL = 0x1,
17894 NM_MAQ_SA_W_PHR = 0x2,
17895 NM_MAQ_SA_W_PHL = 0x3,
17898 /* POOL32Axf_1_7 instruction pool */
17899 enum {
17900 NM_EXTR_W = 0x0,
17901 NM_EXTR_R_W = 0x1,
17902 NM_EXTR_RS_W = 0x2,
17903 NM_EXTR_S_H = 0x3,
17906 /* POOL32Axf_2_0_7 instruction pool */
17907 enum {
17908 NM_DPA_W_PH = 0x0,
17909 NM_DPAQ_S_W_PH = 0x1,
17910 NM_DPS_W_PH = 0x2,
17911 NM_DPSQ_S_W_PH = 0x3,
17912 NM_BALIGN = 0x4,
17913 NM_MADD = 0x5,
17914 NM_MULT = 0x6,
17915 NM_EXTRV_W = 0x7,
17918 /* POOL32Axf_2_8_15 instruction pool */
17919 enum {
17920 NM_DPAX_W_PH = 0x0,
17921 NM_DPAQ_SA_L_W = 0x1,
17922 NM_DPSX_W_PH = 0x2,
17923 NM_DPSQ_SA_L_W = 0x3,
17924 NM_MADDU = 0x5,
17925 NM_MULTU = 0x6,
17926 NM_EXTRV_R_W = 0x7,
17929 /* POOL32Axf_2_16_23 instruction pool */
17930 enum {
17931 NM_DPAU_H_QBL = 0x0,
17932 NM_DPAQX_S_W_PH = 0x1,
17933 NM_DPSU_H_QBL = 0x2,
17934 NM_DPSQX_S_W_PH = 0x3,
17935 NM_EXTPV = 0x4,
17936 NM_MSUB = 0x5,
17937 NM_MULSA_W_PH = 0x6,
17938 NM_EXTRV_RS_W = 0x7,
17941 /* POOL32Axf_2_24_31 instruction pool */
17942 enum {
17943 NM_DPAU_H_QBR = 0x0,
17944 NM_DPAQX_SA_W_PH = 0x1,
17945 NM_DPSU_H_QBR = 0x2,
17946 NM_DPSQX_SA_W_PH = 0x3,
17947 NM_EXTPDPV = 0x4,
17948 NM_MSUBU = 0x5,
17949 NM_MULSAQ_S_W_PH = 0x6,
17950 NM_EXTRV_S_H = 0x7,
17953 /* POOL32Axf_{4, 5} instruction pool */
17954 enum {
17955 NM_CLO = 0x25,
17956 NM_CLZ = 0x2d,
17958 NM_TLBP = 0x01,
17959 NM_TLBR = 0x09,
17960 NM_TLBWI = 0x11,
17961 NM_TLBWR = 0x19,
17962 NM_TLBINV = 0x03,
17963 NM_TLBINVF = 0x0b,
17964 NM_DI = 0x23,
17965 NM_EI = 0x2b,
17966 NM_RDPGPR = 0x70,
17967 NM_WRPGPR = 0x78,
17968 NM_WAIT = 0x61,
17969 NM_DERET = 0x71,
17970 NM_ERETX = 0x79,
17972 /* nanoMIPS DSP instructions */
17973 NM_ABSQ_S_QB = 0x00,
17974 NM_ABSQ_S_PH = 0x08,
17975 NM_ABSQ_S_W = 0x10,
17976 NM_PRECEQ_W_PHL = 0x28,
17977 NM_PRECEQ_W_PHR = 0x30,
17978 NM_PRECEQU_PH_QBL = 0x38,
17979 NM_PRECEQU_PH_QBR = 0x48,
17980 NM_PRECEU_PH_QBL = 0x58,
17981 NM_PRECEU_PH_QBR = 0x68,
17982 NM_PRECEQU_PH_QBLA = 0x39,
17983 NM_PRECEQU_PH_QBRA = 0x49,
17984 NM_PRECEU_PH_QBLA = 0x59,
17985 NM_PRECEU_PH_QBRA = 0x69,
17986 NM_REPLV_PH = 0x01,
17987 NM_REPLV_QB = 0x09,
17988 NM_BITREV = 0x18,
17989 NM_INSV = 0x20,
17990 NM_RADDU_W_QB = 0x78,
17992 NM_BITSWAP = 0x05,
17993 NM_WSBH = 0x3d,
17996 /* PP.SR instruction pool */
17997 enum {
17998 NM_SAVE = 0x00,
17999 NM_RESTORE = 0x02,
18000 NM_RESTORE_JRC = 0x03,
18003 /* P.SR.F instruction pool */
18004 enum {
18005 NM_SAVEF = 0x00,
18006 NM_RESTOREF = 0x01,
18009 /* P16.SYSCALL instruction pool */
18010 enum {
18011 NM_SYSCALL16 = 0x00,
18012 NM_HYPCALL16 = 0x01,
18015 /* POOL16C_00 instruction pool */
18016 enum {
18017 NM_NOT16 = 0x00,
18018 NM_XOR16 = 0x01,
18019 NM_AND16 = 0x02,
18020 NM_OR16 = 0x03,
18023 /* PP.LSX and PP.LSXS instruction pool */
18024 enum {
18025 NM_LBX = 0x00,
18026 NM_LHX = 0x04,
18027 NM_LWX = 0x08,
18028 NM_LDX = 0x0c,
18030 NM_SBX = 0x01,
18031 NM_SHX = 0x05,
18032 NM_SWX = 0x09,
18033 NM_SDX = 0x0d,
18035 NM_LBUX = 0x02,
18036 NM_LHUX = 0x06,
18037 NM_LWC1X = 0x0a,
18038 NM_LDC1X = 0x0e,
18040 NM_LWUX = 0x07,
18041 NM_SWC1X = 0x0b,
18042 NM_SDC1X = 0x0f,
18044 NM_LHXS = 0x04,
18045 NM_LWXS = 0x08,
18046 NM_LDXS = 0x0c,
18048 NM_SHXS = 0x05,
18049 NM_SWXS = 0x09,
18050 NM_SDXS = 0x0d,
18052 NM_LHUXS = 0x06,
18053 NM_LWC1XS = 0x0a,
18054 NM_LDC1XS = 0x0e,
18056 NM_LWUXS = 0x07,
18057 NM_SWC1XS = 0x0b,
18058 NM_SDC1XS = 0x0f,
18061 /* ERETx instruction pool */
18062 enum {
18063 NM_ERET = 0x00,
18064 NM_ERETNC = 0x01,
18067 /* POOL32FxF_{0, 1} insturction pool */
18068 enum {
18069 NM_CFC1 = 0x40,
18070 NM_CTC1 = 0x60,
18071 NM_MFC1 = 0x80,
18072 NM_MTC1 = 0xa0,
18073 NM_MFHC1 = 0xc0,
18074 NM_MTHC1 = 0xe0,
18076 NM_CVT_S_PL = 0x84,
18077 NM_CVT_S_PU = 0xa4,
18079 NM_CVT_L_S = 0x004,
18080 NM_CVT_L_D = 0x104,
18081 NM_CVT_W_S = 0x024,
18082 NM_CVT_W_D = 0x124,
18084 NM_RSQRT_S = 0x008,
18085 NM_RSQRT_D = 0x108,
18087 NM_SQRT_S = 0x028,
18088 NM_SQRT_D = 0x128,
18090 NM_RECIP_S = 0x048,
18091 NM_RECIP_D = 0x148,
18093 NM_FLOOR_L_S = 0x00c,
18094 NM_FLOOR_L_D = 0x10c,
18096 NM_FLOOR_W_S = 0x02c,
18097 NM_FLOOR_W_D = 0x12c,
18099 NM_CEIL_L_S = 0x04c,
18100 NM_CEIL_L_D = 0x14c,
18101 NM_CEIL_W_S = 0x06c,
18102 NM_CEIL_W_D = 0x16c,
18103 NM_TRUNC_L_S = 0x08c,
18104 NM_TRUNC_L_D = 0x18c,
18105 NM_TRUNC_W_S = 0x0ac,
18106 NM_TRUNC_W_D = 0x1ac,
18107 NM_ROUND_L_S = 0x0cc,
18108 NM_ROUND_L_D = 0x1cc,
18109 NM_ROUND_W_S = 0x0ec,
18110 NM_ROUND_W_D = 0x1ec,
18112 NM_MOV_S = 0x01,
18113 NM_MOV_D = 0x81,
18114 NM_ABS_S = 0x0d,
18115 NM_ABS_D = 0x8d,
18116 NM_NEG_S = 0x2d,
18117 NM_NEG_D = 0xad,
18118 NM_CVT_D_S = 0x04d,
18119 NM_CVT_D_W = 0x0cd,
18120 NM_CVT_D_L = 0x14d,
18121 NM_CVT_S_D = 0x06d,
18122 NM_CVT_S_W = 0x0ed,
18123 NM_CVT_S_L = 0x16d,
18126 /* P.LL instruction pool */
18127 enum {
18128 NM_LL = 0x00,
18129 NM_LLWP = 0x01,
18132 /* P.SC instruction pool */
18133 enum {
18134 NM_SC = 0x00,
18135 NM_SCWP = 0x01,
18138 /* P.DVP instruction pool */
18139 enum {
18140 NM_DVP = 0x00,
18141 NM_EVP = 0x01,
18147 * nanoMIPS decoding engine
18152 /* extraction utilities */
18154 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18155 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18156 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18157 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18158 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18159 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18161 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18162 static inline int decode_gpr_gpr3(int r)
18164 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18166 return map[r & 0x7];
18169 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18170 static inline int decode_gpr_gpr3_src_store(int r)
18172 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18174 return map[r & 0x7];
18177 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18178 static inline int decode_gpr_gpr4(int r)
18180 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18181 16, 17, 18, 19, 20, 21, 22, 23 };
18183 return map[r & 0xf];
18186 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18187 static inline int decode_gpr_gpr4_zero(int r)
18189 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18190 16, 17, 18, 19, 20, 21, 22, 23 };
18192 return map[r & 0xf];
18196 /* extraction utilities */
18198 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18199 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18200 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18201 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18202 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18203 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18206 static void gen_adjust_sp(DisasContext *ctx, int u)
18208 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18211 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18212 uint8_t gp, uint16_t u)
18214 int counter = 0;
18215 TCGv va = tcg_temp_new();
18216 TCGv t0 = tcg_temp_new();
18218 while (counter != count) {
18219 bool use_gp = gp && (counter == count - 1);
18220 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18221 int this_offset = -((counter + 1) << 2);
18222 gen_base_offset_addr(ctx, va, 29, this_offset);
18223 gen_load_gpr(t0, this_rt);
18224 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18225 (MO_TEUL | ctx->default_tcg_memop_mask));
18226 counter++;
18229 /* adjust stack pointer */
18230 gen_adjust_sp(ctx, -u);
18232 tcg_temp_free(t0);
18233 tcg_temp_free(va);
18236 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18237 uint8_t gp, uint16_t u)
18239 int counter = 0;
18240 TCGv va = tcg_temp_new();
18241 TCGv t0 = tcg_temp_new();
18243 while (counter != count) {
18244 bool use_gp = gp && (counter == count - 1);
18245 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18246 int this_offset = u - ((counter + 1) << 2);
18247 gen_base_offset_addr(ctx, va, 29, this_offset);
18248 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18249 ctx->default_tcg_memop_mask);
18250 tcg_gen_ext32s_tl(t0, t0);
18251 gen_store_gpr(t0, this_rt);
18252 counter++;
18255 /* adjust stack pointer */
18256 gen_adjust_sp(ctx, u);
18258 tcg_temp_free(t0);
18259 tcg_temp_free(va);
18262 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18264 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18265 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18267 switch (extract32(ctx->opcode, 2, 2)) {
18268 case NM_NOT16:
18269 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18270 break;
18271 case NM_AND16:
18272 gen_logic(ctx, OPC_AND, rt, rt, rs);
18273 break;
18274 case NM_XOR16:
18275 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18276 break;
18277 case NM_OR16:
18278 gen_logic(ctx, OPC_OR, rt, rt, rs);
18279 break;
18283 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18285 int rt = extract32(ctx->opcode, 21, 5);
18286 int rs = extract32(ctx->opcode, 16, 5);
18287 int rd = extract32(ctx->opcode, 11, 5);
18289 switch (extract32(ctx->opcode, 3, 7)) {
18290 case NM_P_TRAP:
18291 switch (extract32(ctx->opcode, 10, 1)) {
18292 case NM_TEQ:
18293 check_nms(ctx);
18294 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18295 break;
18296 case NM_TNE:
18297 check_nms(ctx);
18298 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18299 break;
18301 break;
18302 case NM_RDHWR:
18303 check_nms(ctx);
18304 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18305 break;
18306 case NM_SEB:
18307 check_nms(ctx);
18308 gen_bshfl(ctx, OPC_SEB, rs, rt);
18309 break;
18310 case NM_SEH:
18311 gen_bshfl(ctx, OPC_SEH, rs, rt);
18312 break;
18313 case NM_SLLV:
18314 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18315 break;
18316 case NM_SRLV:
18317 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18318 break;
18319 case NM_SRAV:
18320 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18321 break;
18322 case NM_ROTRV:
18323 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18324 break;
18325 case NM_ADD:
18326 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18327 break;
18328 case NM_ADDU:
18329 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18330 break;
18331 case NM_SUB:
18332 check_nms(ctx);
18333 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18334 break;
18335 case NM_SUBU:
18336 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18337 break;
18338 case NM_P_CMOVE:
18339 switch (extract32(ctx->opcode, 10, 1)) {
18340 case NM_MOVZ:
18341 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18342 break;
18343 case NM_MOVN:
18344 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18345 break;
18347 break;
18348 case NM_AND:
18349 gen_logic(ctx, OPC_AND, rd, rs, rt);
18350 break;
18351 case NM_OR:
18352 gen_logic(ctx, OPC_OR, rd, rs, rt);
18353 break;
18354 case NM_NOR:
18355 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18356 break;
18357 case NM_XOR:
18358 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18359 break;
18360 case NM_SLT:
18361 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18362 break;
18363 case NM_P_SLTU:
18364 if (rd == 0) {
18365 /* P_DVP */
18366 #ifndef CONFIG_USER_ONLY
18367 TCGv t0 = tcg_temp_new();
18368 switch (extract32(ctx->opcode, 10, 1)) {
18369 case NM_DVP:
18370 if (ctx->vp) {
18371 check_cp0_enabled(ctx);
18372 gen_helper_dvp(t0, cpu_env);
18373 gen_store_gpr(t0, rt);
18375 break;
18376 case NM_EVP:
18377 if (ctx->vp) {
18378 check_cp0_enabled(ctx);
18379 gen_helper_evp(t0, cpu_env);
18380 gen_store_gpr(t0, rt);
18382 break;
18384 tcg_temp_free(t0);
18385 #endif
18386 } else {
18387 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18389 break;
18390 case NM_SOV:
18392 TCGv t0 = tcg_temp_new();
18393 TCGv t1 = tcg_temp_new();
18394 TCGv t2 = tcg_temp_new();
18396 gen_load_gpr(t1, rs);
18397 gen_load_gpr(t2, rt);
18398 tcg_gen_add_tl(t0, t1, t2);
18399 tcg_gen_ext32s_tl(t0, t0);
18400 tcg_gen_xor_tl(t1, t1, t2);
18401 tcg_gen_xor_tl(t2, t0, t2);
18402 tcg_gen_andc_tl(t1, t2, t1);
18404 /* operands of same sign, result different sign */
18405 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18406 gen_store_gpr(t0, rd);
18408 tcg_temp_free(t0);
18409 tcg_temp_free(t1);
18410 tcg_temp_free(t2);
18412 break;
18413 case NM_MUL:
18414 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18415 break;
18416 case NM_MUH:
18417 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18418 break;
18419 case NM_MULU:
18420 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18421 break;
18422 case NM_MUHU:
18423 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18424 break;
18425 case NM_DIV:
18426 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18427 break;
18428 case NM_MOD:
18429 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18430 break;
18431 case NM_DIVU:
18432 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18433 break;
18434 case NM_MODU:
18435 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18436 break;
18437 #ifndef CONFIG_USER_ONLY
18438 case NM_MFC0:
18439 check_cp0_enabled(ctx);
18440 if (rt == 0) {
18441 /* Treat as NOP. */
18442 break;
18444 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18445 break;
18446 case NM_MTC0:
18447 check_cp0_enabled(ctx);
18449 TCGv t0 = tcg_temp_new();
18451 gen_load_gpr(t0, rt);
18452 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18453 tcg_temp_free(t0);
18455 break;
18456 case NM_D_E_MT_VPE:
18458 uint8_t sc = extract32(ctx->opcode, 10, 1);
18459 TCGv t0 = tcg_temp_new();
18461 switch (sc) {
18462 case 0:
18463 if (rs == 1) {
18464 /* DMT */
18465 check_cp0_mt(ctx);
18466 gen_helper_dmt(t0);
18467 gen_store_gpr(t0, rt);
18468 } else if (rs == 0) {
18469 /* DVPE */
18470 check_cp0_mt(ctx);
18471 gen_helper_dvpe(t0, cpu_env);
18472 gen_store_gpr(t0, rt);
18473 } else {
18474 generate_exception_end(ctx, EXCP_RI);
18476 break;
18477 case 1:
18478 if (rs == 1) {
18479 /* EMT */
18480 check_cp0_mt(ctx);
18481 gen_helper_emt(t0);
18482 gen_store_gpr(t0, rt);
18483 } else if (rs == 0) {
18484 /* EVPE */
18485 check_cp0_mt(ctx);
18486 gen_helper_evpe(t0, cpu_env);
18487 gen_store_gpr(t0, rt);
18488 } else {
18489 generate_exception_end(ctx, EXCP_RI);
18491 break;
18494 tcg_temp_free(t0);
18496 break;
18497 case NM_FORK:
18498 check_mt(ctx);
18500 TCGv t0 = tcg_temp_new();
18501 TCGv t1 = tcg_temp_new();
18503 gen_load_gpr(t0, rt);
18504 gen_load_gpr(t1, rs);
18505 gen_helper_fork(t0, t1);
18506 tcg_temp_free(t0);
18507 tcg_temp_free(t1);
18509 break;
18510 case NM_MFTR:
18511 case NM_MFHTR:
18512 check_cp0_enabled(ctx);
18513 if (rd == 0) {
18514 /* Treat as NOP. */
18515 return;
18517 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18518 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18519 break;
18520 case NM_MTTR:
18521 case NM_MTHTR:
18522 check_cp0_enabled(ctx);
18523 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18524 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18525 break;
18526 case NM_YIELD:
18527 check_mt(ctx);
18529 TCGv t0 = tcg_temp_new();
18531 gen_load_gpr(t0, rs);
18532 gen_helper_yield(t0, cpu_env, t0);
18533 gen_store_gpr(t0, rt);
18534 tcg_temp_free(t0);
18536 break;
18537 #endif
18538 default:
18539 generate_exception_end(ctx, EXCP_RI);
18540 break;
18544 /* dsp */
18545 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18546 int ret, int v1, int v2)
18548 TCGv_i32 t0;
18549 TCGv v0_t;
18550 TCGv v1_t;
18552 t0 = tcg_temp_new_i32();
18554 v0_t = tcg_temp_new();
18555 v1_t = tcg_temp_new();
18557 tcg_gen_movi_i32(t0, v2 >> 3);
18559 gen_load_gpr(v0_t, ret);
18560 gen_load_gpr(v1_t, v1);
18562 switch (opc) {
18563 case NM_MAQ_S_W_PHR:
18564 check_dsp(ctx);
18565 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18566 break;
18567 case NM_MAQ_S_W_PHL:
18568 check_dsp(ctx);
18569 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18570 break;
18571 case NM_MAQ_SA_W_PHR:
18572 check_dsp(ctx);
18573 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18574 break;
18575 case NM_MAQ_SA_W_PHL:
18576 check_dsp(ctx);
18577 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18578 break;
18579 default:
18580 generate_exception_end(ctx, EXCP_RI);
18581 break;
18584 tcg_temp_free_i32(t0);
18586 tcg_temp_free(v0_t);
18587 tcg_temp_free(v1_t);
18591 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18592 int ret, int v1, int v2)
18594 int16_t imm;
18595 TCGv t0 = tcg_temp_new();
18596 TCGv t1 = tcg_temp_new();
18597 TCGv v0_t = tcg_temp_new();
18599 gen_load_gpr(v0_t, v1);
18601 switch (opc) {
18602 case NM_POOL32AXF_1_0:
18603 check_dsp(ctx);
18604 switch (extract32(ctx->opcode, 12, 2)) {
18605 case NM_MFHI:
18606 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18607 break;
18608 case NM_MFLO:
18609 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18610 break;
18611 case NM_MTHI:
18612 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18613 break;
18614 case NM_MTLO:
18615 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18616 break;
18618 break;
18619 case NM_POOL32AXF_1_1:
18620 check_dsp(ctx);
18621 switch (extract32(ctx->opcode, 12, 2)) {
18622 case NM_MTHLIP:
18623 tcg_gen_movi_tl(t0, v2);
18624 gen_helper_mthlip(t0, v0_t, cpu_env);
18625 break;
18626 case NM_SHILOV:
18627 tcg_gen_movi_tl(t0, v2 >> 3);
18628 gen_helper_shilo(t0, v0_t, cpu_env);
18629 break;
18630 default:
18631 generate_exception_end(ctx, EXCP_RI);
18632 break;
18634 break;
18635 case NM_POOL32AXF_1_3:
18636 check_dsp(ctx);
18637 imm = extract32(ctx->opcode, 14, 7);
18638 switch (extract32(ctx->opcode, 12, 2)) {
18639 case NM_RDDSP:
18640 tcg_gen_movi_tl(t0, imm);
18641 gen_helper_rddsp(t0, t0, cpu_env);
18642 gen_store_gpr(t0, ret);
18643 break;
18644 case NM_WRDSP:
18645 gen_load_gpr(t0, ret);
18646 tcg_gen_movi_tl(t1, imm);
18647 gen_helper_wrdsp(t0, t1, cpu_env);
18648 break;
18649 case NM_EXTP:
18650 tcg_gen_movi_tl(t0, v2 >> 3);
18651 tcg_gen_movi_tl(t1, v1);
18652 gen_helper_extp(t0, t0, t1, cpu_env);
18653 gen_store_gpr(t0, ret);
18654 break;
18655 case NM_EXTPDP:
18656 tcg_gen_movi_tl(t0, v2 >> 3);
18657 tcg_gen_movi_tl(t1, v1);
18658 gen_helper_extpdp(t0, t0, t1, cpu_env);
18659 gen_store_gpr(t0, ret);
18660 break;
18662 break;
18663 case NM_POOL32AXF_1_4:
18664 check_dsp(ctx);
18665 tcg_gen_movi_tl(t0, v2 >> 2);
18666 switch (extract32(ctx->opcode, 12, 1)) {
18667 case NM_SHLL_QB:
18668 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18669 gen_store_gpr(t0, ret);
18670 break;
18671 case NM_SHRL_QB:
18672 gen_helper_shrl_qb(t0, t0, v0_t);
18673 gen_store_gpr(t0, ret);
18674 break;
18676 break;
18677 case NM_POOL32AXF_1_5:
18678 opc = extract32(ctx->opcode, 12, 2);
18679 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18680 break;
18681 case NM_POOL32AXF_1_7:
18682 check_dsp(ctx);
18683 tcg_gen_movi_tl(t0, v2 >> 3);
18684 tcg_gen_movi_tl(t1, v1);
18685 switch (extract32(ctx->opcode, 12, 2)) {
18686 case NM_EXTR_W:
18687 gen_helper_extr_w(t0, t0, t1, cpu_env);
18688 gen_store_gpr(t0, ret);
18689 break;
18690 case NM_EXTR_R_W:
18691 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18692 gen_store_gpr(t0, ret);
18693 break;
18694 case NM_EXTR_RS_W:
18695 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18696 gen_store_gpr(t0, ret);
18697 break;
18698 case NM_EXTR_S_H:
18699 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18700 gen_store_gpr(t0, ret);
18701 break;
18703 break;
18704 default:
18705 generate_exception_end(ctx, EXCP_RI);
18706 break;
18709 tcg_temp_free(t0);
18710 tcg_temp_free(t1);
18711 tcg_temp_free(v0_t);
18714 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18715 TCGv v0, TCGv v1, int rd)
18717 TCGv_i32 t0;
18719 t0 = tcg_temp_new_i32();
18721 tcg_gen_movi_i32(t0, rd >> 3);
18723 switch (opc) {
18724 case NM_POOL32AXF_2_0_7:
18725 switch (extract32(ctx->opcode, 9, 3)) {
18726 case NM_DPA_W_PH:
18727 check_dsp_r2(ctx);
18728 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18729 break;
18730 case NM_DPAQ_S_W_PH:
18731 check_dsp(ctx);
18732 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18733 break;
18734 case NM_DPS_W_PH:
18735 check_dsp_r2(ctx);
18736 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18737 break;
18738 case NM_DPSQ_S_W_PH:
18739 check_dsp(ctx);
18740 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18741 break;
18742 default:
18743 generate_exception_end(ctx, EXCP_RI);
18744 break;
18746 break;
18747 case NM_POOL32AXF_2_8_15:
18748 switch (extract32(ctx->opcode, 9, 3)) {
18749 case NM_DPAX_W_PH:
18750 check_dsp_r2(ctx);
18751 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18752 break;
18753 case NM_DPAQ_SA_L_W:
18754 check_dsp(ctx);
18755 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18756 break;
18757 case NM_DPSX_W_PH:
18758 check_dsp_r2(ctx);
18759 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18760 break;
18761 case NM_DPSQ_SA_L_W:
18762 check_dsp(ctx);
18763 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18764 break;
18765 default:
18766 generate_exception_end(ctx, EXCP_RI);
18767 break;
18769 break;
18770 case NM_POOL32AXF_2_16_23:
18771 switch (extract32(ctx->opcode, 9, 3)) {
18772 case NM_DPAU_H_QBL:
18773 check_dsp(ctx);
18774 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18775 break;
18776 case NM_DPAQX_S_W_PH:
18777 check_dsp_r2(ctx);
18778 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18779 break;
18780 case NM_DPSU_H_QBL:
18781 check_dsp(ctx);
18782 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18783 break;
18784 case NM_DPSQX_S_W_PH:
18785 check_dsp_r2(ctx);
18786 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18787 break;
18788 case NM_MULSA_W_PH:
18789 check_dsp_r2(ctx);
18790 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18791 break;
18792 default:
18793 generate_exception_end(ctx, EXCP_RI);
18794 break;
18796 break;
18797 case NM_POOL32AXF_2_24_31:
18798 switch (extract32(ctx->opcode, 9, 3)) {
18799 case NM_DPAU_H_QBR:
18800 check_dsp(ctx);
18801 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18802 break;
18803 case NM_DPAQX_SA_W_PH:
18804 check_dsp_r2(ctx);
18805 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18806 break;
18807 case NM_DPSU_H_QBR:
18808 check_dsp(ctx);
18809 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18810 break;
18811 case NM_DPSQX_SA_W_PH:
18812 check_dsp_r2(ctx);
18813 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18814 break;
18815 case NM_MULSAQ_S_W_PH:
18816 check_dsp(ctx);
18817 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18818 break;
18819 default:
18820 generate_exception_end(ctx, EXCP_RI);
18821 break;
18823 break;
18824 default:
18825 generate_exception_end(ctx, EXCP_RI);
18826 break;
18829 tcg_temp_free_i32(t0);
18832 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18833 int rt, int rs, int rd)
18835 int ret = rt;
18836 TCGv t0 = tcg_temp_new();
18837 TCGv t1 = tcg_temp_new();
18838 TCGv v0_t = tcg_temp_new();
18839 TCGv v1_t = tcg_temp_new();
18841 gen_load_gpr(v0_t, rt);
18842 gen_load_gpr(v1_t, rs);
18844 switch (opc) {
18845 case NM_POOL32AXF_2_0_7:
18846 switch (extract32(ctx->opcode, 9, 3)) {
18847 case NM_DPA_W_PH:
18848 case NM_DPAQ_S_W_PH:
18849 case NM_DPS_W_PH:
18850 case NM_DPSQ_S_W_PH:
18851 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18852 break;
18853 case NM_BALIGN:
18854 check_dsp_r2(ctx);
18855 if (rt != 0) {
18856 gen_load_gpr(t0, rs);
18857 rd &= 3;
18858 if (rd != 0 && rd != 2) {
18859 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18860 tcg_gen_ext32u_tl(t0, t0);
18861 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18862 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18864 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18866 break;
18867 case NM_MADD:
18868 check_dsp(ctx);
18870 int acc = extract32(ctx->opcode, 14, 2);
18871 TCGv_i64 t2 = tcg_temp_new_i64();
18872 TCGv_i64 t3 = tcg_temp_new_i64();
18874 gen_load_gpr(t0, rt);
18875 gen_load_gpr(t1, rs);
18876 tcg_gen_ext_tl_i64(t2, t0);
18877 tcg_gen_ext_tl_i64(t3, t1);
18878 tcg_gen_mul_i64(t2, t2, t3);
18879 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18880 tcg_gen_add_i64(t2, t2, t3);
18881 tcg_temp_free_i64(t3);
18882 gen_move_low32(cpu_LO[acc], t2);
18883 gen_move_high32(cpu_HI[acc], t2);
18884 tcg_temp_free_i64(t2);
18886 break;
18887 case NM_MULT:
18888 check_dsp(ctx);
18890 int acc = extract32(ctx->opcode, 14, 2);
18891 TCGv_i32 t2 = tcg_temp_new_i32();
18892 TCGv_i32 t3 = tcg_temp_new_i32();
18894 gen_load_gpr(t0, rs);
18895 gen_load_gpr(t1, rt);
18896 tcg_gen_trunc_tl_i32(t2, t0);
18897 tcg_gen_trunc_tl_i32(t3, t1);
18898 tcg_gen_muls2_i32(t2, t3, t2, t3);
18899 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18900 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18901 tcg_temp_free_i32(t2);
18902 tcg_temp_free_i32(t3);
18904 break;
18905 case NM_EXTRV_W:
18906 check_dsp(ctx);
18907 gen_load_gpr(v1_t, rs);
18908 tcg_gen_movi_tl(t0, rd >> 3);
18909 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18910 gen_store_gpr(t0, ret);
18911 break;
18913 break;
18914 case NM_POOL32AXF_2_8_15:
18915 switch (extract32(ctx->opcode, 9, 3)) {
18916 case NM_DPAX_W_PH:
18917 case NM_DPAQ_SA_L_W:
18918 case NM_DPSX_W_PH:
18919 case NM_DPSQ_SA_L_W:
18920 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18921 break;
18922 case NM_MADDU:
18923 check_dsp(ctx);
18925 int acc = extract32(ctx->opcode, 14, 2);
18926 TCGv_i64 t2 = tcg_temp_new_i64();
18927 TCGv_i64 t3 = tcg_temp_new_i64();
18929 gen_load_gpr(t0, rs);
18930 gen_load_gpr(t1, rt);
18931 tcg_gen_ext32u_tl(t0, t0);
18932 tcg_gen_ext32u_tl(t1, t1);
18933 tcg_gen_extu_tl_i64(t2, t0);
18934 tcg_gen_extu_tl_i64(t3, t1);
18935 tcg_gen_mul_i64(t2, t2, t3);
18936 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18937 tcg_gen_add_i64(t2, t2, t3);
18938 tcg_temp_free_i64(t3);
18939 gen_move_low32(cpu_LO[acc], t2);
18940 gen_move_high32(cpu_HI[acc], t2);
18941 tcg_temp_free_i64(t2);
18943 break;
18944 case NM_MULTU:
18945 check_dsp(ctx);
18947 int acc = extract32(ctx->opcode, 14, 2);
18948 TCGv_i32 t2 = tcg_temp_new_i32();
18949 TCGv_i32 t3 = tcg_temp_new_i32();
18951 gen_load_gpr(t0, rs);
18952 gen_load_gpr(t1, rt);
18953 tcg_gen_trunc_tl_i32(t2, t0);
18954 tcg_gen_trunc_tl_i32(t3, t1);
18955 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18956 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18957 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18958 tcg_temp_free_i32(t2);
18959 tcg_temp_free_i32(t3);
18961 break;
18962 case NM_EXTRV_R_W:
18963 check_dsp(ctx);
18964 tcg_gen_movi_tl(t0, rd >> 3);
18965 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18966 gen_store_gpr(t0, ret);
18967 break;
18968 default:
18969 generate_exception_end(ctx, EXCP_RI);
18970 break;
18972 break;
18973 case NM_POOL32AXF_2_16_23:
18974 switch (extract32(ctx->opcode, 9, 3)) {
18975 case NM_DPAU_H_QBL:
18976 case NM_DPAQX_S_W_PH:
18977 case NM_DPSU_H_QBL:
18978 case NM_DPSQX_S_W_PH:
18979 case NM_MULSA_W_PH:
18980 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18981 break;
18982 case NM_EXTPV:
18983 check_dsp(ctx);
18984 tcg_gen_movi_tl(t0, rd >> 3);
18985 gen_helper_extp(t0, t0, v1_t, cpu_env);
18986 gen_store_gpr(t0, ret);
18987 break;
18988 case NM_MSUB:
18989 check_dsp(ctx);
18991 int acc = extract32(ctx->opcode, 14, 2);
18992 TCGv_i64 t2 = tcg_temp_new_i64();
18993 TCGv_i64 t3 = tcg_temp_new_i64();
18995 gen_load_gpr(t0, rs);
18996 gen_load_gpr(t1, rt);
18997 tcg_gen_ext_tl_i64(t2, t0);
18998 tcg_gen_ext_tl_i64(t3, t1);
18999 tcg_gen_mul_i64(t2, t2, t3);
19000 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19001 tcg_gen_sub_i64(t2, t3, t2);
19002 tcg_temp_free_i64(t3);
19003 gen_move_low32(cpu_LO[acc], t2);
19004 gen_move_high32(cpu_HI[acc], t2);
19005 tcg_temp_free_i64(t2);
19007 break;
19008 case NM_EXTRV_RS_W:
19009 check_dsp(ctx);
19010 tcg_gen_movi_tl(t0, rd >> 3);
19011 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19012 gen_store_gpr(t0, ret);
19013 break;
19015 break;
19016 case NM_POOL32AXF_2_24_31:
19017 switch (extract32(ctx->opcode, 9, 3)) {
19018 case NM_DPAU_H_QBR:
19019 case NM_DPAQX_SA_W_PH:
19020 case NM_DPSU_H_QBR:
19021 case NM_DPSQX_SA_W_PH:
19022 case NM_MULSAQ_S_W_PH:
19023 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19024 break;
19025 case NM_EXTPDPV:
19026 check_dsp(ctx);
19027 tcg_gen_movi_tl(t0, rd >> 3);
19028 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19029 gen_store_gpr(t0, ret);
19030 break;
19031 case NM_MSUBU:
19032 check_dsp(ctx);
19034 int acc = extract32(ctx->opcode, 14, 2);
19035 TCGv_i64 t2 = tcg_temp_new_i64();
19036 TCGv_i64 t3 = tcg_temp_new_i64();
19038 gen_load_gpr(t0, rs);
19039 gen_load_gpr(t1, rt);
19040 tcg_gen_ext32u_tl(t0, t0);
19041 tcg_gen_ext32u_tl(t1, t1);
19042 tcg_gen_extu_tl_i64(t2, t0);
19043 tcg_gen_extu_tl_i64(t3, t1);
19044 tcg_gen_mul_i64(t2, t2, t3);
19045 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19046 tcg_gen_sub_i64(t2, t3, t2);
19047 tcg_temp_free_i64(t3);
19048 gen_move_low32(cpu_LO[acc], t2);
19049 gen_move_high32(cpu_HI[acc], t2);
19050 tcg_temp_free_i64(t2);
19052 break;
19053 case NM_EXTRV_S_H:
19054 check_dsp(ctx);
19055 tcg_gen_movi_tl(t0, rd >> 3);
19056 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19057 gen_store_gpr(t0, ret);
19058 break;
19060 break;
19061 default:
19062 generate_exception_end(ctx, EXCP_RI);
19063 break;
19066 tcg_temp_free(t0);
19067 tcg_temp_free(t1);
19069 tcg_temp_free(v0_t);
19070 tcg_temp_free(v1_t);
19073 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19074 int rt, int rs)
19076 int ret = rt;
19077 TCGv t0 = tcg_temp_new();
19078 TCGv v0_t = tcg_temp_new();
19080 gen_load_gpr(v0_t, rs);
19082 switch (opc) {
19083 case NM_ABSQ_S_QB:
19084 check_dsp_r2(ctx);
19085 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19086 gen_store_gpr(v0_t, ret);
19087 break;
19088 case NM_ABSQ_S_PH:
19089 check_dsp(ctx);
19090 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19091 gen_store_gpr(v0_t, ret);
19092 break;
19093 case NM_ABSQ_S_W:
19094 check_dsp(ctx);
19095 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19096 gen_store_gpr(v0_t, ret);
19097 break;
19098 case NM_PRECEQ_W_PHL:
19099 check_dsp(ctx);
19100 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19101 tcg_gen_ext32s_tl(v0_t, v0_t);
19102 gen_store_gpr(v0_t, ret);
19103 break;
19104 case NM_PRECEQ_W_PHR:
19105 check_dsp(ctx);
19106 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19107 tcg_gen_shli_tl(v0_t, v0_t, 16);
19108 tcg_gen_ext32s_tl(v0_t, v0_t);
19109 gen_store_gpr(v0_t, ret);
19110 break;
19111 case NM_PRECEQU_PH_QBL:
19112 check_dsp(ctx);
19113 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19114 gen_store_gpr(v0_t, ret);
19115 break;
19116 case NM_PRECEQU_PH_QBR:
19117 check_dsp(ctx);
19118 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19119 gen_store_gpr(v0_t, ret);
19120 break;
19121 case NM_PRECEQU_PH_QBLA:
19122 check_dsp(ctx);
19123 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19124 gen_store_gpr(v0_t, ret);
19125 break;
19126 case NM_PRECEQU_PH_QBRA:
19127 check_dsp(ctx);
19128 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19129 gen_store_gpr(v0_t, ret);
19130 break;
19131 case NM_PRECEU_PH_QBL:
19132 check_dsp(ctx);
19133 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19134 gen_store_gpr(v0_t, ret);
19135 break;
19136 case NM_PRECEU_PH_QBR:
19137 check_dsp(ctx);
19138 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19139 gen_store_gpr(v0_t, ret);
19140 break;
19141 case NM_PRECEU_PH_QBLA:
19142 check_dsp(ctx);
19143 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19144 gen_store_gpr(v0_t, ret);
19145 break;
19146 case NM_PRECEU_PH_QBRA:
19147 check_dsp(ctx);
19148 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19149 gen_store_gpr(v0_t, ret);
19150 break;
19151 case NM_REPLV_PH:
19152 check_dsp(ctx);
19153 tcg_gen_ext16u_tl(v0_t, v0_t);
19154 tcg_gen_shli_tl(t0, v0_t, 16);
19155 tcg_gen_or_tl(v0_t, v0_t, t0);
19156 tcg_gen_ext32s_tl(v0_t, v0_t);
19157 gen_store_gpr(v0_t, ret);
19158 break;
19159 case NM_REPLV_QB:
19160 check_dsp(ctx);
19161 tcg_gen_ext8u_tl(v0_t, v0_t);
19162 tcg_gen_shli_tl(t0, v0_t, 8);
19163 tcg_gen_or_tl(v0_t, v0_t, t0);
19164 tcg_gen_shli_tl(t0, v0_t, 16);
19165 tcg_gen_or_tl(v0_t, v0_t, t0);
19166 tcg_gen_ext32s_tl(v0_t, v0_t);
19167 gen_store_gpr(v0_t, ret);
19168 break;
19169 case NM_BITREV:
19170 check_dsp(ctx);
19171 gen_helper_bitrev(v0_t, v0_t);
19172 gen_store_gpr(v0_t, ret);
19173 break;
19174 case NM_INSV:
19175 check_dsp(ctx);
19177 TCGv tv0 = tcg_temp_new();
19179 gen_load_gpr(tv0, rt);
19180 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19181 gen_store_gpr(v0_t, ret);
19182 tcg_temp_free(tv0);
19184 break;
19185 case NM_RADDU_W_QB:
19186 check_dsp(ctx);
19187 gen_helper_raddu_w_qb(v0_t, v0_t);
19188 gen_store_gpr(v0_t, ret);
19189 break;
19190 case NM_BITSWAP:
19191 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19192 break;
19193 case NM_CLO:
19194 check_nms(ctx);
19195 gen_cl(ctx, OPC_CLO, ret, rs);
19196 break;
19197 case NM_CLZ:
19198 check_nms(ctx);
19199 gen_cl(ctx, OPC_CLZ, ret, rs);
19200 break;
19201 case NM_WSBH:
19202 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19203 break;
19204 default:
19205 generate_exception_end(ctx, EXCP_RI);
19206 break;
19209 tcg_temp_free(v0_t);
19210 tcg_temp_free(t0);
19213 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19214 int rt, int rs, int rd)
19216 TCGv t0 = tcg_temp_new();
19217 TCGv rs_t = tcg_temp_new();
19219 gen_load_gpr(rs_t, rs);
19221 switch (opc) {
19222 case NM_SHRA_R_QB:
19223 check_dsp_r2(ctx);
19224 tcg_gen_movi_tl(t0, rd >> 2);
19225 switch (extract32(ctx->opcode, 12, 1)) {
19226 case 0:
19227 /* NM_SHRA_QB */
19228 gen_helper_shra_qb(t0, t0, rs_t);
19229 gen_store_gpr(t0, rt);
19230 break;
19231 case 1:
19232 /* NM_SHRA_R_QB */
19233 gen_helper_shra_r_qb(t0, t0, rs_t);
19234 gen_store_gpr(t0, rt);
19235 break;
19237 break;
19238 case NM_SHRL_PH:
19239 check_dsp_r2(ctx);
19240 tcg_gen_movi_tl(t0, rd >> 1);
19241 gen_helper_shrl_ph(t0, t0, rs_t);
19242 gen_store_gpr(t0, rt);
19243 break;
19244 case NM_REPL_QB:
19245 check_dsp(ctx);
19247 int16_t imm;
19248 target_long result;
19249 imm = extract32(ctx->opcode, 13, 8);
19250 result = (uint32_t)imm << 24 |
19251 (uint32_t)imm << 16 |
19252 (uint32_t)imm << 8 |
19253 (uint32_t)imm;
19254 result = (int32_t)result;
19255 tcg_gen_movi_tl(t0, result);
19256 gen_store_gpr(t0, rt);
19258 break;
19259 default:
19260 generate_exception_end(ctx, EXCP_RI);
19261 break;
19263 tcg_temp_free(t0);
19264 tcg_temp_free(rs_t);
19268 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19270 int rt = extract32(ctx->opcode, 21, 5);
19271 int rs = extract32(ctx->opcode, 16, 5);
19272 int rd = extract32(ctx->opcode, 11, 5);
19274 switch (extract32(ctx->opcode, 6, 3)) {
19275 case NM_POOL32AXF_1:
19277 int32_t op1 = extract32(ctx->opcode, 9, 3);
19278 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19280 break;
19281 case NM_POOL32AXF_2:
19283 int32_t op1 = extract32(ctx->opcode, 12, 2);
19284 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19286 break;
19287 case NM_POOL32AXF_4:
19289 int32_t op1 = extract32(ctx->opcode, 9, 7);
19290 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19292 break;
19293 case NM_POOL32AXF_5:
19294 switch (extract32(ctx->opcode, 9, 7)) {
19295 #ifndef CONFIG_USER_ONLY
19296 case NM_TLBP:
19297 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19298 break;
19299 case NM_TLBR:
19300 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19301 break;
19302 case NM_TLBWI:
19303 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19304 break;
19305 case NM_TLBWR:
19306 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19307 break;
19308 case NM_TLBINV:
19309 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19310 break;
19311 case NM_TLBINVF:
19312 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19313 break;
19314 case NM_DI:
19315 check_cp0_enabled(ctx);
19317 TCGv t0 = tcg_temp_new();
19319 save_cpu_state(ctx, 1);
19320 gen_helper_di(t0, cpu_env);
19321 gen_store_gpr(t0, rt);
19322 /* Stop translation as we may have switched the execution mode */
19323 ctx->base.is_jmp = DISAS_STOP;
19324 tcg_temp_free(t0);
19326 break;
19327 case NM_EI:
19328 check_cp0_enabled(ctx);
19330 TCGv t0 = tcg_temp_new();
19332 save_cpu_state(ctx, 1);
19333 gen_helper_ei(t0, cpu_env);
19334 gen_store_gpr(t0, rt);
19335 /* Stop translation as we may have switched the execution mode */
19336 ctx->base.is_jmp = DISAS_STOP;
19337 tcg_temp_free(t0);
19339 break;
19340 case NM_RDPGPR:
19341 gen_load_srsgpr(rs, rt);
19342 break;
19343 case NM_WRPGPR:
19344 gen_store_srsgpr(rs, rt);
19345 break;
19346 case NM_WAIT:
19347 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19348 break;
19349 case NM_DERET:
19350 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19351 break;
19352 case NM_ERETX:
19353 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19354 break;
19355 #endif
19356 default:
19357 generate_exception_end(ctx, EXCP_RI);
19358 break;
19360 break;
19361 case NM_POOL32AXF_7:
19363 int32_t op1 = extract32(ctx->opcode, 9, 3);
19364 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19366 break;
19367 default:
19368 generate_exception_end(ctx, EXCP_RI);
19369 break;
19373 /* Immediate Value Compact Branches */
19374 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19375 int rt, int32_t imm, int32_t offset)
19377 TCGCond cond;
19378 int bcond_compute = 0;
19379 TCGv t0 = tcg_temp_new();
19380 TCGv t1 = tcg_temp_new();
19382 gen_load_gpr(t0, rt);
19383 tcg_gen_movi_tl(t1, imm);
19384 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19386 /* Load needed operands and calculate btarget */
19387 switch (opc) {
19388 case NM_BEQIC:
19389 if (rt == 0 && imm == 0) {
19390 /* Unconditional branch */
19391 } else if (rt == 0 && imm != 0) {
19392 /* Treat as NOP */
19393 goto out;
19394 } else {
19395 bcond_compute = 1;
19396 cond = TCG_COND_EQ;
19398 break;
19399 case NM_BBEQZC:
19400 case NM_BBNEZC:
19401 check_nms(ctx);
19402 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19403 generate_exception_end(ctx, EXCP_RI);
19404 goto out;
19405 } else if (rt == 0 && opc == NM_BBEQZC) {
19406 /* Unconditional branch */
19407 } else if (rt == 0 && opc == NM_BBNEZC) {
19408 /* Treat as NOP */
19409 goto out;
19410 } else {
19411 tcg_gen_shri_tl(t0, t0, imm);
19412 tcg_gen_andi_tl(t0, t0, 1);
19413 tcg_gen_movi_tl(t1, 0);
19414 bcond_compute = 1;
19415 if (opc == NM_BBEQZC) {
19416 cond = TCG_COND_EQ;
19417 } else {
19418 cond = TCG_COND_NE;
19421 break;
19422 case NM_BNEIC:
19423 if (rt == 0 && imm == 0) {
19424 /* Treat as NOP */
19425 goto out;
19426 } else if (rt == 0 && imm != 0) {
19427 /* Unconditional branch */
19428 } else {
19429 bcond_compute = 1;
19430 cond = TCG_COND_NE;
19432 break;
19433 case NM_BGEIC:
19434 if (rt == 0 && imm == 0) {
19435 /* Unconditional branch */
19436 } else {
19437 bcond_compute = 1;
19438 cond = TCG_COND_GE;
19440 break;
19441 case NM_BLTIC:
19442 bcond_compute = 1;
19443 cond = TCG_COND_LT;
19444 break;
19445 case NM_BGEIUC:
19446 if (rt == 0 && imm == 0) {
19447 /* Unconditional branch */
19448 } else {
19449 bcond_compute = 1;
19450 cond = TCG_COND_GEU;
19452 break;
19453 case NM_BLTIUC:
19454 bcond_compute = 1;
19455 cond = TCG_COND_LTU;
19456 break;
19457 default:
19458 MIPS_INVAL("Immediate Value Compact branch");
19459 generate_exception_end(ctx, EXCP_RI);
19460 goto out;
19463 if (bcond_compute == 0) {
19464 /* Uncoditional compact branch */
19465 gen_goto_tb(ctx, 0, ctx->btarget);
19466 } else {
19467 /* Conditional compact branch */
19468 TCGLabel *fs = gen_new_label();
19470 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19472 gen_goto_tb(ctx, 1, ctx->btarget);
19473 gen_set_label(fs);
19475 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19478 out:
19479 tcg_temp_free(t0);
19480 tcg_temp_free(t1);
19483 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19484 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19485 int rt)
19487 TCGv t0 = tcg_temp_new();
19488 TCGv t1 = tcg_temp_new();
19490 /* load rs */
19491 gen_load_gpr(t0, rs);
19493 /* link */
19494 if (rt != 0) {
19495 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19498 /* calculate btarget */
19499 tcg_gen_shli_tl(t0, t0, 1);
19500 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19501 gen_op_addr_add(ctx, btarget, t1, t0);
19503 /* unconditional branch to register */
19504 tcg_gen_mov_tl(cpu_PC, btarget);
19505 tcg_gen_lookup_and_goto_ptr();
19507 tcg_temp_free(t0);
19508 tcg_temp_free(t1);
19511 /* nanoMIPS Branches */
19512 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19513 int rs, int rt, int32_t offset)
19515 int bcond_compute = 0;
19516 TCGv t0 = tcg_temp_new();
19517 TCGv t1 = tcg_temp_new();
19519 /* Load needed operands and calculate btarget */
19520 switch (opc) {
19521 /* compact branch */
19522 case OPC_BGEC:
19523 case OPC_BLTC:
19524 gen_load_gpr(t0, rs);
19525 gen_load_gpr(t1, rt);
19526 bcond_compute = 1;
19527 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19528 break;
19529 case OPC_BGEUC:
19530 case OPC_BLTUC:
19531 if (rs == 0 || rs == rt) {
19532 /* OPC_BLEZALC, OPC_BGEZALC */
19533 /* OPC_BGTZALC, OPC_BLTZALC */
19534 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19536 gen_load_gpr(t0, rs);
19537 gen_load_gpr(t1, rt);
19538 bcond_compute = 1;
19539 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19540 break;
19541 case OPC_BC:
19542 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19543 break;
19544 case OPC_BEQZC:
19545 if (rs != 0) {
19546 /* OPC_BEQZC, OPC_BNEZC */
19547 gen_load_gpr(t0, rs);
19548 bcond_compute = 1;
19549 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19550 } else {
19551 /* OPC_JIC, OPC_JIALC */
19552 TCGv tbase = tcg_temp_new();
19553 TCGv toffset = tcg_temp_new();
19555 gen_load_gpr(tbase, rt);
19556 tcg_gen_movi_tl(toffset, offset);
19557 gen_op_addr_add(ctx, btarget, tbase, toffset);
19558 tcg_temp_free(tbase);
19559 tcg_temp_free(toffset);
19561 break;
19562 default:
19563 MIPS_INVAL("Compact branch/jump");
19564 generate_exception_end(ctx, EXCP_RI);
19565 goto out;
19568 if (bcond_compute == 0) {
19569 /* Uncoditional compact branch */
19570 switch (opc) {
19571 case OPC_BC:
19572 gen_goto_tb(ctx, 0, ctx->btarget);
19573 break;
19574 default:
19575 MIPS_INVAL("Compact branch/jump");
19576 generate_exception_end(ctx, EXCP_RI);
19577 goto out;
19579 } else {
19580 /* Conditional compact branch */
19581 TCGLabel *fs = gen_new_label();
19583 switch (opc) {
19584 case OPC_BGEUC:
19585 if (rs == 0 && rt != 0) {
19586 /* OPC_BLEZALC */
19587 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19588 } else if (rs != 0 && rt != 0 && rs == rt) {
19589 /* OPC_BGEZALC */
19590 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19591 } else {
19592 /* OPC_BGEUC */
19593 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19595 break;
19596 case OPC_BLTUC:
19597 if (rs == 0 && rt != 0) {
19598 /* OPC_BGTZALC */
19599 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19600 } else if (rs != 0 && rt != 0 && rs == rt) {
19601 /* OPC_BLTZALC */
19602 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19603 } else {
19604 /* OPC_BLTUC */
19605 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19607 break;
19608 case OPC_BGEC:
19609 if (rs == 0 && rt != 0) {
19610 /* OPC_BLEZC */
19611 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19612 } else if (rs != 0 && rt != 0 && rs == rt) {
19613 /* OPC_BGEZC */
19614 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19615 } else {
19616 /* OPC_BGEC */
19617 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19619 break;
19620 case OPC_BLTC:
19621 if (rs == 0 && rt != 0) {
19622 /* OPC_BGTZC */
19623 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19624 } else if (rs != 0 && rt != 0 && rs == rt) {
19625 /* OPC_BLTZC */
19626 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19627 } else {
19628 /* OPC_BLTC */
19629 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19631 break;
19632 case OPC_BEQZC:
19633 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19634 break;
19635 default:
19636 MIPS_INVAL("Compact conditional branch/jump");
19637 generate_exception_end(ctx, EXCP_RI);
19638 goto out;
19641 /* Generating branch here as compact branches don't have delay slot */
19642 gen_goto_tb(ctx, 1, ctx->btarget);
19643 gen_set_label(fs);
19645 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19648 out:
19649 tcg_temp_free(t0);
19650 tcg_temp_free(t1);
19654 /* nanoMIPS CP1 Branches */
19655 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19656 int32_t ft, int32_t offset)
19658 target_ulong btarget;
19659 TCGv_i64 t0 = tcg_temp_new_i64();
19661 gen_load_fpr64(ctx, t0, ft);
19662 tcg_gen_andi_i64(t0, t0, 1);
19664 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19666 switch (op) {
19667 case NM_BC1EQZC:
19668 tcg_gen_xori_i64(t0, t0, 1);
19669 ctx->hflags |= MIPS_HFLAG_BC;
19670 break;
19671 case NM_BC1NEZC:
19672 /* t0 already set */
19673 ctx->hflags |= MIPS_HFLAG_BC;
19674 break;
19675 default:
19676 MIPS_INVAL("cp1 cond branch");
19677 generate_exception_end(ctx, EXCP_RI);
19678 goto out;
19681 tcg_gen_trunc_i64_tl(bcond, t0);
19683 ctx->btarget = btarget;
19685 out:
19686 tcg_temp_free_i64(t0);
19690 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19692 TCGv t0, t1;
19693 t0 = tcg_temp_new();
19694 t1 = tcg_temp_new();
19696 gen_load_gpr(t0, rs);
19697 gen_load_gpr(t1, rt);
19699 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19700 /* PP.LSXS instructions require shifting */
19701 switch (extract32(ctx->opcode, 7, 4)) {
19702 case NM_SHXS:
19703 check_nms(ctx);
19704 case NM_LHXS:
19705 case NM_LHUXS:
19706 tcg_gen_shli_tl(t0, t0, 1);
19707 break;
19708 case NM_SWXS:
19709 check_nms(ctx);
19710 case NM_LWXS:
19711 case NM_LWC1XS:
19712 case NM_SWC1XS:
19713 tcg_gen_shli_tl(t0, t0, 2);
19714 break;
19715 case NM_LDC1XS:
19716 case NM_SDC1XS:
19717 tcg_gen_shli_tl(t0, t0, 3);
19718 break;
19721 gen_op_addr_add(ctx, t0, t0, t1);
19723 switch (extract32(ctx->opcode, 7, 4)) {
19724 case NM_LBX:
19725 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19726 MO_SB);
19727 gen_store_gpr(t0, rd);
19728 break;
19729 case NM_LHX:
19730 /*case NM_LHXS:*/
19731 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19732 MO_TESW);
19733 gen_store_gpr(t0, rd);
19734 break;
19735 case NM_LWX:
19736 /*case NM_LWXS:*/
19737 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19738 MO_TESL);
19739 gen_store_gpr(t0, rd);
19740 break;
19741 case NM_LBUX:
19742 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19743 MO_UB);
19744 gen_store_gpr(t0, rd);
19745 break;
19746 case NM_LHUX:
19747 /*case NM_LHUXS:*/
19748 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19749 MO_TEUW);
19750 gen_store_gpr(t0, rd);
19751 break;
19752 case NM_SBX:
19753 check_nms(ctx);
19754 gen_load_gpr(t1, rd);
19755 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19756 MO_8);
19757 break;
19758 case NM_SHX:
19759 /*case NM_SHXS:*/
19760 check_nms(ctx);
19761 gen_load_gpr(t1, rd);
19762 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19763 MO_TEUW);
19764 break;
19765 case NM_SWX:
19766 /*case NM_SWXS:*/
19767 check_nms(ctx);
19768 gen_load_gpr(t1, rd);
19769 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19770 MO_TEUL);
19771 break;
19772 case NM_LWC1X:
19773 /*case NM_LWC1XS:*/
19774 case NM_LDC1X:
19775 /*case NM_LDC1XS:*/
19776 case NM_SWC1X:
19777 /*case NM_SWC1XS:*/
19778 case NM_SDC1X:
19779 /*case NM_SDC1XS:*/
19780 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19781 check_cp1_enabled(ctx);
19782 switch (extract32(ctx->opcode, 7, 4)) {
19783 case NM_LWC1X:
19784 /*case NM_LWC1XS:*/
19785 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19786 break;
19787 case NM_LDC1X:
19788 /*case NM_LDC1XS:*/
19789 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19790 break;
19791 case NM_SWC1X:
19792 /*case NM_SWC1XS:*/
19793 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19794 break;
19795 case NM_SDC1X:
19796 /*case NM_SDC1XS:*/
19797 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19798 break;
19800 } else {
19801 generate_exception_err(ctx, EXCP_CpU, 1);
19803 break;
19804 default:
19805 generate_exception_end(ctx, EXCP_RI);
19806 break;
19809 tcg_temp_free(t0);
19810 tcg_temp_free(t1);
19813 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19815 int rt, rs, rd;
19817 rt = extract32(ctx->opcode, 21, 5);
19818 rs = extract32(ctx->opcode, 16, 5);
19819 rd = extract32(ctx->opcode, 11, 5);
19821 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19822 generate_exception_end(ctx, EXCP_RI);
19823 return;
19825 check_cp1_enabled(ctx);
19826 switch (extract32(ctx->opcode, 0, 3)) {
19827 case NM_POOL32F_0:
19828 switch (extract32(ctx->opcode, 3, 7)) {
19829 case NM_RINT_S:
19830 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19831 break;
19832 case NM_RINT_D:
19833 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19834 break;
19835 case NM_CLASS_S:
19836 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19837 break;
19838 case NM_CLASS_D:
19839 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19840 break;
19841 case NM_ADD_S:
19842 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19843 break;
19844 case NM_ADD_D:
19845 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19846 break;
19847 case NM_SUB_S:
19848 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19849 break;
19850 case NM_SUB_D:
19851 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19852 break;
19853 case NM_MUL_S:
19854 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19855 break;
19856 case NM_MUL_D:
19857 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19858 break;
19859 case NM_DIV_S:
19860 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19861 break;
19862 case NM_DIV_D:
19863 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19864 break;
19865 case NM_SELEQZ_S:
19866 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19867 break;
19868 case NM_SELEQZ_D:
19869 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19870 break;
19871 case NM_SELNEZ_S:
19872 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19873 break;
19874 case NM_SELNEZ_D:
19875 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19876 break;
19877 case NM_SEL_S:
19878 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19879 break;
19880 case NM_SEL_D:
19881 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19882 break;
19883 case NM_MADDF_S:
19884 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19885 break;
19886 case NM_MADDF_D:
19887 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19888 break;
19889 case NM_MSUBF_S:
19890 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19891 break;
19892 case NM_MSUBF_D:
19893 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19894 break;
19895 default:
19896 generate_exception_end(ctx, EXCP_RI);
19897 break;
19899 break;
19900 case NM_POOL32F_3:
19901 switch (extract32(ctx->opcode, 3, 3)) {
19902 case NM_MIN_FMT:
19903 switch (extract32(ctx->opcode, 9, 1)) {
19904 case FMT_SDPS_S:
19905 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19906 break;
19907 case FMT_SDPS_D:
19908 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19909 break;
19911 break;
19912 case NM_MAX_FMT:
19913 switch (extract32(ctx->opcode, 9, 1)) {
19914 case FMT_SDPS_S:
19915 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19916 break;
19917 case FMT_SDPS_D:
19918 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19919 break;
19921 break;
19922 case NM_MINA_FMT:
19923 switch (extract32(ctx->opcode, 9, 1)) {
19924 case FMT_SDPS_S:
19925 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19926 break;
19927 case FMT_SDPS_D:
19928 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19929 break;
19931 break;
19932 case NM_MAXA_FMT:
19933 switch (extract32(ctx->opcode, 9, 1)) {
19934 case FMT_SDPS_S:
19935 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19936 break;
19937 case FMT_SDPS_D:
19938 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19939 break;
19941 break;
19942 case NM_POOL32FXF:
19943 switch (extract32(ctx->opcode, 6, 8)) {
19944 case NM_CFC1:
19945 gen_cp1(ctx, OPC_CFC1, rt, rs);
19946 break;
19947 case NM_CTC1:
19948 gen_cp1(ctx, OPC_CTC1, rt, rs);
19949 break;
19950 case NM_MFC1:
19951 gen_cp1(ctx, OPC_MFC1, rt, rs);
19952 break;
19953 case NM_MTC1:
19954 gen_cp1(ctx, OPC_MTC1, rt, rs);
19955 break;
19956 case NM_MFHC1:
19957 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19958 break;
19959 case NM_MTHC1:
19960 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19961 break;
19962 case NM_CVT_S_PL:
19963 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19964 break;
19965 case NM_CVT_S_PU:
19966 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19967 break;
19968 default:
19969 switch (extract32(ctx->opcode, 6, 9)) {
19970 case NM_CVT_L_S:
19971 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19972 break;
19973 case NM_CVT_L_D:
19974 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19975 break;
19976 case NM_CVT_W_S:
19977 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19978 break;
19979 case NM_CVT_W_D:
19980 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19981 break;
19982 case NM_RSQRT_S:
19983 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19984 break;
19985 case NM_RSQRT_D:
19986 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19987 break;
19988 case NM_SQRT_S:
19989 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19990 break;
19991 case NM_SQRT_D:
19992 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19993 break;
19994 case NM_RECIP_S:
19995 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19996 break;
19997 case NM_RECIP_D:
19998 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19999 break;
20000 case NM_FLOOR_L_S:
20001 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20002 break;
20003 case NM_FLOOR_L_D:
20004 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20005 break;
20006 case NM_FLOOR_W_S:
20007 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20008 break;
20009 case NM_FLOOR_W_D:
20010 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20011 break;
20012 case NM_CEIL_L_S:
20013 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20014 break;
20015 case NM_CEIL_L_D:
20016 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20017 break;
20018 case NM_CEIL_W_S:
20019 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20020 break;
20021 case NM_CEIL_W_D:
20022 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20023 break;
20024 case NM_TRUNC_L_S:
20025 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20026 break;
20027 case NM_TRUNC_L_D:
20028 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20029 break;
20030 case NM_TRUNC_W_S:
20031 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20032 break;
20033 case NM_TRUNC_W_D:
20034 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20035 break;
20036 case NM_ROUND_L_S:
20037 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20038 break;
20039 case NM_ROUND_L_D:
20040 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20041 break;
20042 case NM_ROUND_W_S:
20043 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20044 break;
20045 case NM_ROUND_W_D:
20046 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20047 break;
20048 case NM_MOV_S:
20049 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20050 break;
20051 case NM_MOV_D:
20052 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20053 break;
20054 case NM_ABS_S:
20055 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20056 break;
20057 case NM_ABS_D:
20058 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20059 break;
20060 case NM_NEG_S:
20061 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20062 break;
20063 case NM_NEG_D:
20064 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20065 break;
20066 case NM_CVT_D_S:
20067 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20068 break;
20069 case NM_CVT_D_W:
20070 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20071 break;
20072 case NM_CVT_D_L:
20073 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20074 break;
20075 case NM_CVT_S_D:
20076 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20077 break;
20078 case NM_CVT_S_W:
20079 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20080 break;
20081 case NM_CVT_S_L:
20082 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20083 break;
20084 default:
20085 generate_exception_end(ctx, EXCP_RI);
20086 break;
20088 break;
20090 break;
20092 break;
20093 case NM_POOL32F_5:
20094 switch (extract32(ctx->opcode, 3, 3)) {
20095 case NM_CMP_CONDN_S:
20096 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20097 break;
20098 case NM_CMP_CONDN_D:
20099 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20100 break;
20101 default:
20102 generate_exception_end(ctx, EXCP_RI);
20103 break;
20105 break;
20106 default:
20107 generate_exception_end(ctx, EXCP_RI);
20108 break;
20112 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20113 int rd, int rs, int rt)
20115 int ret = rd;
20116 TCGv t0 = tcg_temp_new();
20117 TCGv v1_t = tcg_temp_new();
20118 TCGv v2_t = tcg_temp_new();
20120 gen_load_gpr(v1_t, rs);
20121 gen_load_gpr(v2_t, rt);
20123 switch (opc) {
20124 case NM_CMP_EQ_PH:
20125 check_dsp(ctx);
20126 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20127 break;
20128 case NM_CMP_LT_PH:
20129 check_dsp(ctx);
20130 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20131 break;
20132 case NM_CMP_LE_PH:
20133 check_dsp(ctx);
20134 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20135 break;
20136 case NM_CMPU_EQ_QB:
20137 check_dsp(ctx);
20138 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20139 break;
20140 case NM_CMPU_LT_QB:
20141 check_dsp(ctx);
20142 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20143 break;
20144 case NM_CMPU_LE_QB:
20145 check_dsp(ctx);
20146 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20147 break;
20148 case NM_CMPGU_EQ_QB:
20149 check_dsp(ctx);
20150 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20151 gen_store_gpr(v1_t, ret);
20152 break;
20153 case NM_CMPGU_LT_QB:
20154 check_dsp(ctx);
20155 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20156 gen_store_gpr(v1_t, ret);
20157 break;
20158 case NM_CMPGU_LE_QB:
20159 check_dsp(ctx);
20160 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20161 gen_store_gpr(v1_t, ret);
20162 break;
20163 case NM_CMPGDU_EQ_QB:
20164 check_dsp_r2(ctx);
20165 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20166 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20167 gen_store_gpr(v1_t, ret);
20168 break;
20169 case NM_CMPGDU_LT_QB:
20170 check_dsp_r2(ctx);
20171 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20172 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20173 gen_store_gpr(v1_t, ret);
20174 break;
20175 case NM_CMPGDU_LE_QB:
20176 check_dsp_r2(ctx);
20177 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20178 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20179 gen_store_gpr(v1_t, ret);
20180 break;
20181 case NM_PACKRL_PH:
20182 check_dsp(ctx);
20183 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20184 gen_store_gpr(v1_t, ret);
20185 break;
20186 case NM_PICK_QB:
20187 check_dsp(ctx);
20188 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20189 gen_store_gpr(v1_t, ret);
20190 break;
20191 case NM_PICK_PH:
20192 check_dsp(ctx);
20193 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20194 gen_store_gpr(v1_t, ret);
20195 break;
20196 case NM_ADDQ_S_W:
20197 check_dsp(ctx);
20198 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20199 gen_store_gpr(v1_t, ret);
20200 break;
20201 case NM_SUBQ_S_W:
20202 check_dsp(ctx);
20203 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20204 gen_store_gpr(v1_t, ret);
20205 break;
20206 case NM_ADDSC:
20207 check_dsp(ctx);
20208 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20209 gen_store_gpr(v1_t, ret);
20210 break;
20211 case NM_ADDWC:
20212 check_dsp(ctx);
20213 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20214 gen_store_gpr(v1_t, ret);
20215 break;
20216 case NM_ADDQ_S_PH:
20217 check_dsp(ctx);
20218 switch (extract32(ctx->opcode, 10, 1)) {
20219 case 0:
20220 /* ADDQ_PH */
20221 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20222 gen_store_gpr(v1_t, ret);
20223 break;
20224 case 1:
20225 /* ADDQ_S_PH */
20226 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20227 gen_store_gpr(v1_t, ret);
20228 break;
20230 break;
20231 case NM_ADDQH_R_PH:
20232 check_dsp_r2(ctx);
20233 switch (extract32(ctx->opcode, 10, 1)) {
20234 case 0:
20235 /* ADDQH_PH */
20236 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20237 gen_store_gpr(v1_t, ret);
20238 break;
20239 case 1:
20240 /* ADDQH_R_PH */
20241 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20242 gen_store_gpr(v1_t, ret);
20243 break;
20245 break;
20246 case NM_ADDQH_R_W:
20247 check_dsp_r2(ctx);
20248 switch (extract32(ctx->opcode, 10, 1)) {
20249 case 0:
20250 /* ADDQH_W */
20251 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20252 gen_store_gpr(v1_t, ret);
20253 break;
20254 case 1:
20255 /* ADDQH_R_W */
20256 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20257 gen_store_gpr(v1_t, ret);
20258 break;
20260 break;
20261 case NM_ADDU_S_QB:
20262 check_dsp(ctx);
20263 switch (extract32(ctx->opcode, 10, 1)) {
20264 case 0:
20265 /* ADDU_QB */
20266 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20267 gen_store_gpr(v1_t, ret);
20268 break;
20269 case 1:
20270 /* ADDU_S_QB */
20271 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20272 gen_store_gpr(v1_t, ret);
20273 break;
20275 break;
20276 case NM_ADDU_S_PH:
20277 check_dsp_r2(ctx);
20278 switch (extract32(ctx->opcode, 10, 1)) {
20279 case 0:
20280 /* ADDU_PH */
20281 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20282 gen_store_gpr(v1_t, ret);
20283 break;
20284 case 1:
20285 /* ADDU_S_PH */
20286 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20287 gen_store_gpr(v1_t, ret);
20288 break;
20290 break;
20291 case NM_ADDUH_R_QB:
20292 check_dsp_r2(ctx);
20293 switch (extract32(ctx->opcode, 10, 1)) {
20294 case 0:
20295 /* ADDUH_QB */
20296 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20297 gen_store_gpr(v1_t, ret);
20298 break;
20299 case 1:
20300 /* ADDUH_R_QB */
20301 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20302 gen_store_gpr(v1_t, ret);
20303 break;
20305 break;
20306 case NM_SHRAV_R_PH:
20307 check_dsp(ctx);
20308 switch (extract32(ctx->opcode, 10, 1)) {
20309 case 0:
20310 /* SHRAV_PH */
20311 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20312 gen_store_gpr(v1_t, ret);
20313 break;
20314 case 1:
20315 /* SHRAV_R_PH */
20316 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20317 gen_store_gpr(v1_t, ret);
20318 break;
20320 break;
20321 case NM_SHRAV_R_QB:
20322 check_dsp_r2(ctx);
20323 switch (extract32(ctx->opcode, 10, 1)) {
20324 case 0:
20325 /* SHRAV_QB */
20326 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20327 gen_store_gpr(v1_t, ret);
20328 break;
20329 case 1:
20330 /* SHRAV_R_QB */
20331 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20332 gen_store_gpr(v1_t, ret);
20333 break;
20335 break;
20336 case NM_SUBQ_S_PH:
20337 check_dsp(ctx);
20338 switch (extract32(ctx->opcode, 10, 1)) {
20339 case 0:
20340 /* SUBQ_PH */
20341 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20342 gen_store_gpr(v1_t, ret);
20343 break;
20344 case 1:
20345 /* SUBQ_S_PH */
20346 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20347 gen_store_gpr(v1_t, ret);
20348 break;
20350 break;
20351 case NM_SUBQH_R_PH:
20352 check_dsp_r2(ctx);
20353 switch (extract32(ctx->opcode, 10, 1)) {
20354 case 0:
20355 /* SUBQH_PH */
20356 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20357 gen_store_gpr(v1_t, ret);
20358 break;
20359 case 1:
20360 /* SUBQH_R_PH */
20361 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20362 gen_store_gpr(v1_t, ret);
20363 break;
20365 break;
20366 case NM_SUBQH_R_W:
20367 check_dsp_r2(ctx);
20368 switch (extract32(ctx->opcode, 10, 1)) {
20369 case 0:
20370 /* SUBQH_W */
20371 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20372 gen_store_gpr(v1_t, ret);
20373 break;
20374 case 1:
20375 /* SUBQH_R_W */
20376 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20377 gen_store_gpr(v1_t, ret);
20378 break;
20380 break;
20381 case NM_SUBU_S_QB:
20382 check_dsp(ctx);
20383 switch (extract32(ctx->opcode, 10, 1)) {
20384 case 0:
20385 /* SUBU_QB */
20386 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20387 gen_store_gpr(v1_t, ret);
20388 break;
20389 case 1:
20390 /* SUBU_S_QB */
20391 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20392 gen_store_gpr(v1_t, ret);
20393 break;
20395 break;
20396 case NM_SUBU_S_PH:
20397 check_dsp_r2(ctx);
20398 switch (extract32(ctx->opcode, 10, 1)) {
20399 case 0:
20400 /* SUBU_PH */
20401 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20402 gen_store_gpr(v1_t, ret);
20403 break;
20404 case 1:
20405 /* SUBU_S_PH */
20406 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20407 gen_store_gpr(v1_t, ret);
20408 break;
20410 break;
20411 case NM_SUBUH_R_QB:
20412 check_dsp_r2(ctx);
20413 switch (extract32(ctx->opcode, 10, 1)) {
20414 case 0:
20415 /* SUBUH_QB */
20416 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20417 gen_store_gpr(v1_t, ret);
20418 break;
20419 case 1:
20420 /* SUBUH_R_QB */
20421 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20422 gen_store_gpr(v1_t, ret);
20423 break;
20425 break;
20426 case NM_SHLLV_S_PH:
20427 check_dsp(ctx);
20428 switch (extract32(ctx->opcode, 10, 1)) {
20429 case 0:
20430 /* SHLLV_PH */
20431 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20432 gen_store_gpr(v1_t, ret);
20433 break;
20434 case 1:
20435 /* SHLLV_S_PH */
20436 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20437 gen_store_gpr(v1_t, ret);
20438 break;
20440 break;
20441 case NM_PRECR_SRA_R_PH_W:
20442 check_dsp_r2(ctx);
20443 switch (extract32(ctx->opcode, 10, 1)) {
20444 case 0:
20445 /* PRECR_SRA_PH_W */
20447 TCGv_i32 sa_t = tcg_const_i32(rd);
20448 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20449 cpu_gpr[rt]);
20450 gen_store_gpr(v1_t, rt);
20451 tcg_temp_free_i32(sa_t);
20453 break;
20454 case 1:
20455 /* PRECR_SRA_R_PH_W */
20457 TCGv_i32 sa_t = tcg_const_i32(rd);
20458 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20459 cpu_gpr[rt]);
20460 gen_store_gpr(v1_t, rt);
20461 tcg_temp_free_i32(sa_t);
20463 break;
20465 break;
20466 case NM_MULEU_S_PH_QBL:
20467 check_dsp(ctx);
20468 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20469 gen_store_gpr(v1_t, ret);
20470 break;
20471 case NM_MULEU_S_PH_QBR:
20472 check_dsp(ctx);
20473 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20474 gen_store_gpr(v1_t, ret);
20475 break;
20476 case NM_MULQ_RS_PH:
20477 check_dsp(ctx);
20478 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20479 gen_store_gpr(v1_t, ret);
20480 break;
20481 case NM_MULQ_S_PH:
20482 check_dsp_r2(ctx);
20483 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20484 gen_store_gpr(v1_t, ret);
20485 break;
20486 case NM_MULQ_RS_W:
20487 check_dsp_r2(ctx);
20488 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20489 gen_store_gpr(v1_t, ret);
20490 break;
20491 case NM_MULQ_S_W:
20492 check_dsp_r2(ctx);
20493 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20494 gen_store_gpr(v1_t, ret);
20495 break;
20496 case NM_APPEND:
20497 check_dsp_r2(ctx);
20498 gen_load_gpr(t0, rs);
20499 if (rd != 0) {
20500 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20502 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20503 break;
20504 case NM_MODSUB:
20505 check_dsp(ctx);
20506 gen_helper_modsub(v1_t, v1_t, v2_t);
20507 gen_store_gpr(v1_t, ret);
20508 break;
20509 case NM_SHRAV_R_W:
20510 check_dsp(ctx);
20511 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20512 gen_store_gpr(v1_t, ret);
20513 break;
20514 case NM_SHRLV_PH:
20515 check_dsp_r2(ctx);
20516 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20517 gen_store_gpr(v1_t, ret);
20518 break;
20519 case NM_SHRLV_QB:
20520 check_dsp(ctx);
20521 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20522 gen_store_gpr(v1_t, ret);
20523 break;
20524 case NM_SHLLV_QB:
20525 check_dsp(ctx);
20526 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20527 gen_store_gpr(v1_t, ret);
20528 break;
20529 case NM_SHLLV_S_W:
20530 check_dsp(ctx);
20531 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20532 gen_store_gpr(v1_t, ret);
20533 break;
20534 case NM_SHILO:
20535 check_dsp(ctx);
20537 TCGv tv0 = tcg_temp_new();
20538 TCGv tv1 = tcg_temp_new();
20539 int16_t imm = extract32(ctx->opcode, 16, 7);
20541 tcg_gen_movi_tl(tv0, rd >> 3);
20542 tcg_gen_movi_tl(tv1, imm);
20543 gen_helper_shilo(tv0, tv1, cpu_env);
20545 break;
20546 case NM_MULEQ_S_W_PHL:
20547 check_dsp(ctx);
20548 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20549 gen_store_gpr(v1_t, ret);
20550 break;
20551 case NM_MULEQ_S_W_PHR:
20552 check_dsp(ctx);
20553 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20554 gen_store_gpr(v1_t, ret);
20555 break;
20556 case NM_MUL_S_PH:
20557 check_dsp_r2(ctx);
20558 switch (extract32(ctx->opcode, 10, 1)) {
20559 case 0:
20560 /* MUL_PH */
20561 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20562 gen_store_gpr(v1_t, ret);
20563 break;
20564 case 1:
20565 /* MUL_S_PH */
20566 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20567 gen_store_gpr(v1_t, ret);
20568 break;
20570 break;
20571 case NM_PRECR_QB_PH:
20572 check_dsp_r2(ctx);
20573 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20574 gen_store_gpr(v1_t, ret);
20575 break;
20576 case NM_PRECRQ_QB_PH:
20577 check_dsp(ctx);
20578 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20579 gen_store_gpr(v1_t, ret);
20580 break;
20581 case NM_PRECRQ_PH_W:
20582 check_dsp(ctx);
20583 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20584 gen_store_gpr(v1_t, ret);
20585 break;
20586 case NM_PRECRQ_RS_PH_W:
20587 check_dsp(ctx);
20588 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20589 gen_store_gpr(v1_t, ret);
20590 break;
20591 case NM_PRECRQU_S_QB_PH:
20592 check_dsp(ctx);
20593 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20594 gen_store_gpr(v1_t, ret);
20595 break;
20596 case NM_SHRA_R_W:
20597 check_dsp(ctx);
20598 tcg_gen_movi_tl(t0, rd);
20599 gen_helper_shra_r_w(v1_t, t0, v1_t);
20600 gen_store_gpr(v1_t, rt);
20601 break;
20602 case NM_SHRA_R_PH:
20603 check_dsp(ctx);
20604 tcg_gen_movi_tl(t0, rd >> 1);
20605 switch (extract32(ctx->opcode, 10, 1)) {
20606 case 0:
20607 /* SHRA_PH */
20608 gen_helper_shra_ph(v1_t, t0, v1_t);
20609 gen_store_gpr(v1_t, rt);
20610 break;
20611 case 1:
20612 /* SHRA_R_PH */
20613 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20614 gen_store_gpr(v1_t, rt);
20615 break;
20617 break;
20618 case NM_SHLL_S_PH:
20619 check_dsp(ctx);
20620 tcg_gen_movi_tl(t0, rd >> 1);
20621 switch (extract32(ctx->opcode, 10, 2)) {
20622 case 0:
20623 /* SHLL_PH */
20624 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20625 gen_store_gpr(v1_t, rt);
20626 break;
20627 case 2:
20628 /* SHLL_S_PH */
20629 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20630 gen_store_gpr(v1_t, rt);
20631 break;
20632 default:
20633 generate_exception_end(ctx, EXCP_RI);
20634 break;
20636 break;
20637 case NM_SHLL_S_W:
20638 check_dsp(ctx);
20639 tcg_gen_movi_tl(t0, rd);
20640 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20641 gen_store_gpr(v1_t, rt);
20642 break;
20643 case NM_REPL_PH:
20644 check_dsp(ctx);
20646 int16_t imm;
20647 imm = sextract32(ctx->opcode, 11, 11);
20648 imm = (int16_t)(imm << 6) >> 6;
20649 if (rt != 0) {
20650 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20653 break;
20654 default:
20655 generate_exception_end(ctx, EXCP_RI);
20656 break;
20660 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20662 uint16_t insn;
20663 uint32_t op;
20664 int rt, rs, rd;
20665 int offset;
20666 int imm;
20668 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20669 ctx->opcode = (ctx->opcode << 16) | insn;
20671 rt = extract32(ctx->opcode, 21, 5);
20672 rs = extract32(ctx->opcode, 16, 5);
20673 rd = extract32(ctx->opcode, 11, 5);
20675 op = extract32(ctx->opcode, 26, 6);
20676 switch (op) {
20677 case NM_P_ADDIU:
20678 if (rt == 0) {
20679 /* P.RI */
20680 switch (extract32(ctx->opcode, 19, 2)) {
20681 case NM_SIGRIE:
20682 default:
20683 generate_exception_end(ctx, EXCP_RI);
20684 break;
20685 case NM_P_SYSCALL:
20686 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20687 generate_exception_end(ctx, EXCP_SYSCALL);
20688 } else {
20689 generate_exception_end(ctx, EXCP_RI);
20691 break;
20692 case NM_BREAK:
20693 generate_exception_end(ctx, EXCP_BREAK);
20694 break;
20695 case NM_SDBBP:
20696 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20697 gen_helper_do_semihosting(cpu_env);
20698 } else {
20699 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20700 generate_exception_end(ctx, EXCP_RI);
20701 } else {
20702 generate_exception_end(ctx, EXCP_DBp);
20705 break;
20707 } else {
20708 /* NM_ADDIU */
20709 imm = extract32(ctx->opcode, 0, 16);
20710 if (rs != 0) {
20711 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20712 } else {
20713 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20715 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20717 break;
20718 case NM_ADDIUPC:
20719 if (rt != 0) {
20720 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20721 extract32(ctx->opcode, 1, 20) << 1;
20722 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20723 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20725 break;
20726 case NM_POOL32A:
20727 switch (ctx->opcode & 0x07) {
20728 case NM_POOL32A0:
20729 gen_pool32a0_nanomips_insn(env, ctx);
20730 break;
20731 case NM_POOL32A5:
20733 int32_t op1 = extract32(ctx->opcode, 3, 7);
20734 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20736 break;
20737 case NM_POOL32A7:
20738 switch (extract32(ctx->opcode, 3, 3)) {
20739 case NM_P_LSX:
20740 gen_p_lsx(ctx, rd, rs, rt);
20741 break;
20742 case NM_LSA:
20743 /* In nanoMIPS, the shift field directly encodes the shift
20744 * amount, meaning that the supported shift values are in
20745 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20746 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20747 extract32(ctx->opcode, 9, 2) - 1);
20748 break;
20749 case NM_EXTW:
20750 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20751 break;
20752 case NM_POOL32AXF:
20753 gen_pool32axf_nanomips_insn(env, ctx);
20754 break;
20755 default:
20756 generate_exception_end(ctx, EXCP_RI);
20757 break;
20759 break;
20760 default:
20761 generate_exception_end(ctx, EXCP_RI);
20762 break;
20764 break;
20765 case NM_P_GP_W:
20766 switch (ctx->opcode & 0x03) {
20767 case NM_ADDIUGP_W:
20768 if (rt != 0) {
20769 offset = extract32(ctx->opcode, 0, 21);
20770 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20772 break;
20773 case NM_LWGP:
20774 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20775 break;
20776 case NM_SWGP:
20777 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20778 break;
20779 default:
20780 generate_exception_end(ctx, EXCP_RI);
20781 break;
20783 break;
20784 case NM_P48I:
20786 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20787 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20788 switch (extract32(ctx->opcode, 16, 5)) {
20789 case NM_LI48:
20790 check_nms(ctx);
20791 if (rt != 0) {
20792 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20794 break;
20795 case NM_ADDIU48:
20796 check_nms(ctx);
20797 if (rt != 0) {
20798 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20799 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20801 break;
20802 case NM_ADDIUGP48:
20803 check_nms(ctx);
20804 if (rt != 0) {
20805 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20807 break;
20808 case NM_ADDIUPC48:
20809 check_nms(ctx);
20810 if (rt != 0) {
20811 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20812 addr_off);
20814 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20816 break;
20817 case NM_LWPC48:
20818 check_nms(ctx);
20819 if (rt != 0) {
20820 TCGv t0;
20821 t0 = tcg_temp_new();
20823 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20824 addr_off);
20826 tcg_gen_movi_tl(t0, addr);
20827 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20828 tcg_temp_free(t0);
20830 break;
20831 case NM_SWPC48:
20832 check_nms(ctx);
20834 TCGv t0, t1;
20835 t0 = tcg_temp_new();
20836 t1 = tcg_temp_new();
20838 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20839 addr_off);
20841 tcg_gen_movi_tl(t0, addr);
20842 gen_load_gpr(t1, rt);
20844 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20846 tcg_temp_free(t0);
20847 tcg_temp_free(t1);
20849 break;
20850 default:
20851 generate_exception_end(ctx, EXCP_RI);
20852 break;
20854 return 6;
20856 case NM_P_U12:
20857 switch (extract32(ctx->opcode, 12, 4)) {
20858 case NM_ORI:
20859 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20860 break;
20861 case NM_XORI:
20862 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20863 break;
20864 case NM_ANDI:
20865 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20866 break;
20867 case NM_P_SR:
20868 switch (extract32(ctx->opcode, 20, 1)) {
20869 case NM_PP_SR:
20870 switch (ctx->opcode & 3) {
20871 case NM_SAVE:
20872 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20873 extract32(ctx->opcode, 2, 1),
20874 extract32(ctx->opcode, 3, 9) << 3);
20875 break;
20876 case NM_RESTORE:
20877 case NM_RESTORE_JRC:
20878 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20879 extract32(ctx->opcode, 2, 1),
20880 extract32(ctx->opcode, 3, 9) << 3);
20881 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20882 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20884 break;
20885 default:
20886 generate_exception_end(ctx, EXCP_RI);
20887 break;
20889 break;
20890 case NM_P_SR_F:
20891 generate_exception_end(ctx, EXCP_RI);
20892 break;
20894 break;
20895 case NM_SLTI:
20896 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20897 break;
20898 case NM_SLTIU:
20899 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20900 break;
20901 case NM_SEQI:
20903 TCGv t0 = tcg_temp_new();
20905 imm = extract32(ctx->opcode, 0, 12);
20906 gen_load_gpr(t0, rs);
20907 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20908 gen_store_gpr(t0, rt);
20910 tcg_temp_free(t0);
20912 break;
20913 case NM_ADDIUNEG:
20914 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20915 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20916 break;
20917 case NM_P_SHIFT:
20919 int shift = extract32(ctx->opcode, 0, 5);
20920 switch (extract32(ctx->opcode, 5, 4)) {
20921 case NM_P_SLL:
20922 if (rt == 0 && shift == 0) {
20923 /* NOP */
20924 } else if (rt == 0 && shift == 3) {
20925 /* EHB - treat as NOP */
20926 } else if (rt == 0 && shift == 5) {
20927 /* PAUSE - treat as NOP */
20928 } else if (rt == 0 && shift == 6) {
20929 /* SYNC */
20930 gen_sync(extract32(ctx->opcode, 16, 5));
20931 } else {
20932 /* SLL */
20933 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20934 extract32(ctx->opcode, 0, 5));
20936 break;
20937 case NM_SRL:
20938 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20939 extract32(ctx->opcode, 0, 5));
20940 break;
20941 case NM_SRA:
20942 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20943 extract32(ctx->opcode, 0, 5));
20944 break;
20945 case NM_ROTR:
20946 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20947 extract32(ctx->opcode, 0, 5));
20948 break;
20951 break;
20952 case NM_P_ROTX:
20953 check_nms(ctx);
20954 if (rt != 0) {
20955 TCGv t0 = tcg_temp_new();
20956 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20957 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20958 << 1);
20959 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20961 gen_load_gpr(t0, rs);
20962 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20963 tcg_temp_free(t0);
20965 tcg_temp_free_i32(shift);
20966 tcg_temp_free_i32(shiftx);
20967 tcg_temp_free_i32(stripe);
20969 break;
20970 case NM_P_INS:
20971 switch (((ctx->opcode >> 10) & 2) |
20972 (extract32(ctx->opcode, 5, 1))) {
20973 case NM_INS:
20974 check_nms(ctx);
20975 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20976 extract32(ctx->opcode, 6, 5));
20977 break;
20978 default:
20979 generate_exception_end(ctx, EXCP_RI);
20980 break;
20982 break;
20983 case NM_P_EXT:
20984 switch (((ctx->opcode >> 10) & 2) |
20985 (extract32(ctx->opcode, 5, 1))) {
20986 case NM_EXT:
20987 check_nms(ctx);
20988 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20989 extract32(ctx->opcode, 6, 5));
20990 break;
20991 default:
20992 generate_exception_end(ctx, EXCP_RI);
20993 break;
20995 break;
20996 default:
20997 generate_exception_end(ctx, EXCP_RI);
20998 break;
21000 break;
21001 case NM_POOL32F:
21002 gen_pool32f_nanomips_insn(ctx);
21003 break;
21004 case NM_POOL32S:
21005 break;
21006 case NM_P_LUI:
21007 switch (extract32(ctx->opcode, 1, 1)) {
21008 case NM_LUI:
21009 if (rt != 0) {
21010 tcg_gen_movi_tl(cpu_gpr[rt],
21011 sextract32(ctx->opcode, 0, 1) << 31 |
21012 extract32(ctx->opcode, 2, 10) << 21 |
21013 extract32(ctx->opcode, 12, 9) << 12);
21015 break;
21016 case NM_ALUIPC:
21017 if (rt != 0) {
21018 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21019 extract32(ctx->opcode, 2, 10) << 21 |
21020 extract32(ctx->opcode, 12, 9) << 12;
21021 target_long addr;
21022 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21023 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21025 break;
21027 break;
21028 case NM_P_GP_BH:
21030 uint32_t u = extract32(ctx->opcode, 0, 18);
21032 switch (extract32(ctx->opcode, 18, 3)) {
21033 case NM_LBGP:
21034 gen_ld(ctx, OPC_LB, rt, 28, u);
21035 break;
21036 case NM_SBGP:
21037 gen_st(ctx, OPC_SB, rt, 28, u);
21038 break;
21039 case NM_LBUGP:
21040 gen_ld(ctx, OPC_LBU, rt, 28, u);
21041 break;
21042 case NM_ADDIUGP_B:
21043 if (rt != 0) {
21044 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21046 break;
21047 case NM_P_GP_LH:
21048 u &= ~1;
21049 switch (ctx->opcode & 1) {
21050 case NM_LHGP:
21051 gen_ld(ctx, OPC_LH, rt, 28, u);
21052 break;
21053 case NM_LHUGP:
21054 gen_ld(ctx, OPC_LHU, rt, 28, u);
21055 break;
21057 break;
21058 case NM_P_GP_SH:
21059 u &= ~1;
21060 switch (ctx->opcode & 1) {
21061 case NM_SHGP:
21062 gen_st(ctx, OPC_SH, rt, 28, u);
21063 break;
21064 default:
21065 generate_exception_end(ctx, EXCP_RI);
21066 break;
21068 break;
21069 case NM_P_GP_CP1:
21070 u &= ~0x3;
21071 switch (ctx->opcode & 0x3) {
21072 case NM_LWC1GP:
21073 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21074 break;
21075 case NM_LDC1GP:
21076 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21077 break;
21078 case NM_SWC1GP:
21079 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21080 break;
21081 case NM_SDC1GP:
21082 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21083 break;
21085 break;
21086 default:
21087 generate_exception_end(ctx, EXCP_RI);
21088 break;
21091 break;
21092 case NM_P_LS_U12:
21094 uint32_t u = extract32(ctx->opcode, 0, 12);
21096 switch (extract32(ctx->opcode, 12, 4)) {
21097 case NM_P_PREFU12:
21098 if (rt == 31) {
21099 /* SYNCI */
21100 /* Break the TB to be able to sync copied instructions
21101 immediately */
21102 ctx->base.is_jmp = DISAS_STOP;
21103 } else {
21104 /* PREF */
21105 /* Treat as NOP. */
21107 break;
21108 case NM_LB:
21109 gen_ld(ctx, OPC_LB, rt, rs, u);
21110 break;
21111 case NM_LH:
21112 gen_ld(ctx, OPC_LH, rt, rs, u);
21113 break;
21114 case NM_LW:
21115 gen_ld(ctx, OPC_LW, rt, rs, u);
21116 break;
21117 case NM_LBU:
21118 gen_ld(ctx, OPC_LBU, rt, rs, u);
21119 break;
21120 case NM_LHU:
21121 gen_ld(ctx, OPC_LHU, rt, rs, u);
21122 break;
21123 case NM_SB:
21124 gen_st(ctx, OPC_SB, rt, rs, u);
21125 break;
21126 case NM_SH:
21127 gen_st(ctx, OPC_SH, rt, rs, u);
21128 break;
21129 case NM_SW:
21130 gen_st(ctx, OPC_SW, rt, rs, u);
21131 break;
21132 case NM_LWC1:
21133 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21134 break;
21135 case NM_LDC1:
21136 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21137 break;
21138 case NM_SWC1:
21139 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21140 break;
21141 case NM_SDC1:
21142 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21143 break;
21144 default:
21145 generate_exception_end(ctx, EXCP_RI);
21146 break;
21149 break;
21150 case NM_P_LS_S9:
21152 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21153 extract32(ctx->opcode, 0, 8);
21155 switch (extract32(ctx->opcode, 8, 3)) {
21156 case NM_P_LS_S0:
21157 switch (extract32(ctx->opcode, 11, 4)) {
21158 case NM_LBS9:
21159 gen_ld(ctx, OPC_LB, rt, rs, s);
21160 break;
21161 case NM_LHS9:
21162 gen_ld(ctx, OPC_LH, rt, rs, s);
21163 break;
21164 case NM_LWS9:
21165 gen_ld(ctx, OPC_LW, rt, rs, s);
21166 break;
21167 case NM_LBUS9:
21168 gen_ld(ctx, OPC_LBU, rt, rs, s);
21169 break;
21170 case NM_LHUS9:
21171 gen_ld(ctx, OPC_LHU, rt, rs, s);
21172 break;
21173 case NM_SBS9:
21174 gen_st(ctx, OPC_SB, rt, rs, s);
21175 break;
21176 case NM_SHS9:
21177 gen_st(ctx, OPC_SH, rt, rs, s);
21178 break;
21179 case NM_SWS9:
21180 gen_st(ctx, OPC_SW, rt, rs, s);
21181 break;
21182 case NM_LWC1S9:
21183 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21184 break;
21185 case NM_LDC1S9:
21186 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21187 break;
21188 case NM_SWC1S9:
21189 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21190 break;
21191 case NM_SDC1S9:
21192 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21193 break;
21194 case NM_P_PREFS9:
21195 if (rt == 31) {
21196 /* SYNCI */
21197 /* Break the TB to be able to sync copied instructions
21198 immediately */
21199 ctx->base.is_jmp = DISAS_STOP;
21200 } else {
21201 /* PREF */
21202 /* Treat as NOP. */
21204 break;
21205 default:
21206 generate_exception_end(ctx, EXCP_RI);
21207 break;
21209 break;
21210 case NM_P_LS_S1:
21211 switch (extract32(ctx->opcode, 11, 4)) {
21212 case NM_UALH:
21213 case NM_UASH:
21214 check_nms(ctx);
21216 TCGv t0 = tcg_temp_new();
21217 TCGv t1 = tcg_temp_new();
21219 gen_base_offset_addr(ctx, t0, rs, s);
21221 switch (extract32(ctx->opcode, 11, 4)) {
21222 case NM_UALH:
21223 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21224 MO_UNALN);
21225 gen_store_gpr(t0, rt);
21226 break;
21227 case NM_UASH:
21228 gen_load_gpr(t1, rt);
21229 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21230 MO_UNALN);
21231 break;
21233 tcg_temp_free(t0);
21234 tcg_temp_free(t1);
21236 break;
21237 case NM_P_LL:
21238 switch (ctx->opcode & 0x03) {
21239 case NM_LL:
21240 gen_ld(ctx, OPC_LL, rt, rs, s);
21241 break;
21242 case NM_LLWP:
21243 check_xnp(ctx);
21244 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21245 break;
21247 break;
21248 case NM_P_SC:
21249 switch (ctx->opcode & 0x03) {
21250 case NM_SC:
21251 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21252 break;
21253 case NM_SCWP:
21254 check_xnp(ctx);
21255 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21256 break;
21258 break;
21259 case NM_CACHE:
21260 check_cp0_enabled(ctx);
21261 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21262 gen_cache_operation(ctx, rt, rs, s);
21264 break;
21266 break;
21267 case NM_P_LS_E0:
21268 switch (extract32(ctx->opcode, 11, 4)) {
21269 case NM_LBE:
21270 check_eva(ctx);
21271 check_cp0_enabled(ctx);
21272 gen_ld(ctx, OPC_LBE, rt, rs, s);
21273 break;
21274 case NM_SBE:
21275 check_eva(ctx);
21276 check_cp0_enabled(ctx);
21277 gen_st(ctx, OPC_SBE, rt, rs, s);
21278 break;
21279 case NM_LBUE:
21280 check_eva(ctx);
21281 check_cp0_enabled(ctx);
21282 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21283 break;
21284 case NM_P_PREFE:
21285 if (rt == 31) {
21286 /* case NM_SYNCIE */
21287 check_eva(ctx);
21288 check_cp0_enabled(ctx);
21289 /* Break the TB to be able to sync copied instructions
21290 immediately */
21291 ctx->base.is_jmp = DISAS_STOP;
21292 } else {
21293 /* case NM_PREFE */
21294 check_eva(ctx);
21295 check_cp0_enabled(ctx);
21296 /* Treat as NOP. */
21298 break;
21299 case NM_LHE:
21300 check_eva(ctx);
21301 check_cp0_enabled(ctx);
21302 gen_ld(ctx, OPC_LHE, rt, rs, s);
21303 break;
21304 case NM_SHE:
21305 check_eva(ctx);
21306 check_cp0_enabled(ctx);
21307 gen_st(ctx, OPC_SHE, rt, rs, s);
21308 break;
21309 case NM_LHUE:
21310 check_eva(ctx);
21311 check_cp0_enabled(ctx);
21312 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21313 break;
21314 case NM_CACHEE:
21315 check_nms_dl_il_sl_tl_l2c(ctx);
21316 gen_cache_operation(ctx, rt, rs, s);
21317 break;
21318 case NM_LWE:
21319 check_eva(ctx);
21320 check_cp0_enabled(ctx);
21321 gen_ld(ctx, OPC_LWE, rt, rs, s);
21322 break;
21323 case NM_SWE:
21324 check_eva(ctx);
21325 check_cp0_enabled(ctx);
21326 gen_st(ctx, OPC_SWE, rt, rs, s);
21327 break;
21328 case NM_P_LLE:
21329 switch (extract32(ctx->opcode, 2, 2)) {
21330 case NM_LLE:
21331 check_xnp(ctx);
21332 check_eva(ctx);
21333 check_cp0_enabled(ctx);
21334 gen_ld(ctx, OPC_LLE, rt, rs, s);
21335 break;
21336 case NM_LLWPE:
21337 check_xnp(ctx);
21338 check_eva(ctx);
21339 check_cp0_enabled(ctx);
21340 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21341 break;
21342 default:
21343 generate_exception_end(ctx, EXCP_RI);
21344 break;
21346 break;
21347 case NM_P_SCE:
21348 switch (extract32(ctx->opcode, 2, 2)) {
21349 case NM_SCE:
21350 check_xnp(ctx);
21351 check_eva(ctx);
21352 check_cp0_enabled(ctx);
21353 gen_st_cond(ctx, OPC_SCE, rt, rs, s);
21354 break;
21355 case NM_SCWPE:
21356 check_xnp(ctx);
21357 check_eva(ctx);
21358 check_cp0_enabled(ctx);
21359 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21360 break;
21361 default:
21362 generate_exception_end(ctx, EXCP_RI);
21363 break;
21365 break;
21367 break;
21368 case NM_P_LS_WM:
21369 case NM_P_LS_UAWM:
21370 check_nms(ctx);
21372 int count = extract32(ctx->opcode, 12, 3);
21373 int counter = 0;
21375 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21376 extract32(ctx->opcode, 0, 8);
21377 TCGv va = tcg_temp_new();
21378 TCGv t1 = tcg_temp_new();
21379 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21380 NM_P_LS_UAWM ? MO_UNALN : 0;
21382 count = (count == 0) ? 8 : count;
21383 while (counter != count) {
21384 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21385 int this_offset = offset + (counter << 2);
21387 gen_base_offset_addr(ctx, va, rs, this_offset);
21389 switch (extract32(ctx->opcode, 11, 1)) {
21390 case NM_LWM:
21391 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21392 memop | MO_TESL);
21393 gen_store_gpr(t1, this_rt);
21394 if ((this_rt == rs) &&
21395 (counter != (count - 1))) {
21396 /* UNPREDICTABLE */
21398 break;
21399 case NM_SWM:
21400 this_rt = (rt == 0) ? 0 : this_rt;
21401 gen_load_gpr(t1, this_rt);
21402 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21403 memop | MO_TEUL);
21404 break;
21406 counter++;
21408 tcg_temp_free(va);
21409 tcg_temp_free(t1);
21411 break;
21412 default:
21413 generate_exception_end(ctx, EXCP_RI);
21414 break;
21417 break;
21418 case NM_MOVE_BALC:
21419 check_nms(ctx);
21421 TCGv t0 = tcg_temp_new();
21422 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21423 extract32(ctx->opcode, 1, 20) << 1;
21424 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21425 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21426 extract32(ctx->opcode, 21, 3));
21427 gen_load_gpr(t0, rt);
21428 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21429 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21430 tcg_temp_free(t0);
21432 break;
21433 case NM_P_BAL:
21435 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21436 extract32(ctx->opcode, 1, 24) << 1;
21438 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21439 /* BC */
21440 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21441 } else {
21442 /* BALC */
21443 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21446 break;
21447 case NM_P_J:
21448 switch (extract32(ctx->opcode, 12, 4)) {
21449 case NM_JALRC:
21450 case NM_JALRC_HB:
21451 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21452 break;
21453 case NM_P_BALRSC:
21454 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21455 break;
21456 default:
21457 generate_exception_end(ctx, EXCP_RI);
21458 break;
21460 break;
21461 case NM_P_BR1:
21463 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21464 extract32(ctx->opcode, 1, 13) << 1;
21465 switch (extract32(ctx->opcode, 14, 2)) {
21466 case NM_BEQC:
21467 check_nms(ctx);
21468 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21469 break;
21470 case NM_P_BR3A:
21471 s = sextract32(ctx->opcode, 0, 1) << 14 |
21472 extract32(ctx->opcode, 1, 13) << 1;
21473 check_cp1_enabled(ctx);
21474 switch (extract32(ctx->opcode, 16, 5)) {
21475 case NM_BC1EQZC:
21476 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21477 break;
21478 case NM_BC1NEZC:
21479 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21480 break;
21481 case NM_BPOSGE32C:
21482 check_dsp_r3(ctx);
21484 int32_t imm = extract32(ctx->opcode, 1, 13) |
21485 extract32(ctx->opcode, 0, 1) << 13;
21487 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21488 imm);
21490 break;
21491 default:
21492 generate_exception_end(ctx, EXCP_RI);
21493 break;
21495 break;
21496 case NM_BGEC:
21497 if (rs == rt) {
21498 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21499 } else {
21500 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21502 break;
21503 case NM_BGEUC:
21504 if (rs == rt || rt == 0) {
21505 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21506 } else if (rs == 0) {
21507 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21508 } else {
21509 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21511 break;
21514 break;
21515 case NM_P_BR2:
21517 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21518 extract32(ctx->opcode, 1, 13) << 1;
21519 switch (extract32(ctx->opcode, 14, 2)) {
21520 case NM_BNEC:
21521 check_nms(ctx);
21522 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21523 break;
21524 case NM_BLTC:
21525 if (rs != 0 && rt != 0 && rs == rt) {
21526 /* NOP */
21527 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21528 } else {
21529 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21531 break;
21532 case NM_BLTUC:
21533 if (rs == 0 || rs == rt) {
21534 /* NOP */
21535 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21536 } else {
21537 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21539 break;
21540 default:
21541 generate_exception_end(ctx, EXCP_RI);
21542 break;
21545 break;
21546 case NM_P_BRI:
21548 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21549 extract32(ctx->opcode, 1, 10) << 1;
21550 uint32_t u = extract32(ctx->opcode, 11, 7);
21552 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21553 rt, u, s);
21555 break;
21556 default:
21557 generate_exception_end(ctx, EXCP_RI);
21558 break;
21560 return 4;
21563 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21565 uint32_t op;
21566 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21567 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21568 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21569 int offset;
21570 int imm;
21572 /* make sure instructions are on a halfword boundary */
21573 if (ctx->base.pc_next & 0x1) {
21574 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21575 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21576 tcg_temp_free(tmp);
21577 generate_exception_end(ctx, EXCP_AdEL);
21578 return 2;
21581 op = extract32(ctx->opcode, 10, 6);
21582 switch (op) {
21583 case NM_P16_MV:
21584 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21585 if (rt != 0) {
21586 /* MOVE */
21587 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21588 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21589 } else {
21590 /* P16.RI */
21591 switch (extract32(ctx->opcode, 3, 2)) {
21592 case NM_P16_SYSCALL:
21593 if (extract32(ctx->opcode, 2, 1) == 0) {
21594 generate_exception_end(ctx, EXCP_SYSCALL);
21595 } else {
21596 generate_exception_end(ctx, EXCP_RI);
21598 break;
21599 case NM_BREAK16:
21600 generate_exception_end(ctx, EXCP_BREAK);
21601 break;
21602 case NM_SDBBP16:
21603 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21604 gen_helper_do_semihosting(cpu_env);
21605 } else {
21606 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21607 generate_exception_end(ctx, EXCP_RI);
21608 } else {
21609 generate_exception_end(ctx, EXCP_DBp);
21612 break;
21613 default:
21614 generate_exception_end(ctx, EXCP_RI);
21615 break;
21618 break;
21619 case NM_P16_SHIFT:
21621 int shift = extract32(ctx->opcode, 0, 3);
21622 uint32_t opc = 0;
21623 shift = (shift == 0) ? 8 : shift;
21625 switch (extract32(ctx->opcode, 3, 1)) {
21626 case NM_SLL16:
21627 opc = OPC_SLL;
21628 break;
21629 case NM_SRL16:
21630 opc = OPC_SRL;
21631 break;
21633 gen_shift_imm(ctx, opc, rt, rs, shift);
21635 break;
21636 case NM_P16C:
21637 switch (ctx->opcode & 1) {
21638 case NM_POOL16C_0:
21639 gen_pool16c_nanomips_insn(ctx);
21640 break;
21641 case NM_LWXS16:
21642 gen_ldxs(ctx, rt, rs, rd);
21643 break;
21645 break;
21646 case NM_P16_A1:
21647 switch (extract32(ctx->opcode, 6, 1)) {
21648 case NM_ADDIUR1SP:
21649 imm = extract32(ctx->opcode, 0, 6) << 2;
21650 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21651 break;
21652 default:
21653 generate_exception_end(ctx, EXCP_RI);
21654 break;
21656 break;
21657 case NM_P16_A2:
21658 switch (extract32(ctx->opcode, 3, 1)) {
21659 case NM_ADDIUR2:
21660 imm = extract32(ctx->opcode, 0, 3) << 2;
21661 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21662 break;
21663 case NM_P_ADDIURS5:
21664 rt = extract32(ctx->opcode, 5, 5);
21665 if (rt != 0) {
21666 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21667 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21668 (extract32(ctx->opcode, 0, 3));
21669 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21671 break;
21673 break;
21674 case NM_P16_ADDU:
21675 switch (ctx->opcode & 0x1) {
21676 case NM_ADDU16:
21677 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21678 break;
21679 case NM_SUBU16:
21680 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21681 break;
21683 break;
21684 case NM_P16_4X4:
21685 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21686 extract32(ctx->opcode, 5, 3);
21687 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21688 extract32(ctx->opcode, 0, 3);
21689 rt = decode_gpr_gpr4(rt);
21690 rs = decode_gpr_gpr4(rs);
21691 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21692 (extract32(ctx->opcode, 3, 1))) {
21693 case NM_ADDU4X4:
21694 check_nms(ctx);
21695 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21696 break;
21697 case NM_MUL4X4:
21698 check_nms(ctx);
21699 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21700 break;
21701 default:
21702 generate_exception_end(ctx, EXCP_RI);
21703 break;
21705 break;
21706 case NM_LI16:
21708 int imm = extract32(ctx->opcode, 0, 7);
21709 imm = (imm == 0x7f ? -1 : imm);
21710 if (rt != 0) {
21711 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21714 break;
21715 case NM_ANDI16:
21717 uint32_t u = extract32(ctx->opcode, 0, 4);
21718 u = (u == 12) ? 0xff :
21719 (u == 13) ? 0xffff : u;
21720 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21722 break;
21723 case NM_P16_LB:
21724 offset = extract32(ctx->opcode, 0, 2);
21725 switch (extract32(ctx->opcode, 2, 2)) {
21726 case NM_LB16:
21727 gen_ld(ctx, OPC_LB, rt, rs, offset);
21728 break;
21729 case NM_SB16:
21730 rt = decode_gpr_gpr3_src_store(
21731 NANOMIPS_EXTRACT_RD(ctx->opcode));
21732 gen_st(ctx, OPC_SB, rt, rs, offset);
21733 break;
21734 case NM_LBU16:
21735 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21736 break;
21737 default:
21738 generate_exception_end(ctx, EXCP_RI);
21739 break;
21741 break;
21742 case NM_P16_LH:
21743 offset = extract32(ctx->opcode, 1, 2) << 1;
21744 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21745 case NM_LH16:
21746 gen_ld(ctx, OPC_LH, rt, rs, offset);
21747 break;
21748 case NM_SH16:
21749 rt = decode_gpr_gpr3_src_store(
21750 NANOMIPS_EXTRACT_RD(ctx->opcode));
21751 gen_st(ctx, OPC_SH, rt, rs, offset);
21752 break;
21753 case NM_LHU16:
21754 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21755 break;
21756 default:
21757 generate_exception_end(ctx, EXCP_RI);
21758 break;
21760 break;
21761 case NM_LW16:
21762 offset = extract32(ctx->opcode, 0, 4) << 2;
21763 gen_ld(ctx, OPC_LW, rt, rs, offset);
21764 break;
21765 case NM_LWSP16:
21766 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21767 offset = extract32(ctx->opcode, 0, 5) << 2;
21768 gen_ld(ctx, OPC_LW, rt, 29, offset);
21769 break;
21770 case NM_LW4X4:
21771 check_nms(ctx);
21772 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21773 extract32(ctx->opcode, 5, 3);
21774 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21775 extract32(ctx->opcode, 0, 3);
21776 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21777 (extract32(ctx->opcode, 8, 1) << 2);
21778 rt = decode_gpr_gpr4(rt);
21779 rs = decode_gpr_gpr4(rs);
21780 gen_ld(ctx, OPC_LW, rt, rs, offset);
21781 break;
21782 case NM_SW4X4:
21783 check_nms(ctx);
21784 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21785 extract32(ctx->opcode, 5, 3);
21786 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21787 extract32(ctx->opcode, 0, 3);
21788 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21789 (extract32(ctx->opcode, 8, 1) << 2);
21790 rt = decode_gpr_gpr4_zero(rt);
21791 rs = decode_gpr_gpr4(rs);
21792 gen_st(ctx, OPC_SW, rt, rs, offset);
21793 break;
21794 case NM_LWGP16:
21795 offset = extract32(ctx->opcode, 0, 7) << 2;
21796 gen_ld(ctx, OPC_LW, rt, 28, offset);
21797 break;
21798 case NM_SWSP16:
21799 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21800 offset = extract32(ctx->opcode, 0, 5) << 2;
21801 gen_st(ctx, OPC_SW, rt, 29, offset);
21802 break;
21803 case NM_SW16:
21804 rt = decode_gpr_gpr3_src_store(
21805 NANOMIPS_EXTRACT_RD(ctx->opcode));
21806 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21807 offset = extract32(ctx->opcode, 0, 4) << 2;
21808 gen_st(ctx, OPC_SW, rt, rs, offset);
21809 break;
21810 case NM_SWGP16:
21811 rt = decode_gpr_gpr3_src_store(
21812 NANOMIPS_EXTRACT_RD(ctx->opcode));
21813 offset = extract32(ctx->opcode, 0, 7) << 2;
21814 gen_st(ctx, OPC_SW, rt, 28, offset);
21815 break;
21816 case NM_BC16:
21817 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21818 (sextract32(ctx->opcode, 0, 1) << 10) |
21819 (extract32(ctx->opcode, 1, 9) << 1));
21820 break;
21821 case NM_BALC16:
21822 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21823 (sextract32(ctx->opcode, 0, 1) << 10) |
21824 (extract32(ctx->opcode, 1, 9) << 1));
21825 break;
21826 case NM_BEQZC16:
21827 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21828 (sextract32(ctx->opcode, 0, 1) << 7) |
21829 (extract32(ctx->opcode, 1, 6) << 1));
21830 break;
21831 case NM_BNEZC16:
21832 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21833 (sextract32(ctx->opcode, 0, 1) << 7) |
21834 (extract32(ctx->opcode, 1, 6) << 1));
21835 break;
21836 case NM_P16_BR:
21837 switch (ctx->opcode & 0xf) {
21838 case 0:
21839 /* P16.JRC */
21840 switch (extract32(ctx->opcode, 4, 1)) {
21841 case NM_JRC:
21842 gen_compute_branch_nm(ctx, OPC_JR, 2,
21843 extract32(ctx->opcode, 5, 5), 0, 0);
21844 break;
21845 case NM_JALRC16:
21846 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21847 extract32(ctx->opcode, 5, 5), 31, 0);
21848 break;
21850 break;
21851 default:
21853 /* P16.BRI */
21854 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21855 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21856 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21857 extract32(ctx->opcode, 0, 4) << 1);
21859 break;
21861 break;
21862 case NM_P16_SR:
21864 int count = extract32(ctx->opcode, 0, 4);
21865 int u = extract32(ctx->opcode, 4, 4) << 4;
21867 rt = 30 + extract32(ctx->opcode, 9, 1);
21868 switch (extract32(ctx->opcode, 8, 1)) {
21869 case NM_SAVE16:
21870 gen_save(ctx, rt, count, 0, u);
21871 break;
21872 case NM_RESTORE_JRC16:
21873 gen_restore(ctx, rt, count, 0, u);
21874 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21875 break;
21878 break;
21879 case NM_MOVEP:
21880 case NM_MOVEPREV:
21881 check_nms(ctx);
21883 static const int gpr2reg1[] = {4, 5, 6, 7};
21884 static const int gpr2reg2[] = {5, 6, 7, 8};
21885 int re;
21886 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21887 extract32(ctx->opcode, 8, 1);
21888 int r1 = gpr2reg1[rd2];
21889 int r2 = gpr2reg2[rd2];
21890 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21891 extract32(ctx->opcode, 0, 3);
21892 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21893 extract32(ctx->opcode, 5, 3);
21894 TCGv t0 = tcg_temp_new();
21895 TCGv t1 = tcg_temp_new();
21896 if (op == NM_MOVEP) {
21897 rd = r1;
21898 re = r2;
21899 rs = decode_gpr_gpr4_zero(r3);
21900 rt = decode_gpr_gpr4_zero(r4);
21901 } else {
21902 rd = decode_gpr_gpr4(r3);
21903 re = decode_gpr_gpr4(r4);
21904 rs = r1;
21905 rt = r2;
21907 gen_load_gpr(t0, rs);
21908 gen_load_gpr(t1, rt);
21909 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21910 tcg_gen_mov_tl(cpu_gpr[re], t1);
21911 tcg_temp_free(t0);
21912 tcg_temp_free(t1);
21914 break;
21915 default:
21916 return decode_nanomips_32_48_opc(env, ctx);
21919 return 2;
21923 /* SmartMIPS extension to MIPS32 */
21925 #if defined(TARGET_MIPS64)
21927 /* MDMX extension to MIPS64 */
21929 #endif
21931 /* MIPSDSP functions. */
21932 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21933 int rd, int base, int offset)
21935 TCGv t0;
21937 check_dsp(ctx);
21938 t0 = tcg_temp_new();
21940 if (base == 0) {
21941 gen_load_gpr(t0, offset);
21942 } else if (offset == 0) {
21943 gen_load_gpr(t0, base);
21944 } else {
21945 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21948 switch (opc) {
21949 case OPC_LBUX:
21950 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21951 gen_store_gpr(t0, rd);
21952 break;
21953 case OPC_LHX:
21954 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21955 gen_store_gpr(t0, rd);
21956 break;
21957 case OPC_LWX:
21958 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21959 gen_store_gpr(t0, rd);
21960 break;
21961 #if defined(TARGET_MIPS64)
21962 case OPC_LDX:
21963 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21964 gen_store_gpr(t0, rd);
21965 break;
21966 #endif
21968 tcg_temp_free(t0);
21971 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21972 int ret, int v1, int v2)
21974 TCGv v1_t;
21975 TCGv v2_t;
21977 if (ret == 0) {
21978 /* Treat as NOP. */
21979 return;
21982 v1_t = tcg_temp_new();
21983 v2_t = tcg_temp_new();
21985 gen_load_gpr(v1_t, v1);
21986 gen_load_gpr(v2_t, v2);
21988 switch (op1) {
21989 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21990 case OPC_MULT_G_2E:
21991 check_dsp_r2(ctx);
21992 switch (op2) {
21993 case OPC_ADDUH_QB:
21994 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21995 break;
21996 case OPC_ADDUH_R_QB:
21997 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21998 break;
21999 case OPC_ADDQH_PH:
22000 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22001 break;
22002 case OPC_ADDQH_R_PH:
22003 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22004 break;
22005 case OPC_ADDQH_W:
22006 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22007 break;
22008 case OPC_ADDQH_R_W:
22009 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22010 break;
22011 case OPC_SUBUH_QB:
22012 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22013 break;
22014 case OPC_SUBUH_R_QB:
22015 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22016 break;
22017 case OPC_SUBQH_PH:
22018 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22019 break;
22020 case OPC_SUBQH_R_PH:
22021 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22022 break;
22023 case OPC_SUBQH_W:
22024 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22025 break;
22026 case OPC_SUBQH_R_W:
22027 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22028 break;
22030 break;
22031 case OPC_ABSQ_S_PH_DSP:
22032 switch (op2) {
22033 case OPC_ABSQ_S_QB:
22034 check_dsp_r2(ctx);
22035 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22036 break;
22037 case OPC_ABSQ_S_PH:
22038 check_dsp(ctx);
22039 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22040 break;
22041 case OPC_ABSQ_S_W:
22042 check_dsp(ctx);
22043 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22044 break;
22045 case OPC_PRECEQ_W_PHL:
22046 check_dsp(ctx);
22047 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22048 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22049 break;
22050 case OPC_PRECEQ_W_PHR:
22051 check_dsp(ctx);
22052 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22053 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22054 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22055 break;
22056 case OPC_PRECEQU_PH_QBL:
22057 check_dsp(ctx);
22058 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22059 break;
22060 case OPC_PRECEQU_PH_QBR:
22061 check_dsp(ctx);
22062 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22063 break;
22064 case OPC_PRECEQU_PH_QBLA:
22065 check_dsp(ctx);
22066 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22067 break;
22068 case OPC_PRECEQU_PH_QBRA:
22069 check_dsp(ctx);
22070 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22071 break;
22072 case OPC_PRECEU_PH_QBL:
22073 check_dsp(ctx);
22074 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22075 break;
22076 case OPC_PRECEU_PH_QBR:
22077 check_dsp(ctx);
22078 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22079 break;
22080 case OPC_PRECEU_PH_QBLA:
22081 check_dsp(ctx);
22082 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22083 break;
22084 case OPC_PRECEU_PH_QBRA:
22085 check_dsp(ctx);
22086 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22087 break;
22089 break;
22090 case OPC_ADDU_QB_DSP:
22091 switch (op2) {
22092 case OPC_ADDQ_PH:
22093 check_dsp(ctx);
22094 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22095 break;
22096 case OPC_ADDQ_S_PH:
22097 check_dsp(ctx);
22098 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22099 break;
22100 case OPC_ADDQ_S_W:
22101 check_dsp(ctx);
22102 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22103 break;
22104 case OPC_ADDU_QB:
22105 check_dsp(ctx);
22106 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22107 break;
22108 case OPC_ADDU_S_QB:
22109 check_dsp(ctx);
22110 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22111 break;
22112 case OPC_ADDU_PH:
22113 check_dsp_r2(ctx);
22114 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22115 break;
22116 case OPC_ADDU_S_PH:
22117 check_dsp_r2(ctx);
22118 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22119 break;
22120 case OPC_SUBQ_PH:
22121 check_dsp(ctx);
22122 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22123 break;
22124 case OPC_SUBQ_S_PH:
22125 check_dsp(ctx);
22126 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22127 break;
22128 case OPC_SUBQ_S_W:
22129 check_dsp(ctx);
22130 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22131 break;
22132 case OPC_SUBU_QB:
22133 check_dsp(ctx);
22134 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22135 break;
22136 case OPC_SUBU_S_QB:
22137 check_dsp(ctx);
22138 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22139 break;
22140 case OPC_SUBU_PH:
22141 check_dsp_r2(ctx);
22142 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22143 break;
22144 case OPC_SUBU_S_PH:
22145 check_dsp_r2(ctx);
22146 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22147 break;
22148 case OPC_ADDSC:
22149 check_dsp(ctx);
22150 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22151 break;
22152 case OPC_ADDWC:
22153 check_dsp(ctx);
22154 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22155 break;
22156 case OPC_MODSUB:
22157 check_dsp(ctx);
22158 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22159 break;
22160 case OPC_RADDU_W_QB:
22161 check_dsp(ctx);
22162 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22163 break;
22165 break;
22166 case OPC_CMPU_EQ_QB_DSP:
22167 switch (op2) {
22168 case OPC_PRECR_QB_PH:
22169 check_dsp_r2(ctx);
22170 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22171 break;
22172 case OPC_PRECRQ_QB_PH:
22173 check_dsp(ctx);
22174 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22175 break;
22176 case OPC_PRECR_SRA_PH_W:
22177 check_dsp_r2(ctx);
22179 TCGv_i32 sa_t = tcg_const_i32(v2);
22180 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22181 cpu_gpr[ret]);
22182 tcg_temp_free_i32(sa_t);
22183 break;
22185 case OPC_PRECR_SRA_R_PH_W:
22186 check_dsp_r2(ctx);
22188 TCGv_i32 sa_t = tcg_const_i32(v2);
22189 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22190 cpu_gpr[ret]);
22191 tcg_temp_free_i32(sa_t);
22192 break;
22194 case OPC_PRECRQ_PH_W:
22195 check_dsp(ctx);
22196 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22197 break;
22198 case OPC_PRECRQ_RS_PH_W:
22199 check_dsp(ctx);
22200 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22201 break;
22202 case OPC_PRECRQU_S_QB_PH:
22203 check_dsp(ctx);
22204 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22205 break;
22207 break;
22208 #ifdef TARGET_MIPS64
22209 case OPC_ABSQ_S_QH_DSP:
22210 switch (op2) {
22211 case OPC_PRECEQ_L_PWL:
22212 check_dsp(ctx);
22213 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22214 break;
22215 case OPC_PRECEQ_L_PWR:
22216 check_dsp(ctx);
22217 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22218 break;
22219 case OPC_PRECEQ_PW_QHL:
22220 check_dsp(ctx);
22221 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22222 break;
22223 case OPC_PRECEQ_PW_QHR:
22224 check_dsp(ctx);
22225 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22226 break;
22227 case OPC_PRECEQ_PW_QHLA:
22228 check_dsp(ctx);
22229 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22230 break;
22231 case OPC_PRECEQ_PW_QHRA:
22232 check_dsp(ctx);
22233 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22234 break;
22235 case OPC_PRECEQU_QH_OBL:
22236 check_dsp(ctx);
22237 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22238 break;
22239 case OPC_PRECEQU_QH_OBR:
22240 check_dsp(ctx);
22241 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22242 break;
22243 case OPC_PRECEQU_QH_OBLA:
22244 check_dsp(ctx);
22245 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22246 break;
22247 case OPC_PRECEQU_QH_OBRA:
22248 check_dsp(ctx);
22249 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22250 break;
22251 case OPC_PRECEU_QH_OBL:
22252 check_dsp(ctx);
22253 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22254 break;
22255 case OPC_PRECEU_QH_OBR:
22256 check_dsp(ctx);
22257 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22258 break;
22259 case OPC_PRECEU_QH_OBLA:
22260 check_dsp(ctx);
22261 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22262 break;
22263 case OPC_PRECEU_QH_OBRA:
22264 check_dsp(ctx);
22265 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22266 break;
22267 case OPC_ABSQ_S_OB:
22268 check_dsp_r2(ctx);
22269 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22270 break;
22271 case OPC_ABSQ_S_PW:
22272 check_dsp(ctx);
22273 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22274 break;
22275 case OPC_ABSQ_S_QH:
22276 check_dsp(ctx);
22277 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22278 break;
22280 break;
22281 case OPC_ADDU_OB_DSP:
22282 switch (op2) {
22283 case OPC_RADDU_L_OB:
22284 check_dsp(ctx);
22285 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22286 break;
22287 case OPC_SUBQ_PW:
22288 check_dsp(ctx);
22289 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22290 break;
22291 case OPC_SUBQ_S_PW:
22292 check_dsp(ctx);
22293 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22294 break;
22295 case OPC_SUBQ_QH:
22296 check_dsp(ctx);
22297 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22298 break;
22299 case OPC_SUBQ_S_QH:
22300 check_dsp(ctx);
22301 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22302 break;
22303 case OPC_SUBU_OB:
22304 check_dsp(ctx);
22305 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22306 break;
22307 case OPC_SUBU_S_OB:
22308 check_dsp(ctx);
22309 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22310 break;
22311 case OPC_SUBU_QH:
22312 check_dsp_r2(ctx);
22313 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22314 break;
22315 case OPC_SUBU_S_QH:
22316 check_dsp_r2(ctx);
22317 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22318 break;
22319 case OPC_SUBUH_OB:
22320 check_dsp_r2(ctx);
22321 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22322 break;
22323 case OPC_SUBUH_R_OB:
22324 check_dsp_r2(ctx);
22325 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22326 break;
22327 case OPC_ADDQ_PW:
22328 check_dsp(ctx);
22329 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22330 break;
22331 case OPC_ADDQ_S_PW:
22332 check_dsp(ctx);
22333 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22334 break;
22335 case OPC_ADDQ_QH:
22336 check_dsp(ctx);
22337 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22338 break;
22339 case OPC_ADDQ_S_QH:
22340 check_dsp(ctx);
22341 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22342 break;
22343 case OPC_ADDU_OB:
22344 check_dsp(ctx);
22345 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22346 break;
22347 case OPC_ADDU_S_OB:
22348 check_dsp(ctx);
22349 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22350 break;
22351 case OPC_ADDU_QH:
22352 check_dsp_r2(ctx);
22353 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22354 break;
22355 case OPC_ADDU_S_QH:
22356 check_dsp_r2(ctx);
22357 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22358 break;
22359 case OPC_ADDUH_OB:
22360 check_dsp_r2(ctx);
22361 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22362 break;
22363 case OPC_ADDUH_R_OB:
22364 check_dsp_r2(ctx);
22365 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22366 break;
22368 break;
22369 case OPC_CMPU_EQ_OB_DSP:
22370 switch (op2) {
22371 case OPC_PRECR_OB_QH:
22372 check_dsp_r2(ctx);
22373 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22374 break;
22375 case OPC_PRECR_SRA_QH_PW:
22376 check_dsp_r2(ctx);
22378 TCGv_i32 ret_t = tcg_const_i32(ret);
22379 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22380 tcg_temp_free_i32(ret_t);
22381 break;
22383 case OPC_PRECR_SRA_R_QH_PW:
22384 check_dsp_r2(ctx);
22386 TCGv_i32 sa_v = tcg_const_i32(ret);
22387 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22388 tcg_temp_free_i32(sa_v);
22389 break;
22391 case OPC_PRECRQ_OB_QH:
22392 check_dsp(ctx);
22393 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22394 break;
22395 case OPC_PRECRQ_PW_L:
22396 check_dsp(ctx);
22397 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22398 break;
22399 case OPC_PRECRQ_QH_PW:
22400 check_dsp(ctx);
22401 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22402 break;
22403 case OPC_PRECRQ_RS_QH_PW:
22404 check_dsp(ctx);
22405 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22406 break;
22407 case OPC_PRECRQU_S_OB_QH:
22408 check_dsp(ctx);
22409 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22410 break;
22412 break;
22413 #endif
22416 tcg_temp_free(v1_t);
22417 tcg_temp_free(v2_t);
22420 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22421 int ret, int v1, int v2)
22423 uint32_t op2;
22424 TCGv t0;
22425 TCGv v1_t;
22426 TCGv v2_t;
22428 if (ret == 0) {
22429 /* Treat as NOP. */
22430 return;
22433 t0 = tcg_temp_new();
22434 v1_t = tcg_temp_new();
22435 v2_t = tcg_temp_new();
22437 tcg_gen_movi_tl(t0, v1);
22438 gen_load_gpr(v1_t, v1);
22439 gen_load_gpr(v2_t, v2);
22441 switch (opc) {
22442 case OPC_SHLL_QB_DSP:
22444 op2 = MASK_SHLL_QB(ctx->opcode);
22445 switch (op2) {
22446 case OPC_SHLL_QB:
22447 check_dsp(ctx);
22448 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22449 break;
22450 case OPC_SHLLV_QB:
22451 check_dsp(ctx);
22452 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22453 break;
22454 case OPC_SHLL_PH:
22455 check_dsp(ctx);
22456 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22457 break;
22458 case OPC_SHLLV_PH:
22459 check_dsp(ctx);
22460 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22461 break;
22462 case OPC_SHLL_S_PH:
22463 check_dsp(ctx);
22464 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22465 break;
22466 case OPC_SHLLV_S_PH:
22467 check_dsp(ctx);
22468 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22469 break;
22470 case OPC_SHLL_S_W:
22471 check_dsp(ctx);
22472 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22473 break;
22474 case OPC_SHLLV_S_W:
22475 check_dsp(ctx);
22476 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22477 break;
22478 case OPC_SHRL_QB:
22479 check_dsp(ctx);
22480 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22481 break;
22482 case OPC_SHRLV_QB:
22483 check_dsp(ctx);
22484 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22485 break;
22486 case OPC_SHRL_PH:
22487 check_dsp_r2(ctx);
22488 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22489 break;
22490 case OPC_SHRLV_PH:
22491 check_dsp_r2(ctx);
22492 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22493 break;
22494 case OPC_SHRA_QB:
22495 check_dsp_r2(ctx);
22496 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22497 break;
22498 case OPC_SHRA_R_QB:
22499 check_dsp_r2(ctx);
22500 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22501 break;
22502 case OPC_SHRAV_QB:
22503 check_dsp_r2(ctx);
22504 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22505 break;
22506 case OPC_SHRAV_R_QB:
22507 check_dsp_r2(ctx);
22508 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22509 break;
22510 case OPC_SHRA_PH:
22511 check_dsp(ctx);
22512 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22513 break;
22514 case OPC_SHRA_R_PH:
22515 check_dsp(ctx);
22516 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22517 break;
22518 case OPC_SHRAV_PH:
22519 check_dsp(ctx);
22520 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22521 break;
22522 case OPC_SHRAV_R_PH:
22523 check_dsp(ctx);
22524 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22525 break;
22526 case OPC_SHRA_R_W:
22527 check_dsp(ctx);
22528 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22529 break;
22530 case OPC_SHRAV_R_W:
22531 check_dsp(ctx);
22532 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22533 break;
22534 default: /* Invalid */
22535 MIPS_INVAL("MASK SHLL.QB");
22536 generate_exception_end(ctx, EXCP_RI);
22537 break;
22539 break;
22541 #ifdef TARGET_MIPS64
22542 case OPC_SHLL_OB_DSP:
22543 op2 = MASK_SHLL_OB(ctx->opcode);
22544 switch (op2) {
22545 case OPC_SHLL_PW:
22546 check_dsp(ctx);
22547 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22548 break;
22549 case OPC_SHLLV_PW:
22550 check_dsp(ctx);
22551 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22552 break;
22553 case OPC_SHLL_S_PW:
22554 check_dsp(ctx);
22555 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22556 break;
22557 case OPC_SHLLV_S_PW:
22558 check_dsp(ctx);
22559 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22560 break;
22561 case OPC_SHLL_OB:
22562 check_dsp(ctx);
22563 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22564 break;
22565 case OPC_SHLLV_OB:
22566 check_dsp(ctx);
22567 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22568 break;
22569 case OPC_SHLL_QH:
22570 check_dsp(ctx);
22571 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22572 break;
22573 case OPC_SHLLV_QH:
22574 check_dsp(ctx);
22575 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22576 break;
22577 case OPC_SHLL_S_QH:
22578 check_dsp(ctx);
22579 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22580 break;
22581 case OPC_SHLLV_S_QH:
22582 check_dsp(ctx);
22583 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22584 break;
22585 case OPC_SHRA_OB:
22586 check_dsp_r2(ctx);
22587 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22588 break;
22589 case OPC_SHRAV_OB:
22590 check_dsp_r2(ctx);
22591 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22592 break;
22593 case OPC_SHRA_R_OB:
22594 check_dsp_r2(ctx);
22595 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22596 break;
22597 case OPC_SHRAV_R_OB:
22598 check_dsp_r2(ctx);
22599 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22600 break;
22601 case OPC_SHRA_PW:
22602 check_dsp(ctx);
22603 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22604 break;
22605 case OPC_SHRAV_PW:
22606 check_dsp(ctx);
22607 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22608 break;
22609 case OPC_SHRA_R_PW:
22610 check_dsp(ctx);
22611 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22612 break;
22613 case OPC_SHRAV_R_PW:
22614 check_dsp(ctx);
22615 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22616 break;
22617 case OPC_SHRA_QH:
22618 check_dsp(ctx);
22619 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22620 break;
22621 case OPC_SHRAV_QH:
22622 check_dsp(ctx);
22623 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22624 break;
22625 case OPC_SHRA_R_QH:
22626 check_dsp(ctx);
22627 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22628 break;
22629 case OPC_SHRAV_R_QH:
22630 check_dsp(ctx);
22631 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22632 break;
22633 case OPC_SHRL_OB:
22634 check_dsp(ctx);
22635 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22636 break;
22637 case OPC_SHRLV_OB:
22638 check_dsp(ctx);
22639 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22640 break;
22641 case OPC_SHRL_QH:
22642 check_dsp_r2(ctx);
22643 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22644 break;
22645 case OPC_SHRLV_QH:
22646 check_dsp_r2(ctx);
22647 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22648 break;
22649 default: /* Invalid */
22650 MIPS_INVAL("MASK SHLL.OB");
22651 generate_exception_end(ctx, EXCP_RI);
22652 break;
22654 break;
22655 #endif
22658 tcg_temp_free(t0);
22659 tcg_temp_free(v1_t);
22660 tcg_temp_free(v2_t);
22663 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22664 int ret, int v1, int v2, int check_ret)
22666 TCGv_i32 t0;
22667 TCGv v1_t;
22668 TCGv v2_t;
22670 if ((ret == 0) && (check_ret == 1)) {
22671 /* Treat as NOP. */
22672 return;
22675 t0 = tcg_temp_new_i32();
22676 v1_t = tcg_temp_new();
22677 v2_t = tcg_temp_new();
22679 tcg_gen_movi_i32(t0, ret);
22680 gen_load_gpr(v1_t, v1);
22681 gen_load_gpr(v2_t, v2);
22683 switch (op1) {
22684 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22685 * the same mask and op1. */
22686 case OPC_MULT_G_2E:
22687 check_dsp_r2(ctx);
22688 switch (op2) {
22689 case OPC_MUL_PH:
22690 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22691 break;
22692 case OPC_MUL_S_PH:
22693 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22694 break;
22695 case OPC_MULQ_S_W:
22696 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22697 break;
22698 case OPC_MULQ_RS_W:
22699 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22700 break;
22702 break;
22703 case OPC_DPA_W_PH_DSP:
22704 switch (op2) {
22705 case OPC_DPAU_H_QBL:
22706 check_dsp(ctx);
22707 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22708 break;
22709 case OPC_DPAU_H_QBR:
22710 check_dsp(ctx);
22711 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22712 break;
22713 case OPC_DPSU_H_QBL:
22714 check_dsp(ctx);
22715 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22716 break;
22717 case OPC_DPSU_H_QBR:
22718 check_dsp(ctx);
22719 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22720 break;
22721 case OPC_DPA_W_PH:
22722 check_dsp_r2(ctx);
22723 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22724 break;
22725 case OPC_DPAX_W_PH:
22726 check_dsp_r2(ctx);
22727 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22728 break;
22729 case OPC_DPAQ_S_W_PH:
22730 check_dsp(ctx);
22731 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22732 break;
22733 case OPC_DPAQX_S_W_PH:
22734 check_dsp_r2(ctx);
22735 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22736 break;
22737 case OPC_DPAQX_SA_W_PH:
22738 check_dsp_r2(ctx);
22739 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22740 break;
22741 case OPC_DPS_W_PH:
22742 check_dsp_r2(ctx);
22743 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22744 break;
22745 case OPC_DPSX_W_PH:
22746 check_dsp_r2(ctx);
22747 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22748 break;
22749 case OPC_DPSQ_S_W_PH:
22750 check_dsp(ctx);
22751 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22752 break;
22753 case OPC_DPSQX_S_W_PH:
22754 check_dsp_r2(ctx);
22755 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22756 break;
22757 case OPC_DPSQX_SA_W_PH:
22758 check_dsp_r2(ctx);
22759 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22760 break;
22761 case OPC_MULSAQ_S_W_PH:
22762 check_dsp(ctx);
22763 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22764 break;
22765 case OPC_DPAQ_SA_L_W:
22766 check_dsp(ctx);
22767 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22768 break;
22769 case OPC_DPSQ_SA_L_W:
22770 check_dsp(ctx);
22771 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22772 break;
22773 case OPC_MAQ_S_W_PHL:
22774 check_dsp(ctx);
22775 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22776 break;
22777 case OPC_MAQ_S_W_PHR:
22778 check_dsp(ctx);
22779 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22780 break;
22781 case OPC_MAQ_SA_W_PHL:
22782 check_dsp(ctx);
22783 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22784 break;
22785 case OPC_MAQ_SA_W_PHR:
22786 check_dsp(ctx);
22787 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22788 break;
22789 case OPC_MULSA_W_PH:
22790 check_dsp_r2(ctx);
22791 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22792 break;
22794 break;
22795 #ifdef TARGET_MIPS64
22796 case OPC_DPAQ_W_QH_DSP:
22798 int ac = ret & 0x03;
22799 tcg_gen_movi_i32(t0, ac);
22801 switch (op2) {
22802 case OPC_DMADD:
22803 check_dsp(ctx);
22804 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22805 break;
22806 case OPC_DMADDU:
22807 check_dsp(ctx);
22808 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22809 break;
22810 case OPC_DMSUB:
22811 check_dsp(ctx);
22812 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22813 break;
22814 case OPC_DMSUBU:
22815 check_dsp(ctx);
22816 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22817 break;
22818 case OPC_DPA_W_QH:
22819 check_dsp_r2(ctx);
22820 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22821 break;
22822 case OPC_DPAQ_S_W_QH:
22823 check_dsp(ctx);
22824 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22825 break;
22826 case OPC_DPAQ_SA_L_PW:
22827 check_dsp(ctx);
22828 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22829 break;
22830 case OPC_DPAU_H_OBL:
22831 check_dsp(ctx);
22832 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22833 break;
22834 case OPC_DPAU_H_OBR:
22835 check_dsp(ctx);
22836 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22837 break;
22838 case OPC_DPS_W_QH:
22839 check_dsp_r2(ctx);
22840 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22841 break;
22842 case OPC_DPSQ_S_W_QH:
22843 check_dsp(ctx);
22844 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22845 break;
22846 case OPC_DPSQ_SA_L_PW:
22847 check_dsp(ctx);
22848 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22849 break;
22850 case OPC_DPSU_H_OBL:
22851 check_dsp(ctx);
22852 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22853 break;
22854 case OPC_DPSU_H_OBR:
22855 check_dsp(ctx);
22856 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22857 break;
22858 case OPC_MAQ_S_L_PWL:
22859 check_dsp(ctx);
22860 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22861 break;
22862 case OPC_MAQ_S_L_PWR:
22863 check_dsp(ctx);
22864 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22865 break;
22866 case OPC_MAQ_S_W_QHLL:
22867 check_dsp(ctx);
22868 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22869 break;
22870 case OPC_MAQ_SA_W_QHLL:
22871 check_dsp(ctx);
22872 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22873 break;
22874 case OPC_MAQ_S_W_QHLR:
22875 check_dsp(ctx);
22876 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22877 break;
22878 case OPC_MAQ_SA_W_QHLR:
22879 check_dsp(ctx);
22880 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22881 break;
22882 case OPC_MAQ_S_W_QHRL:
22883 check_dsp(ctx);
22884 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22885 break;
22886 case OPC_MAQ_SA_W_QHRL:
22887 check_dsp(ctx);
22888 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22889 break;
22890 case OPC_MAQ_S_W_QHRR:
22891 check_dsp(ctx);
22892 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22893 break;
22894 case OPC_MAQ_SA_W_QHRR:
22895 check_dsp(ctx);
22896 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22897 break;
22898 case OPC_MULSAQ_S_L_PW:
22899 check_dsp(ctx);
22900 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22901 break;
22902 case OPC_MULSAQ_S_W_QH:
22903 check_dsp(ctx);
22904 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22905 break;
22908 break;
22909 #endif
22910 case OPC_ADDU_QB_DSP:
22911 switch (op2) {
22912 case OPC_MULEU_S_PH_QBL:
22913 check_dsp(ctx);
22914 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22915 break;
22916 case OPC_MULEU_S_PH_QBR:
22917 check_dsp(ctx);
22918 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22919 break;
22920 case OPC_MULQ_RS_PH:
22921 check_dsp(ctx);
22922 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22923 break;
22924 case OPC_MULEQ_S_W_PHL:
22925 check_dsp(ctx);
22926 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22927 break;
22928 case OPC_MULEQ_S_W_PHR:
22929 check_dsp(ctx);
22930 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22931 break;
22932 case OPC_MULQ_S_PH:
22933 check_dsp_r2(ctx);
22934 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22935 break;
22937 break;
22938 #ifdef TARGET_MIPS64
22939 case OPC_ADDU_OB_DSP:
22940 switch (op2) {
22941 case OPC_MULEQ_S_PW_QHL:
22942 check_dsp(ctx);
22943 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22944 break;
22945 case OPC_MULEQ_S_PW_QHR:
22946 check_dsp(ctx);
22947 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22948 break;
22949 case OPC_MULEU_S_QH_OBL:
22950 check_dsp(ctx);
22951 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22952 break;
22953 case OPC_MULEU_S_QH_OBR:
22954 check_dsp(ctx);
22955 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22956 break;
22957 case OPC_MULQ_RS_QH:
22958 check_dsp(ctx);
22959 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22960 break;
22962 break;
22963 #endif
22966 tcg_temp_free_i32(t0);
22967 tcg_temp_free(v1_t);
22968 tcg_temp_free(v2_t);
22971 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22972 int ret, int val)
22974 int16_t imm;
22975 TCGv t0;
22976 TCGv val_t;
22978 if (ret == 0) {
22979 /* Treat as NOP. */
22980 return;
22983 t0 = tcg_temp_new();
22984 val_t = tcg_temp_new();
22985 gen_load_gpr(val_t, val);
22987 switch (op1) {
22988 case OPC_ABSQ_S_PH_DSP:
22989 switch (op2) {
22990 case OPC_BITREV:
22991 check_dsp(ctx);
22992 gen_helper_bitrev(cpu_gpr[ret], val_t);
22993 break;
22994 case OPC_REPL_QB:
22995 check_dsp(ctx);
22997 target_long result;
22998 imm = (ctx->opcode >> 16) & 0xFF;
22999 result = (uint32_t)imm << 24 |
23000 (uint32_t)imm << 16 |
23001 (uint32_t)imm << 8 |
23002 (uint32_t)imm;
23003 result = (int32_t)result;
23004 tcg_gen_movi_tl(cpu_gpr[ret], result);
23006 break;
23007 case OPC_REPLV_QB:
23008 check_dsp(ctx);
23009 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23010 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23011 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23012 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23013 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23014 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23015 break;
23016 case OPC_REPL_PH:
23017 check_dsp(ctx);
23019 imm = (ctx->opcode >> 16) & 0x03FF;
23020 imm = (int16_t)(imm << 6) >> 6;
23021 tcg_gen_movi_tl(cpu_gpr[ret], \
23022 (target_long)((int32_t)imm << 16 | \
23023 (uint16_t)imm));
23025 break;
23026 case OPC_REPLV_PH:
23027 check_dsp(ctx);
23028 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23029 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23030 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23031 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23032 break;
23034 break;
23035 #ifdef TARGET_MIPS64
23036 case OPC_ABSQ_S_QH_DSP:
23037 switch (op2) {
23038 case OPC_REPL_OB:
23039 check_dsp(ctx);
23041 target_long temp;
23043 imm = (ctx->opcode >> 16) & 0xFF;
23044 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23045 temp = (temp << 16) | temp;
23046 temp = (temp << 32) | temp;
23047 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23048 break;
23050 case OPC_REPL_PW:
23051 check_dsp(ctx);
23053 target_long temp;
23055 imm = (ctx->opcode >> 16) & 0x03FF;
23056 imm = (int16_t)(imm << 6) >> 6;
23057 temp = ((target_long)imm << 32) \
23058 | ((target_long)imm & 0xFFFFFFFF);
23059 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23060 break;
23062 case OPC_REPL_QH:
23063 check_dsp(ctx);
23065 target_long temp;
23067 imm = (ctx->opcode >> 16) & 0x03FF;
23068 imm = (int16_t)(imm << 6) >> 6;
23070 temp = ((uint64_t)(uint16_t)imm << 48) |
23071 ((uint64_t)(uint16_t)imm << 32) |
23072 ((uint64_t)(uint16_t)imm << 16) |
23073 (uint64_t)(uint16_t)imm;
23074 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23075 break;
23077 case OPC_REPLV_OB:
23078 check_dsp(ctx);
23079 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23080 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23081 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23082 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23083 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23084 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23085 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23086 break;
23087 case OPC_REPLV_PW:
23088 check_dsp(ctx);
23089 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23090 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23091 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23092 break;
23093 case OPC_REPLV_QH:
23094 check_dsp(ctx);
23095 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23096 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23097 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23098 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23099 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23100 break;
23102 break;
23103 #endif
23105 tcg_temp_free(t0);
23106 tcg_temp_free(val_t);
23109 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23110 uint32_t op1, uint32_t op2,
23111 int ret, int v1, int v2, int check_ret)
23113 TCGv t1;
23114 TCGv v1_t;
23115 TCGv v2_t;
23117 if ((ret == 0) && (check_ret == 1)) {
23118 /* Treat as NOP. */
23119 return;
23122 t1 = tcg_temp_new();
23123 v1_t = tcg_temp_new();
23124 v2_t = tcg_temp_new();
23126 gen_load_gpr(v1_t, v1);
23127 gen_load_gpr(v2_t, v2);
23129 switch (op1) {
23130 case OPC_CMPU_EQ_QB_DSP:
23131 switch (op2) {
23132 case OPC_CMPU_EQ_QB:
23133 check_dsp(ctx);
23134 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23135 break;
23136 case OPC_CMPU_LT_QB:
23137 check_dsp(ctx);
23138 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23139 break;
23140 case OPC_CMPU_LE_QB:
23141 check_dsp(ctx);
23142 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23143 break;
23144 case OPC_CMPGU_EQ_QB:
23145 check_dsp(ctx);
23146 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23147 break;
23148 case OPC_CMPGU_LT_QB:
23149 check_dsp(ctx);
23150 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23151 break;
23152 case OPC_CMPGU_LE_QB:
23153 check_dsp(ctx);
23154 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23155 break;
23156 case OPC_CMPGDU_EQ_QB:
23157 check_dsp_r2(ctx);
23158 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23159 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23160 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23161 tcg_gen_shli_tl(t1, t1, 24);
23162 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23163 break;
23164 case OPC_CMPGDU_LT_QB:
23165 check_dsp_r2(ctx);
23166 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23167 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23168 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23169 tcg_gen_shli_tl(t1, t1, 24);
23170 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23171 break;
23172 case OPC_CMPGDU_LE_QB:
23173 check_dsp_r2(ctx);
23174 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23175 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23176 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23177 tcg_gen_shli_tl(t1, t1, 24);
23178 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23179 break;
23180 case OPC_CMP_EQ_PH:
23181 check_dsp(ctx);
23182 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23183 break;
23184 case OPC_CMP_LT_PH:
23185 check_dsp(ctx);
23186 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23187 break;
23188 case OPC_CMP_LE_PH:
23189 check_dsp(ctx);
23190 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23191 break;
23192 case OPC_PICK_QB:
23193 check_dsp(ctx);
23194 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23195 break;
23196 case OPC_PICK_PH:
23197 check_dsp(ctx);
23198 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23199 break;
23200 case OPC_PACKRL_PH:
23201 check_dsp(ctx);
23202 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23203 break;
23205 break;
23206 #ifdef TARGET_MIPS64
23207 case OPC_CMPU_EQ_OB_DSP:
23208 switch (op2) {
23209 case OPC_CMP_EQ_PW:
23210 check_dsp(ctx);
23211 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23212 break;
23213 case OPC_CMP_LT_PW:
23214 check_dsp(ctx);
23215 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23216 break;
23217 case OPC_CMP_LE_PW:
23218 check_dsp(ctx);
23219 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23220 break;
23221 case OPC_CMP_EQ_QH:
23222 check_dsp(ctx);
23223 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23224 break;
23225 case OPC_CMP_LT_QH:
23226 check_dsp(ctx);
23227 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23228 break;
23229 case OPC_CMP_LE_QH:
23230 check_dsp(ctx);
23231 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23232 break;
23233 case OPC_CMPGDU_EQ_OB:
23234 check_dsp_r2(ctx);
23235 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23236 break;
23237 case OPC_CMPGDU_LT_OB:
23238 check_dsp_r2(ctx);
23239 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23240 break;
23241 case OPC_CMPGDU_LE_OB:
23242 check_dsp_r2(ctx);
23243 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23244 break;
23245 case OPC_CMPGU_EQ_OB:
23246 check_dsp(ctx);
23247 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23248 break;
23249 case OPC_CMPGU_LT_OB:
23250 check_dsp(ctx);
23251 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23252 break;
23253 case OPC_CMPGU_LE_OB:
23254 check_dsp(ctx);
23255 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23256 break;
23257 case OPC_CMPU_EQ_OB:
23258 check_dsp(ctx);
23259 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23260 break;
23261 case OPC_CMPU_LT_OB:
23262 check_dsp(ctx);
23263 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23264 break;
23265 case OPC_CMPU_LE_OB:
23266 check_dsp(ctx);
23267 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23268 break;
23269 case OPC_PACKRL_PW:
23270 check_dsp(ctx);
23271 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23272 break;
23273 case OPC_PICK_OB:
23274 check_dsp(ctx);
23275 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23276 break;
23277 case OPC_PICK_PW:
23278 check_dsp(ctx);
23279 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23280 break;
23281 case OPC_PICK_QH:
23282 check_dsp(ctx);
23283 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23284 break;
23286 break;
23287 #endif
23290 tcg_temp_free(t1);
23291 tcg_temp_free(v1_t);
23292 tcg_temp_free(v2_t);
23295 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23296 uint32_t op1, int rt, int rs, int sa)
23298 TCGv t0;
23300 check_dsp_r2(ctx);
23302 if (rt == 0) {
23303 /* Treat as NOP. */
23304 return;
23307 t0 = tcg_temp_new();
23308 gen_load_gpr(t0, rs);
23310 switch (op1) {
23311 case OPC_APPEND_DSP:
23312 switch (MASK_APPEND(ctx->opcode)) {
23313 case OPC_APPEND:
23314 if (sa != 0) {
23315 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23317 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23318 break;
23319 case OPC_PREPEND:
23320 if (sa != 0) {
23321 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23322 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23323 tcg_gen_shli_tl(t0, t0, 32 - sa);
23324 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23326 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23327 break;
23328 case OPC_BALIGN:
23329 sa &= 3;
23330 if (sa != 0 && sa != 2) {
23331 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23332 tcg_gen_ext32u_tl(t0, t0);
23333 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23334 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23336 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23337 break;
23338 default: /* Invalid */
23339 MIPS_INVAL("MASK APPEND");
23340 generate_exception_end(ctx, EXCP_RI);
23341 break;
23343 break;
23344 #ifdef TARGET_MIPS64
23345 case OPC_DAPPEND_DSP:
23346 switch (MASK_DAPPEND(ctx->opcode)) {
23347 case OPC_DAPPEND:
23348 if (sa != 0) {
23349 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23351 break;
23352 case OPC_PREPENDD:
23353 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23354 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23355 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23356 break;
23357 case OPC_PREPENDW:
23358 if (sa != 0) {
23359 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23360 tcg_gen_shli_tl(t0, t0, 64 - sa);
23361 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23363 break;
23364 case OPC_DBALIGN:
23365 sa &= 7;
23366 if (sa != 0 && sa != 2 && sa != 4) {
23367 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23368 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23369 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23371 break;
23372 default: /* Invalid */
23373 MIPS_INVAL("MASK DAPPEND");
23374 generate_exception_end(ctx, EXCP_RI);
23375 break;
23377 break;
23378 #endif
23380 tcg_temp_free(t0);
23383 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23384 int ret, int v1, int v2, int check_ret)
23387 TCGv t0;
23388 TCGv t1;
23389 TCGv v1_t;
23390 TCGv v2_t;
23391 int16_t imm;
23393 if ((ret == 0) && (check_ret == 1)) {
23394 /* Treat as NOP. */
23395 return;
23398 t0 = tcg_temp_new();
23399 t1 = tcg_temp_new();
23400 v1_t = tcg_temp_new();
23401 v2_t = tcg_temp_new();
23403 gen_load_gpr(v1_t, v1);
23404 gen_load_gpr(v2_t, v2);
23406 switch (op1) {
23407 case OPC_EXTR_W_DSP:
23408 check_dsp(ctx);
23409 switch (op2) {
23410 case OPC_EXTR_W:
23411 tcg_gen_movi_tl(t0, v2);
23412 tcg_gen_movi_tl(t1, v1);
23413 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23414 break;
23415 case OPC_EXTR_R_W:
23416 tcg_gen_movi_tl(t0, v2);
23417 tcg_gen_movi_tl(t1, v1);
23418 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23419 break;
23420 case OPC_EXTR_RS_W:
23421 tcg_gen_movi_tl(t0, v2);
23422 tcg_gen_movi_tl(t1, v1);
23423 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23424 break;
23425 case OPC_EXTR_S_H:
23426 tcg_gen_movi_tl(t0, v2);
23427 tcg_gen_movi_tl(t1, v1);
23428 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23429 break;
23430 case OPC_EXTRV_S_H:
23431 tcg_gen_movi_tl(t0, v2);
23432 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23433 break;
23434 case OPC_EXTRV_W:
23435 tcg_gen_movi_tl(t0, v2);
23436 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23437 break;
23438 case OPC_EXTRV_R_W:
23439 tcg_gen_movi_tl(t0, v2);
23440 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23441 break;
23442 case OPC_EXTRV_RS_W:
23443 tcg_gen_movi_tl(t0, v2);
23444 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23445 break;
23446 case OPC_EXTP:
23447 tcg_gen_movi_tl(t0, v2);
23448 tcg_gen_movi_tl(t1, v1);
23449 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23450 break;
23451 case OPC_EXTPV:
23452 tcg_gen_movi_tl(t0, v2);
23453 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23454 break;
23455 case OPC_EXTPDP:
23456 tcg_gen_movi_tl(t0, v2);
23457 tcg_gen_movi_tl(t1, v1);
23458 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23459 break;
23460 case OPC_EXTPDPV:
23461 tcg_gen_movi_tl(t0, v2);
23462 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23463 break;
23464 case OPC_SHILO:
23465 imm = (ctx->opcode >> 20) & 0x3F;
23466 tcg_gen_movi_tl(t0, ret);
23467 tcg_gen_movi_tl(t1, imm);
23468 gen_helper_shilo(t0, t1, cpu_env);
23469 break;
23470 case OPC_SHILOV:
23471 tcg_gen_movi_tl(t0, ret);
23472 gen_helper_shilo(t0, v1_t, cpu_env);
23473 break;
23474 case OPC_MTHLIP:
23475 tcg_gen_movi_tl(t0, ret);
23476 gen_helper_mthlip(t0, v1_t, cpu_env);
23477 break;
23478 case OPC_WRDSP:
23479 imm = (ctx->opcode >> 11) & 0x3FF;
23480 tcg_gen_movi_tl(t0, imm);
23481 gen_helper_wrdsp(v1_t, t0, cpu_env);
23482 break;
23483 case OPC_RDDSP:
23484 imm = (ctx->opcode >> 16) & 0x03FF;
23485 tcg_gen_movi_tl(t0, imm);
23486 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23487 break;
23489 break;
23490 #ifdef TARGET_MIPS64
23491 case OPC_DEXTR_W_DSP:
23492 check_dsp(ctx);
23493 switch (op2) {
23494 case OPC_DMTHLIP:
23495 tcg_gen_movi_tl(t0, ret);
23496 gen_helper_dmthlip(v1_t, t0, cpu_env);
23497 break;
23498 case OPC_DSHILO:
23500 int shift = (ctx->opcode >> 19) & 0x7F;
23501 int ac = (ctx->opcode >> 11) & 0x03;
23502 tcg_gen_movi_tl(t0, shift);
23503 tcg_gen_movi_tl(t1, ac);
23504 gen_helper_dshilo(t0, t1, cpu_env);
23505 break;
23507 case OPC_DSHILOV:
23509 int ac = (ctx->opcode >> 11) & 0x03;
23510 tcg_gen_movi_tl(t0, ac);
23511 gen_helper_dshilo(v1_t, t0, cpu_env);
23512 break;
23514 case OPC_DEXTP:
23515 tcg_gen_movi_tl(t0, v2);
23516 tcg_gen_movi_tl(t1, v1);
23518 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23519 break;
23520 case OPC_DEXTPV:
23521 tcg_gen_movi_tl(t0, v2);
23522 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23523 break;
23524 case OPC_DEXTPDP:
23525 tcg_gen_movi_tl(t0, v2);
23526 tcg_gen_movi_tl(t1, v1);
23527 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23528 break;
23529 case OPC_DEXTPDPV:
23530 tcg_gen_movi_tl(t0, v2);
23531 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23532 break;
23533 case OPC_DEXTR_L:
23534 tcg_gen_movi_tl(t0, v2);
23535 tcg_gen_movi_tl(t1, v1);
23536 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23537 break;
23538 case OPC_DEXTR_R_L:
23539 tcg_gen_movi_tl(t0, v2);
23540 tcg_gen_movi_tl(t1, v1);
23541 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23542 break;
23543 case OPC_DEXTR_RS_L:
23544 tcg_gen_movi_tl(t0, v2);
23545 tcg_gen_movi_tl(t1, v1);
23546 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23547 break;
23548 case OPC_DEXTR_W:
23549 tcg_gen_movi_tl(t0, v2);
23550 tcg_gen_movi_tl(t1, v1);
23551 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23552 break;
23553 case OPC_DEXTR_R_W:
23554 tcg_gen_movi_tl(t0, v2);
23555 tcg_gen_movi_tl(t1, v1);
23556 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23557 break;
23558 case OPC_DEXTR_RS_W:
23559 tcg_gen_movi_tl(t0, v2);
23560 tcg_gen_movi_tl(t1, v1);
23561 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23562 break;
23563 case OPC_DEXTR_S_H:
23564 tcg_gen_movi_tl(t0, v2);
23565 tcg_gen_movi_tl(t1, v1);
23566 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23567 break;
23568 case OPC_DEXTRV_S_H:
23569 tcg_gen_movi_tl(t0, v2);
23570 tcg_gen_movi_tl(t1, v1);
23571 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23572 break;
23573 case OPC_DEXTRV_L:
23574 tcg_gen_movi_tl(t0, v2);
23575 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23576 break;
23577 case OPC_DEXTRV_R_L:
23578 tcg_gen_movi_tl(t0, v2);
23579 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23580 break;
23581 case OPC_DEXTRV_RS_L:
23582 tcg_gen_movi_tl(t0, v2);
23583 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23584 break;
23585 case OPC_DEXTRV_W:
23586 tcg_gen_movi_tl(t0, v2);
23587 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23588 break;
23589 case OPC_DEXTRV_R_W:
23590 tcg_gen_movi_tl(t0, v2);
23591 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23592 break;
23593 case OPC_DEXTRV_RS_W:
23594 tcg_gen_movi_tl(t0, v2);
23595 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23596 break;
23598 break;
23599 #endif
23602 tcg_temp_free(t0);
23603 tcg_temp_free(t1);
23604 tcg_temp_free(v1_t);
23605 tcg_temp_free(v2_t);
23608 /* End MIPSDSP functions. */
23610 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23612 int rs, rt, rd, sa;
23613 uint32_t op1, op2;
23615 rs = (ctx->opcode >> 21) & 0x1f;
23616 rt = (ctx->opcode >> 16) & 0x1f;
23617 rd = (ctx->opcode >> 11) & 0x1f;
23618 sa = (ctx->opcode >> 6) & 0x1f;
23620 op1 = MASK_SPECIAL(ctx->opcode);
23621 switch (op1) {
23622 case OPC_LSA:
23623 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23624 break;
23625 case OPC_MULT:
23626 case OPC_MULTU:
23627 case OPC_DIV:
23628 case OPC_DIVU:
23629 op2 = MASK_R6_MULDIV(ctx->opcode);
23630 switch (op2) {
23631 case R6_OPC_MUL:
23632 case R6_OPC_MUH:
23633 case R6_OPC_MULU:
23634 case R6_OPC_MUHU:
23635 case R6_OPC_DIV:
23636 case R6_OPC_MOD:
23637 case R6_OPC_DIVU:
23638 case R6_OPC_MODU:
23639 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23640 break;
23641 default:
23642 MIPS_INVAL("special_r6 muldiv");
23643 generate_exception_end(ctx, EXCP_RI);
23644 break;
23646 break;
23647 case OPC_SELEQZ:
23648 case OPC_SELNEZ:
23649 gen_cond_move(ctx, op1, rd, rs, rt);
23650 break;
23651 case R6_OPC_CLO:
23652 case R6_OPC_CLZ:
23653 if (rt == 0 && sa == 1) {
23654 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23655 We need additionally to check other fields */
23656 gen_cl(ctx, op1, rd, rs);
23657 } else {
23658 generate_exception_end(ctx, EXCP_RI);
23660 break;
23661 case R6_OPC_SDBBP:
23662 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23663 gen_helper_do_semihosting(cpu_env);
23664 } else {
23665 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23666 generate_exception_end(ctx, EXCP_RI);
23667 } else {
23668 generate_exception_end(ctx, EXCP_DBp);
23671 break;
23672 #if defined(TARGET_MIPS64)
23673 case OPC_DLSA:
23674 check_mips_64(ctx);
23675 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23676 break;
23677 case R6_OPC_DCLO:
23678 case R6_OPC_DCLZ:
23679 if (rt == 0 && sa == 1) {
23680 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23681 We need additionally to check other fields */
23682 check_mips_64(ctx);
23683 gen_cl(ctx, op1, rd, rs);
23684 } else {
23685 generate_exception_end(ctx, EXCP_RI);
23687 break;
23688 case OPC_DMULT:
23689 case OPC_DMULTU:
23690 case OPC_DDIV:
23691 case OPC_DDIVU:
23693 op2 = MASK_R6_MULDIV(ctx->opcode);
23694 switch (op2) {
23695 case R6_OPC_DMUL:
23696 case R6_OPC_DMUH:
23697 case R6_OPC_DMULU:
23698 case R6_OPC_DMUHU:
23699 case R6_OPC_DDIV:
23700 case R6_OPC_DMOD:
23701 case R6_OPC_DDIVU:
23702 case R6_OPC_DMODU:
23703 check_mips_64(ctx);
23704 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23705 break;
23706 default:
23707 MIPS_INVAL("special_r6 muldiv");
23708 generate_exception_end(ctx, EXCP_RI);
23709 break;
23711 break;
23712 #endif
23713 default: /* Invalid */
23714 MIPS_INVAL("special_r6");
23715 generate_exception_end(ctx, EXCP_RI);
23716 break;
23720 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23722 int rs, rt, rd, sa;
23723 uint32_t op1;
23725 rs = (ctx->opcode >> 21) & 0x1f;
23726 rt = (ctx->opcode >> 16) & 0x1f;
23727 rd = (ctx->opcode >> 11) & 0x1f;
23728 sa = (ctx->opcode >> 6) & 0x1f;
23730 op1 = MASK_SPECIAL(ctx->opcode);
23731 switch (op1) {
23732 case OPC_MOVN: /* Conditional move */
23733 case OPC_MOVZ:
23734 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23735 INSN_LOONGSON2E | INSN_LOONGSON2F | INSN_R5900);
23736 gen_cond_move(ctx, op1, rd, rs, rt);
23737 break;
23738 case OPC_MFHI: /* Move from HI/LO */
23739 case OPC_MFLO:
23740 gen_HILO(ctx, op1, rs & 3, rd);
23741 break;
23742 case OPC_MTHI:
23743 case OPC_MTLO: /* Move to HI/LO */
23744 gen_HILO(ctx, op1, rd & 3, rs);
23745 break;
23746 case OPC_MOVCI:
23747 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23748 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23749 check_cp1_enabled(ctx);
23750 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23751 (ctx->opcode >> 16) & 1);
23752 } else {
23753 generate_exception_err(ctx, EXCP_CpU, 1);
23755 break;
23756 case OPC_MULT:
23757 case OPC_MULTU:
23758 if (sa) {
23759 check_insn(ctx, INSN_VR54XX);
23760 op1 = MASK_MUL_VR54XX(ctx->opcode);
23761 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23762 } else if (ctx->insn_flags & INSN_R5900) {
23763 gen_mul_txx9(ctx, op1, rd, rs, rt);
23764 } else {
23765 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23767 break;
23768 case OPC_DIV:
23769 case OPC_DIVU:
23770 gen_muldiv(ctx, op1, 0, rs, rt);
23771 break;
23772 #if defined(TARGET_MIPS64)
23773 case OPC_DMULT:
23774 case OPC_DMULTU:
23775 case OPC_DDIV:
23776 case OPC_DDIVU:
23777 check_insn(ctx, ISA_MIPS3);
23778 check_insn_opc_user_only(ctx, INSN_R5900);
23779 check_mips_64(ctx);
23780 gen_muldiv(ctx, op1, 0, rs, rt);
23781 break;
23782 #endif
23783 case OPC_JR:
23784 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23785 break;
23786 case OPC_SPIM:
23787 #ifdef MIPS_STRICT_STANDARD
23788 MIPS_INVAL("SPIM");
23789 generate_exception_end(ctx, EXCP_RI);
23790 #else
23791 /* Implemented as RI exception for now. */
23792 MIPS_INVAL("spim (unofficial)");
23793 generate_exception_end(ctx, EXCP_RI);
23794 #endif
23795 break;
23796 default: /* Invalid */
23797 MIPS_INVAL("special_legacy");
23798 generate_exception_end(ctx, EXCP_RI);
23799 break;
23803 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23805 int rs, rt, rd, sa;
23806 uint32_t op1;
23808 rs = (ctx->opcode >> 21) & 0x1f;
23809 rt = (ctx->opcode >> 16) & 0x1f;
23810 rd = (ctx->opcode >> 11) & 0x1f;
23811 sa = (ctx->opcode >> 6) & 0x1f;
23813 op1 = MASK_SPECIAL(ctx->opcode);
23814 switch (op1) {
23815 case OPC_SLL: /* Shift with immediate */
23816 if (sa == 5 && rd == 0 &&
23817 rs == 0 && rt == 0) { /* PAUSE */
23818 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23819 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23820 generate_exception_end(ctx, EXCP_RI);
23821 break;
23824 /* Fallthrough */
23825 case OPC_SRA:
23826 gen_shift_imm(ctx, op1, rd, rt, sa);
23827 break;
23828 case OPC_SRL:
23829 switch ((ctx->opcode >> 21) & 0x1f) {
23830 case 1:
23831 /* rotr is decoded as srl on non-R2 CPUs */
23832 if (ctx->insn_flags & ISA_MIPS32R2) {
23833 op1 = OPC_ROTR;
23835 /* Fallthrough */
23836 case 0:
23837 gen_shift_imm(ctx, op1, rd, rt, sa);
23838 break;
23839 default:
23840 generate_exception_end(ctx, EXCP_RI);
23841 break;
23843 break;
23844 case OPC_ADD:
23845 case OPC_ADDU:
23846 case OPC_SUB:
23847 case OPC_SUBU:
23848 gen_arith(ctx, op1, rd, rs, rt);
23849 break;
23850 case OPC_SLLV: /* Shifts */
23851 case OPC_SRAV:
23852 gen_shift(ctx, op1, rd, rs, rt);
23853 break;
23854 case OPC_SRLV:
23855 switch ((ctx->opcode >> 6) & 0x1f) {
23856 case 1:
23857 /* rotrv is decoded as srlv on non-R2 CPUs */
23858 if (ctx->insn_flags & ISA_MIPS32R2) {
23859 op1 = OPC_ROTRV;
23861 /* Fallthrough */
23862 case 0:
23863 gen_shift(ctx, op1, rd, rs, rt);
23864 break;
23865 default:
23866 generate_exception_end(ctx, EXCP_RI);
23867 break;
23869 break;
23870 case OPC_SLT: /* Set on less than */
23871 case OPC_SLTU:
23872 gen_slt(ctx, op1, rd, rs, rt);
23873 break;
23874 case OPC_AND: /* Logic*/
23875 case OPC_OR:
23876 case OPC_NOR:
23877 case OPC_XOR:
23878 gen_logic(ctx, op1, rd, rs, rt);
23879 break;
23880 case OPC_JALR:
23881 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23882 break;
23883 case OPC_TGE: /* Traps */
23884 case OPC_TGEU:
23885 case OPC_TLT:
23886 case OPC_TLTU:
23887 case OPC_TEQ:
23888 case OPC_TNE:
23889 check_insn(ctx, ISA_MIPS2);
23890 gen_trap(ctx, op1, rs, rt, -1);
23891 break;
23892 case OPC_LSA: /* OPC_PMON */
23893 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23894 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23895 decode_opc_special_r6(env, ctx);
23896 } else {
23897 /* Pmon entry point, also R4010 selsl */
23898 #ifdef MIPS_STRICT_STANDARD
23899 MIPS_INVAL("PMON / selsl");
23900 generate_exception_end(ctx, EXCP_RI);
23901 #else
23902 gen_helper_0e0i(pmon, sa);
23903 #endif
23905 break;
23906 case OPC_SYSCALL:
23907 generate_exception_end(ctx, EXCP_SYSCALL);
23908 break;
23909 case OPC_BREAK:
23910 generate_exception_end(ctx, EXCP_BREAK);
23911 break;
23912 case OPC_SYNC:
23913 check_insn(ctx, ISA_MIPS2);
23914 gen_sync(extract32(ctx->opcode, 6, 5));
23915 break;
23917 #if defined(TARGET_MIPS64)
23918 /* MIPS64 specific opcodes */
23919 case OPC_DSLL:
23920 case OPC_DSRA:
23921 case OPC_DSLL32:
23922 case OPC_DSRA32:
23923 check_insn(ctx, ISA_MIPS3);
23924 check_mips_64(ctx);
23925 gen_shift_imm(ctx, op1, rd, rt, sa);
23926 break;
23927 case OPC_DSRL:
23928 switch ((ctx->opcode >> 21) & 0x1f) {
23929 case 1:
23930 /* drotr is decoded as dsrl on non-R2 CPUs */
23931 if (ctx->insn_flags & ISA_MIPS32R2) {
23932 op1 = OPC_DROTR;
23934 /* Fallthrough */
23935 case 0:
23936 check_insn(ctx, ISA_MIPS3);
23937 check_mips_64(ctx);
23938 gen_shift_imm(ctx, op1, rd, rt, sa);
23939 break;
23940 default:
23941 generate_exception_end(ctx, EXCP_RI);
23942 break;
23944 break;
23945 case OPC_DSRL32:
23946 switch ((ctx->opcode >> 21) & 0x1f) {
23947 case 1:
23948 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23949 if (ctx->insn_flags & ISA_MIPS32R2) {
23950 op1 = OPC_DROTR32;
23952 /* Fallthrough */
23953 case 0:
23954 check_insn(ctx, ISA_MIPS3);
23955 check_mips_64(ctx);
23956 gen_shift_imm(ctx, op1, rd, rt, sa);
23957 break;
23958 default:
23959 generate_exception_end(ctx, EXCP_RI);
23960 break;
23962 break;
23963 case OPC_DADD:
23964 case OPC_DADDU:
23965 case OPC_DSUB:
23966 case OPC_DSUBU:
23967 check_insn(ctx, ISA_MIPS3);
23968 check_mips_64(ctx);
23969 gen_arith(ctx, op1, rd, rs, rt);
23970 break;
23971 case OPC_DSLLV:
23972 case OPC_DSRAV:
23973 check_insn(ctx, ISA_MIPS3);
23974 check_mips_64(ctx);
23975 gen_shift(ctx, op1, rd, rs, rt);
23976 break;
23977 case OPC_DSRLV:
23978 switch ((ctx->opcode >> 6) & 0x1f) {
23979 case 1:
23980 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23981 if (ctx->insn_flags & ISA_MIPS32R2) {
23982 op1 = OPC_DROTRV;
23984 /* Fallthrough */
23985 case 0:
23986 check_insn(ctx, ISA_MIPS3);
23987 check_mips_64(ctx);
23988 gen_shift(ctx, op1, rd, rs, rt);
23989 break;
23990 default:
23991 generate_exception_end(ctx, EXCP_RI);
23992 break;
23994 break;
23995 case OPC_DLSA:
23996 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23997 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23998 decode_opc_special_r6(env, ctx);
24000 break;
24001 #endif
24002 default:
24003 if (ctx->insn_flags & ISA_MIPS32R6) {
24004 decode_opc_special_r6(env, ctx);
24005 } else {
24006 decode_opc_special_legacy(env, ctx);
24012 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24013 #define MXU_APTN1_A 0
24014 #define MXU_APTN1_S 1
24016 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24017 #define MXU_APTN2_AA 0
24018 #define MXU_APTN2_AS 1
24019 #define MXU_APTN2_SA 2
24020 #define MXU_APTN2_SS 3
24022 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24023 #define MXU_EPTN2_AA 0
24024 #define MXU_EPTN2_AS 1
24025 #define MXU_EPTN2_SA 2
24026 #define MXU_EPTN2_SS 3
24028 /* MXU operand getting pattern 'optn2' */
24029 #define MXU_OPTN2_WW 0
24030 #define MXU_OPTN2_LW 1
24031 #define MXU_OPTN2_HW 2
24032 #define MXU_OPTN2_XW 3
24034 /* MXU operand getting pattern 'optn3' */
24035 #define MXU_OPTN3_PTN0 0
24036 #define MXU_OPTN3_PTN1 1
24037 #define MXU_OPTN3_PTN2 2
24038 #define MXU_OPTN3_PTN3 3
24039 #define MXU_OPTN3_PTN4 4
24040 #define MXU_OPTN3_PTN5 5
24041 #define MXU_OPTN3_PTN6 6
24042 #define MXU_OPTN3_PTN7 7
24046 * S32I2M XRa, rb - Register move from GRF to XRF
24048 static void gen_mxu_s32i2m(DisasContext *ctx)
24050 TCGv t0;
24051 uint32_t XRa, Rb;
24053 t0 = tcg_temp_new();
24055 XRa = extract32(ctx->opcode, 6, 5);
24056 Rb = extract32(ctx->opcode, 16, 5);
24058 gen_load_gpr(t0, Rb);
24059 if (XRa <= 15) {
24060 gen_store_mxu_gpr(t0, XRa);
24061 } else if (XRa == 16) {
24062 gen_store_mxu_cr(t0);
24065 tcg_temp_free(t0);
24069 * S32M2I XRa, rb - Register move from XRF to GRF
24071 static void gen_mxu_s32m2i(DisasContext *ctx)
24073 TCGv t0;
24074 uint32_t XRa, Rb;
24076 t0 = tcg_temp_new();
24078 XRa = extract32(ctx->opcode, 6, 5);
24079 Rb = extract32(ctx->opcode, 16, 5);
24081 if (XRa <= 15) {
24082 gen_load_mxu_gpr(t0, XRa);
24083 } else if (XRa == 16) {
24084 gen_load_mxu_cr(t0);
24087 gen_store_gpr(t0, Rb);
24089 tcg_temp_free(t0);
24093 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24095 static void gen_mxu_s8ldd(DisasContext *ctx)
24097 TCGv t0, t1;
24098 TCGLabel *l0;
24099 uint32_t XRa, Rb, s8, optn3;
24101 t0 = tcg_temp_new();
24102 t1 = tcg_temp_new();
24104 l0 = gen_new_label();
24106 XRa = extract32(ctx->opcode, 6, 4);
24107 s8 = extract32(ctx->opcode, 10, 8);
24108 optn3 = extract32(ctx->opcode, 18, 3);
24109 Rb = extract32(ctx->opcode, 21, 5);
24111 gen_load_mxu_cr(t0);
24112 tcg_gen_andi_tl(t0, t0, MXU_CR_MXU_EN);
24113 tcg_gen_brcondi_tl(TCG_COND_NE, t0, MXU_CR_MXU_EN, l0);
24115 gen_load_gpr(t0, Rb);
24116 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24118 switch (optn3) {
24119 /* XRa[7:0] = tmp8 */
24120 case MXU_OPTN3_PTN0:
24121 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24122 gen_load_mxu_gpr(t0, XRa);
24123 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24124 break;
24125 /* XRa[15:8] = tmp8 */
24126 case MXU_OPTN3_PTN1:
24127 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24128 gen_load_mxu_gpr(t0, XRa);
24129 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24130 break;
24131 /* XRa[23:16] = tmp8 */
24132 case MXU_OPTN3_PTN2:
24133 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24134 gen_load_mxu_gpr(t0, XRa);
24135 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24136 break;
24137 /* XRa[31:24] = tmp8 */
24138 case MXU_OPTN3_PTN3:
24139 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24140 gen_load_mxu_gpr(t0, XRa);
24141 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24142 break;
24143 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24144 case MXU_OPTN3_PTN4:
24145 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24146 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24147 break;
24148 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24149 case MXU_OPTN3_PTN5:
24150 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24151 tcg_gen_shli_tl(t1, t1, 8);
24152 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24153 break;
24154 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24155 case MXU_OPTN3_PTN6:
24156 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24157 tcg_gen_mov_tl(t0, t1);
24158 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24159 tcg_gen_shli_tl(t1, t1, 16);
24160 tcg_gen_or_tl(t0, t0, t1);
24161 break;
24162 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24163 case MXU_OPTN3_PTN7:
24164 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24165 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24166 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24167 break;
24170 gen_store_mxu_gpr(t0, XRa);
24172 gen_set_label(l0);
24174 tcg_temp_free(t0);
24175 tcg_temp_free(t1);
24179 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24181 static void gen_mxu_d16mul(DisasContext *ctx)
24183 TCGv t0, t1, t2, t3;
24184 TCGLabel *l0;
24185 uint32_t XRa, XRb, XRc, XRd, optn2;
24187 t0 = tcg_temp_new();
24188 t1 = tcg_temp_new();
24189 t2 = tcg_temp_new();
24190 t3 = tcg_temp_new();
24192 l0 = gen_new_label();
24194 XRa = extract32(ctx->opcode, 6, 4);
24195 XRb = extract32(ctx->opcode, 10, 4);
24196 XRc = extract32(ctx->opcode, 14, 4);
24197 XRd = extract32(ctx->opcode, 18, 4);
24198 optn2 = extract32(ctx->opcode, 22, 2);
24200 gen_load_mxu_cr(t0);
24201 tcg_gen_andi_tl(t0, t0, MXU_CR_MXU_EN);
24202 tcg_gen_brcondi_tl(TCG_COND_NE, t0, MXU_CR_MXU_EN, l0);
24204 gen_load_mxu_gpr(t1, XRb);
24205 tcg_gen_sextract_tl(t0, t1, 0, 16);
24206 tcg_gen_sextract_tl(t1, t1, 16, 16);
24207 gen_load_mxu_gpr(t3, XRc);
24208 tcg_gen_sextract_tl(t2, t3, 0, 16);
24209 tcg_gen_sextract_tl(t3, t3, 16, 16);
24211 switch (optn2) {
24212 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24213 tcg_gen_mul_tl(t3, t1, t3);
24214 tcg_gen_mul_tl(t2, t0, t2);
24215 break;
24216 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24217 tcg_gen_mul_tl(t3, t0, t3);
24218 tcg_gen_mul_tl(t2, t0, t2);
24219 break;
24220 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24221 tcg_gen_mul_tl(t3, t1, t3);
24222 tcg_gen_mul_tl(t2, t1, t2);
24223 break;
24224 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24225 tcg_gen_mul_tl(t3, t0, t3);
24226 tcg_gen_mul_tl(t2, t1, t2);
24227 break;
24229 gen_store_mxu_gpr(t3, XRa);
24230 gen_store_mxu_gpr(t2, XRd);
24232 gen_set_label(l0);
24234 tcg_temp_free(t0);
24235 tcg_temp_free(t1);
24236 tcg_temp_free(t2);
24237 tcg_temp_free(t3);
24241 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24242 * and accumulate
24244 static void gen_mxu_d16mac(DisasContext *ctx)
24246 TCGv t0, t1, t2, t3;
24247 TCGLabel *l0;
24248 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24250 t0 = tcg_temp_new();
24251 t1 = tcg_temp_new();
24252 t2 = tcg_temp_new();
24253 t3 = tcg_temp_new();
24255 l0 = gen_new_label();
24257 XRa = extract32(ctx->opcode, 6, 4);
24258 XRb = extract32(ctx->opcode, 10, 4);
24259 XRc = extract32(ctx->opcode, 14, 4);
24260 XRd = extract32(ctx->opcode, 18, 4);
24261 optn2 = extract32(ctx->opcode, 22, 2);
24262 aptn2 = extract32(ctx->opcode, 24, 2);
24264 gen_load_mxu_cr(t0);
24265 tcg_gen_andi_tl(t0, t0, MXU_CR_MXU_EN);
24266 tcg_gen_brcondi_tl(TCG_COND_NE, t0, MXU_CR_MXU_EN, l0);
24268 gen_load_mxu_gpr(t1, XRb);
24269 tcg_gen_sextract_tl(t0, t1, 0, 16);
24270 tcg_gen_sextract_tl(t1, t1, 16, 16);
24272 gen_load_mxu_gpr(t3, XRc);
24273 tcg_gen_sextract_tl(t2, t3, 0, 16);
24274 tcg_gen_sextract_tl(t3, t3, 16, 16);
24276 switch (optn2) {
24277 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24278 tcg_gen_mul_tl(t3, t1, t3);
24279 tcg_gen_mul_tl(t2, t0, t2);
24280 break;
24281 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24282 tcg_gen_mul_tl(t3, t0, t3);
24283 tcg_gen_mul_tl(t2, t0, t2);
24284 break;
24285 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24286 tcg_gen_mul_tl(t3, t1, t3);
24287 tcg_gen_mul_tl(t2, t1, t2);
24288 break;
24289 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24290 tcg_gen_mul_tl(t3, t0, t3);
24291 tcg_gen_mul_tl(t2, t1, t2);
24292 break;
24294 gen_load_mxu_gpr(t0, XRa);
24295 gen_load_mxu_gpr(t1, XRd);
24297 switch (aptn2) {
24298 case MXU_APTN2_AA:
24299 tcg_gen_add_tl(t3, t0, t3);
24300 tcg_gen_add_tl(t2, t1, t2);
24301 break;
24302 case MXU_APTN2_AS:
24303 tcg_gen_add_tl(t3, t0, t3);
24304 tcg_gen_sub_tl(t2, t1, t2);
24305 break;
24306 case MXU_APTN2_SA:
24307 tcg_gen_sub_tl(t3, t0, t3);
24308 tcg_gen_add_tl(t2, t1, t2);
24309 break;
24310 case MXU_APTN2_SS:
24311 tcg_gen_sub_tl(t3, t0, t3);
24312 tcg_gen_sub_tl(t2, t1, t2);
24313 break;
24315 gen_store_mxu_gpr(t3, XRa);
24316 gen_store_mxu_gpr(t2, XRd);
24318 gen_set_label(l0);
24320 tcg_temp_free(t0);
24321 tcg_temp_free(t1);
24322 tcg_temp_free(t2);
24323 tcg_temp_free(t3);
24328 * Decoding engine for MXU
24329 * =======================
24334 * Decode MXU pool00
24336 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24337 * +-----------+---------+-----+-------+-------+-------+-----------+
24338 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
24339 * +-----------+---------+-----+-------+-------+-------+-----------+
24342 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
24344 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24346 switch (opcode) {
24347 case OPC_MXU_S32MAX:
24348 /* TODO: Implement emulation of S32MAX instruction. */
24349 MIPS_INVAL("OPC_MXU_S32MAX");
24350 generate_exception_end(ctx, EXCP_RI);
24351 break;
24352 case OPC_MXU_S32MIN:
24353 /* TODO: Implement emulation of S32MIN instruction. */
24354 MIPS_INVAL("OPC_MXU_S32MIN");
24355 generate_exception_end(ctx, EXCP_RI);
24356 break;
24357 case OPC_MXU_D16MAX:
24358 /* TODO: Implement emulation of D16MAX instruction. */
24359 MIPS_INVAL("OPC_MXU_D16MAX");
24360 generate_exception_end(ctx, EXCP_RI);
24361 break;
24362 case OPC_MXU_D16MIN:
24363 /* TODO: Implement emulation of D16MIN instruction. */
24364 MIPS_INVAL("OPC_MXU_D16MIN");
24365 generate_exception_end(ctx, EXCP_RI);
24366 break;
24367 case OPC_MXU_Q8MAX:
24368 /* TODO: Implement emulation of Q8MAX instruction. */
24369 MIPS_INVAL("OPC_MXU_Q8MAX");
24370 generate_exception_end(ctx, EXCP_RI);
24371 break;
24372 case OPC_MXU_Q8MIN:
24373 /* TODO: Implement emulation of Q8MIN instruction. */
24374 MIPS_INVAL("OPC_MXU_Q8MIN");
24375 generate_exception_end(ctx, EXCP_RI);
24376 break;
24377 case OPC_MXU_Q8SLT:
24378 /* TODO: Implement emulation of Q8SLT instruction. */
24379 MIPS_INVAL("OPC_MXU_Q8SLT");
24380 generate_exception_end(ctx, EXCP_RI);
24381 break;
24382 case OPC_MXU_Q8SLTU:
24383 /* TODO: Implement emulation of Q8SLTU instruction. */
24384 MIPS_INVAL("OPC_MXU_Q8SLTU");
24385 generate_exception_end(ctx, EXCP_RI);
24386 break;
24387 default:
24388 MIPS_INVAL("decode_opc_mxu");
24389 generate_exception_end(ctx, EXCP_RI);
24390 break;
24396 * Decode MXU pool01
24398 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
24399 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24400 * +-----------+---------+-----+-------+-------+-------+-----------+
24401 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
24402 * +-----------+---------+-----+-------+-------+-------+-----------+
24404 * Q8ADD:
24405 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24406 * +-----------+---+-----+-----+-------+-------+-------+-----------+
24407 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
24408 * +-----------+---+-----+-----+-------+-------+-------+-----------+
24411 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
24413 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24415 switch (opcode) {
24416 case OPC_MXU_S32SLT:
24417 /* TODO: Implement emulation of S32SLT instruction. */
24418 MIPS_INVAL("OPC_MXU_S32SLT");
24419 generate_exception_end(ctx, EXCP_RI);
24420 break;
24421 case OPC_MXU_D16SLT:
24422 /* TODO: Implement emulation of D16SLT instruction. */
24423 MIPS_INVAL("OPC_MXU_D16SLT");
24424 generate_exception_end(ctx, EXCP_RI);
24425 break;
24426 case OPC_MXU_D16AVG:
24427 /* TODO: Implement emulation of D16AVG instruction. */
24428 MIPS_INVAL("OPC_MXU_D16AVG");
24429 generate_exception_end(ctx, EXCP_RI);
24430 break;
24431 case OPC_MXU_D16AVGR:
24432 /* TODO: Implement emulation of D16AVGR instruction. */
24433 MIPS_INVAL("OPC_MXU_D16AVGR");
24434 generate_exception_end(ctx, EXCP_RI);
24435 break;
24436 case OPC_MXU_Q8AVG:
24437 /* TODO: Implement emulation of Q8AVG instruction. */
24438 MIPS_INVAL("OPC_MXU_Q8AVG");
24439 generate_exception_end(ctx, EXCP_RI);
24440 break;
24441 case OPC_MXU_Q8AVGR:
24442 /* TODO: Implement emulation of Q8AVGR instruction. */
24443 MIPS_INVAL("OPC_MXU_Q8AVGR");
24444 generate_exception_end(ctx, EXCP_RI);
24445 break;
24446 case OPC_MXU_Q8ADD:
24447 /* TODO: Implement emulation of Q8ADD instruction. */
24448 MIPS_INVAL("OPC_MXU_Q8ADD");
24449 generate_exception_end(ctx, EXCP_RI);
24450 break;
24451 default:
24452 MIPS_INVAL("decode_opc_mxu");
24453 generate_exception_end(ctx, EXCP_RI);
24454 break;
24460 * Decode MXU pool02
24462 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24463 * +-----------+---------+-----+-------+-------+-------+-----------+
24464 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
24465 * +-----------+---------+-----+-------+-------+-------+-----------+
24468 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
24470 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24472 switch (opcode) {
24473 case OPC_MXU_S32CPS:
24474 /* TODO: Implement emulation of S32CPS instruction. */
24475 MIPS_INVAL("OPC_MXU_S32CPS");
24476 generate_exception_end(ctx, EXCP_RI);
24477 break;
24478 case OPC_MXU_D16CPS:
24479 /* TODO: Implement emulation of D16CPS instruction. */
24480 MIPS_INVAL("OPC_MXU_D16CPS");
24481 generate_exception_end(ctx, EXCP_RI);
24482 break;
24483 case OPC_MXU_Q8ABD:
24484 /* TODO: Implement emulation of Q8ABD instruction. */
24485 MIPS_INVAL("OPC_MXU_Q8ABD");
24486 generate_exception_end(ctx, EXCP_RI);
24487 break;
24488 case OPC_MXU_Q16SAT:
24489 /* TODO: Implement emulation of Q16SAT instruction. */
24490 MIPS_INVAL("OPC_MXU_Q16SAT");
24491 generate_exception_end(ctx, EXCP_RI);
24492 break;
24493 default:
24494 MIPS_INVAL("decode_opc_mxu");
24495 generate_exception_end(ctx, EXCP_RI);
24496 break;
24502 * Decode MXU pool03
24504 * D16MULF:
24505 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24506 * +-----------+---+---+-------+-------+-------+-------+-----------+
24507 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
24508 * +-----------+---+---+-------+-------+-------+-------+-----------+
24510 * D16MULE:
24511 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24512 * +-----------+---+---+-------+-------+-------+-------+-----------+
24513 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
24514 * +-----------+---+---+-------+-------+-------+-------+-----------+
24517 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
24519 uint32_t opcode = extract32(ctx->opcode, 24, 2);
24521 switch (opcode) {
24522 case OPC_MXU_D16MULF:
24523 /* TODO: Implement emulation of D16MULF instruction. */
24524 MIPS_INVAL("OPC_MXU_D16MULF");
24525 generate_exception_end(ctx, EXCP_RI);
24526 break;
24527 case OPC_MXU_D16MULE:
24528 /* TODO: Implement emulation of D16MULE instruction. */
24529 MIPS_INVAL("OPC_MXU_D16MULE");
24530 generate_exception_end(ctx, EXCP_RI);
24531 break;
24532 default:
24533 MIPS_INVAL("decode_opc_mxu");
24534 generate_exception_end(ctx, EXCP_RI);
24535 break;
24541 * Decode MXU pool04
24543 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24544 * +-----------+---------+-+-------------------+-------+-----------+
24545 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
24546 * +-----------+---------+-+-------------------+-------+-----------+
24549 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
24551 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24553 switch (opcode) {
24554 case OPC_MXU_S32LDD:
24555 /* TODO: Implement emulation of S32LDD instruction. */
24556 MIPS_INVAL("OPC_MXU_S32LDD");
24557 generate_exception_end(ctx, EXCP_RI);
24558 break;
24559 case OPC_MXU_S32LDDR:
24560 /* TODO: Implement emulation of S32LDDR instruction. */
24561 MIPS_INVAL("OPC_MXU_S32LDDR");
24562 generate_exception_end(ctx, EXCP_RI);
24563 break;
24564 default:
24565 MIPS_INVAL("decode_opc_mxu");
24566 generate_exception_end(ctx, EXCP_RI);
24567 break;
24573 * Decode MXU pool05
24575 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24576 * +-----------+---------+-+-------------------+-------+-----------+
24577 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
24578 * +-----------+---------+-+-------------------+-------+-----------+
24581 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
24583 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24585 switch (opcode) {
24586 case OPC_MXU_S32STD:
24587 /* TODO: Implement emulation of S32STD instruction. */
24588 MIPS_INVAL("OPC_MXU_S32STD");
24589 generate_exception_end(ctx, EXCP_RI);
24590 break;
24591 case OPC_MXU_S32STDR:
24592 /* TODO: Implement emulation of S32STDR instruction. */
24593 MIPS_INVAL("OPC_MXU_S32STDR");
24594 generate_exception_end(ctx, EXCP_RI);
24595 break;
24596 default:
24597 MIPS_INVAL("decode_opc_mxu");
24598 generate_exception_end(ctx, EXCP_RI);
24599 break;
24605 * Decode MXU pool06
24607 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24608 * +-----------+---------+---------+---+-------+-------+-----------+
24609 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
24610 * +-----------+---------+---------+---+-------+-------+-----------+
24613 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
24615 uint32_t opcode = extract32(ctx->opcode, 10, 4);
24617 switch (opcode) {
24618 case OPC_MXU_S32LDDV:
24619 /* TODO: Implement emulation of S32LDDV instruction. */
24620 MIPS_INVAL("OPC_MXU_S32LDDV");
24621 generate_exception_end(ctx, EXCP_RI);
24622 break;
24623 case OPC_MXU_S32LDDVR:
24624 /* TODO: Implement emulation of S32LDDVR instruction. */
24625 MIPS_INVAL("OPC_MXU_S32LDDVR");
24626 generate_exception_end(ctx, EXCP_RI);
24627 break;
24628 default:
24629 MIPS_INVAL("decode_opc_mxu");
24630 generate_exception_end(ctx, EXCP_RI);
24631 break;
24637 * Decode MXU pool07
24639 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24640 * +-----------+---------+---------+---+-------+-------+-----------+
24641 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
24642 * +-----------+---------+---------+---+-------+-------+-----------+
24645 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
24647 uint32_t opcode = extract32(ctx->opcode, 10, 4);
24649 switch (opcode) {
24650 case OPC_MXU_S32STDV:
24651 /* TODO: Implement emulation of S32TDV instruction. */
24652 MIPS_INVAL("OPC_MXU_S32TDV");
24653 generate_exception_end(ctx, EXCP_RI);
24654 break;
24655 case OPC_MXU_S32STDVR:
24656 /* TODO: Implement emulation of S32TDVR instruction. */
24657 MIPS_INVAL("OPC_MXU_S32TDVR");
24658 generate_exception_end(ctx, EXCP_RI);
24659 break;
24660 default:
24661 MIPS_INVAL("decode_opc_mxu");
24662 generate_exception_end(ctx, EXCP_RI);
24663 break;
24669 * Decode MXU pool08
24671 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24672 * +-----------+---------+-+-------------------+-------+-----------+
24673 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
24674 * +-----------+---------+-+-------------------+-------+-----------+
24677 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
24679 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24681 switch (opcode) {
24682 case OPC_MXU_S32LDI:
24683 /* TODO: Implement emulation of S32LDI instruction. */
24684 MIPS_INVAL("OPC_MXU_S32LDI");
24685 generate_exception_end(ctx, EXCP_RI);
24686 break;
24687 case OPC_MXU_S32LDIR:
24688 /* TODO: Implement emulation of S32LDIR instruction. */
24689 MIPS_INVAL("OPC_MXU_S32LDIR");
24690 generate_exception_end(ctx, EXCP_RI);
24691 break;
24692 default:
24693 MIPS_INVAL("decode_opc_mxu");
24694 generate_exception_end(ctx, EXCP_RI);
24695 break;
24701 * Decode MXU pool09
24703 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24704 * +-----------+---------+-+-------------------+-------+-----------+
24705 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
24706 * +-----------+---------+-+-------------------+-------+-----------+
24709 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
24711 uint32_t opcode = extract32(ctx->opcode, 5, 0);
24713 switch (opcode) {
24714 case OPC_MXU_S32SDI:
24715 /* TODO: Implement emulation of S32SDI instruction. */
24716 MIPS_INVAL("OPC_MXU_S32SDI");
24717 generate_exception_end(ctx, EXCP_RI);
24718 break;
24719 case OPC_MXU_S32SDIR:
24720 /* TODO: Implement emulation of S32SDIR instruction. */
24721 MIPS_INVAL("OPC_MXU_S32SDIR");
24722 generate_exception_end(ctx, EXCP_RI);
24723 break;
24724 default:
24725 MIPS_INVAL("decode_opc_mxu");
24726 generate_exception_end(ctx, EXCP_RI);
24727 break;
24733 * Decode MXU pool10
24735 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24736 * +-----------+---------+---------+---+-------+-------+-----------+
24737 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
24738 * +-----------+---------+---------+---+-------+-------+-----------+
24741 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
24743 uint32_t opcode = extract32(ctx->opcode, 5, 0);
24745 switch (opcode) {
24746 case OPC_MXU_S32LDIV:
24747 /* TODO: Implement emulation of S32LDIV instruction. */
24748 MIPS_INVAL("OPC_MXU_S32LDIV");
24749 generate_exception_end(ctx, EXCP_RI);
24750 break;
24751 case OPC_MXU_S32LDIVR:
24752 /* TODO: Implement emulation of S32LDIVR instruction. */
24753 MIPS_INVAL("OPC_MXU_S32LDIVR");
24754 generate_exception_end(ctx, EXCP_RI);
24755 break;
24756 default:
24757 MIPS_INVAL("decode_opc_mxu");
24758 generate_exception_end(ctx, EXCP_RI);
24759 break;
24765 * Decode MXU pool11
24767 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24768 * +-----------+---------+---------+---+-------+-------+-----------+
24769 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
24770 * +-----------+---------+---------+---+-------+-------+-----------+
24773 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
24775 uint32_t opcode = extract32(ctx->opcode, 10, 4);
24777 switch (opcode) {
24778 case OPC_MXU_S32SDIV:
24779 /* TODO: Implement emulation of S32SDIV instruction. */
24780 MIPS_INVAL("OPC_MXU_S32SDIV");
24781 generate_exception_end(ctx, EXCP_RI);
24782 break;
24783 case OPC_MXU_S32SDIVR:
24784 /* TODO: Implement emulation of S32SDIVR instruction. */
24785 MIPS_INVAL("OPC_MXU_S32SDIVR");
24786 generate_exception_end(ctx, EXCP_RI);
24787 break;
24788 default:
24789 MIPS_INVAL("decode_opc_mxu");
24790 generate_exception_end(ctx, EXCP_RI);
24791 break;
24797 * Decode MXU pool12
24799 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24800 * +-----------+---+---+-------+-------+-------+-------+-----------+
24801 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
24802 * +-----------+---+---+-------+-------+-------+-------+-----------+
24805 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
24807 uint32_t opcode = extract32(ctx->opcode, 22, 2);
24809 switch (opcode) {
24810 case OPC_MXU_D32ACC:
24811 /* TODO: Implement emulation of D32ACC instruction. */
24812 MIPS_INVAL("OPC_MXU_D32ACC");
24813 generate_exception_end(ctx, EXCP_RI);
24814 break;
24815 case OPC_MXU_D32ACCM:
24816 /* TODO: Implement emulation of D32ACCM instruction. */
24817 MIPS_INVAL("OPC_MXU_D32ACCM");
24818 generate_exception_end(ctx, EXCP_RI);
24819 break;
24820 case OPC_MXU_D32ASUM:
24821 /* TODO: Implement emulation of D32ASUM instruction. */
24822 MIPS_INVAL("OPC_MXU_D32ASUM");
24823 generate_exception_end(ctx, EXCP_RI);
24824 break;
24825 default:
24826 MIPS_INVAL("decode_opc_mxu");
24827 generate_exception_end(ctx, EXCP_RI);
24828 break;
24834 * Decode MXU pool13
24836 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24837 * +-----------+---+---+-------+-------+-------+-------+-----------+
24838 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
24839 * +-----------+---+---+-------+-------+-------+-------+-----------+
24842 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
24844 uint32_t opcode = extract32(ctx->opcode, 22, 2);
24846 switch (opcode) {
24847 case OPC_MXU_Q16ACC:
24848 /* TODO: Implement emulation of Q16ACC instruction. */
24849 MIPS_INVAL("OPC_MXU_Q16ACC");
24850 generate_exception_end(ctx, EXCP_RI);
24851 break;
24852 case OPC_MXU_Q16ACCM:
24853 /* TODO: Implement emulation of Q16ACCM instruction. */
24854 MIPS_INVAL("OPC_MXU_Q16ACCM");
24855 generate_exception_end(ctx, EXCP_RI);
24856 break;
24857 case OPC_MXU_Q16ASUM:
24858 /* TODO: Implement emulation of Q16ASUM instruction. */
24859 MIPS_INVAL("OPC_MXU_Q16ASUM");
24860 generate_exception_end(ctx, EXCP_RI);
24861 break;
24862 default:
24863 MIPS_INVAL("decode_opc_mxu");
24864 generate_exception_end(ctx, EXCP_RI);
24865 break;
24871 * Decode MXU pool14
24873 * Q8ADDE, Q8ACCE:
24874 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24875 * +-----------+---+---+-------+-------+-------+-------+-----------+
24876 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
24877 * +-----------+---+---+-------+-------+-------+-------+-----------+
24879 * D8SUM, D8SUMC:
24880 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24881 * +-----------+---+---+-------+-------+-------+-------+-----------+
24882 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
24883 * +-----------+---+---+-------+-------+-------+-------+-----------+
24886 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
24888 uint32_t opcode = extract32(ctx->opcode, 22, 2);
24890 switch (opcode) {
24891 case OPC_MXU_Q8ADDE:
24892 /* TODO: Implement emulation of Q8ADDE instruction. */
24893 MIPS_INVAL("OPC_MXU_Q8ADDE");
24894 generate_exception_end(ctx, EXCP_RI);
24895 break;
24896 case OPC_MXU_D8SUM:
24897 /* TODO: Implement emulation of D8SUM instruction. */
24898 MIPS_INVAL("OPC_MXU_D8SUM");
24899 generate_exception_end(ctx, EXCP_RI);
24900 break;
24901 case OPC_MXU_D8SUMC:
24902 /* TODO: Implement emulation of D8SUMC instruction. */
24903 MIPS_INVAL("OPC_MXU_D8SUMC");
24904 generate_exception_end(ctx, EXCP_RI);
24905 break;
24906 default:
24907 MIPS_INVAL("decode_opc_mxu");
24908 generate_exception_end(ctx, EXCP_RI);
24909 break;
24915 * Decode MXU pool15
24917 * S32MUL, S32MULU, S32EXTRV:
24918 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24919 * +-----------+---------+---------+---+-------+-------+-----------+
24920 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
24921 * +-----------+---------+---------+---+-------+-------+-----------+
24923 * S32EXTR:
24924 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24925 * +-----------+---------+---------+---+-------+-------+-----------+
24926 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
24927 * +-----------+---------+---------+---+-------+-------+-----------+
24930 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
24932 uint32_t opcode = extract32(ctx->opcode, 14, 2);
24934 switch (opcode) {
24935 case OPC_MXU_S32MUL:
24936 /* TODO: Implement emulation of S32MUL instruction. */
24937 MIPS_INVAL("OPC_MXU_S32MUL");
24938 generate_exception_end(ctx, EXCP_RI);
24939 break;
24940 case OPC_MXU_S32MULU:
24941 /* TODO: Implement emulation of S32MULU instruction. */
24942 MIPS_INVAL("OPC_MXU_S32MULU");
24943 generate_exception_end(ctx, EXCP_RI);
24944 break;
24945 case OPC_MXU_S32EXTR:
24946 /* TODO: Implement emulation of S32EXTR instruction. */
24947 MIPS_INVAL("OPC_MXU_S32EXTR");
24948 generate_exception_end(ctx, EXCP_RI);
24949 break;
24950 case OPC_MXU_S32EXTRV:
24951 /* TODO: Implement emulation of S32EXTRV instruction. */
24952 MIPS_INVAL("OPC_MXU_S32EXTRV");
24953 generate_exception_end(ctx, EXCP_RI);
24954 break;
24955 default:
24956 MIPS_INVAL("decode_opc_mxu");
24957 generate_exception_end(ctx, EXCP_RI);
24958 break;
24964 * Decode MXU pool16
24966 * D32SARW:
24967 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24968 * +-----------+---------+-----+-------+-------+-------+-----------+
24969 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
24970 * +-----------+---------+-----+-------+-------+-------+-----------+
24972 * S32ALN:
24973 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24974 * +-----------+---------+-----+-------+-------+-------+-----------+
24975 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
24976 * +-----------+---------+-----+-------+-------+-------+-----------+
24978 * S32ALNI:
24979 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24980 * +-----------+-----+---+-----+-------+-------+-------+-----------+
24981 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
24982 * +-----------+-----+---+-----+-------+-------+-------+-----------+
24984 * S32NOR, S32AND, S32OR, S32XOR:
24985 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24986 * +-----------+---------+-----+-------+-------+-------+-----------+
24987 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
24988 * +-----------+---------+-----+-------+-------+-------+-----------+
24990 * S32LUI:
24991 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
24992 * +-----------+-----+---+-----+-------+---------------+-----------+
24993 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
24994 * +-----------+-----+---+-----+-------+---------------+-----------+
24997 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
24999 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25001 switch (opcode) {
25002 case OPC_MXU_D32SARW:
25003 /* TODO: Implement emulation of D32SARW instruction. */
25004 MIPS_INVAL("OPC_MXU_D32SARW");
25005 generate_exception_end(ctx, EXCP_RI);
25006 break;
25007 case OPC_MXU_S32ALN:
25008 /* TODO: Implement emulation of S32ALN instruction. */
25009 MIPS_INVAL("OPC_MXU_S32ALN");
25010 generate_exception_end(ctx, EXCP_RI);
25011 break;
25012 case OPC_MXU_S32ALNI:
25013 /* TODO: Implement emulation of S32ALNI instruction. */
25014 MIPS_INVAL("OPC_MXU_S32ALNI");
25015 generate_exception_end(ctx, EXCP_RI);
25016 break;
25017 case OPC_MXU_S32NOR:
25018 /* TODO: Implement emulation of S32NOR instruction. */
25019 MIPS_INVAL("OPC_MXU_S32NOR");
25020 generate_exception_end(ctx, EXCP_RI);
25021 break;
25022 case OPC_MXU_S32AND:
25023 /* TODO: Implement emulation of S32AND instruction. */
25024 MIPS_INVAL("OPC_MXU_S32AND");
25025 generate_exception_end(ctx, EXCP_RI);
25026 break;
25027 case OPC_MXU_S32OR:
25028 /* TODO: Implement emulation of S32OR instruction. */
25029 MIPS_INVAL("OPC_MXU_S32OR");
25030 generate_exception_end(ctx, EXCP_RI);
25031 break;
25032 case OPC_MXU_S32XOR:
25033 /* TODO: Implement emulation of S32XOR instruction. */
25034 MIPS_INVAL("OPC_MXU_S32XOR");
25035 generate_exception_end(ctx, EXCP_RI);
25036 break;
25037 case OPC_MXU_S32LUI:
25038 /* TODO: Implement emulation of S32LUI instruction. */
25039 MIPS_INVAL("OPC_MXU_S32LUI");
25040 generate_exception_end(ctx, EXCP_RI);
25041 break;
25042 default:
25043 MIPS_INVAL("decode_opc_mxu");
25044 generate_exception_end(ctx, EXCP_RI);
25045 break;
25051 * Decode MXU pool17
25053 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25054 * +-----------+---------+-----+-------+-------+-------+-----------+
25055 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL17|
25056 * +-----------+---------+-----+-------+-------+-------+-----------+
25059 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
25061 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25063 switch (opcode) {
25064 case OPC_MXU_D32SLLV:
25065 /* TODO: Implement emulation of D32SLLV instruction. */
25066 MIPS_INVAL("OPC_MXU_D32SLLV");
25067 generate_exception_end(ctx, EXCP_RI);
25068 break;
25069 case OPC_MXU_D32SLRV:
25070 /* TODO: Implement emulation of D32SLRV instruction. */
25071 MIPS_INVAL("OPC_MXU_D32SLRV");
25072 generate_exception_end(ctx, EXCP_RI);
25073 break;
25074 case OPC_MXU_D32SARV:
25075 /* TODO: Implement emulation of D32SARV instruction. */
25076 MIPS_INVAL("OPC_MXU_D32SARV");
25077 generate_exception_end(ctx, EXCP_RI);
25078 break;
25079 case OPC_MXU_Q16SLLV:
25080 /* TODO: Implement emulation of Q16SLLV instruction. */
25081 MIPS_INVAL("OPC_MXU_Q16SLLV");
25082 generate_exception_end(ctx, EXCP_RI);
25083 break;
25084 case OPC_MXU_Q16SLRV:
25085 /* TODO: Implement emulation of Q16SLRV instruction. */
25086 MIPS_INVAL("OPC_MXU_Q16SLRV");
25087 generate_exception_end(ctx, EXCP_RI);
25088 break;
25089 case OPC_MXU_Q16SARV:
25090 /* TODO: Implement emulation of Q16SARV instruction. */
25091 MIPS_INVAL("OPC_MXU_Q16SARV");
25092 generate_exception_end(ctx, EXCP_RI);
25093 break;
25094 default:
25095 MIPS_INVAL("decode_opc_mxu");
25096 generate_exception_end(ctx, EXCP_RI);
25097 break;
25103 * Decode MXU pool18
25105 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25106 * +-----------+---+---+-------+-------+-------+-------+-----------+
25107 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL18|
25108 * +-----------+---+---+-------+-------+-------+-------+-----------+
25111 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
25113 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25115 switch (opcode) {
25116 case OPC_MXU_Q8MUL:
25117 /* TODO: Implement emulation of Q8MUL instruction. */
25118 MIPS_INVAL("OPC_MXU_Q8MUL");
25119 generate_exception_end(ctx, EXCP_RI);
25120 break;
25121 case OPC_MXU_Q8MULSU:
25122 /* TODO: Implement emulation of Q8MULSU instruction. */
25123 MIPS_INVAL("OPC_MXU_Q8MULSU");
25124 generate_exception_end(ctx, EXCP_RI);
25125 break;
25126 default:
25127 MIPS_INVAL("decode_opc_mxu");
25128 generate_exception_end(ctx, EXCP_RI);
25129 break;
25135 * Decode MXU pool19
25137 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25138 * +-----------+---------+-----+-------+-------+-------+-----------+
25139 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL19|
25140 * +-----------+---------+-----+-------+-------+-------+-----------+
25143 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
25145 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25147 switch (opcode) {
25148 case OPC_MXU_Q8MOVZ:
25149 /* TODO: Implement emulation of Q8MOVZ instruction. */
25150 MIPS_INVAL("OPC_MXU_Q8MOVZ");
25151 generate_exception_end(ctx, EXCP_RI);
25152 break;
25153 case OPC_MXU_Q8MOVN:
25154 /* TODO: Implement emulation of Q8MOVN instruction. */
25155 MIPS_INVAL("OPC_MXU_Q8MOVN");
25156 generate_exception_end(ctx, EXCP_RI);
25157 break;
25158 case OPC_MXU_D16MOVZ:
25159 /* TODO: Implement emulation of D16MOVZ instruction. */
25160 MIPS_INVAL("OPC_MXU_D16MOVZ");
25161 generate_exception_end(ctx, EXCP_RI);
25162 break;
25163 case OPC_MXU_D16MOVN:
25164 /* TODO: Implement emulation of D16MOVN instruction. */
25165 MIPS_INVAL("OPC_MXU_D16MOVN");
25166 generate_exception_end(ctx, EXCP_RI);
25167 break;
25168 case OPC_MXU_S32MOVZ:
25169 /* TODO: Implement emulation of S32MOVZ instruction. */
25170 MIPS_INVAL("OPC_MXU_S32MOVZ");
25171 generate_exception_end(ctx, EXCP_RI);
25172 break;
25173 case OPC_MXU_S32MOVN:
25174 /* TODO: Implement emulation of S32MOVN instruction. */
25175 MIPS_INVAL("OPC_MXU_S32MOVN");
25176 generate_exception_end(ctx, EXCP_RI);
25177 break;
25178 default:
25179 MIPS_INVAL("decode_opc_mxu");
25180 generate_exception_end(ctx, EXCP_RI);
25181 break;
25187 * Decode MXU pool20
25189 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25190 * +-----------+---+---+-------+-------+-------+-------+-----------+
25191 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL20|
25192 * +-----------+---+---+-------+-------+-------+-------+-----------+
25195 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
25197 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25199 switch (opcode) {
25200 case OPC_MXU_Q8MAC:
25201 /* TODO: Implement emulation of Q8MAC instruction. */
25202 MIPS_INVAL("OPC_MXU_Q8MAC");
25203 generate_exception_end(ctx, EXCP_RI);
25204 break;
25205 case OPC_MXU_Q8MACSU:
25206 /* TODO: Implement emulation of Q8MACSU instruction. */
25207 MIPS_INVAL("OPC_MXU_Q8MACSU");
25208 generate_exception_end(ctx, EXCP_RI);
25209 break;
25210 default:
25211 MIPS_INVAL("decode_opc_mxu");
25212 generate_exception_end(ctx, EXCP_RI);
25213 break;
25219 * Main MXU decoding function
25221 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25222 * +-----------+---------------------------------------+-----------+
25223 * | SPECIAL2 | |x x x x x x|
25224 * +-----------+---------------------------------------+-----------+
25227 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
25230 * TODO: Investigate necessity of including handling of
25231 * CLZ, CLO, SDBB in this function, as they belong to
25232 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
25234 uint32_t opcode = extract32(ctx->opcode, 0, 6);
25236 if (opcode == OPC__MXU_MUL) {
25237 uint32_t rs, rt, rd, op1;
25239 rs = extract32(ctx->opcode, 21, 5);
25240 rt = extract32(ctx->opcode, 16, 5);
25241 rd = extract32(ctx->opcode, 11, 5);
25242 op1 = MASK_SPECIAL2(ctx->opcode);
25244 gen_arith(ctx, op1, rd, rs, rt);
25246 return;
25249 if (opcode == OPC_MXU_S32M2I) {
25250 gen_mxu_s32m2i(ctx);
25251 return;
25254 if (opcode == OPC_MXU_S32I2M) {
25255 gen_mxu_s32i2m(ctx);
25256 return;
25259 switch (opcode) {
25260 case OPC_MXU_S32MADD:
25261 /* TODO: Implement emulation of S32MADD instruction. */
25262 MIPS_INVAL("OPC_MXU_S32MADD");
25263 generate_exception_end(ctx, EXCP_RI);
25264 break;
25265 case OPC_MXU_S32MADDU:
25266 /* TODO: Implement emulation of S32MADDU instruction. */
25267 MIPS_INVAL("OPC_MXU_S32MADDU");
25268 generate_exception_end(ctx, EXCP_RI);
25269 break;
25270 case OPC_MXU__POOL00:
25271 decode_opc_mxu__pool00(env, ctx);
25272 break;
25273 case OPC_MXU_S32MSUB:
25274 /* TODO: Implement emulation of S32MSUB instruction. */
25275 MIPS_INVAL("OPC_MXU_S32MSUB");
25276 generate_exception_end(ctx, EXCP_RI);
25277 break;
25278 case OPC_MXU_S32MSUBU:
25279 /* TODO: Implement emulation of S32MSUBU instruction. */
25280 MIPS_INVAL("OPC_MXU_S32MSUBU");
25281 generate_exception_end(ctx, EXCP_RI);
25282 break;
25283 case OPC_MXU__POOL01:
25284 decode_opc_mxu__pool01(env, ctx);
25285 break;
25286 case OPC_MXU__POOL02:
25287 decode_opc_mxu__pool02(env, ctx);
25288 break;
25289 case OPC_MXU_D16MUL:
25290 gen_mxu_d16mul(ctx);
25291 break;
25292 case OPC_MXU__POOL03:
25293 decode_opc_mxu__pool03(env, ctx);
25294 break;
25295 case OPC_MXU_D16MAC:
25296 gen_mxu_d16mac(ctx);
25297 break;
25298 case OPC_MXU_D16MACF:
25299 /* TODO: Implement emulation of D16MACF instruction. */
25300 MIPS_INVAL("OPC_MXU_D16MACF");
25301 generate_exception_end(ctx, EXCP_RI);
25302 break;
25303 case OPC_MXU_D16MADL:
25304 /* TODO: Implement emulation of D16MADL instruction. */
25305 MIPS_INVAL("OPC_MXU_D16MADL");
25306 generate_exception_end(ctx, EXCP_RI);
25307 break;
25308 case OPC_MXU_S16MAD:
25309 /* TODO: Implement emulation of S16MAD instruction. */
25310 MIPS_INVAL("OPC_MXU_S16MAD");
25311 generate_exception_end(ctx, EXCP_RI);
25312 break;
25313 case OPC_MXU_Q16ADD:
25314 /* TODO: Implement emulation of Q16ADD instruction. */
25315 MIPS_INVAL("OPC_MXU_Q16ADD");
25316 generate_exception_end(ctx, EXCP_RI);
25317 break;
25318 case OPC_MXU_D16MACE:
25319 /* TODO: Implement emulation of D16MACE instruction. */
25320 MIPS_INVAL("OPC_MXU_D16MACE");
25321 generate_exception_end(ctx, EXCP_RI);
25322 break;
25323 case OPC_MXU__POOL04:
25324 decode_opc_mxu__pool04(env, ctx);
25325 break;
25326 case OPC_MXU__POOL05:
25327 decode_opc_mxu__pool05(env, ctx);
25328 break;
25329 case OPC_MXU__POOL06:
25330 decode_opc_mxu__pool06(env, ctx);
25331 break;
25332 case OPC_MXU__POOL07:
25333 decode_opc_mxu__pool07(env, ctx);
25334 break;
25335 case OPC_MXU__POOL08:
25336 decode_opc_mxu__pool08(env, ctx);
25337 break;
25338 case OPC_MXU__POOL09:
25339 decode_opc_mxu__pool09(env, ctx);
25340 break;
25341 case OPC_MXU__POOL10:
25342 decode_opc_mxu__pool10(env, ctx);
25343 break;
25344 case OPC_MXU__POOL11:
25345 decode_opc_mxu__pool11(env, ctx);
25346 break;
25347 case OPC_MXU_D32ADD:
25348 /* TODO: Implement emulation of D32ADD instruction. */
25349 MIPS_INVAL("OPC_MXU_D32ADD");
25350 generate_exception_end(ctx, EXCP_RI);
25351 break;
25352 case OPC_MXU__POOL12:
25353 decode_opc_mxu__pool12(env, ctx);
25354 break;
25355 case OPC_MXU__POOL13:
25356 decode_opc_mxu__pool13(env, ctx);
25357 break;
25358 case OPC_MXU__POOL14:
25359 decode_opc_mxu__pool14(env, ctx);
25360 break;
25361 case OPC_MXU_Q8ACCE:
25362 /* TODO: Implement emulation of Q8ACCE instruction. */
25363 MIPS_INVAL("OPC_MXU_Q8ACCE");
25364 generate_exception_end(ctx, EXCP_RI);
25365 break;
25366 case OPC_MXU_S8LDD:
25367 gen_mxu_s8ldd(ctx);
25368 break;
25369 case OPC_MXU_S8STD:
25370 /* TODO: Implement emulation of S8STD instruction. */
25371 MIPS_INVAL("OPC_MXU_S8STD");
25372 generate_exception_end(ctx, EXCP_RI);
25373 break;
25374 case OPC_MXU_S8LDI:
25375 /* TODO: Implement emulation of S8LDI instruction. */
25376 MIPS_INVAL("OPC_MXU_S8LDI");
25377 generate_exception_end(ctx, EXCP_RI);
25378 break;
25379 case OPC_MXU_S8SDI:
25380 /* TODO: Implement emulation of S8SDI instruction. */
25381 MIPS_INVAL("OPC_MXU_S8SDI");
25382 generate_exception_end(ctx, EXCP_RI);
25383 break;
25384 case OPC_MXU__POOL15:
25385 decode_opc_mxu__pool15(env, ctx);
25386 break;
25387 case OPC_MXU__POOL16:
25388 decode_opc_mxu__pool16(env, ctx);
25389 break;
25390 case OPC_MXU_LXB:
25391 /* TODO: Implement emulation of LXB instruction. */
25392 MIPS_INVAL("OPC_MXU_LXB");
25393 generate_exception_end(ctx, EXCP_RI);
25394 break;
25395 case OPC_MXU_S16LDD:
25396 /* TODO: Implement emulation of S16LDD instruction. */
25397 MIPS_INVAL("OPC_MXU_S16LDD");
25398 generate_exception_end(ctx, EXCP_RI);
25399 break;
25400 case OPC_MXU_S16STD:
25401 /* TODO: Implement emulation of S16STD instruction. */
25402 MIPS_INVAL("OPC_MXU_S16STD");
25403 generate_exception_end(ctx, EXCP_RI);
25404 break;
25405 case OPC_MXU_S16LDI:
25406 /* TODO: Implement emulation of S16LDI instruction. */
25407 MIPS_INVAL("OPC_MXU_S16LDI");
25408 generate_exception_end(ctx, EXCP_RI);
25409 break;
25410 case OPC_MXU_S16SDI:
25411 /* TODO: Implement emulation of S16SDI instruction. */
25412 MIPS_INVAL("OPC_MXU_S16SDI");
25413 generate_exception_end(ctx, EXCP_RI);
25414 break;
25415 case OPC_MXU_D32SLL:
25416 /* TODO: Implement emulation of D32SLL instruction. */
25417 MIPS_INVAL("OPC_MXU_D32SLL");
25418 generate_exception_end(ctx, EXCP_RI);
25419 break;
25420 case OPC_MXU_D32SLR:
25421 /* TODO: Implement emulation of D32SLR instruction. */
25422 MIPS_INVAL("OPC_MXU_D32SLR");
25423 generate_exception_end(ctx, EXCP_RI);
25424 break;
25425 case OPC_MXU_D32SARL:
25426 /* TODO: Implement emulation of D32SARL instruction. */
25427 MIPS_INVAL("OPC_MXU_D32SARL");
25428 generate_exception_end(ctx, EXCP_RI);
25429 break;
25430 case OPC_MXU_D32SAR:
25431 /* TODO: Implement emulation of D32SAR instruction. */
25432 MIPS_INVAL("OPC_MXU_D32SAR");
25433 generate_exception_end(ctx, EXCP_RI);
25434 break;
25435 case OPC_MXU_Q16SLL:
25436 /* TODO: Implement emulation of Q16SLL instruction. */
25437 MIPS_INVAL("OPC_MXU_Q16SLL");
25438 generate_exception_end(ctx, EXCP_RI);
25439 break;
25440 case OPC_MXU_Q16SLR:
25441 /* TODO: Implement emulation of Q16SLR instruction. */
25442 MIPS_INVAL("OPC_MXU_Q16SLR");
25443 generate_exception_end(ctx, EXCP_RI);
25444 break;
25445 case OPC_MXU__POOL17:
25446 decode_opc_mxu__pool17(env, ctx);
25447 break;
25448 case OPC_MXU_Q16SAR:
25449 /* TODO: Implement emulation of Q16SAR instruction. */
25450 MIPS_INVAL("OPC_MXU_Q16SAR");
25451 generate_exception_end(ctx, EXCP_RI);
25452 break;
25453 case OPC_MXU__POOL18:
25454 decode_opc_mxu__pool18(env, ctx);
25455 break;
25456 case OPC_MXU__POOL19:
25457 decode_opc_mxu__pool19(env, ctx);
25458 break;
25459 case OPC_MXU__POOL20:
25460 decode_opc_mxu__pool20(env, ctx);
25461 break;
25462 case OPC_MXU_Q16SCOP:
25463 /* TODO: Implement emulation of Q16SCOP instruction. */
25464 MIPS_INVAL("OPC_MXU_Q16SCOP");
25465 generate_exception_end(ctx, EXCP_RI);
25466 break;
25467 case OPC_MXU_Q8MADL:
25468 /* TODO: Implement emulation of Q8MADL instruction. */
25469 MIPS_INVAL("OPC_MXU_Q8MADL");
25470 generate_exception_end(ctx, EXCP_RI);
25471 break;
25472 case OPC_MXU_S32SFL:
25473 /* TODO: Implement emulation of S32SFL instruction. */
25474 MIPS_INVAL("OPC_MXU_S32SFL");
25475 generate_exception_end(ctx, EXCP_RI);
25476 break;
25477 case OPC_MXU_Q8SAD:
25478 /* TODO: Implement emulation of Q8SAD instruction. */
25479 MIPS_INVAL("OPC_MXU_Q8SAD");
25480 generate_exception_end(ctx, EXCP_RI);
25481 break;
25482 default:
25483 MIPS_INVAL("decode_opc_mxu");
25484 generate_exception_end(ctx, EXCP_RI);
25489 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
25491 int rs, rt, rd;
25492 uint32_t op1;
25494 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25496 rs = (ctx->opcode >> 21) & 0x1f;
25497 rt = (ctx->opcode >> 16) & 0x1f;
25498 rd = (ctx->opcode >> 11) & 0x1f;
25500 op1 = MASK_SPECIAL2(ctx->opcode);
25501 switch (op1) {
25502 case OPC_MADD: /* Multiply and add/sub */
25503 case OPC_MADDU:
25504 case OPC_MSUB:
25505 case OPC_MSUBU:
25506 check_insn(ctx, ISA_MIPS32);
25507 gen_muldiv(ctx, op1, rd & 3, rs, rt);
25508 break;
25509 case OPC_MUL:
25510 gen_arith(ctx, op1, rd, rs, rt);
25511 break;
25512 case OPC_DIV_G_2F:
25513 case OPC_DIVU_G_2F:
25514 case OPC_MULT_G_2F:
25515 case OPC_MULTU_G_2F:
25516 case OPC_MOD_G_2F:
25517 case OPC_MODU_G_2F:
25518 check_insn(ctx, INSN_LOONGSON2F);
25519 gen_loongson_integer(ctx, op1, rd, rs, rt);
25520 break;
25521 case OPC_CLO:
25522 case OPC_CLZ:
25523 check_insn(ctx, ISA_MIPS32);
25524 gen_cl(ctx, op1, rd, rs);
25525 break;
25526 case OPC_SDBBP:
25527 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
25528 gen_helper_do_semihosting(cpu_env);
25529 } else {
25530 /* XXX: not clear which exception should be raised
25531 * when in debug mode...
25533 check_insn(ctx, ISA_MIPS32);
25534 generate_exception_end(ctx, EXCP_DBp);
25536 break;
25537 #if defined(TARGET_MIPS64)
25538 case OPC_DCLO:
25539 case OPC_DCLZ:
25540 check_insn(ctx, ISA_MIPS64);
25541 check_mips_64(ctx);
25542 gen_cl(ctx, op1, rd, rs);
25543 break;
25544 case OPC_DMULT_G_2F:
25545 case OPC_DMULTU_G_2F:
25546 case OPC_DDIV_G_2F:
25547 case OPC_DDIVU_G_2F:
25548 case OPC_DMOD_G_2F:
25549 case OPC_DMODU_G_2F:
25550 check_insn(ctx, INSN_LOONGSON2F);
25551 gen_loongson_integer(ctx, op1, rd, rs, rt);
25552 break;
25553 #endif
25554 default: /* Invalid */
25555 MIPS_INVAL("special2_legacy");
25556 generate_exception_end(ctx, EXCP_RI);
25557 break;
25561 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
25563 int rs, rt, rd, sa;
25564 uint32_t op1, op2;
25565 int16_t imm;
25567 rs = (ctx->opcode >> 21) & 0x1f;
25568 rt = (ctx->opcode >> 16) & 0x1f;
25569 rd = (ctx->opcode >> 11) & 0x1f;
25570 sa = (ctx->opcode >> 6) & 0x1f;
25571 imm = (int16_t)ctx->opcode >> 7;
25573 op1 = MASK_SPECIAL3(ctx->opcode);
25574 switch (op1) {
25575 case R6_OPC_PREF:
25576 if (rt >= 24) {
25577 /* hint codes 24-31 are reserved and signal RI */
25578 generate_exception_end(ctx, EXCP_RI);
25580 /* Treat as NOP. */
25581 break;
25582 case R6_OPC_CACHE:
25583 check_cp0_enabled(ctx);
25584 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25585 gen_cache_operation(ctx, rt, rs, imm);
25587 break;
25588 case R6_OPC_SC:
25589 gen_st_cond(ctx, op1, rt, rs, imm);
25590 break;
25591 case R6_OPC_LL:
25592 gen_ld(ctx, op1, rt, rs, imm);
25593 break;
25594 case OPC_BSHFL:
25596 if (rd == 0) {
25597 /* Treat as NOP. */
25598 break;
25600 op2 = MASK_BSHFL(ctx->opcode);
25601 switch (op2) {
25602 case OPC_ALIGN:
25603 case OPC_ALIGN_1:
25604 case OPC_ALIGN_2:
25605 case OPC_ALIGN_3:
25606 gen_align(ctx, 32, rd, rs, rt, sa & 3);
25607 break;
25608 case OPC_BITSWAP:
25609 gen_bitswap(ctx, op2, rd, rt);
25610 break;
25613 break;
25614 #if defined(TARGET_MIPS64)
25615 case R6_OPC_SCD:
25616 gen_st_cond(ctx, op1, rt, rs, imm);
25617 break;
25618 case R6_OPC_LLD:
25619 gen_ld(ctx, op1, rt, rs, imm);
25620 break;
25621 case OPC_DBSHFL:
25622 check_mips_64(ctx);
25624 if (rd == 0) {
25625 /* Treat as NOP. */
25626 break;
25628 op2 = MASK_DBSHFL(ctx->opcode);
25629 switch (op2) {
25630 case OPC_DALIGN:
25631 case OPC_DALIGN_1:
25632 case OPC_DALIGN_2:
25633 case OPC_DALIGN_3:
25634 case OPC_DALIGN_4:
25635 case OPC_DALIGN_5:
25636 case OPC_DALIGN_6:
25637 case OPC_DALIGN_7:
25638 gen_align(ctx, 64, rd, rs, rt, sa & 7);
25639 break;
25640 case OPC_DBITSWAP:
25641 gen_bitswap(ctx, op2, rd, rt);
25642 break;
25646 break;
25647 #endif
25648 default: /* Invalid */
25649 MIPS_INVAL("special3_r6");
25650 generate_exception_end(ctx, EXCP_RI);
25651 break;
25655 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
25657 int rs, rt, rd;
25658 uint32_t op1, op2;
25660 rs = (ctx->opcode >> 21) & 0x1f;
25661 rt = (ctx->opcode >> 16) & 0x1f;
25662 rd = (ctx->opcode >> 11) & 0x1f;
25664 op1 = MASK_SPECIAL3(ctx->opcode);
25665 switch (op1) {
25666 case OPC_DIV_G_2E:
25667 case OPC_DIVU_G_2E:
25668 case OPC_MOD_G_2E:
25669 case OPC_MODU_G_2E:
25670 case OPC_MULT_G_2E:
25671 case OPC_MULTU_G_2E:
25672 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
25673 * the same mask and op1. */
25674 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
25675 op2 = MASK_ADDUH_QB(ctx->opcode);
25676 switch (op2) {
25677 case OPC_ADDUH_QB:
25678 case OPC_ADDUH_R_QB:
25679 case OPC_ADDQH_PH:
25680 case OPC_ADDQH_R_PH:
25681 case OPC_ADDQH_W:
25682 case OPC_ADDQH_R_W:
25683 case OPC_SUBUH_QB:
25684 case OPC_SUBUH_R_QB:
25685 case OPC_SUBQH_PH:
25686 case OPC_SUBQH_R_PH:
25687 case OPC_SUBQH_W:
25688 case OPC_SUBQH_R_W:
25689 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25690 break;
25691 case OPC_MUL_PH:
25692 case OPC_MUL_S_PH:
25693 case OPC_MULQ_S_W:
25694 case OPC_MULQ_RS_W:
25695 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
25696 break;
25697 default:
25698 MIPS_INVAL("MASK ADDUH.QB");
25699 generate_exception_end(ctx, EXCP_RI);
25700 break;
25702 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
25703 gen_loongson_integer(ctx, op1, rd, rs, rt);
25704 } else {
25705 generate_exception_end(ctx, EXCP_RI);
25707 break;
25708 case OPC_LX_DSP:
25709 op2 = MASK_LX(ctx->opcode);
25710 switch (op2) {
25711 #if defined(TARGET_MIPS64)
25712 case OPC_LDX:
25713 #endif
25714 case OPC_LBUX:
25715 case OPC_LHX:
25716 case OPC_LWX:
25717 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
25718 break;
25719 default: /* Invalid */
25720 MIPS_INVAL("MASK LX");
25721 generate_exception_end(ctx, EXCP_RI);
25722 break;
25724 break;
25725 case OPC_ABSQ_S_PH_DSP:
25726 op2 = MASK_ABSQ_S_PH(ctx->opcode);
25727 switch (op2) {
25728 case OPC_ABSQ_S_QB:
25729 case OPC_ABSQ_S_PH:
25730 case OPC_ABSQ_S_W:
25731 case OPC_PRECEQ_W_PHL:
25732 case OPC_PRECEQ_W_PHR:
25733 case OPC_PRECEQU_PH_QBL:
25734 case OPC_PRECEQU_PH_QBR:
25735 case OPC_PRECEQU_PH_QBLA:
25736 case OPC_PRECEQU_PH_QBRA:
25737 case OPC_PRECEU_PH_QBL:
25738 case OPC_PRECEU_PH_QBR:
25739 case OPC_PRECEU_PH_QBLA:
25740 case OPC_PRECEU_PH_QBRA:
25741 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25742 break;
25743 case OPC_BITREV:
25744 case OPC_REPL_QB:
25745 case OPC_REPLV_QB:
25746 case OPC_REPL_PH:
25747 case OPC_REPLV_PH:
25748 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
25749 break;
25750 default:
25751 MIPS_INVAL("MASK ABSQ_S.PH");
25752 generate_exception_end(ctx, EXCP_RI);
25753 break;
25755 break;
25756 case OPC_ADDU_QB_DSP:
25757 op2 = MASK_ADDU_QB(ctx->opcode);
25758 switch (op2) {
25759 case OPC_ADDQ_PH:
25760 case OPC_ADDQ_S_PH:
25761 case OPC_ADDQ_S_W:
25762 case OPC_ADDU_QB:
25763 case OPC_ADDU_S_QB:
25764 case OPC_ADDU_PH:
25765 case OPC_ADDU_S_PH:
25766 case OPC_SUBQ_PH:
25767 case OPC_SUBQ_S_PH:
25768 case OPC_SUBQ_S_W:
25769 case OPC_SUBU_QB:
25770 case OPC_SUBU_S_QB:
25771 case OPC_SUBU_PH:
25772 case OPC_SUBU_S_PH:
25773 case OPC_ADDSC:
25774 case OPC_ADDWC:
25775 case OPC_MODSUB:
25776 case OPC_RADDU_W_QB:
25777 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25778 break;
25779 case OPC_MULEU_S_PH_QBL:
25780 case OPC_MULEU_S_PH_QBR:
25781 case OPC_MULQ_RS_PH:
25782 case OPC_MULEQ_S_W_PHL:
25783 case OPC_MULEQ_S_W_PHR:
25784 case OPC_MULQ_S_PH:
25785 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
25786 break;
25787 default: /* Invalid */
25788 MIPS_INVAL("MASK ADDU.QB");
25789 generate_exception_end(ctx, EXCP_RI);
25790 break;
25793 break;
25794 case OPC_CMPU_EQ_QB_DSP:
25795 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
25796 switch (op2) {
25797 case OPC_PRECR_SRA_PH_W:
25798 case OPC_PRECR_SRA_R_PH_W:
25799 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
25800 break;
25801 case OPC_PRECR_QB_PH:
25802 case OPC_PRECRQ_QB_PH:
25803 case OPC_PRECRQ_PH_W:
25804 case OPC_PRECRQ_RS_PH_W:
25805 case OPC_PRECRQU_S_QB_PH:
25806 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25807 break;
25808 case OPC_CMPU_EQ_QB:
25809 case OPC_CMPU_LT_QB:
25810 case OPC_CMPU_LE_QB:
25811 case OPC_CMP_EQ_PH:
25812 case OPC_CMP_LT_PH:
25813 case OPC_CMP_LE_PH:
25814 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
25815 break;
25816 case OPC_CMPGU_EQ_QB:
25817 case OPC_CMPGU_LT_QB:
25818 case OPC_CMPGU_LE_QB:
25819 case OPC_CMPGDU_EQ_QB:
25820 case OPC_CMPGDU_LT_QB:
25821 case OPC_CMPGDU_LE_QB:
25822 case OPC_PICK_QB:
25823 case OPC_PICK_PH:
25824 case OPC_PACKRL_PH:
25825 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
25826 break;
25827 default: /* Invalid */
25828 MIPS_INVAL("MASK CMPU.EQ.QB");
25829 generate_exception_end(ctx, EXCP_RI);
25830 break;
25832 break;
25833 case OPC_SHLL_QB_DSP:
25834 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
25835 break;
25836 case OPC_DPA_W_PH_DSP:
25837 op2 = MASK_DPA_W_PH(ctx->opcode);
25838 switch (op2) {
25839 case OPC_DPAU_H_QBL:
25840 case OPC_DPAU_H_QBR:
25841 case OPC_DPSU_H_QBL:
25842 case OPC_DPSU_H_QBR:
25843 case OPC_DPA_W_PH:
25844 case OPC_DPAX_W_PH:
25845 case OPC_DPAQ_S_W_PH:
25846 case OPC_DPAQX_S_W_PH:
25847 case OPC_DPAQX_SA_W_PH:
25848 case OPC_DPS_W_PH:
25849 case OPC_DPSX_W_PH:
25850 case OPC_DPSQ_S_W_PH:
25851 case OPC_DPSQX_S_W_PH:
25852 case OPC_DPSQX_SA_W_PH:
25853 case OPC_MULSAQ_S_W_PH:
25854 case OPC_DPAQ_SA_L_W:
25855 case OPC_DPSQ_SA_L_W:
25856 case OPC_MAQ_S_W_PHL:
25857 case OPC_MAQ_S_W_PHR:
25858 case OPC_MAQ_SA_W_PHL:
25859 case OPC_MAQ_SA_W_PHR:
25860 case OPC_MULSA_W_PH:
25861 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
25862 break;
25863 default: /* Invalid */
25864 MIPS_INVAL("MASK DPAW.PH");
25865 generate_exception_end(ctx, EXCP_RI);
25866 break;
25868 break;
25869 case OPC_INSV_DSP:
25870 op2 = MASK_INSV(ctx->opcode);
25871 switch (op2) {
25872 case OPC_INSV:
25873 check_dsp(ctx);
25875 TCGv t0, t1;
25877 if (rt == 0) {
25878 break;
25881 t0 = tcg_temp_new();
25882 t1 = tcg_temp_new();
25884 gen_load_gpr(t0, rt);
25885 gen_load_gpr(t1, rs);
25887 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
25889 tcg_temp_free(t0);
25890 tcg_temp_free(t1);
25891 break;
25893 default: /* Invalid */
25894 MIPS_INVAL("MASK INSV");
25895 generate_exception_end(ctx, EXCP_RI);
25896 break;
25898 break;
25899 case OPC_APPEND_DSP:
25900 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
25901 break;
25902 case OPC_EXTR_W_DSP:
25903 op2 = MASK_EXTR_W(ctx->opcode);
25904 switch (op2) {
25905 case OPC_EXTR_W:
25906 case OPC_EXTR_R_W:
25907 case OPC_EXTR_RS_W:
25908 case OPC_EXTR_S_H:
25909 case OPC_EXTRV_S_H:
25910 case OPC_EXTRV_W:
25911 case OPC_EXTRV_R_W:
25912 case OPC_EXTRV_RS_W:
25913 case OPC_EXTP:
25914 case OPC_EXTPV:
25915 case OPC_EXTPDP:
25916 case OPC_EXTPDPV:
25917 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
25918 break;
25919 case OPC_RDDSP:
25920 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
25921 break;
25922 case OPC_SHILO:
25923 case OPC_SHILOV:
25924 case OPC_MTHLIP:
25925 case OPC_WRDSP:
25926 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
25927 break;
25928 default: /* Invalid */
25929 MIPS_INVAL("MASK EXTR.W");
25930 generate_exception_end(ctx, EXCP_RI);
25931 break;
25933 break;
25934 #if defined(TARGET_MIPS64)
25935 case OPC_DDIV_G_2E:
25936 case OPC_DDIVU_G_2E:
25937 case OPC_DMULT_G_2E:
25938 case OPC_DMULTU_G_2E:
25939 case OPC_DMOD_G_2E:
25940 case OPC_DMODU_G_2E:
25941 check_insn(ctx, INSN_LOONGSON2E);
25942 gen_loongson_integer(ctx, op1, rd, rs, rt);
25943 break;
25944 case OPC_ABSQ_S_QH_DSP:
25945 op2 = MASK_ABSQ_S_QH(ctx->opcode);
25946 switch (op2) {
25947 case OPC_PRECEQ_L_PWL:
25948 case OPC_PRECEQ_L_PWR:
25949 case OPC_PRECEQ_PW_QHL:
25950 case OPC_PRECEQ_PW_QHR:
25951 case OPC_PRECEQ_PW_QHLA:
25952 case OPC_PRECEQ_PW_QHRA:
25953 case OPC_PRECEQU_QH_OBL:
25954 case OPC_PRECEQU_QH_OBR:
25955 case OPC_PRECEQU_QH_OBLA:
25956 case OPC_PRECEQU_QH_OBRA:
25957 case OPC_PRECEU_QH_OBL:
25958 case OPC_PRECEU_QH_OBR:
25959 case OPC_PRECEU_QH_OBLA:
25960 case OPC_PRECEU_QH_OBRA:
25961 case OPC_ABSQ_S_OB:
25962 case OPC_ABSQ_S_PW:
25963 case OPC_ABSQ_S_QH:
25964 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25965 break;
25966 case OPC_REPL_OB:
25967 case OPC_REPL_PW:
25968 case OPC_REPL_QH:
25969 case OPC_REPLV_OB:
25970 case OPC_REPLV_PW:
25971 case OPC_REPLV_QH:
25972 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
25973 break;
25974 default: /* Invalid */
25975 MIPS_INVAL("MASK ABSQ_S.QH");
25976 generate_exception_end(ctx, EXCP_RI);
25977 break;
25979 break;
25980 case OPC_ADDU_OB_DSP:
25981 op2 = MASK_ADDU_OB(ctx->opcode);
25982 switch (op2) {
25983 case OPC_RADDU_L_OB:
25984 case OPC_SUBQ_PW:
25985 case OPC_SUBQ_S_PW:
25986 case OPC_SUBQ_QH:
25987 case OPC_SUBQ_S_QH:
25988 case OPC_SUBU_OB:
25989 case OPC_SUBU_S_OB:
25990 case OPC_SUBU_QH:
25991 case OPC_SUBU_S_QH:
25992 case OPC_SUBUH_OB:
25993 case OPC_SUBUH_R_OB:
25994 case OPC_ADDQ_PW:
25995 case OPC_ADDQ_S_PW:
25996 case OPC_ADDQ_QH:
25997 case OPC_ADDQ_S_QH:
25998 case OPC_ADDU_OB:
25999 case OPC_ADDU_S_OB:
26000 case OPC_ADDU_QH:
26001 case OPC_ADDU_S_QH:
26002 case OPC_ADDUH_OB:
26003 case OPC_ADDUH_R_OB:
26004 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26005 break;
26006 case OPC_MULEQ_S_PW_QHL:
26007 case OPC_MULEQ_S_PW_QHR:
26008 case OPC_MULEU_S_QH_OBL:
26009 case OPC_MULEU_S_QH_OBR:
26010 case OPC_MULQ_RS_QH:
26011 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26012 break;
26013 default: /* Invalid */
26014 MIPS_INVAL("MASK ADDU.OB");
26015 generate_exception_end(ctx, EXCP_RI);
26016 break;
26018 break;
26019 case OPC_CMPU_EQ_OB_DSP:
26020 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
26021 switch (op2) {
26022 case OPC_PRECR_SRA_QH_PW:
26023 case OPC_PRECR_SRA_R_QH_PW:
26024 /* Return value is rt. */
26025 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26026 break;
26027 case OPC_PRECR_OB_QH:
26028 case OPC_PRECRQ_OB_QH:
26029 case OPC_PRECRQ_PW_L:
26030 case OPC_PRECRQ_QH_PW:
26031 case OPC_PRECRQ_RS_QH_PW:
26032 case OPC_PRECRQU_S_OB_QH:
26033 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26034 break;
26035 case OPC_CMPU_EQ_OB:
26036 case OPC_CMPU_LT_OB:
26037 case OPC_CMPU_LE_OB:
26038 case OPC_CMP_EQ_QH:
26039 case OPC_CMP_LT_QH:
26040 case OPC_CMP_LE_QH:
26041 case OPC_CMP_EQ_PW:
26042 case OPC_CMP_LT_PW:
26043 case OPC_CMP_LE_PW:
26044 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26045 break;
26046 case OPC_CMPGDU_EQ_OB:
26047 case OPC_CMPGDU_LT_OB:
26048 case OPC_CMPGDU_LE_OB:
26049 case OPC_CMPGU_EQ_OB:
26050 case OPC_CMPGU_LT_OB:
26051 case OPC_CMPGU_LE_OB:
26052 case OPC_PACKRL_PW:
26053 case OPC_PICK_OB:
26054 case OPC_PICK_PW:
26055 case OPC_PICK_QH:
26056 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26057 break;
26058 default: /* Invalid */
26059 MIPS_INVAL("MASK CMPU_EQ.OB");
26060 generate_exception_end(ctx, EXCP_RI);
26061 break;
26063 break;
26064 case OPC_DAPPEND_DSP:
26065 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
26066 break;
26067 case OPC_DEXTR_W_DSP:
26068 op2 = MASK_DEXTR_W(ctx->opcode);
26069 switch (op2) {
26070 case OPC_DEXTP:
26071 case OPC_DEXTPDP:
26072 case OPC_DEXTPDPV:
26073 case OPC_DEXTPV:
26074 case OPC_DEXTR_L:
26075 case OPC_DEXTR_R_L:
26076 case OPC_DEXTR_RS_L:
26077 case OPC_DEXTR_W:
26078 case OPC_DEXTR_R_W:
26079 case OPC_DEXTR_RS_W:
26080 case OPC_DEXTR_S_H:
26081 case OPC_DEXTRV_L:
26082 case OPC_DEXTRV_R_L:
26083 case OPC_DEXTRV_RS_L:
26084 case OPC_DEXTRV_S_H:
26085 case OPC_DEXTRV_W:
26086 case OPC_DEXTRV_R_W:
26087 case OPC_DEXTRV_RS_W:
26088 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
26089 break;
26090 case OPC_DMTHLIP:
26091 case OPC_DSHILO:
26092 case OPC_DSHILOV:
26093 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
26094 break;
26095 default: /* Invalid */
26096 MIPS_INVAL("MASK EXTR.W");
26097 generate_exception_end(ctx, EXCP_RI);
26098 break;
26100 break;
26101 case OPC_DPAQ_W_QH_DSP:
26102 op2 = MASK_DPAQ_W_QH(ctx->opcode);
26103 switch (op2) {
26104 case OPC_DPAU_H_OBL:
26105 case OPC_DPAU_H_OBR:
26106 case OPC_DPSU_H_OBL:
26107 case OPC_DPSU_H_OBR:
26108 case OPC_DPA_W_QH:
26109 case OPC_DPAQ_S_W_QH:
26110 case OPC_DPS_W_QH:
26111 case OPC_DPSQ_S_W_QH:
26112 case OPC_MULSAQ_S_W_QH:
26113 case OPC_DPAQ_SA_L_PW:
26114 case OPC_DPSQ_SA_L_PW:
26115 case OPC_MULSAQ_S_L_PW:
26116 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26117 break;
26118 case OPC_MAQ_S_W_QHLL:
26119 case OPC_MAQ_S_W_QHLR:
26120 case OPC_MAQ_S_W_QHRL:
26121 case OPC_MAQ_S_W_QHRR:
26122 case OPC_MAQ_SA_W_QHLL:
26123 case OPC_MAQ_SA_W_QHLR:
26124 case OPC_MAQ_SA_W_QHRL:
26125 case OPC_MAQ_SA_W_QHRR:
26126 case OPC_MAQ_S_L_PWL:
26127 case OPC_MAQ_S_L_PWR:
26128 case OPC_DMADD:
26129 case OPC_DMADDU:
26130 case OPC_DMSUB:
26131 case OPC_DMSUBU:
26132 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26133 break;
26134 default: /* Invalid */
26135 MIPS_INVAL("MASK DPAQ.W.QH");
26136 generate_exception_end(ctx, EXCP_RI);
26137 break;
26139 break;
26140 case OPC_DINSV_DSP:
26141 op2 = MASK_INSV(ctx->opcode);
26142 switch (op2) {
26143 case OPC_DINSV:
26145 TCGv t0, t1;
26147 if (rt == 0) {
26148 break;
26150 check_dsp(ctx);
26152 t0 = tcg_temp_new();
26153 t1 = tcg_temp_new();
26155 gen_load_gpr(t0, rt);
26156 gen_load_gpr(t1, rs);
26158 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
26160 tcg_temp_free(t0);
26161 tcg_temp_free(t1);
26162 break;
26164 default: /* Invalid */
26165 MIPS_INVAL("MASK DINSV");
26166 generate_exception_end(ctx, EXCP_RI);
26167 break;
26169 break;
26170 case OPC_SHLL_OB_DSP:
26171 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26172 break;
26173 #endif
26174 default: /* Invalid */
26175 MIPS_INVAL("special3_legacy");
26176 generate_exception_end(ctx, EXCP_RI);
26177 break;
26181 static void decode_tx79_mmi0(CPUMIPSState *env, DisasContext *ctx)
26183 uint32_t opc = MASK_TX79_MMI0(ctx->opcode);
26185 switch (opc) {
26186 case TX79_MMI0_PADDW: /* TODO: TX79_MMI0_PADDW */
26187 case TX79_MMI0_PSUBW: /* TODO: TX79_MMI0_PSUBW */
26188 case TX79_MMI0_PCGTW: /* TODO: TX79_MMI0_PCGTW */
26189 case TX79_MMI0_PMAXW: /* TODO: TX79_MMI0_PMAXW */
26190 case TX79_MMI0_PADDH: /* TODO: TX79_MMI0_PADDH */
26191 case TX79_MMI0_PSUBH: /* TODO: TX79_MMI0_PSUBH */
26192 case TX79_MMI0_PCGTH: /* TODO: TX79_MMI0_PCGTH */
26193 case TX79_MMI0_PMAXH: /* TODO: TX79_MMI0_PMAXH */
26194 case TX79_MMI0_PADDB: /* TODO: TX79_MMI0_PADDB */
26195 case TX79_MMI0_PSUBB: /* TODO: TX79_MMI0_PSUBB */
26196 case TX79_MMI0_PCGTB: /* TODO: TX79_MMI0_PCGTB */
26197 case TX79_MMI0_PADDSW: /* TODO: TX79_MMI0_PADDSW */
26198 case TX79_MMI0_PSUBSW: /* TODO: TX79_MMI0_PSUBSW */
26199 case TX79_MMI0_PEXTLW: /* TODO: TX79_MMI0_PEXTLW */
26200 case TX79_MMI0_PPACW: /* TODO: TX79_MMI0_PPACW */
26201 case TX79_MMI0_PADDSH: /* TODO: TX79_MMI0_PADDSH */
26202 case TX79_MMI0_PSUBSH: /* TODO: TX79_MMI0_PSUBSH */
26203 case TX79_MMI0_PEXTLH: /* TODO: TX79_MMI0_PEXTLH */
26204 case TX79_MMI0_PPACH: /* TODO: TX79_MMI0_PPACH */
26205 case TX79_MMI0_PADDSB: /* TODO: TX79_MMI0_PADDSB */
26206 case TX79_MMI0_PSUBSB: /* TODO: TX79_MMI0_PSUBSB */
26207 case TX79_MMI0_PEXTLB: /* TODO: TX79_MMI0_PEXTLB */
26208 case TX79_MMI0_PPACB: /* TODO: TX79_MMI0_PPACB */
26209 case TX79_MMI0_PEXT5: /* TODO: TX79_MMI0_PEXT5 */
26210 case TX79_MMI0_PPAC5: /* TODO: TX79_MMI0_PPAC5 */
26211 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI0 */
26212 break;
26213 default:
26214 MIPS_INVAL("TX79 MMI class MMI0");
26215 generate_exception_end(ctx, EXCP_RI);
26216 break;
26220 static void decode_tx79_mmi1(CPUMIPSState *env, DisasContext *ctx)
26222 uint32_t opc = MASK_TX79_MMI1(ctx->opcode);
26224 switch (opc) {
26225 case TX79_MMI1_PABSW: /* TODO: TX79_MMI1_PABSW */
26226 case TX79_MMI1_PCEQW: /* TODO: TX79_MMI1_PCEQW */
26227 case TX79_MMI1_PMINW: /* TODO: TX79_MMI1_PMINW */
26228 case TX79_MMI1_PADSBH: /* TODO: TX79_MMI1_PADSBH */
26229 case TX79_MMI1_PABSH: /* TODO: TX79_MMI1_PABSH */
26230 case TX79_MMI1_PCEQH: /* TODO: TX79_MMI1_PCEQH */
26231 case TX79_MMI1_PMINH: /* TODO: TX79_MMI1_PMINH */
26232 case TX79_MMI1_PCEQB: /* TODO: TX79_MMI1_PCEQB */
26233 case TX79_MMI1_PADDUW: /* TODO: TX79_MMI1_PADDUW */
26234 case TX79_MMI1_PSUBUW: /* TODO: TX79_MMI1_PSUBUW */
26235 case TX79_MMI1_PEXTUW: /* TODO: TX79_MMI1_PEXTUW */
26236 case TX79_MMI1_PADDUH: /* TODO: TX79_MMI1_PADDUH */
26237 case TX79_MMI1_PSUBUH: /* TODO: TX79_MMI1_PSUBUH */
26238 case TX79_MMI1_PEXTUH: /* TODO: TX79_MMI1_PEXTUH */
26239 case TX79_MMI1_PADDUB: /* TODO: TX79_MMI1_PADDUB */
26240 case TX79_MMI1_PSUBUB: /* TODO: TX79_MMI1_PSUBUB */
26241 case TX79_MMI1_PEXTUB: /* TODO: TX79_MMI1_PEXTUB */
26242 case TX79_MMI1_QFSRV: /* TODO: TX79_MMI1_QFSRV */
26243 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI1 */
26244 break;
26245 default:
26246 MIPS_INVAL("TX79 MMI class MMI1");
26247 generate_exception_end(ctx, EXCP_RI);
26248 break;
26252 static void decode_tx79_mmi2(CPUMIPSState *env, DisasContext *ctx)
26254 uint32_t opc = MASK_TX79_MMI2(ctx->opcode);
26256 switch (opc) {
26257 case TX79_MMI2_PMADDW: /* TODO: TX79_MMI2_PMADDW */
26258 case TX79_MMI2_PSLLVW: /* TODO: TX79_MMI2_PSLLVW */
26259 case TX79_MMI2_PSRLVW: /* TODO: TX79_MMI2_PSRLVW */
26260 case TX79_MMI2_PMSUBW: /* TODO: TX79_MMI2_PMSUBW */
26261 case TX79_MMI2_PMFHI: /* TODO: TX79_MMI2_PMFHI */
26262 case TX79_MMI2_PMFLO: /* TODO: TX79_MMI2_PMFLO */
26263 case TX79_MMI2_PINTH: /* TODO: TX79_MMI2_PINTH */
26264 case TX79_MMI2_PMULTW: /* TODO: TX79_MMI2_PMULTW */
26265 case TX79_MMI2_PDIVW: /* TODO: TX79_MMI2_PDIVW */
26266 case TX79_MMI2_PCPYLD: /* TODO: TX79_MMI2_PCPYLD */
26267 case TX79_MMI2_PMADDH: /* TODO: TX79_MMI2_PMADDH */
26268 case TX79_MMI2_PHMADH: /* TODO: TX79_MMI2_PHMADH */
26269 case TX79_MMI2_PAND: /* TODO: TX79_MMI2_PAND */
26270 case TX79_MMI2_PXOR: /* TODO: TX79_MMI2_PXOR */
26271 case TX79_MMI2_PMSUBH: /* TODO: TX79_MMI2_PMSUBH */
26272 case TX79_MMI2_PHMSBH: /* TODO: TX79_MMI2_PHMSBH */
26273 case TX79_MMI2_PEXEH: /* TODO: TX79_MMI2_PEXEH */
26274 case TX79_MMI2_PREVH: /* TODO: TX79_MMI2_PREVH */
26275 case TX79_MMI2_PMULTH: /* TODO: TX79_MMI2_PMULTH */
26276 case TX79_MMI2_PDIVBW: /* TODO: TX79_MMI2_PDIVBW */
26277 case TX79_MMI2_PEXEW: /* TODO: TX79_MMI2_PEXEW */
26278 case TX79_MMI2_PROT3W: /* TODO: TX79_MMI2_PROT3W */
26279 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI2 */
26280 break;
26281 default:
26282 MIPS_INVAL("TX79 MMI class MMI2");
26283 generate_exception_end(ctx, EXCP_RI);
26284 break;
26288 static void decode_tx79_mmi3(CPUMIPSState *env, DisasContext *ctx)
26290 uint32_t opc = MASK_TX79_MMI3(ctx->opcode);
26292 switch (opc) {
26293 case TX79_MMI3_PMADDUW: /* TODO: TX79_MMI3_PMADDUW */
26294 case TX79_MMI3_PSRAVW: /* TODO: TX79_MMI3_PSRAVW */
26295 case TX79_MMI3_PMTHI: /* TODO: TX79_MMI3_PMTHI */
26296 case TX79_MMI3_PMTLO: /* TODO: TX79_MMI3_PMTLO */
26297 case TX79_MMI3_PINTEH: /* TODO: TX79_MMI3_PINTEH */
26298 case TX79_MMI3_PMULTUW: /* TODO: TX79_MMI3_PMULTUW */
26299 case TX79_MMI3_PDIVUW: /* TODO: TX79_MMI3_PDIVUW */
26300 case TX79_MMI3_PCPYUD: /* TODO: TX79_MMI3_PCPYUD */
26301 case TX79_MMI3_POR: /* TODO: TX79_MMI3_POR */
26302 case TX79_MMI3_PNOR: /* TODO: TX79_MMI3_PNOR */
26303 case TX79_MMI3_PEXCH: /* TODO: TX79_MMI3_PEXCH */
26304 case TX79_MMI3_PCPYH: /* TODO: TX79_MMI3_PCPYH */
26305 case TX79_MMI3_PEXCW: /* TODO: TX79_MMI3_PEXCW */
26306 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI3 */
26307 break;
26308 default:
26309 MIPS_INVAL("TX79 MMI class MMI3");
26310 generate_exception_end(ctx, EXCP_RI);
26311 break;
26315 static void decode_tx79_mmi(CPUMIPSState *env, DisasContext *ctx)
26317 uint32_t opc = MASK_TX79_MMI(ctx->opcode);
26318 int rs = extract32(ctx->opcode, 21, 5);
26319 int rt = extract32(ctx->opcode, 16, 5);
26320 int rd = extract32(ctx->opcode, 11, 5);
26322 switch (opc) {
26323 case TX79_MMI_CLASS_MMI0:
26324 decode_tx79_mmi0(env, ctx);
26325 break;
26326 case TX79_MMI_CLASS_MMI1:
26327 decode_tx79_mmi1(env, ctx);
26328 break;
26329 case TX79_MMI_CLASS_MMI2:
26330 decode_tx79_mmi2(env, ctx);
26331 break;
26332 case TX79_MMI_CLASS_MMI3:
26333 decode_tx79_mmi3(env, ctx);
26334 break;
26335 case TX79_MMI_MULT1:
26336 case TX79_MMI_MULTU1:
26337 gen_mul_txx9(ctx, opc, rd, rs, rt);
26338 break;
26339 case TX79_MMI_DIV1:
26340 case TX79_MMI_DIVU1:
26341 gen_muldiv(ctx, opc, 1, rs, rt);
26342 break;
26343 case TX79_MMI_MTLO1:
26344 case TX79_MMI_MTHI1:
26345 gen_HILO(ctx, opc, 1, rs);
26346 break;
26347 case TX79_MMI_MFLO1:
26348 case TX79_MMI_MFHI1:
26349 gen_HILO(ctx, opc, 1, rd);
26350 break;
26351 case TX79_MMI_MADD: /* TODO: TX79_MMI_MADD */
26352 case TX79_MMI_MADDU: /* TODO: TX79_MMI_MADDU */
26353 case TX79_MMI_PLZCW: /* TODO: TX79_MMI_PLZCW */
26354 case TX79_MMI_MADD1: /* TODO: TX79_MMI_MADD1 */
26355 case TX79_MMI_MADDU1: /* TODO: TX79_MMI_MADDU1 */
26356 case TX79_MMI_PMFHL: /* TODO: TX79_MMI_PMFHL */
26357 case TX79_MMI_PMTHL: /* TODO: TX79_MMI_PMTHL */
26358 case TX79_MMI_PSLLH: /* TODO: TX79_MMI_PSLLH */
26359 case TX79_MMI_PSRLH: /* TODO: TX79_MMI_PSRLH */
26360 case TX79_MMI_PSRAH: /* TODO: TX79_MMI_PSRAH */
26361 case TX79_MMI_PSLLW: /* TODO: TX79_MMI_PSLLW */
26362 case TX79_MMI_PSRLW: /* TODO: TX79_MMI_PSRLW */
26363 case TX79_MMI_PSRAW: /* TODO: TX79_MMI_PSRAW */
26364 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_CLASS_MMI */
26365 break;
26366 default:
26367 MIPS_INVAL("TX79 MMI class");
26368 generate_exception_end(ctx, EXCP_RI);
26369 break;
26373 static void decode_tx79_lq(CPUMIPSState *env, DisasContext *ctx)
26375 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_LQ */
26378 static void gen_tx79_sq(DisasContext *ctx, int base, int rt, int offset)
26380 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_SQ */
26384 * The TX79-specific instruction Store Quadword
26386 * +--------+-------+-------+------------------------+
26387 * | 011111 | base | rt | offset | SQ
26388 * +--------+-------+-------+------------------------+
26389 * 6 5 5 16
26391 * has the same opcode as the Read Hardware Register instruction
26393 * +--------+-------+-------+-------+-------+--------+
26394 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
26395 * +--------+-------+-------+-------+-------+--------+
26396 * 6 5 5 5 5 6
26398 * that is required, trapped and emulated by the Linux kernel. However, all
26399 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
26400 * offset is odd. Therefore all valid SQ instructions can execute normally.
26401 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
26402 * between SQ and RDHWR, as the Linux kernel does.
26404 static void decode_tx79_sq(CPUMIPSState *env, DisasContext *ctx)
26406 int base = extract32(ctx->opcode, 21, 5);
26407 int rt = extract32(ctx->opcode, 16, 5);
26408 int offset = extract32(ctx->opcode, 0, 16);
26410 #ifdef CONFIG_USER_ONLY
26411 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
26412 uint32_t op2 = extract32(ctx->opcode, 6, 5);
26414 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
26415 int rd = extract32(ctx->opcode, 11, 5);
26417 gen_rdhwr(ctx, rt, rd, 0);
26418 return;
26420 #endif
26422 gen_tx79_sq(ctx, base, rt, offset);
26425 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
26427 int rs, rt, rd, sa;
26428 uint32_t op1, op2;
26429 int16_t imm;
26431 rs = (ctx->opcode >> 21) & 0x1f;
26432 rt = (ctx->opcode >> 16) & 0x1f;
26433 rd = (ctx->opcode >> 11) & 0x1f;
26434 sa = (ctx->opcode >> 6) & 0x1f;
26435 imm = sextract32(ctx->opcode, 7, 9);
26437 op1 = MASK_SPECIAL3(ctx->opcode);
26440 * EVA loads and stores overlap Loongson 2E instructions decoded by
26441 * decode_opc_special3_legacy(), so be careful to allow their decoding when
26442 * EVA is absent.
26444 if (ctx->eva) {
26445 switch (op1) {
26446 case OPC_LWLE:
26447 case OPC_LWRE:
26448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26449 /* fall through */
26450 case OPC_LBUE:
26451 case OPC_LHUE:
26452 case OPC_LBE:
26453 case OPC_LHE:
26454 case OPC_LLE:
26455 case OPC_LWE:
26456 check_cp0_enabled(ctx);
26457 gen_ld(ctx, op1, rt, rs, imm);
26458 return;
26459 case OPC_SWLE:
26460 case OPC_SWRE:
26461 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26462 /* fall through */
26463 case OPC_SBE:
26464 case OPC_SHE:
26465 case OPC_SWE:
26466 check_cp0_enabled(ctx);
26467 gen_st(ctx, op1, rt, rs, imm);
26468 return;
26469 case OPC_SCE:
26470 check_cp0_enabled(ctx);
26471 gen_st_cond(ctx, op1, rt, rs, imm);
26472 return;
26473 case OPC_CACHEE:
26474 check_cp0_enabled(ctx);
26475 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26476 gen_cache_operation(ctx, rt, rs, imm);
26478 /* Treat as NOP. */
26479 return;
26480 case OPC_PREFE:
26481 check_cp0_enabled(ctx);
26482 /* Treat as NOP. */
26483 return;
26487 switch (op1) {
26488 case OPC_EXT:
26489 case OPC_INS:
26490 check_insn(ctx, ISA_MIPS32R2);
26491 gen_bitops(ctx, op1, rt, rs, sa, rd);
26492 break;
26493 case OPC_BSHFL:
26494 op2 = MASK_BSHFL(ctx->opcode);
26495 switch (op2) {
26496 case OPC_ALIGN:
26497 case OPC_ALIGN_1:
26498 case OPC_ALIGN_2:
26499 case OPC_ALIGN_3:
26500 case OPC_BITSWAP:
26501 check_insn(ctx, ISA_MIPS32R6);
26502 decode_opc_special3_r6(env, ctx);
26503 break;
26504 default:
26505 check_insn(ctx, ISA_MIPS32R2);
26506 gen_bshfl(ctx, op2, rt, rd);
26507 break;
26509 break;
26510 #if defined(TARGET_MIPS64)
26511 case OPC_DEXTM:
26512 case OPC_DEXTU:
26513 case OPC_DEXT:
26514 case OPC_DINSM:
26515 case OPC_DINSU:
26516 case OPC_DINS:
26517 check_insn(ctx, ISA_MIPS64R2);
26518 check_mips_64(ctx);
26519 gen_bitops(ctx, op1, rt, rs, sa, rd);
26520 break;
26521 case OPC_DBSHFL:
26522 op2 = MASK_DBSHFL(ctx->opcode);
26523 switch (op2) {
26524 case OPC_DALIGN:
26525 case OPC_DALIGN_1:
26526 case OPC_DALIGN_2:
26527 case OPC_DALIGN_3:
26528 case OPC_DALIGN_4:
26529 case OPC_DALIGN_5:
26530 case OPC_DALIGN_6:
26531 case OPC_DALIGN_7:
26532 case OPC_DBITSWAP:
26533 check_insn(ctx, ISA_MIPS32R6);
26534 decode_opc_special3_r6(env, ctx);
26535 break;
26536 default:
26537 check_insn(ctx, ISA_MIPS64R2);
26538 check_mips_64(ctx);
26539 op2 = MASK_DBSHFL(ctx->opcode);
26540 gen_bshfl(ctx, op2, rt, rd);
26541 break;
26543 break;
26544 #endif
26545 case OPC_RDHWR:
26546 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
26547 break;
26548 case OPC_FORK:
26549 check_mt(ctx);
26551 TCGv t0 = tcg_temp_new();
26552 TCGv t1 = tcg_temp_new();
26554 gen_load_gpr(t0, rt);
26555 gen_load_gpr(t1, rs);
26556 gen_helper_fork(t0, t1);
26557 tcg_temp_free(t0);
26558 tcg_temp_free(t1);
26560 break;
26561 case OPC_YIELD:
26562 check_mt(ctx);
26564 TCGv t0 = tcg_temp_new();
26566 gen_load_gpr(t0, rs);
26567 gen_helper_yield(t0, cpu_env, t0);
26568 gen_store_gpr(t0, rd);
26569 tcg_temp_free(t0);
26571 break;
26572 default:
26573 if (ctx->insn_flags & ISA_MIPS32R6) {
26574 decode_opc_special3_r6(env, ctx);
26575 } else {
26576 decode_opc_special3_legacy(env, ctx);
26581 /* MIPS SIMD Architecture (MSA) */
26582 static inline int check_msa_access(DisasContext *ctx)
26584 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
26585 !(ctx->hflags & MIPS_HFLAG_F64))) {
26586 generate_exception_end(ctx, EXCP_RI);
26587 return 0;
26590 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
26591 if (ctx->insn_flags & ASE_MSA) {
26592 generate_exception_end(ctx, EXCP_MSADIS);
26593 return 0;
26594 } else {
26595 generate_exception_end(ctx, EXCP_RI);
26596 return 0;
26599 return 1;
26602 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
26604 /* generates tcg ops to check if any element is 0 */
26605 /* Note this function only works with MSA_WRLEN = 128 */
26606 uint64_t eval_zero_or_big = 0;
26607 uint64_t eval_big = 0;
26608 TCGv_i64 t0 = tcg_temp_new_i64();
26609 TCGv_i64 t1 = tcg_temp_new_i64();
26610 switch (df) {
26611 case DF_BYTE:
26612 eval_zero_or_big = 0x0101010101010101ULL;
26613 eval_big = 0x8080808080808080ULL;
26614 break;
26615 case DF_HALF:
26616 eval_zero_or_big = 0x0001000100010001ULL;
26617 eval_big = 0x8000800080008000ULL;
26618 break;
26619 case DF_WORD:
26620 eval_zero_or_big = 0x0000000100000001ULL;
26621 eval_big = 0x8000000080000000ULL;
26622 break;
26623 case DF_DOUBLE:
26624 eval_zero_or_big = 0x0000000000000001ULL;
26625 eval_big = 0x8000000000000000ULL;
26626 break;
26628 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
26629 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
26630 tcg_gen_andi_i64(t0, t0, eval_big);
26631 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
26632 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
26633 tcg_gen_andi_i64(t1, t1, eval_big);
26634 tcg_gen_or_i64(t0, t0, t1);
26635 /* if all bits are zero then all elements are not zero */
26636 /* if some bit is non-zero then some element is zero */
26637 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
26638 tcg_gen_trunc_i64_tl(tresult, t0);
26639 tcg_temp_free_i64(t0);
26640 tcg_temp_free_i64(t1);
26643 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
26645 uint8_t df = (ctx->opcode >> 21) & 0x3;
26646 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
26647 int64_t s16 = (int16_t)ctx->opcode;
26649 check_msa_access(ctx);
26651 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26652 generate_exception_end(ctx, EXCP_RI);
26653 return;
26655 switch (op1) {
26656 case OPC_BZ_V:
26657 case OPC_BNZ_V:
26659 TCGv_i64 t0 = tcg_temp_new_i64();
26660 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
26661 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
26662 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
26663 tcg_gen_trunc_i64_tl(bcond, t0);
26664 tcg_temp_free_i64(t0);
26666 break;
26667 case OPC_BZ_B:
26668 case OPC_BZ_H:
26669 case OPC_BZ_W:
26670 case OPC_BZ_D:
26671 gen_check_zero_element(bcond, df, wt);
26672 break;
26673 case OPC_BNZ_B:
26674 case OPC_BNZ_H:
26675 case OPC_BNZ_W:
26676 case OPC_BNZ_D:
26677 gen_check_zero_element(bcond, df, wt);
26678 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
26679 break;
26682 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
26684 ctx->hflags |= MIPS_HFLAG_BC;
26685 ctx->hflags |= MIPS_HFLAG_BDS32;
26688 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
26690 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
26691 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
26692 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26693 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26695 TCGv_i32 twd = tcg_const_i32(wd);
26696 TCGv_i32 tws = tcg_const_i32(ws);
26697 TCGv_i32 ti8 = tcg_const_i32(i8);
26699 switch (MASK_MSA_I8(ctx->opcode)) {
26700 case OPC_ANDI_B:
26701 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
26702 break;
26703 case OPC_ORI_B:
26704 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
26705 break;
26706 case OPC_NORI_B:
26707 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
26708 break;
26709 case OPC_XORI_B:
26710 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
26711 break;
26712 case OPC_BMNZI_B:
26713 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
26714 break;
26715 case OPC_BMZI_B:
26716 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
26717 break;
26718 case OPC_BSELI_B:
26719 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
26720 break;
26721 case OPC_SHF_B:
26722 case OPC_SHF_H:
26723 case OPC_SHF_W:
26725 uint8_t df = (ctx->opcode >> 24) & 0x3;
26726 if (df == DF_DOUBLE) {
26727 generate_exception_end(ctx, EXCP_RI);
26728 } else {
26729 TCGv_i32 tdf = tcg_const_i32(df);
26730 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
26731 tcg_temp_free_i32(tdf);
26734 break;
26735 default:
26736 MIPS_INVAL("MSA instruction");
26737 generate_exception_end(ctx, EXCP_RI);
26738 break;
26741 tcg_temp_free_i32(twd);
26742 tcg_temp_free_i32(tws);
26743 tcg_temp_free_i32(ti8);
26746 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
26748 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
26749 uint8_t df = (ctx->opcode >> 21) & 0x3;
26750 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
26751 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
26752 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26753 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26755 TCGv_i32 tdf = tcg_const_i32(df);
26756 TCGv_i32 twd = tcg_const_i32(wd);
26757 TCGv_i32 tws = tcg_const_i32(ws);
26758 TCGv_i32 timm = tcg_temp_new_i32();
26759 tcg_gen_movi_i32(timm, u5);
26761 switch (MASK_MSA_I5(ctx->opcode)) {
26762 case OPC_ADDVI_df:
26763 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
26764 break;
26765 case OPC_SUBVI_df:
26766 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
26767 break;
26768 case OPC_MAXI_S_df:
26769 tcg_gen_movi_i32(timm, s5);
26770 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
26771 break;
26772 case OPC_MAXI_U_df:
26773 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
26774 break;
26775 case OPC_MINI_S_df:
26776 tcg_gen_movi_i32(timm, s5);
26777 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
26778 break;
26779 case OPC_MINI_U_df:
26780 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
26781 break;
26782 case OPC_CEQI_df:
26783 tcg_gen_movi_i32(timm, s5);
26784 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
26785 break;
26786 case OPC_CLTI_S_df:
26787 tcg_gen_movi_i32(timm, s5);
26788 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
26789 break;
26790 case OPC_CLTI_U_df:
26791 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
26792 break;
26793 case OPC_CLEI_S_df:
26794 tcg_gen_movi_i32(timm, s5);
26795 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
26796 break;
26797 case OPC_CLEI_U_df:
26798 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
26799 break;
26800 case OPC_LDI_df:
26802 int32_t s10 = sextract32(ctx->opcode, 11, 10);
26803 tcg_gen_movi_i32(timm, s10);
26804 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
26806 break;
26807 default:
26808 MIPS_INVAL("MSA instruction");
26809 generate_exception_end(ctx, EXCP_RI);
26810 break;
26813 tcg_temp_free_i32(tdf);
26814 tcg_temp_free_i32(twd);
26815 tcg_temp_free_i32(tws);
26816 tcg_temp_free_i32(timm);
26819 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
26821 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
26822 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
26823 uint32_t df = 0, m = 0;
26824 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26825 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26827 TCGv_i32 tdf;
26828 TCGv_i32 tm;
26829 TCGv_i32 twd;
26830 TCGv_i32 tws;
26832 if ((dfm & 0x40) == 0x00) {
26833 m = dfm & 0x3f;
26834 df = DF_DOUBLE;
26835 } else if ((dfm & 0x60) == 0x40) {
26836 m = dfm & 0x1f;
26837 df = DF_WORD;
26838 } else if ((dfm & 0x70) == 0x60) {
26839 m = dfm & 0x0f;
26840 df = DF_HALF;
26841 } else if ((dfm & 0x78) == 0x70) {
26842 m = dfm & 0x7;
26843 df = DF_BYTE;
26844 } else {
26845 generate_exception_end(ctx, EXCP_RI);
26846 return;
26849 tdf = tcg_const_i32(df);
26850 tm = tcg_const_i32(m);
26851 twd = tcg_const_i32(wd);
26852 tws = tcg_const_i32(ws);
26854 switch (MASK_MSA_BIT(ctx->opcode)) {
26855 case OPC_SLLI_df:
26856 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
26857 break;
26858 case OPC_SRAI_df:
26859 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
26860 break;
26861 case OPC_SRLI_df:
26862 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
26863 break;
26864 case OPC_BCLRI_df:
26865 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
26866 break;
26867 case OPC_BSETI_df:
26868 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
26869 break;
26870 case OPC_BNEGI_df:
26871 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
26872 break;
26873 case OPC_BINSLI_df:
26874 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
26875 break;
26876 case OPC_BINSRI_df:
26877 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
26878 break;
26879 case OPC_SAT_S_df:
26880 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
26881 break;
26882 case OPC_SAT_U_df:
26883 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
26884 break;
26885 case OPC_SRARI_df:
26886 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
26887 break;
26888 case OPC_SRLRI_df:
26889 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
26890 break;
26891 default:
26892 MIPS_INVAL("MSA instruction");
26893 generate_exception_end(ctx, EXCP_RI);
26894 break;
26897 tcg_temp_free_i32(tdf);
26898 tcg_temp_free_i32(tm);
26899 tcg_temp_free_i32(twd);
26900 tcg_temp_free_i32(tws);
26903 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
26905 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
26906 uint8_t df = (ctx->opcode >> 21) & 0x3;
26907 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
26908 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26909 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26911 TCGv_i32 tdf = tcg_const_i32(df);
26912 TCGv_i32 twd = tcg_const_i32(wd);
26913 TCGv_i32 tws = tcg_const_i32(ws);
26914 TCGv_i32 twt = tcg_const_i32(wt);
26916 switch (MASK_MSA_3R(ctx->opcode)) {
26917 case OPC_SLL_df:
26918 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
26919 break;
26920 case OPC_ADDV_df:
26921 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
26922 break;
26923 case OPC_CEQ_df:
26924 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
26925 break;
26926 case OPC_ADD_A_df:
26927 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
26928 break;
26929 case OPC_SUBS_S_df:
26930 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
26931 break;
26932 case OPC_MULV_df:
26933 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
26934 break;
26935 case OPC_SLD_df:
26936 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
26937 break;
26938 case OPC_VSHF_df:
26939 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
26940 break;
26941 case OPC_SRA_df:
26942 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
26943 break;
26944 case OPC_SUBV_df:
26945 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
26946 break;
26947 case OPC_ADDS_A_df:
26948 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
26949 break;
26950 case OPC_SUBS_U_df:
26951 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
26952 break;
26953 case OPC_MADDV_df:
26954 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
26955 break;
26956 case OPC_SPLAT_df:
26957 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
26958 break;
26959 case OPC_SRAR_df:
26960 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
26961 break;
26962 case OPC_SRL_df:
26963 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
26964 break;
26965 case OPC_MAX_S_df:
26966 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
26967 break;
26968 case OPC_CLT_S_df:
26969 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
26970 break;
26971 case OPC_ADDS_S_df:
26972 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
26973 break;
26974 case OPC_SUBSUS_U_df:
26975 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
26976 break;
26977 case OPC_MSUBV_df:
26978 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
26979 break;
26980 case OPC_PCKEV_df:
26981 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
26982 break;
26983 case OPC_SRLR_df:
26984 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
26985 break;
26986 case OPC_BCLR_df:
26987 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
26988 break;
26989 case OPC_MAX_U_df:
26990 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
26991 break;
26992 case OPC_CLT_U_df:
26993 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
26994 break;
26995 case OPC_ADDS_U_df:
26996 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
26997 break;
26998 case OPC_SUBSUU_S_df:
26999 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
27000 break;
27001 case OPC_PCKOD_df:
27002 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
27003 break;
27004 case OPC_BSET_df:
27005 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
27006 break;
27007 case OPC_MIN_S_df:
27008 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
27009 break;
27010 case OPC_CLE_S_df:
27011 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
27012 break;
27013 case OPC_AVE_S_df:
27014 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
27015 break;
27016 case OPC_ASUB_S_df:
27017 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
27018 break;
27019 case OPC_DIV_S_df:
27020 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
27021 break;
27022 case OPC_ILVL_df:
27023 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
27024 break;
27025 case OPC_BNEG_df:
27026 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
27027 break;
27028 case OPC_MIN_U_df:
27029 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
27030 break;
27031 case OPC_CLE_U_df:
27032 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
27033 break;
27034 case OPC_AVE_U_df:
27035 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
27036 break;
27037 case OPC_ASUB_U_df:
27038 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
27039 break;
27040 case OPC_DIV_U_df:
27041 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
27042 break;
27043 case OPC_ILVR_df:
27044 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
27045 break;
27046 case OPC_BINSL_df:
27047 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
27048 break;
27049 case OPC_MAX_A_df:
27050 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
27051 break;
27052 case OPC_AVER_S_df:
27053 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
27054 break;
27055 case OPC_MOD_S_df:
27056 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
27057 break;
27058 case OPC_ILVEV_df:
27059 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
27060 break;
27061 case OPC_BINSR_df:
27062 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
27063 break;
27064 case OPC_MIN_A_df:
27065 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
27066 break;
27067 case OPC_AVER_U_df:
27068 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
27069 break;
27070 case OPC_MOD_U_df:
27071 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
27072 break;
27073 case OPC_ILVOD_df:
27074 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
27075 break;
27077 case OPC_DOTP_S_df:
27078 case OPC_DOTP_U_df:
27079 case OPC_DPADD_S_df:
27080 case OPC_DPADD_U_df:
27081 case OPC_DPSUB_S_df:
27082 case OPC_HADD_S_df:
27083 case OPC_DPSUB_U_df:
27084 case OPC_HADD_U_df:
27085 case OPC_HSUB_S_df:
27086 case OPC_HSUB_U_df:
27087 if (df == DF_BYTE) {
27088 generate_exception_end(ctx, EXCP_RI);
27089 break;
27091 switch (MASK_MSA_3R(ctx->opcode)) {
27092 case OPC_DOTP_S_df:
27093 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
27094 break;
27095 case OPC_DOTP_U_df:
27096 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
27097 break;
27098 case OPC_DPADD_S_df:
27099 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
27100 break;
27101 case OPC_DPADD_U_df:
27102 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
27103 break;
27104 case OPC_DPSUB_S_df:
27105 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
27106 break;
27107 case OPC_HADD_S_df:
27108 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
27109 break;
27110 case OPC_DPSUB_U_df:
27111 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
27112 break;
27113 case OPC_HADD_U_df:
27114 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
27115 break;
27116 case OPC_HSUB_S_df:
27117 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
27118 break;
27119 case OPC_HSUB_U_df:
27120 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
27121 break;
27123 break;
27124 default:
27125 MIPS_INVAL("MSA instruction");
27126 generate_exception_end(ctx, EXCP_RI);
27127 break;
27129 tcg_temp_free_i32(twd);
27130 tcg_temp_free_i32(tws);
27131 tcg_temp_free_i32(twt);
27132 tcg_temp_free_i32(tdf);
27135 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
27137 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
27138 uint8_t source = (ctx->opcode >> 11) & 0x1f;
27139 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
27140 TCGv telm = tcg_temp_new();
27141 TCGv_i32 tsr = tcg_const_i32(source);
27142 TCGv_i32 tdt = tcg_const_i32(dest);
27144 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
27145 case OPC_CTCMSA:
27146 gen_load_gpr(telm, source);
27147 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
27148 break;
27149 case OPC_CFCMSA:
27150 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
27151 gen_store_gpr(telm, dest);
27152 break;
27153 case OPC_MOVE_V:
27154 gen_helper_msa_move_v(cpu_env, tdt, tsr);
27155 break;
27156 default:
27157 MIPS_INVAL("MSA instruction");
27158 generate_exception_end(ctx, EXCP_RI);
27159 break;
27162 tcg_temp_free(telm);
27163 tcg_temp_free_i32(tdt);
27164 tcg_temp_free_i32(tsr);
27167 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
27168 uint32_t n)
27170 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
27171 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27172 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27174 TCGv_i32 tws = tcg_const_i32(ws);
27175 TCGv_i32 twd = tcg_const_i32(wd);
27176 TCGv_i32 tn = tcg_const_i32(n);
27177 TCGv_i32 tdf = tcg_const_i32(df);
27179 switch (MASK_MSA_ELM(ctx->opcode)) {
27180 case OPC_SLDI_df:
27181 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
27182 break;
27183 case OPC_SPLATI_df:
27184 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
27185 break;
27186 case OPC_INSVE_df:
27187 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
27188 break;
27189 case OPC_COPY_S_df:
27190 case OPC_COPY_U_df:
27191 case OPC_INSERT_df:
27192 #if !defined(TARGET_MIPS64)
27193 /* Double format valid only for MIPS64 */
27194 if (df == DF_DOUBLE) {
27195 generate_exception_end(ctx, EXCP_RI);
27196 break;
27198 #endif
27199 switch (MASK_MSA_ELM(ctx->opcode)) {
27200 case OPC_COPY_S_df:
27201 if (likely(wd != 0)) {
27202 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
27204 break;
27205 case OPC_COPY_U_df:
27206 if (likely(wd != 0)) {
27207 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
27209 break;
27210 case OPC_INSERT_df:
27211 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
27212 break;
27214 break;
27215 default:
27216 MIPS_INVAL("MSA instruction");
27217 generate_exception_end(ctx, EXCP_RI);
27219 tcg_temp_free_i32(twd);
27220 tcg_temp_free_i32(tws);
27221 tcg_temp_free_i32(tn);
27222 tcg_temp_free_i32(tdf);
27225 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
27227 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
27228 uint32_t df = 0, n = 0;
27230 if ((dfn & 0x30) == 0x00) {
27231 n = dfn & 0x0f;
27232 df = DF_BYTE;
27233 } else if ((dfn & 0x38) == 0x20) {
27234 n = dfn & 0x07;
27235 df = DF_HALF;
27236 } else if ((dfn & 0x3c) == 0x30) {
27237 n = dfn & 0x03;
27238 df = DF_WORD;
27239 } else if ((dfn & 0x3e) == 0x38) {
27240 n = dfn & 0x01;
27241 df = DF_DOUBLE;
27242 } else if (dfn == 0x3E) {
27243 /* CTCMSA, CFCMSA, MOVE.V */
27244 gen_msa_elm_3e(env, ctx);
27245 return;
27246 } else {
27247 generate_exception_end(ctx, EXCP_RI);
27248 return;
27251 gen_msa_elm_df(env, ctx, df, n);
27254 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
27256 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
27257 uint8_t df = (ctx->opcode >> 21) & 0x1;
27258 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27259 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27260 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27262 TCGv_i32 twd = tcg_const_i32(wd);
27263 TCGv_i32 tws = tcg_const_i32(ws);
27264 TCGv_i32 twt = tcg_const_i32(wt);
27265 TCGv_i32 tdf = tcg_temp_new_i32();
27267 /* adjust df value for floating-point instruction */
27268 tcg_gen_movi_i32(tdf, df + 2);
27270 switch (MASK_MSA_3RF(ctx->opcode)) {
27271 case OPC_FCAF_df:
27272 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
27273 break;
27274 case OPC_FADD_df:
27275 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
27276 break;
27277 case OPC_FCUN_df:
27278 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
27279 break;
27280 case OPC_FSUB_df:
27281 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
27282 break;
27283 case OPC_FCOR_df:
27284 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
27285 break;
27286 case OPC_FCEQ_df:
27287 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
27288 break;
27289 case OPC_FMUL_df:
27290 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
27291 break;
27292 case OPC_FCUNE_df:
27293 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
27294 break;
27295 case OPC_FCUEQ_df:
27296 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
27297 break;
27298 case OPC_FDIV_df:
27299 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
27300 break;
27301 case OPC_FCNE_df:
27302 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
27303 break;
27304 case OPC_FCLT_df:
27305 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
27306 break;
27307 case OPC_FMADD_df:
27308 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
27309 break;
27310 case OPC_MUL_Q_df:
27311 tcg_gen_movi_i32(tdf, df + 1);
27312 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
27313 break;
27314 case OPC_FCULT_df:
27315 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
27316 break;
27317 case OPC_FMSUB_df:
27318 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
27319 break;
27320 case OPC_MADD_Q_df:
27321 tcg_gen_movi_i32(tdf, df + 1);
27322 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
27323 break;
27324 case OPC_FCLE_df:
27325 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
27326 break;
27327 case OPC_MSUB_Q_df:
27328 tcg_gen_movi_i32(tdf, df + 1);
27329 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
27330 break;
27331 case OPC_FCULE_df:
27332 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
27333 break;
27334 case OPC_FEXP2_df:
27335 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
27336 break;
27337 case OPC_FSAF_df:
27338 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
27339 break;
27340 case OPC_FEXDO_df:
27341 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
27342 break;
27343 case OPC_FSUN_df:
27344 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
27345 break;
27346 case OPC_FSOR_df:
27347 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
27348 break;
27349 case OPC_FSEQ_df:
27350 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
27351 break;
27352 case OPC_FTQ_df:
27353 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
27354 break;
27355 case OPC_FSUNE_df:
27356 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
27357 break;
27358 case OPC_FSUEQ_df:
27359 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
27360 break;
27361 case OPC_FSNE_df:
27362 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
27363 break;
27364 case OPC_FSLT_df:
27365 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
27366 break;
27367 case OPC_FMIN_df:
27368 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
27369 break;
27370 case OPC_MULR_Q_df:
27371 tcg_gen_movi_i32(tdf, df + 1);
27372 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
27373 break;
27374 case OPC_FSULT_df:
27375 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
27376 break;
27377 case OPC_FMIN_A_df:
27378 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
27379 break;
27380 case OPC_MADDR_Q_df:
27381 tcg_gen_movi_i32(tdf, df + 1);
27382 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
27383 break;
27384 case OPC_FSLE_df:
27385 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
27386 break;
27387 case OPC_FMAX_df:
27388 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
27389 break;
27390 case OPC_MSUBR_Q_df:
27391 tcg_gen_movi_i32(tdf, df + 1);
27392 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
27393 break;
27394 case OPC_FSULE_df:
27395 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
27396 break;
27397 case OPC_FMAX_A_df:
27398 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
27399 break;
27400 default:
27401 MIPS_INVAL("MSA instruction");
27402 generate_exception_end(ctx, EXCP_RI);
27403 break;
27406 tcg_temp_free_i32(twd);
27407 tcg_temp_free_i32(tws);
27408 tcg_temp_free_i32(twt);
27409 tcg_temp_free_i32(tdf);
27412 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
27414 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
27415 (op & (0x7 << 18)))
27416 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27417 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27418 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27419 uint8_t df = (ctx->opcode >> 16) & 0x3;
27420 TCGv_i32 twd = tcg_const_i32(wd);
27421 TCGv_i32 tws = tcg_const_i32(ws);
27422 TCGv_i32 twt = tcg_const_i32(wt);
27423 TCGv_i32 tdf = tcg_const_i32(df);
27425 switch (MASK_MSA_2R(ctx->opcode)) {
27426 case OPC_FILL_df:
27427 #if !defined(TARGET_MIPS64)
27428 /* Double format valid only for MIPS64 */
27429 if (df == DF_DOUBLE) {
27430 generate_exception_end(ctx, EXCP_RI);
27431 break;
27433 #endif
27434 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
27435 break;
27436 case OPC_PCNT_df:
27437 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
27438 break;
27439 case OPC_NLOC_df:
27440 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
27441 break;
27442 case OPC_NLZC_df:
27443 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
27444 break;
27445 default:
27446 MIPS_INVAL("MSA instruction");
27447 generate_exception_end(ctx, EXCP_RI);
27448 break;
27451 tcg_temp_free_i32(twd);
27452 tcg_temp_free_i32(tws);
27453 tcg_temp_free_i32(twt);
27454 tcg_temp_free_i32(tdf);
27457 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
27459 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
27460 (op & (0xf << 17)))
27461 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27462 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27463 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27464 uint8_t df = (ctx->opcode >> 16) & 0x1;
27465 TCGv_i32 twd = tcg_const_i32(wd);
27466 TCGv_i32 tws = tcg_const_i32(ws);
27467 TCGv_i32 twt = tcg_const_i32(wt);
27468 /* adjust df value for floating-point instruction */
27469 TCGv_i32 tdf = tcg_const_i32(df + 2);
27471 switch (MASK_MSA_2RF(ctx->opcode)) {
27472 case OPC_FCLASS_df:
27473 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
27474 break;
27475 case OPC_FTRUNC_S_df:
27476 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
27477 break;
27478 case OPC_FTRUNC_U_df:
27479 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
27480 break;
27481 case OPC_FSQRT_df:
27482 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
27483 break;
27484 case OPC_FRSQRT_df:
27485 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
27486 break;
27487 case OPC_FRCP_df:
27488 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
27489 break;
27490 case OPC_FRINT_df:
27491 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
27492 break;
27493 case OPC_FLOG2_df:
27494 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
27495 break;
27496 case OPC_FEXUPL_df:
27497 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
27498 break;
27499 case OPC_FEXUPR_df:
27500 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
27501 break;
27502 case OPC_FFQL_df:
27503 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
27504 break;
27505 case OPC_FFQR_df:
27506 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
27507 break;
27508 case OPC_FTINT_S_df:
27509 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
27510 break;
27511 case OPC_FTINT_U_df:
27512 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
27513 break;
27514 case OPC_FFINT_S_df:
27515 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
27516 break;
27517 case OPC_FFINT_U_df:
27518 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
27519 break;
27522 tcg_temp_free_i32(twd);
27523 tcg_temp_free_i32(tws);
27524 tcg_temp_free_i32(twt);
27525 tcg_temp_free_i32(tdf);
27528 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
27530 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
27531 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27532 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27533 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27534 TCGv_i32 twd = tcg_const_i32(wd);
27535 TCGv_i32 tws = tcg_const_i32(ws);
27536 TCGv_i32 twt = tcg_const_i32(wt);
27538 switch (MASK_MSA_VEC(ctx->opcode)) {
27539 case OPC_AND_V:
27540 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
27541 break;
27542 case OPC_OR_V:
27543 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
27544 break;
27545 case OPC_NOR_V:
27546 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
27547 break;
27548 case OPC_XOR_V:
27549 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
27550 break;
27551 case OPC_BMNZ_V:
27552 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
27553 break;
27554 case OPC_BMZ_V:
27555 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
27556 break;
27557 case OPC_BSEL_V:
27558 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
27559 break;
27560 default:
27561 MIPS_INVAL("MSA instruction");
27562 generate_exception_end(ctx, EXCP_RI);
27563 break;
27566 tcg_temp_free_i32(twd);
27567 tcg_temp_free_i32(tws);
27568 tcg_temp_free_i32(twt);
27571 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
27573 switch (MASK_MSA_VEC(ctx->opcode)) {
27574 case OPC_AND_V:
27575 case OPC_OR_V:
27576 case OPC_NOR_V:
27577 case OPC_XOR_V:
27578 case OPC_BMNZ_V:
27579 case OPC_BMZ_V:
27580 case OPC_BSEL_V:
27581 gen_msa_vec_v(env, ctx);
27582 break;
27583 case OPC_MSA_2R:
27584 gen_msa_2r(env, ctx);
27585 break;
27586 case OPC_MSA_2RF:
27587 gen_msa_2rf(env, ctx);
27588 break;
27589 default:
27590 MIPS_INVAL("MSA instruction");
27591 generate_exception_end(ctx, EXCP_RI);
27592 break;
27596 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
27598 uint32_t opcode = ctx->opcode;
27599 check_insn(ctx, ASE_MSA);
27600 check_msa_access(ctx);
27602 switch (MASK_MSA_MINOR(opcode)) {
27603 case OPC_MSA_I8_00:
27604 case OPC_MSA_I8_01:
27605 case OPC_MSA_I8_02:
27606 gen_msa_i8(env, ctx);
27607 break;
27608 case OPC_MSA_I5_06:
27609 case OPC_MSA_I5_07:
27610 gen_msa_i5(env, ctx);
27611 break;
27612 case OPC_MSA_BIT_09:
27613 case OPC_MSA_BIT_0A:
27614 gen_msa_bit(env, ctx);
27615 break;
27616 case OPC_MSA_3R_0D:
27617 case OPC_MSA_3R_0E:
27618 case OPC_MSA_3R_0F:
27619 case OPC_MSA_3R_10:
27620 case OPC_MSA_3R_11:
27621 case OPC_MSA_3R_12:
27622 case OPC_MSA_3R_13:
27623 case OPC_MSA_3R_14:
27624 case OPC_MSA_3R_15:
27625 gen_msa_3r(env, ctx);
27626 break;
27627 case OPC_MSA_ELM:
27628 gen_msa_elm(env, ctx);
27629 break;
27630 case OPC_MSA_3RF_1A:
27631 case OPC_MSA_3RF_1B:
27632 case OPC_MSA_3RF_1C:
27633 gen_msa_3rf(env, ctx);
27634 break;
27635 case OPC_MSA_VEC:
27636 gen_msa_vec(env, ctx);
27637 break;
27638 case OPC_LD_B:
27639 case OPC_LD_H:
27640 case OPC_LD_W:
27641 case OPC_LD_D:
27642 case OPC_ST_B:
27643 case OPC_ST_H:
27644 case OPC_ST_W:
27645 case OPC_ST_D:
27647 int32_t s10 = sextract32(ctx->opcode, 16, 10);
27648 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
27649 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27650 uint8_t df = (ctx->opcode >> 0) & 0x3;
27652 TCGv_i32 twd = tcg_const_i32(wd);
27653 TCGv taddr = tcg_temp_new();
27654 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
27656 switch (MASK_MSA_MINOR(opcode)) {
27657 case OPC_LD_B:
27658 gen_helper_msa_ld_b(cpu_env, twd, taddr);
27659 break;
27660 case OPC_LD_H:
27661 gen_helper_msa_ld_h(cpu_env, twd, taddr);
27662 break;
27663 case OPC_LD_W:
27664 gen_helper_msa_ld_w(cpu_env, twd, taddr);
27665 break;
27666 case OPC_LD_D:
27667 gen_helper_msa_ld_d(cpu_env, twd, taddr);
27668 break;
27669 case OPC_ST_B:
27670 gen_helper_msa_st_b(cpu_env, twd, taddr);
27671 break;
27672 case OPC_ST_H:
27673 gen_helper_msa_st_h(cpu_env, twd, taddr);
27674 break;
27675 case OPC_ST_W:
27676 gen_helper_msa_st_w(cpu_env, twd, taddr);
27677 break;
27678 case OPC_ST_D:
27679 gen_helper_msa_st_d(cpu_env, twd, taddr);
27680 break;
27683 tcg_temp_free_i32(twd);
27684 tcg_temp_free(taddr);
27686 break;
27687 default:
27688 MIPS_INVAL("MSA instruction");
27689 generate_exception_end(ctx, EXCP_RI);
27690 break;
27695 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
27697 int32_t offset;
27698 int rs, rt, rd, sa;
27699 uint32_t op, op1;
27700 int16_t imm;
27702 /* make sure instructions are on a word boundary */
27703 if (ctx->base.pc_next & 0x3) {
27704 env->CP0_BadVAddr = ctx->base.pc_next;
27705 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
27706 return;
27709 /* Handle blikely not taken case */
27710 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
27711 TCGLabel *l1 = gen_new_label();
27713 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
27714 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
27715 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
27716 gen_set_label(l1);
27719 op = MASK_OP_MAJOR(ctx->opcode);
27720 rs = (ctx->opcode >> 21) & 0x1f;
27721 rt = (ctx->opcode >> 16) & 0x1f;
27722 rd = (ctx->opcode >> 11) & 0x1f;
27723 sa = (ctx->opcode >> 6) & 0x1f;
27724 imm = (int16_t)ctx->opcode;
27725 switch (op) {
27726 case OPC_SPECIAL:
27727 decode_opc_special(env, ctx);
27728 break;
27729 case OPC_SPECIAL2:
27730 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
27731 decode_tx79_mmi(env, ctx);
27732 } else if (ctx->insn_flags & ASE_MXU) {
27733 decode_opc_mxu(env, ctx);
27734 } else {
27735 decode_opc_special2_legacy(env, ctx);
27737 break;
27738 case OPC_SPECIAL3:
27739 if (ctx->insn_flags & INSN_R5900) {
27740 decode_tx79_sq(env, ctx); /* TX79_SQ */
27741 } else {
27742 decode_opc_special3(env, ctx);
27744 break;
27745 case OPC_REGIMM:
27746 op1 = MASK_REGIMM(ctx->opcode);
27747 switch (op1) {
27748 case OPC_BLTZL: /* REGIMM branches */
27749 case OPC_BGEZL:
27750 case OPC_BLTZALL:
27751 case OPC_BGEZALL:
27752 check_insn(ctx, ISA_MIPS2);
27753 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27754 /* Fallthrough */
27755 case OPC_BLTZ:
27756 case OPC_BGEZ:
27757 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
27758 break;
27759 case OPC_BLTZAL:
27760 case OPC_BGEZAL:
27761 if (ctx->insn_flags & ISA_MIPS32R6) {
27762 if (rs == 0) {
27763 /* OPC_NAL, OPC_BAL */
27764 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
27765 } else {
27766 generate_exception_end(ctx, EXCP_RI);
27768 } else {
27769 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
27771 break;
27772 case OPC_TGEI: /* REGIMM traps */
27773 case OPC_TGEIU:
27774 case OPC_TLTI:
27775 case OPC_TLTIU:
27776 case OPC_TEQI:
27778 case OPC_TNEI:
27779 check_insn(ctx, ISA_MIPS2);
27780 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27781 gen_trap(ctx, op1, rs, -1, imm);
27782 break;
27783 case OPC_SIGRIE:
27784 check_insn(ctx, ISA_MIPS32R6);
27785 generate_exception_end(ctx, EXCP_RI);
27786 break;
27787 case OPC_SYNCI:
27788 check_insn(ctx, ISA_MIPS32R2);
27789 /* Break the TB to be able to sync copied instructions
27790 immediately */
27791 ctx->base.is_jmp = DISAS_STOP;
27792 break;
27793 case OPC_BPOSGE32: /* MIPS DSP branch */
27794 #if defined(TARGET_MIPS64)
27795 case OPC_BPOSGE64:
27796 #endif
27797 check_dsp(ctx);
27798 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
27799 break;
27800 #if defined(TARGET_MIPS64)
27801 case OPC_DAHI:
27802 check_insn(ctx, ISA_MIPS32R6);
27803 check_mips_64(ctx);
27804 if (rs != 0) {
27805 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
27807 break;
27808 case OPC_DATI:
27809 check_insn(ctx, ISA_MIPS32R6);
27810 check_mips_64(ctx);
27811 if (rs != 0) {
27812 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
27814 break;
27815 #endif
27816 default: /* Invalid */
27817 MIPS_INVAL("regimm");
27818 generate_exception_end(ctx, EXCP_RI);
27819 break;
27821 break;
27822 case OPC_CP0:
27823 check_cp0_enabled(ctx);
27824 op1 = MASK_CP0(ctx->opcode);
27825 switch (op1) {
27826 case OPC_MFC0:
27827 case OPC_MTC0:
27828 case OPC_MFTR:
27829 case OPC_MTTR:
27830 case OPC_MFHC0:
27831 case OPC_MTHC0:
27832 #if defined(TARGET_MIPS64)
27833 case OPC_DMFC0:
27834 case OPC_DMTC0:
27835 #endif
27836 #ifndef CONFIG_USER_ONLY
27837 gen_cp0(env, ctx, op1, rt, rd);
27838 #endif /* !CONFIG_USER_ONLY */
27839 break;
27840 case OPC_C0:
27841 case OPC_C0_1:
27842 case OPC_C0_2:
27843 case OPC_C0_3:
27844 case OPC_C0_4:
27845 case OPC_C0_5:
27846 case OPC_C0_6:
27847 case OPC_C0_7:
27848 case OPC_C0_8:
27849 case OPC_C0_9:
27850 case OPC_C0_A:
27851 case OPC_C0_B:
27852 case OPC_C0_C:
27853 case OPC_C0_D:
27854 case OPC_C0_E:
27855 case OPC_C0_F:
27856 #ifndef CONFIG_USER_ONLY
27857 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
27858 #endif /* !CONFIG_USER_ONLY */
27859 break;
27860 case OPC_MFMC0:
27861 #ifndef CONFIG_USER_ONLY
27863 uint32_t op2;
27864 TCGv t0 = tcg_temp_new();
27866 op2 = MASK_MFMC0(ctx->opcode);
27867 switch (op2) {
27868 case OPC_DMT:
27869 check_cp0_mt(ctx);
27870 gen_helper_dmt(t0);
27871 gen_store_gpr(t0, rt);
27872 break;
27873 case OPC_EMT:
27874 check_cp0_mt(ctx);
27875 gen_helper_emt(t0);
27876 gen_store_gpr(t0, rt);
27877 break;
27878 case OPC_DVPE:
27879 check_cp0_mt(ctx);
27880 gen_helper_dvpe(t0, cpu_env);
27881 gen_store_gpr(t0, rt);
27882 break;
27883 case OPC_EVPE:
27884 check_cp0_mt(ctx);
27885 gen_helper_evpe(t0, cpu_env);
27886 gen_store_gpr(t0, rt);
27887 break;
27888 case OPC_DVP:
27889 check_insn(ctx, ISA_MIPS32R6);
27890 if (ctx->vp) {
27891 gen_helper_dvp(t0, cpu_env);
27892 gen_store_gpr(t0, rt);
27894 break;
27895 case OPC_EVP:
27896 check_insn(ctx, ISA_MIPS32R6);
27897 if (ctx->vp) {
27898 gen_helper_evp(t0, cpu_env);
27899 gen_store_gpr(t0, rt);
27901 break;
27902 case OPC_DI:
27903 check_insn(ctx, ISA_MIPS32R2);
27904 save_cpu_state(ctx, 1);
27905 gen_helper_di(t0, cpu_env);
27906 gen_store_gpr(t0, rt);
27907 /* Stop translation as we may have switched
27908 the execution mode. */
27909 ctx->base.is_jmp = DISAS_STOP;
27910 break;
27911 case OPC_EI:
27912 check_insn(ctx, ISA_MIPS32R2);
27913 save_cpu_state(ctx, 1);
27914 gen_helper_ei(t0, cpu_env);
27915 gen_store_gpr(t0, rt);
27916 /* DISAS_STOP isn't sufficient, we need to ensure we break
27917 out of translated code to check for pending interrupts */
27918 gen_save_pc(ctx->base.pc_next + 4);
27919 ctx->base.is_jmp = DISAS_EXIT;
27920 break;
27921 default: /* Invalid */
27922 MIPS_INVAL("mfmc0");
27923 generate_exception_end(ctx, EXCP_RI);
27924 break;
27926 tcg_temp_free(t0);
27928 #endif /* !CONFIG_USER_ONLY */
27929 break;
27930 case OPC_RDPGPR:
27931 check_insn(ctx, ISA_MIPS32R2);
27932 gen_load_srsgpr(rt, rd);
27933 break;
27934 case OPC_WRPGPR:
27935 check_insn(ctx, ISA_MIPS32R2);
27936 gen_store_srsgpr(rt, rd);
27937 break;
27938 default:
27939 MIPS_INVAL("cp0");
27940 generate_exception_end(ctx, EXCP_RI);
27941 break;
27943 break;
27944 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
27945 if (ctx->insn_flags & ISA_MIPS32R6) {
27946 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
27947 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27948 } else {
27949 /* OPC_ADDI */
27950 /* Arithmetic with immediate opcode */
27951 gen_arith_imm(ctx, op, rt, rs, imm);
27953 break;
27954 case OPC_ADDIU:
27955 gen_arith_imm(ctx, op, rt, rs, imm);
27956 break;
27957 case OPC_SLTI: /* Set on less than with immediate opcode */
27958 case OPC_SLTIU:
27959 gen_slt_imm(ctx, op, rt, rs, imm);
27960 break;
27961 case OPC_ANDI: /* Arithmetic with immediate opcode */
27962 case OPC_LUI: /* OPC_AUI */
27963 case OPC_ORI:
27964 case OPC_XORI:
27965 gen_logic_imm(ctx, op, rt, rs, imm);
27966 break;
27967 case OPC_J: /* Jump */
27968 case OPC_JAL:
27969 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
27970 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
27971 break;
27972 /* Branch */
27973 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
27974 if (ctx->insn_flags & ISA_MIPS32R6) {
27975 if (rt == 0) {
27976 generate_exception_end(ctx, EXCP_RI);
27977 break;
27979 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
27980 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27981 } else {
27982 /* OPC_BLEZL */
27983 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27985 break;
27986 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
27987 if (ctx->insn_flags & ISA_MIPS32R6) {
27988 if (rt == 0) {
27989 generate_exception_end(ctx, EXCP_RI);
27990 break;
27992 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
27993 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
27994 } else {
27995 /* OPC_BGTZL */
27996 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
27998 break;
27999 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
28000 if (rt == 0) {
28001 /* OPC_BLEZ */
28002 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28003 } else {
28004 check_insn(ctx, ISA_MIPS32R6);
28005 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
28006 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28008 break;
28009 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
28010 if (rt == 0) {
28011 /* OPC_BGTZ */
28012 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28013 } else {
28014 check_insn(ctx, ISA_MIPS32R6);
28015 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
28016 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28018 break;
28019 case OPC_BEQL:
28020 case OPC_BNEL:
28021 check_insn(ctx, ISA_MIPS2);
28022 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28023 /* Fallthrough */
28024 case OPC_BEQ:
28025 case OPC_BNE:
28026 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28027 break;
28028 case OPC_LL: /* Load and stores */
28029 check_insn(ctx, ISA_MIPS2);
28030 check_insn_opc_user_only(ctx, INSN_R5900);
28031 /* Fallthrough */
28032 case OPC_LWL:
28033 case OPC_LWR:
28034 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28035 /* Fallthrough */
28036 case OPC_LB:
28037 case OPC_LH:
28038 case OPC_LW:
28039 case OPC_LWPC:
28040 case OPC_LBU:
28041 case OPC_LHU:
28042 gen_ld(ctx, op, rt, rs, imm);
28043 break;
28044 case OPC_SWL:
28045 case OPC_SWR:
28046 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28047 /* fall through */
28048 case OPC_SB:
28049 case OPC_SH:
28050 case OPC_SW:
28051 gen_st(ctx, op, rt, rs, imm);
28052 break;
28053 case OPC_SC:
28054 check_insn(ctx, ISA_MIPS2);
28055 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28056 check_insn_opc_user_only(ctx, INSN_R5900);
28057 gen_st_cond(ctx, op, rt, rs, imm);
28058 break;
28059 case OPC_CACHE:
28060 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28061 check_cp0_enabled(ctx);
28062 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
28063 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28064 gen_cache_operation(ctx, rt, rs, imm);
28066 /* Treat as NOP. */
28067 break;
28068 case OPC_PREF:
28069 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28070 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
28071 INSN_R5900);
28072 /* Treat as NOP. */
28073 break;
28075 /* Floating point (COP1). */
28076 case OPC_LWC1:
28077 case OPC_LDC1:
28078 case OPC_SWC1:
28079 case OPC_SDC1:
28080 gen_cop1_ldst(ctx, op, rt, rs, imm);
28081 break;
28083 case OPC_CP1:
28084 op1 = MASK_CP1(ctx->opcode);
28086 switch (op1) {
28087 case OPC_MFHC1:
28088 case OPC_MTHC1:
28089 check_cp1_enabled(ctx);
28090 check_insn(ctx, ISA_MIPS32R2);
28091 /* fall through */
28092 case OPC_MFC1:
28093 case OPC_CFC1:
28094 case OPC_MTC1:
28095 case OPC_CTC1:
28096 check_cp1_enabled(ctx);
28097 gen_cp1(ctx, op1, rt, rd);
28098 break;
28099 #if defined(TARGET_MIPS64)
28100 case OPC_DMFC1:
28101 case OPC_DMTC1:
28102 check_cp1_enabled(ctx);
28103 check_insn(ctx, ISA_MIPS3);
28104 check_mips_64(ctx);
28105 gen_cp1(ctx, op1, rt, rd);
28106 break;
28107 #endif
28108 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
28109 check_cp1_enabled(ctx);
28110 if (ctx->insn_flags & ISA_MIPS32R6) {
28111 /* OPC_BC1EQZ */
28112 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
28113 rt, imm << 2, 4);
28114 } else {
28115 /* OPC_BC1ANY2 */
28116 check_cop1x(ctx);
28117 check_insn(ctx, ASE_MIPS3D);
28118 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
28119 (rt >> 2) & 0x7, imm << 2);
28121 break;
28122 case OPC_BC1NEZ:
28123 check_cp1_enabled(ctx);
28124 check_insn(ctx, ISA_MIPS32R6);
28125 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
28126 rt, imm << 2, 4);
28127 break;
28128 case OPC_BC1ANY4:
28129 check_cp1_enabled(ctx);
28130 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28131 check_cop1x(ctx);
28132 check_insn(ctx, ASE_MIPS3D);
28133 /* fall through */
28134 case OPC_BC1:
28135 check_cp1_enabled(ctx);
28136 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28137 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
28138 (rt >> 2) & 0x7, imm << 2);
28139 break;
28140 case OPC_PS_FMT:
28141 check_ps(ctx);
28142 /* fall through */
28143 case OPC_S_FMT:
28144 case OPC_D_FMT:
28145 check_cp1_enabled(ctx);
28146 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
28147 (imm >> 8) & 0x7);
28148 break;
28149 case OPC_W_FMT:
28150 case OPC_L_FMT:
28152 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
28153 check_cp1_enabled(ctx);
28154 if (ctx->insn_flags & ISA_MIPS32R6) {
28155 switch (r6_op) {
28156 case R6_OPC_CMP_AF_S:
28157 case R6_OPC_CMP_UN_S:
28158 case R6_OPC_CMP_EQ_S:
28159 case R6_OPC_CMP_UEQ_S:
28160 case R6_OPC_CMP_LT_S:
28161 case R6_OPC_CMP_ULT_S:
28162 case R6_OPC_CMP_LE_S:
28163 case R6_OPC_CMP_ULE_S:
28164 case R6_OPC_CMP_SAF_S:
28165 case R6_OPC_CMP_SUN_S:
28166 case R6_OPC_CMP_SEQ_S:
28167 case R6_OPC_CMP_SEUQ_S:
28168 case R6_OPC_CMP_SLT_S:
28169 case R6_OPC_CMP_SULT_S:
28170 case R6_OPC_CMP_SLE_S:
28171 case R6_OPC_CMP_SULE_S:
28172 case R6_OPC_CMP_OR_S:
28173 case R6_OPC_CMP_UNE_S:
28174 case R6_OPC_CMP_NE_S:
28175 case R6_OPC_CMP_SOR_S:
28176 case R6_OPC_CMP_SUNE_S:
28177 case R6_OPC_CMP_SNE_S:
28178 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
28179 break;
28180 case R6_OPC_CMP_AF_D:
28181 case R6_OPC_CMP_UN_D:
28182 case R6_OPC_CMP_EQ_D:
28183 case R6_OPC_CMP_UEQ_D:
28184 case R6_OPC_CMP_LT_D:
28185 case R6_OPC_CMP_ULT_D:
28186 case R6_OPC_CMP_LE_D:
28187 case R6_OPC_CMP_ULE_D:
28188 case R6_OPC_CMP_SAF_D:
28189 case R6_OPC_CMP_SUN_D:
28190 case R6_OPC_CMP_SEQ_D:
28191 case R6_OPC_CMP_SEUQ_D:
28192 case R6_OPC_CMP_SLT_D:
28193 case R6_OPC_CMP_SULT_D:
28194 case R6_OPC_CMP_SLE_D:
28195 case R6_OPC_CMP_SULE_D:
28196 case R6_OPC_CMP_OR_D:
28197 case R6_OPC_CMP_UNE_D:
28198 case R6_OPC_CMP_NE_D:
28199 case R6_OPC_CMP_SOR_D:
28200 case R6_OPC_CMP_SUNE_D:
28201 case R6_OPC_CMP_SNE_D:
28202 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
28203 break;
28204 default:
28205 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
28206 rt, rd, sa, (imm >> 8) & 0x7);
28208 break;
28210 } else {
28211 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
28212 (imm >> 8) & 0x7);
28214 break;
28216 case OPC_BZ_V:
28217 case OPC_BNZ_V:
28218 case OPC_BZ_B:
28219 case OPC_BZ_H:
28220 case OPC_BZ_W:
28221 case OPC_BZ_D:
28222 case OPC_BNZ_B:
28223 case OPC_BNZ_H:
28224 case OPC_BNZ_W:
28225 case OPC_BNZ_D:
28226 check_insn(ctx, ASE_MSA);
28227 gen_msa_branch(env, ctx, op1);
28228 break;
28229 default:
28230 MIPS_INVAL("cp1");
28231 generate_exception_end(ctx, EXCP_RI);
28232 break;
28234 break;
28236 /* Compact branches [R6] and COP2 [non-R6] */
28237 case OPC_BC: /* OPC_LWC2 */
28238 case OPC_BALC: /* OPC_SWC2 */
28239 if (ctx->insn_flags & ISA_MIPS32R6) {
28240 /* OPC_BC, OPC_BALC */
28241 gen_compute_compact_branch(ctx, op, 0, 0,
28242 sextract32(ctx->opcode << 2, 0, 28));
28243 } else {
28244 /* OPC_LWC2, OPC_SWC2 */
28245 /* COP2: Not implemented. */
28246 generate_exception_err(ctx, EXCP_CpU, 2);
28248 break;
28249 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
28250 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
28251 if (ctx->insn_flags & ISA_MIPS32R6) {
28252 if (rs != 0) {
28253 /* OPC_BEQZC, OPC_BNEZC */
28254 gen_compute_compact_branch(ctx, op, rs, 0,
28255 sextract32(ctx->opcode << 2, 0, 23));
28256 } else {
28257 /* OPC_JIC, OPC_JIALC */
28258 gen_compute_compact_branch(ctx, op, 0, rt, imm);
28260 } else {
28261 /* OPC_LWC2, OPC_SWC2 */
28262 /* COP2: Not implemented. */
28263 generate_exception_err(ctx, EXCP_CpU, 2);
28265 break;
28266 case OPC_CP2:
28267 check_insn(ctx, INSN_LOONGSON2F);
28268 /* Note that these instructions use different fields. */
28269 gen_loongson_multimedia(ctx, sa, rd, rt);
28270 break;
28272 case OPC_CP3:
28273 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28274 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
28275 check_cp1_enabled(ctx);
28276 op1 = MASK_CP3(ctx->opcode);
28277 switch (op1) {
28278 case OPC_LUXC1:
28279 case OPC_SUXC1:
28280 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
28281 /* Fallthrough */
28282 case OPC_LWXC1:
28283 case OPC_LDXC1:
28284 case OPC_SWXC1:
28285 case OPC_SDXC1:
28286 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
28287 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
28288 break;
28289 case OPC_PREFX:
28290 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
28291 /* Treat as NOP. */
28292 break;
28293 case OPC_ALNV_PS:
28294 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
28295 /* Fallthrough */
28296 case OPC_MADD_S:
28297 case OPC_MADD_D:
28298 case OPC_MADD_PS:
28299 case OPC_MSUB_S:
28300 case OPC_MSUB_D:
28301 case OPC_MSUB_PS:
28302 case OPC_NMADD_S:
28303 case OPC_NMADD_D:
28304 case OPC_NMADD_PS:
28305 case OPC_NMSUB_S:
28306 case OPC_NMSUB_D:
28307 case OPC_NMSUB_PS:
28308 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
28309 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
28310 break;
28311 default:
28312 MIPS_INVAL("cp3");
28313 generate_exception_end(ctx, EXCP_RI);
28314 break;
28316 } else {
28317 generate_exception_err(ctx, EXCP_CpU, 1);
28319 break;
28321 #if defined(TARGET_MIPS64)
28322 /* MIPS64 opcodes */
28323 case OPC_LLD:
28324 check_insn_opc_user_only(ctx, INSN_R5900);
28325 /* fall through */
28326 case OPC_LDL:
28327 case OPC_LDR:
28328 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28329 /* fall through */
28330 case OPC_LWU:
28331 case OPC_LD:
28332 check_insn(ctx, ISA_MIPS3);
28333 check_mips_64(ctx);
28334 gen_ld(ctx, op, rt, rs, imm);
28335 break;
28336 case OPC_SDL:
28337 case OPC_SDR:
28338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28339 /* fall through */
28340 case OPC_SD:
28341 check_insn(ctx, ISA_MIPS3);
28342 check_mips_64(ctx);
28343 gen_st(ctx, op, rt, rs, imm);
28344 break;
28345 case OPC_SCD:
28346 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28347 check_insn(ctx, ISA_MIPS3);
28348 check_insn_opc_user_only(ctx, INSN_R5900);
28349 check_mips_64(ctx);
28350 gen_st_cond(ctx, op, rt, rs, imm);
28351 break;
28352 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
28353 if (ctx->insn_flags & ISA_MIPS32R6) {
28354 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
28355 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28356 } else {
28357 /* OPC_DADDI */
28358 check_insn(ctx, ISA_MIPS3);
28359 check_mips_64(ctx);
28360 gen_arith_imm(ctx, op, rt, rs, imm);
28362 break;
28363 case OPC_DADDIU:
28364 check_insn(ctx, ISA_MIPS3);
28365 check_mips_64(ctx);
28366 gen_arith_imm(ctx, op, rt, rs, imm);
28367 break;
28368 #else
28369 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
28370 if (ctx->insn_flags & ISA_MIPS32R6) {
28371 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28372 } else {
28373 MIPS_INVAL("major opcode");
28374 generate_exception_end(ctx, EXCP_RI);
28376 break;
28377 #endif
28378 case OPC_DAUI: /* OPC_JALX */
28379 if (ctx->insn_flags & ISA_MIPS32R6) {
28380 #if defined(TARGET_MIPS64)
28381 /* OPC_DAUI */
28382 check_mips_64(ctx);
28383 if (rs == 0) {
28384 generate_exception(ctx, EXCP_RI);
28385 } else if (rt != 0) {
28386 TCGv t0 = tcg_temp_new();
28387 gen_load_gpr(t0, rs);
28388 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
28389 tcg_temp_free(t0);
28391 #else
28392 generate_exception_end(ctx, EXCP_RI);
28393 MIPS_INVAL("major opcode");
28394 #endif
28395 } else {
28396 /* OPC_JALX */
28397 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
28398 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
28399 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
28401 break;
28402 case OPC_MSA: /* OPC_MDMX */
28403 if (ctx->insn_flags & INSN_R5900) {
28404 decode_tx79_lq(env, ctx); /* TX79_LQ */
28405 } else {
28406 /* MDMX: Not implemented. */
28407 gen_msa(env, ctx);
28409 break;
28410 case OPC_PCREL:
28411 check_insn(ctx, ISA_MIPS32R6);
28412 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
28413 break;
28414 default: /* Invalid */
28415 MIPS_INVAL("major opcode");
28416 generate_exception_end(ctx, EXCP_RI);
28417 break;
28421 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
28423 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28424 CPUMIPSState *env = cs->env_ptr;
28426 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
28427 ctx->saved_pc = -1;
28428 ctx->insn_flags = env->insn_flags;
28429 ctx->CP0_Config1 = env->CP0_Config1;
28430 ctx->CP0_Config2 = env->CP0_Config2;
28431 ctx->CP0_Config3 = env->CP0_Config3;
28432 ctx->CP0_Config5 = env->CP0_Config5;
28433 ctx->btarget = 0;
28434 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
28435 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
28436 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
28437 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
28438 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
28439 ctx->PAMask = env->PAMask;
28440 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
28441 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
28442 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
28443 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
28444 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
28445 /* Restore delay slot state from the tb context. */
28446 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
28447 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
28448 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
28449 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
28450 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
28451 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
28452 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
28453 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
28454 restore_cpu_state(env, ctx);
28455 #ifdef CONFIG_USER_ONLY
28456 ctx->mem_idx = MIPS_HFLAG_UM;
28457 #else
28458 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
28459 #endif
28460 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
28461 MO_UNALN : MO_ALIGN;
28463 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
28464 ctx->hflags);
28467 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
28471 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
28473 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28475 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
28476 ctx->btarget);
28479 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
28480 const CPUBreakpoint *bp)
28482 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28484 save_cpu_state(ctx, 1);
28485 ctx->base.is_jmp = DISAS_NORETURN;
28486 gen_helper_raise_exception_debug(cpu_env);
28487 /* The address covered by the breakpoint must be included in
28488 [tb->pc, tb->pc + tb->size) in order to for it to be
28489 properly cleared -- thus we increment the PC here so that
28490 the logic setting tb->size below does the right thing. */
28491 ctx->base.pc_next += 4;
28492 return true;
28495 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
28497 CPUMIPSState *env = cs->env_ptr;
28498 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28499 int insn_bytes;
28500 int is_slot;
28502 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
28503 if (ctx->insn_flags & ISA_NANOMIPS32) {
28504 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28505 insn_bytes = decode_nanomips_opc(env, ctx);
28506 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
28507 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
28508 insn_bytes = 4;
28509 decode_opc(env, ctx);
28510 } else if (ctx->insn_flags & ASE_MICROMIPS) {
28511 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28512 insn_bytes = decode_micromips_opc(env, ctx);
28513 } else if (ctx->insn_flags & ASE_MIPS16) {
28514 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28515 insn_bytes = decode_mips16_opc(env, ctx);
28516 } else {
28517 generate_exception_end(ctx, EXCP_RI);
28518 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
28519 return;
28522 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28523 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
28524 MIPS_HFLAG_FBNSLOT))) {
28525 /* force to generate branch as there is neither delay nor
28526 forbidden slot */
28527 is_slot = 1;
28529 if ((ctx->hflags & MIPS_HFLAG_M16) &&
28530 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
28531 /* Force to generate branch as microMIPS R6 doesn't restrict
28532 branches in the forbidden slot. */
28533 is_slot = 1;
28536 if (is_slot) {
28537 gen_branch(ctx, insn_bytes);
28539 ctx->base.pc_next += insn_bytes;
28541 if (ctx->base.is_jmp != DISAS_NEXT) {
28542 return;
28544 /* Execute a branch and its delay slot as a single instruction.
28545 This is what GDB expects and is consistent with what the
28546 hardware does (e.g. if a delay slot instruction faults, the
28547 reported PC is the PC of the branch). */
28548 if (ctx->base.singlestep_enabled &&
28549 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
28550 ctx->base.is_jmp = DISAS_TOO_MANY;
28552 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
28553 ctx->base.is_jmp = DISAS_TOO_MANY;
28557 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
28559 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28561 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
28562 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
28563 gen_helper_raise_exception_debug(cpu_env);
28564 } else {
28565 switch (ctx->base.is_jmp) {
28566 case DISAS_STOP:
28567 gen_save_pc(ctx->base.pc_next);
28568 tcg_gen_lookup_and_goto_ptr();
28569 break;
28570 case DISAS_NEXT:
28571 case DISAS_TOO_MANY:
28572 save_cpu_state(ctx, 0);
28573 gen_goto_tb(ctx, 0, ctx->base.pc_next);
28574 break;
28575 case DISAS_EXIT:
28576 tcg_gen_exit_tb(NULL, 0);
28577 break;
28578 case DISAS_NORETURN:
28579 break;
28580 default:
28581 g_assert_not_reached();
28586 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
28588 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
28589 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
28592 static const TranslatorOps mips_tr_ops = {
28593 .init_disas_context = mips_tr_init_disas_context,
28594 .tb_start = mips_tr_tb_start,
28595 .insn_start = mips_tr_insn_start,
28596 .breakpoint_check = mips_tr_breakpoint_check,
28597 .translate_insn = mips_tr_translate_insn,
28598 .tb_stop = mips_tr_tb_stop,
28599 .disas_log = mips_tr_disas_log,
28602 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
28604 DisasContext ctx;
28606 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
28609 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
28610 int flags)
28612 int i;
28613 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
28615 #define printfpr(fp) \
28616 do { \
28617 if (is_fpu64) \
28618 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
28619 " fd:%13g fs:%13g psu: %13g\n", \
28620 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
28621 (double)(fp)->fd, \
28622 (double)(fp)->fs[FP_ENDIAN_IDX], \
28623 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
28624 else { \
28625 fpr_t tmp; \
28626 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
28627 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
28628 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
28629 " fd:%13g fs:%13g psu:%13g\n", \
28630 tmp.w[FP_ENDIAN_IDX], tmp.d, \
28631 (double)tmp.fd, \
28632 (double)tmp.fs[FP_ENDIAN_IDX], \
28633 (double)tmp.fs[!FP_ENDIAN_IDX]); \
28635 } while(0)
28638 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
28639 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
28640 get_float_exception_flags(&env->active_fpu.fp_status));
28641 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
28642 fpu_fprintf(f, "%3s: ", fregnames[i]);
28643 printfpr(&env->active_fpu.fpr[i]);
28646 #undef printfpr
28649 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
28650 int flags)
28652 MIPSCPU *cpu = MIPS_CPU(cs);
28653 CPUMIPSState *env = &cpu->env;
28654 int i;
28656 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
28657 " LO=0x" TARGET_FMT_lx " ds %04x "
28658 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
28659 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
28660 env->hflags, env->btarget, env->bcond);
28661 for (i = 0; i < 32; i++) {
28662 if ((i & 3) == 0)
28663 cpu_fprintf(f, "GPR%02d:", i);
28664 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
28665 if ((i & 3) == 3)
28666 cpu_fprintf(f, "\n");
28669 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
28670 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
28671 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
28672 PRIx64 "\n",
28673 env->CP0_Config0, env->CP0_Config1, env->lladdr);
28674 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
28675 env->CP0_Config2, env->CP0_Config3);
28676 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
28677 env->CP0_Config4, env->CP0_Config5);
28678 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
28679 fpu_dump_state(env, f, cpu_fprintf, flags);
28683 void mips_tcg_init(void)
28685 int i;
28687 cpu_gpr[0] = NULL;
28688 for (i = 1; i < 32; i++)
28689 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
28690 offsetof(CPUMIPSState, active_tc.gpr[i]),
28691 regnames[i]);
28693 for (i = 0; i < 32; i++) {
28694 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
28695 msa_wr_d[i * 2] =
28696 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
28697 /* The scalar floating-point unit (FPU) registers are mapped on
28698 * the MSA vector registers. */
28699 fpu_f64[i] = msa_wr_d[i * 2];
28700 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
28701 msa_wr_d[i * 2 + 1] =
28702 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
28705 cpu_PC = tcg_global_mem_new(cpu_env,
28706 offsetof(CPUMIPSState, active_tc.PC), "PC");
28707 for (i = 0; i < MIPS_DSP_ACC; i++) {
28708 cpu_HI[i] = tcg_global_mem_new(cpu_env,
28709 offsetof(CPUMIPSState, active_tc.HI[i]),
28710 regnames_HI[i]);
28711 cpu_LO[i] = tcg_global_mem_new(cpu_env,
28712 offsetof(CPUMIPSState, active_tc.LO[i]),
28713 regnames_LO[i]);
28715 cpu_dspctrl = tcg_global_mem_new(cpu_env,
28716 offsetof(CPUMIPSState, active_tc.DSPControl),
28717 "DSPControl");
28718 bcond = tcg_global_mem_new(cpu_env,
28719 offsetof(CPUMIPSState, bcond), "bcond");
28720 btarget = tcg_global_mem_new(cpu_env,
28721 offsetof(CPUMIPSState, btarget), "btarget");
28722 hflags = tcg_global_mem_new_i32(cpu_env,
28723 offsetof(CPUMIPSState, hflags), "hflags");
28725 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
28726 offsetof(CPUMIPSState, active_fpu.fcr0),
28727 "fcr0");
28728 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
28729 offsetof(CPUMIPSState, active_fpu.fcr31),
28730 "fcr31");
28732 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
28733 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
28734 offsetof(CPUMIPSState,
28735 active_tc.mxu_gpr[i]),
28736 mxuregnames[i]);
28739 mxu_CR = tcg_global_mem_new(cpu_env,
28740 offsetof(CPUMIPSState, active_tc.mxu_cr),
28741 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
28744 #include "translate_init.inc.c"
28746 void cpu_mips_realize_env(CPUMIPSState *env)
28748 env->exception_base = (int32_t)0xBFC00000;
28750 #ifndef CONFIG_USER_ONLY
28751 mmu_init(env, env->cpu_model);
28752 #endif
28753 fpu_init(env, env->cpu_model);
28754 mvp_init(env, env->cpu_model);
28757 bool cpu_supports_cps_smp(const char *cpu_type)
28759 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
28760 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
28763 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
28765 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
28766 return (mcc->cpu_def->insn_flags & isa) != 0;
28769 void cpu_set_exception_base(int vp_index, target_ulong address)
28771 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
28772 vp->env.exception_base = address;
28775 void cpu_state_reset(CPUMIPSState *env)
28777 MIPSCPU *cpu = mips_env_get_cpu(env);
28778 CPUState *cs = CPU(cpu);
28780 /* Reset registers to their default values */
28781 env->CP0_PRid = env->cpu_model->CP0_PRid;
28782 env->CP0_Config0 = env->cpu_model->CP0_Config0;
28783 #ifdef TARGET_WORDS_BIGENDIAN
28784 env->CP0_Config0 |= (1 << CP0C0_BE);
28785 #endif
28786 env->CP0_Config1 = env->cpu_model->CP0_Config1;
28787 env->CP0_Config2 = env->cpu_model->CP0_Config2;
28788 env->CP0_Config3 = env->cpu_model->CP0_Config3;
28789 env->CP0_Config4 = env->cpu_model->CP0_Config4;
28790 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
28791 env->CP0_Config5 = env->cpu_model->CP0_Config5;
28792 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
28793 env->CP0_Config6 = env->cpu_model->CP0_Config6;
28794 env->CP0_Config7 = env->cpu_model->CP0_Config7;
28795 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
28796 << env->cpu_model->CP0_LLAddr_shift;
28797 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
28798 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
28799 env->CCRes = env->cpu_model->CCRes;
28800 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
28801 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
28802 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
28803 env->current_tc = 0;
28804 env->SEGBITS = env->cpu_model->SEGBITS;
28805 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
28806 #if defined(TARGET_MIPS64)
28807 if (env->cpu_model->insn_flags & ISA_MIPS3) {
28808 env->SEGMask |= 3ULL << 62;
28810 #endif
28811 env->PABITS = env->cpu_model->PABITS;
28812 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
28813 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
28814 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
28815 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
28816 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
28817 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
28818 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
28819 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
28820 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
28821 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
28822 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
28823 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
28824 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
28825 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
28826 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
28827 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
28828 env->msair = env->cpu_model->MSAIR;
28829 env->insn_flags = env->cpu_model->insn_flags;
28831 #if defined(CONFIG_USER_ONLY)
28832 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
28833 # ifdef TARGET_MIPS64
28834 /* Enable 64-bit register mode. */
28835 env->CP0_Status |= (1 << CP0St_PX);
28836 # endif
28837 # ifdef TARGET_ABI_MIPSN64
28838 /* Enable 64-bit address mode. */
28839 env->CP0_Status |= (1 << CP0St_UX);
28840 # endif
28841 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
28842 hardware registers. */
28843 env->CP0_HWREna |= 0x0000000F;
28844 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
28845 env->CP0_Status |= (1 << CP0St_CU1);
28847 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
28848 env->CP0_Status |= (1 << CP0St_MX);
28850 # if defined(TARGET_MIPS64)
28851 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
28852 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
28853 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
28854 env->CP0_Status |= (1 << CP0St_FR);
28856 # endif
28857 #else
28858 if (env->hflags & MIPS_HFLAG_BMASK) {
28859 /* If the exception was raised from a delay slot,
28860 come back to the jump. */
28861 env->CP0_ErrorEPC = (env->active_tc.PC
28862 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
28863 } else {
28864 env->CP0_ErrorEPC = env->active_tc.PC;
28866 env->active_tc.PC = env->exception_base;
28867 env->CP0_Random = env->tlb->nb_tlb - 1;
28868 env->tlb->tlb_in_use = env->tlb->nb_tlb;
28869 env->CP0_Wired = 0;
28870 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
28871 env->CP0_EBase = (cs->cpu_index & 0x3FF);
28872 if (mips_um_ksegs_enabled()) {
28873 env->CP0_EBase |= 0x40000000;
28874 } else {
28875 env->CP0_EBase |= (int32_t)0x80000000;
28877 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
28878 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
28880 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
28881 0x3ff : 0xff;
28882 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
28883 /* vectored interrupts not implemented, timer on int 7,
28884 no performance counters. */
28885 env->CP0_IntCtl = 0xe0000000;
28887 int i;
28889 for (i = 0; i < 7; i++) {
28890 env->CP0_WatchLo[i] = 0;
28891 env->CP0_WatchHi[i] = 0x80000000;
28893 env->CP0_WatchLo[7] = 0;
28894 env->CP0_WatchHi[7] = 0;
28896 /* Count register increments in debug mode, EJTAG version 1 */
28897 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
28899 cpu_mips_store_count(env, 1);
28901 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
28902 int i;
28904 /* Only TC0 on VPE 0 starts as active. */
28905 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
28906 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
28907 env->tcs[i].CP0_TCHalt = 1;
28909 env->active_tc.CP0_TCHalt = 1;
28910 cs->halted = 1;
28912 if (cs->cpu_index == 0) {
28913 /* VPE0 starts up enabled. */
28914 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
28915 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
28917 /* TC0 starts up unhalted. */
28918 cs->halted = 0;
28919 env->active_tc.CP0_TCHalt = 0;
28920 env->tcs[0].CP0_TCHalt = 0;
28921 /* With thread 0 active. */
28922 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
28923 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
28928 * Configure default legacy segmentation control. We use this regardless of
28929 * whether segmentation control is presented to the guest.
28931 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
28932 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
28933 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
28934 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
28935 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
28936 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
28937 (2 << CP0SC_C);
28938 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
28939 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
28940 (3 << CP0SC_C)) << 16;
28941 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
28942 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
28943 (1 << CP0SC_EU) | (2 << CP0SC_C);
28944 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
28945 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
28946 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
28947 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
28948 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
28949 #endif
28950 if ((env->insn_flags & ISA_MIPS32R6) &&
28951 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
28952 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
28953 env->CP0_Status |= (1 << CP0St_FR);
28956 if (env->insn_flags & ISA_MIPS32R6) {
28957 /* PTW = 1 */
28958 env->CP0_PWSize = 0x40;
28959 /* GDI = 12 */
28960 /* UDI = 12 */
28961 /* MDI = 12 */
28962 /* PRI = 12 */
28963 /* PTEI = 2 */
28964 env->CP0_PWField = 0x0C30C302;
28965 } else {
28966 /* GDI = 0 */
28967 /* UDI = 0 */
28968 /* MDI = 0 */
28969 /* PRI = 0 */
28970 /* PTEI = 2 */
28971 env->CP0_PWField = 0x02;
28974 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
28975 /* microMIPS on reset when Config3.ISA is 3 */
28976 env->hflags |= MIPS_HFLAG_M16;
28979 /* MSA */
28980 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
28981 msa_reset(env);
28984 compute_hflags(env);
28985 restore_fp_status(env);
28986 restore_pamask(env);
28987 cs->exception_index = EXCP_NONE;
28989 if (semihosting_get_argc()) {
28990 /* UHI interface can be used to obtain argc and argv */
28991 env->active_tc.gpr[4] = -1;
28995 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
28996 target_ulong *data)
28998 env->active_tc.PC = data[0];
28999 env->hflags &= ~MIPS_HFLAG_BMASK;
29000 env->hflags |= data[1];
29001 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
29002 case MIPS_HFLAG_BR:
29003 break;
29004 case MIPS_HFLAG_BC:
29005 case MIPS_HFLAG_BL:
29006 case MIPS_HFLAG_B:
29007 env->btarget = data[2];
29008 break;